<commit_before>#include "base.h"

#ifdef WIN32
    #include <windows.h>
#endif

#include <string.h>

#define KEY_TAB 9
#define KEY_ESC 27

GLint width  = 400,
      height = 400;

GLfloat ortho2D_minX = -400.0f,
        ortho2D_maxX =  400.0f,
        ortho2D_minY = -400.0f,
        ortho2D_maxY =  400.0f;

bool selectionMode = false;

PWorld world;
int currentObj = -1;
bool isMouseDown = false;

void resize(int width, int height)
{

}

void DrawText(int x, int y, char *s)
{
    int len, i;
    glColor3f(1.0f, 0.0f, 0.0f);
    glRasterPos2f(x, y);
    len = (int) strlen(s);

    for (i = 0; i < len; i++)
    {
        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i]);
    }
}

/**
    Converte o espaço X do mouse, para o espaço X do Ortho.
**/
int convertXSpace(int x)
{
    return (x * 2) - width;
}

/**
    Converte o espaço Y do mouse, para o espaço Y do Ortho.
**/
int convertYSpace(int y)
{
    return (y * -2) + height;
}

void drawMode()
{
    DrawText(ortho2D_minX + 4, ortho2D_minY + 4, (char*)(selectionMode ? "Selecao (Tab)" : "Edicao (Tab)"));
}

void display()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluOrtho2D(ortho2D_minX, ortho2D_maxX, ortho2D_minY, ortho2D_maxY);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    drawMode();
    world->Draw();
    //DrawXYAxes();

    glutSwapBuffers();
}

void keyPress(unsigned char key, int x, int y)
{
    switch (key)
    {
        case KEY_ESC:
            exit(0);
        break;
        case KEY_TAB:
            selectionMode = !selectionMode;
            glutPostRedisplay();
        break;
        default:
            cout << key << "\n";
        break;
    }
}

void specialKeyPress(int key, int x, int y)
{

}

void mouseMove(int x, int y)
{
    //cout << "Current Obj = " << currentObj << "\n";
    //cout << "Mouse is Down = " << isMouseDown << "\n";

    if (isMouseDown && currentObj != -1)
    {
        //cout << "x = " << x << " y = " << y << "\n";

        Point& pe = world->Objects[currentObj]->Points.back();
        pe.x = convertXSpace(x);
        pe.y = convertYSpace(y);

        glutPostRedisplay();
    }
}

void mouseEvent(int button, int state, int x, int y)
{
    // button  GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, or GLUT_RIGHT_BUTTON
    // state GLUT_UP or GLUT_DOWN
    //cout << "x = " << x << " y = " << y << "\n";

    if (selectionMode)
    {

    }
    else
    {
        if (button == GLUT_LEFT_BUTTON)
        {
            if (state == GLUT_DOWN)
            {
                isMouseDown = true;

                // É um novo
                if (currentObj == -1)
                {
                    world->Objects.push_back(new GraphicObject());
                    currentObj = world->Objects.size() - 1;
                }

                Point ps;
                ps.x = convertXSpace(x);
                ps.y = convertYSpace(y);

                world->Objects[currentObj]->Points.push_back(ps);
                world->Objects[currentObj]->Points.push_back(ps);
            }
            else if (state == GLUT_UP)
            {
                isMouseDown = false;

                if (currentObj != -1)
                {
                    Point& pe = world->Objects[currentObj]->Points.back();
                    pe.x = convertXSpace(x);
                    pe.y = convertYSpace(y);
                }
            }

            //cout << "Current Obj = " << currentObj << "\n";
            //cout << "Mouse is Down = " << isMouseDown << "\n";
        }
        else
        {
            currentObj = -1;
        }
    }

    glutPostRedisplay();
}

void createScene()
{
    /*GraphicObject o1;
    o1.Draw();

    GraphicObject* o2 = new GraphicObject();
    o2->Draw();*/
}

void init(void)
{
    /*glClearColor(1.0f,1.0f,1.0f,1.0);

    createScene();*/

    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_LIGHTING);

    glClearColor(0.8f, 0.8f, 1.0f, 1.0f);

    world = new World();
/*
    // Draw line test.
    auto o = new GraphicObject();
    Point p1;
    p1.x = -200;
    p1.y = 0;
    Point p2;
    p2.x = 200;
    p2.y = 0;
    o->Points.push_back(p1);
    o->Points.push_back(p2);
    world->Objects.push_back(o);
*/
}

int main(int argc, const char * argv[])
{
    glutInit(&argc, (char **)argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(300, 250);
    glutInitWindowSize(height, width);

    glutCreateWindow("N3");

    glutReshapeFunc(resize);
    glutDisplayFunc(display);
    glutKeyboardFunc(keyPress);
    glutSpecialFunc(specialKeyPress);
    glutMotionFunc(mouseMove);
    glutMouseFunc(mouseEvent);

    init();
    glutMainLoop();

    return 0;
}<commit_msg>Remove all objects from universe with del key.<commit_after>#include "base.h"

#ifdef WIN32
    #include <windows.h>
#endif

#include <string.h>

#define KEY_TAB 9
#define KEY_ESC 27
#define KEY_DEL 127

GLint width  = 400,
      height = 400;

GLfloat ortho2D_minX = -400.0f,
        ortho2D_maxX =  400.0f,
        ortho2D_minY = -400.0f,
        ortho2D_maxY =  400.0f;

bool selectionMode = false;

PWorld world;
int currentObj = -1;
bool isMouseDown = false;

void resize(int width, int height)
{

}

void DrawText(int x, int y, char *s)
{
    int len, i;
    glColor3f(1.0f, 0.0f, 0.0f);
    glRasterPos2f(x, y);
    len = (int) strlen(s);

    for (i = 0; i < len; i++)
    {
        glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, s[i]);
    }
}

/**
    Converte o espaço X do mouse, para o espaço X do Ortho.
**/
int convertXSpace(int x)
{
    return (x * 2) - width;
}

/**
    Converte o espaço Y do mouse, para o espaço Y do Ortho.
**/
int convertYSpace(int y)
{
    return (y * -2) + height;
}

void drawMode()
{
    DrawText(ortho2D_minX + 4, ortho2D_minY + 4, (char*)(selectionMode ? "Selecao (Tab)" : "Edicao (Tab)"));
}

void display()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluOrtho2D(ortho2D_minX, ortho2D_maxX, ortho2D_minY, ortho2D_maxY);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    drawMode();
    world->Draw();
    //DrawXYAxes();

    glutSwapBuffers();
}

void keyPress(unsigned char key, int x, int y)
{
    switch (key)
    {
        case KEY_ESC:
            exit(0);
        break;
        case KEY_TAB:
            selectionMode = !selectionMode;
            glutPostRedisplay();
        break;
        case KEY_DEL:
            // Limpa a tela se for edição.
            if (!selectionMode)
            {
                currentObj = -1;
                world->Objects.clear();
                glutPostRedisplay();
            }
        break;
        default:
            cout << key << "\n";
        break;
    }
}

void specialKeyPress(int key, int x, int y)
{

}

void mouseMove(int x, int y)
{
    //cout << "Current Obj = " << currentObj << "\n";
    //cout << "Mouse is Down = " << isMouseDown << "\n";

    if (isMouseDown && currentObj != -1)
    {
        //cout << "x = " << x << " y = " << y << "\n";

        Point& pe = world->Objects[currentObj]->Points.back();
        pe.x = convertXSpace(x);
        pe.y = convertYSpace(y);

        glutPostRedisplay();
    }
}

void mouseEvent(int button, int state, int x, int y)
{
    // button  GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, or GLUT_RIGHT_BUTTON
    // state GLUT_UP or GLUT_DOWN
    //cout << "x = " << x << " y = " << y << "\n";

    if (selectionMode)
    {

    }
    else
    {
        if (button == GLUT_LEFT_BUTTON)
        {
            if (state == GLUT_DOWN)
            {
                isMouseDown = true;

                // É um novo
                if (currentObj == -1)
                {
                    world->Objects.push_back(new GraphicObject());
                    currentObj = world->Objects.size() - 1;
                }

                Point ps;
                ps.x = convertXSpace(x);
                ps.y = convertYSpace(y);

                world->Objects[currentObj]->Points.push_back(ps);
                world->Objects[currentObj]->Points.push_back(ps);
            }
            else if (state == GLUT_UP)
            {
                isMouseDown = false;

                if (currentObj != -1)
                {
                    Point& pe = world->Objects[currentObj]->Points.back();
                    pe.x = convertXSpace(x);
                    pe.y = convertYSpace(y);
                }
            }

            //cout << "Current Obj = " << currentObj << "\n";
            //cout << "Mouse is Down = " << isMouseDown << "\n";
        }
        else
        {
            currentObj = -1;
        }
    }

    glutPostRedisplay();
}

void createScene()
{
    /*GraphicObject o1;
    o1.Draw();

    GraphicObject* o2 = new GraphicObject();
    o2->Draw();*/
}

void init(void)
{
    /*glClearColor(1.0f,1.0f,1.0f,1.0);

    createScene();*/

    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_LIGHTING);

    glClearColor(0.8f, 0.8f, 1.0f, 1.0f);

    world = new World();
/*
    // Draw line test.
    auto o = new GraphicObject();
    Point p1;
    p1.x = -200;
    p1.y = 0;
    Point p2;
    p2.x = 200;
    p2.y = 0;
    o->Points.push_back(p1);
    o->Points.push_back(p2);
    world->Objects.push_back(o);
*/
}

int main(int argc, const char * argv[])
{
    glutInit(&argc, (char **)argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(300, 250);
    glutInitWindowSize(height, width);

    glutCreateWindow("N3");

    glutReshapeFunc(resize);
    glutDisplayFunc(display);
    glutKeyboardFunc(keyPress);
    glutSpecialFunc(specialKeyPress);
    glutMotionFunc(mouseMove);
    glutMouseFunc(mouseEvent);

    init();
    glutMainLoop();

    return 0;
}<|endoftext|>


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

#ifndef __rtkBinningImageFilter_cxx
#define __rtkBinningImageFilter_cxx

#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIterator.h>
#include <itkVariableLengthVector.h>
#include <itkImageConstIteratorWithIndex.h>

namespace rtk
{

BinningImageFilter::BinningImageFilter()
{
  m_BinningFactors[0]=2;
  m_BinningFactors[1]=2;
}

void BinningImageFilter::GenerateInputRequestedRegion()
{
  ImageType::Pointer inputPtr = const_cast<ImageType *>(this->GetInput());

  inputPtr->SetRequestedRegion( inputPtr->GetLargestPossibleRegion() );
}

void BinningImageFilter::GenerateOutputInformation()
{
  const ImageType::SpacingType& inputSpacing    = this->GetInput()->GetSpacing();
  const ImageType::SizeType&    inputSize       = this->GetInput()->GetLargestPossibleRegion().GetSize();
  const ImageType::IndexType&   inputStartIndex = this->GetInput()->GetLargestPossibleRegion().GetIndex();
  const ImageType::PointType&   inputOrigin     = this->GetInput()->GetOrigin();

  ImageType::SpacingType  outputSpacing;
  ImageType::SizeType     outputSize;
  ImageType::IndexType    outputStartIndex;
  ImageType::PointType    outputOrigin;

  for (unsigned int i = 0; i < ImageType::ImageDimension; i++)
  {
    outputSpacing[i] = inputSpacing[i] * (double) m_BinningFactors[i];
    outputOrigin[i]  = inputOrigin[i];
    // Round down so that all output pixels fit input region
    outputSize[i] = (unsigned long)vcl_floor(double(inputSize[i]) / double(m_BinningFactors[i]) );

    if( outputSize[i] < 1 )
    {
      outputSize[i] = 1;
    }

    // Because of the later origin shift this starting index is not
    // critical
    outputStartIndex[i] = (long)vcl_ceil((double) inputStartIndex[i] / (double) m_BinningFactors[i] );
  }

  this->GetOutput()->SetSpacing( outputSpacing );
  //FIXME: origin needs to be shifted 0.5 pixels after binning
  this->GetOutput()->SetOrigin( outputOrigin );

  // Set region
  ImageType::RegionType outputLargestPossibleRegion;
  outputLargestPossibleRegion.SetSize( outputSize );
  outputLargestPossibleRegion.SetIndex( outputStartIndex );
  this->GetOutput()->SetLargestPossibleRegion( outputLargestPossibleRegion );
}

void BinningImageFilter
::ThreadedGenerateData(const OutputImageRegionType& itkNotUsed(outputRegionForThread), ThreadIdType threadId )
{

  int inputSize[2], binSize[2];
  inputSize[0] = this->GetInput()->GetLargestPossibleRegion().GetSize()[0];
  inputSize[1] = this->GetInput()->GetLargestPossibleRegion().GetSize()[1];
  binSize[0] = (inputSize[0]>>1);
  binSize[1] = (inputSize[1]>>1);

  typedef   ImageType::PixelType inputPixel;
  typedef   ImageType::PixelType outputPixel;

  //this->GenerateOutputInformation();
  const inputPixel  *bufferIn  = this->GetInput()->GetBufferPointer();
  outputPixel *bufferOut = this->GetOutput()->GetBufferPointer();

  int initX = threadId*inputSize[0]*inputSize[1]/(this->GetNumberOfThreads()*m_BinningFactors[0]);
  int endX = initX + binSize[0]*inputSize[1]/this->GetNumberOfThreads();
  int initY = threadId*binSize[1]/this->GetNumberOfThreads();
  int endY = initY + binSize[1]/this->GetNumberOfThreads();

  // Binning 2x2
  if(m_BinningFactors[0]==2 && m_BinningFactors[1]==2)
  {
    const int Vlength = endX-initX;
    std::vector<int> V(Vlength,0);

    int i, j, idx, pos, vj;
    for (i=0, idx=initX*m_BinningFactors[0]; i < Vlength; i++, idx+=2) // Only works if number of pixels per line multiple of 2
    {
        V[i] = ( (bufferIn[idx])+(bufferIn[idx+1]) );
    }
    for (j=initY, vj=0; j<endY; j++, vj++)
    {
      pos = j*binSize[0];
      for (i=0; i < binSize[0]; i++, pos++)
        {
            bufferOut[pos] = ( (V[2*vj*binSize[0]+i])+(V[(2*vj+1)*binSize[0]+i]) )>>2;
        }
    }
  }

  // Binning 2x1
  else if(m_BinningFactors[0]==2 && m_BinningFactors[1]==1)
  {
    int i, idx;
    for (i=initX, idx=initX*m_BinningFactors[0]; i < endX; i++, idx+=2) // Only works if number of pixels per line multiple of 2
        bufferOut[i] = ( (bufferIn[idx])+(bufferIn[idx+1]) )>>1;
  }

  // Binning 1x2
  else if(m_BinningFactors[0]==1 && m_BinningFactors[1]==2)
  {
    int i, j, pos;
    for (j=initY; j<endY;j++)
    {
      pos = j*inputSize[0];
      for (i=0; i<inputSize[0];i++, pos++)
        bufferOut[pos] = ( (bufferIn[2*j*inputSize[0]+i])+(bufferIn[(2*j+1)*inputSize[0]+i]) )>>1;
    }
  }
  else
  {
    itkExceptionMacro(<< "Binning factors mismatch! Current factors: "
                      << m_BinningFactors[0] << "x"
                      << m_BinningFactors[1] << " "
                      << "accepted modes [2x2] [2x1] and [1x2]")
  }
}

} // end namespace rtk

#endif // __rtkBinningImageFilter_cxx
<commit_msg>Clarified BinningImageFilter::GenerateOutputInformation which was unreadable. Added check on dimension.<commit_after>/*=========================================================================
 *
 *  Copyright RTK Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#ifndef __rtkBinningImageFilter_cxx
#define __rtkBinningImageFilter_cxx

#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIterator.h>
#include <itkVariableLengthVector.h>
#include <itkImageConstIteratorWithIndex.h>

namespace rtk
{

BinningImageFilter::BinningImageFilter()
{
  m_BinningFactors[0]=2;
  m_BinningFactors[1]=2;
}

void BinningImageFilter::GenerateInputRequestedRegion()
{
  ImageType::Pointer inputPtr = const_cast<ImageType *>(this->GetInput());
  inputPtr->SetRequestedRegion( inputPtr->GetLargestPossibleRegion() );
}

void BinningImageFilter::GenerateOutputInformation()
{
  const ImageType::SpacingType& inputSpacing    = this->GetInput()->GetSpacing();
  const ImageType::SizeType&    inputSize       = this->GetInput()->GetLargestPossibleRegion().GetSize();
  const ImageType::IndexType&   inputStartIndex = this->GetInput()->GetLargestPossibleRegion().GetIndex();
  const ImageType::PointType&   inputOrigin     = this->GetInput()->GetOrigin();

  ImageType::SpacingType  outputSpacing;
  ImageType::SizeType     outputSize;
  ImageType::IndexType    outputStartIndex;
  ImageType::PointType    outputOrigin;

  for (unsigned int i = 0; i < ImageType::ImageDimension; i++)
    {
    outputSpacing[i] = inputSpacing[i] * m_BinningFactors[i];
    outputOrigin[i]  = inputOrigin[i] + inputSpacing[i]/m_BinningFactors[i];
    if(inputSize[i]%m_BinningFactors[i] != 0)
      {
      itkExceptionMacro(<< "Binning currently works only for integer divisions")
      }
    else
      outputSize[i] = inputSize[i] / m_BinningFactors[i];

    outputStartIndex[i] = inputStartIndex[i] / m_BinningFactors[i];
  }

  this->GetOutput()->SetSpacing( outputSpacing );
  this->GetOutput()->SetOrigin( outputOrigin );

  // Set region
  ImageType::RegionType outputLargestPossibleRegion;
  outputLargestPossibleRegion.SetSize( outputSize );
  outputLargestPossibleRegion.SetIndex( outputStartIndex );
  this->GetOutput()->SetLargestPossibleRegion( outputLargestPossibleRegion );
}

void BinningImageFilter
::ThreadedGenerateData(const OutputImageRegionType& itkNotUsed(outputRegionForThread), ThreadIdType threadId )
{

  int inputSize[2], binSize[2];
  inputSize[0] = this->GetInput()->GetLargestPossibleRegion().GetSize()[0];
  inputSize[1] = this->GetInput()->GetLargestPossibleRegion().GetSize()[1];
  binSize[0] = (inputSize[0]>>1);
  binSize[1] = (inputSize[1]>>1);

  typedef   ImageType::PixelType inputPixel;
  typedef   ImageType::PixelType outputPixel;

  //this->GenerateOutputInformation();
  const inputPixel  *bufferIn  = this->GetInput()->GetBufferPointer();
  outputPixel *bufferOut = this->GetOutput()->GetBufferPointer();

  int initX = threadId*inputSize[0]*inputSize[1]/(this->GetNumberOfThreads()*m_BinningFactors[0]);
  int endX = initX + binSize[0]*inputSize[1]/this->GetNumberOfThreads();
  int initY = threadId*binSize[1]/this->GetNumberOfThreads();
  int endY = initY + binSize[1]/this->GetNumberOfThreads();

  // Binning 2x2
  if(m_BinningFactors[0]==2 && m_BinningFactors[1]==2)
  {
    const int Vlength = endX-initX;
    std::vector<int> V(Vlength,0);

    int i, j, idx, pos, vj;
    for (i=0, idx=initX*m_BinningFactors[0]; i < Vlength; i++, idx+=2) // Only works if number of pixels per line multiple of 2
    {
        V[i] = ( (bufferIn[idx])+(bufferIn[idx+1]) );
    }
    for (j=initY, vj=0; j<endY; j++, vj++)
    {
      pos = j*binSize[0];
      for (i=0; i < binSize[0]; i++, pos++)
        {
            bufferOut[pos] = ( (V[2*vj*binSize[0]+i])+(V[(2*vj+1)*binSize[0]+i]) )>>2;
        }
    }
  }

  // Binning 2x1
  else if(m_BinningFactors[0]==2 && m_BinningFactors[1]==1)
  {
    int i, idx;
    for (i=initX, idx=initX*m_BinningFactors[0]; i < endX; i++, idx+=2) // Only works if number of pixels per line multiple of 2
        bufferOut[i] = ( (bufferIn[idx])+(bufferIn[idx+1]) )>>1;
  }

  // Binning 1x2
  else if(m_BinningFactors[0]==1 && m_BinningFactors[1]==2)
  {
    int i, j, pos;
    for (j=initY; j<endY;j++)
    {
      pos = j*inputSize[0];
      for (i=0; i<inputSize[0];i++, pos++)
        bufferOut[pos] = ( (bufferIn[2*j*inputSize[0]+i])+(bufferIn[(2*j+1)*inputSize[0]+i]) )>>1;
    }
  }
  else
  {
    itkExceptionMacro(<< "Binning factors mismatch! Current factors: "
                      << m_BinningFactors[0] << "x"
                      << m_BinningFactors[1] << " "
                      << "accepted modes [2x2] [2x1] and [1x2]")
  }
}

} // end namespace rtk

#endif // __rtkBinningImageFilter_cxx
<|endoftext|>


<commit_before>/*
 * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by the
 * Free Software Foundation; either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program 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 Affero General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "Player.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "ruins_of_ahnqiraj.h"

enum Texts
{
    EMOTE_AGGRO                 = 0,
    EMOTE_MANA_FULL             = 1,
    EMOTE_STONE_PHASE           = 2
};

enum Spells
{
    SPELL_TRAMPLE               = 15550,
    SPELL_DRAIN_MANA_SERVERSIDE = 25676,
    SPELL_DRAIN_MANA            = 25671,
    SPELL_ARCANE_ERUPTION       = 25672,
    SPELL_SUMMON_MANA_FIENDS    = 25684,
    SPELL_SUMMON_MANA_FIEND_1   = 25681, // TARGET_DEST_CASTER_FRONT
    SPELL_SUMMON_MANA_FIEND_2   = 25682, // TARGET_DEST_CASTER_LEFT
    SPELL_SUMMON_MANA_FIEND_3   = 25683, // TARGET_DEST_CASTER_RIGHT
    SPELL_ENERGIZE              = 25685,

    SPELL_LARGE_OBSIDIAN_CHUNK  = 27630 //  Server-side
};

enum Events
{
    EVENT_SPELL_TRAMPLE         = 1,
    EVENT_SPELL_DRAIN_MANA      = 2,
    EVENT_STONE_PHASE           = 3,
    EVENT_STONE_PHASE_END       = 4
};

struct boss_moam : public BossAI
{
    boss_moam(Creature* creature) : BossAI(creature, DATA_MOAM) {}

    void Reset() override
    {
        _Reset();
        me->SetPower(POWER_MANA, 0);
        me->SetRegeneratingPower(false);
    }

    void EnterCombat(Unit* who) override
    {
        BossAI::EnterCombat(who);
        Talk(EMOTE_AGGRO);
        events.ScheduleEvent(EVENT_STONE_PHASE, 90s);
        events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9s);
        events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3s);
    }

    void JustDied(Unit* /*killer*/) override
    {
        _JustDied();
        DoCastAOE(SPELL_LARGE_OBSIDIAN_CHUNK, true);
    }

    void SummonedCreatureDies(Creature* /*creature*/, Unit* /*killer*/) override
    {
        if (!summons.IsAnyCreatureAlive() && me->HasAura(SPELL_ENERGIZE))
        {
            events.RescheduleEvent(EVENT_STONE_PHASE_END, 1s);
        }
    }

    void UpdateAI(uint32 diff) override
    {
        if (!UpdateVictim())
            return;

        events.Update(diff);

        if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA))
        {
            if (me->HasAura(SPELL_ENERGIZE))
            {
                me->RemoveAurasDueToSpell(SPELL_ENERGIZE);
                events.RescheduleEvent(EVENT_STONE_PHASE_END, 1s);
            }

            Talk(EMOTE_MANA_FULL);
            DoCastAOE(SPELL_ARCANE_ERUPTION);
        }

        while (uint32 eventId = events.ExecuteEvent())
        {
            switch (eventId)
            {
                case EVENT_STONE_PHASE:
                    Talk(EMOTE_STONE_PHASE);
                    DoCastAOE(SPELL_SUMMON_MANA_FIENDS);
                    DoCastSelf(SPELL_ENERGIZE);
                    events.CancelEvent(EVENT_SPELL_DRAIN_MANA);
                    events.ScheduleEvent(EVENT_STONE_PHASE_END, 90s);
                    break;
                case EVENT_STONE_PHASE_END:
                    me->RemoveAurasDueToSpell(SPELL_ENERGIZE);
                    events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 2s, 6s);
                    events.ScheduleEvent(EVENT_STONE_PHASE, 90s);
                    break;
                case EVENT_SPELL_DRAIN_MANA:
                    DoCastAOE(SPELL_DRAIN_MANA_SERVERSIDE);
                    events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 2s, 6s);
                    break;
                case EVENT_SPELL_TRAMPLE:
                    DoCastAOE(SPELL_TRAMPLE);
                    events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15s);
                    break;
                default:
                    break;
            }
        }

        DoMeleeAttackIfReady();
    }
};

// 25676 - Drain Mana (server-side)
class spell_moam_mana_drain_filter : public SpellScript
{
    PrepareSpellScript(spell_moam_mana_drain_filter);

    void FilterTargets(std::list<WorldObject*>& targets)
    {
        targets.remove_if([&](WorldObject* target) -> bool
        {
            return !target->IsPlayer() || target->ToPlayer()->getPowerType() != POWER_MANA;
        });

        if (!targets.empty())
        {
            Acore::Containers::RandomResize(targets, 6);
        }
    }

    void HandleScript(SpellEffIndex /*effIndex*/)
    {
        if (Unit* caster = GetCaster())
        {
            caster->CastSpell(GetHitUnit(), SPELL_DRAIN_MANA, true);
        }
    }

    void Register() override
    {
        OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_moam_mana_drain_filter::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
        OnEffectHitTarget += SpellEffectFn(spell_moam_mana_drain_filter::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
    }
};

// 25684 - Summon Mana Fiends (server-side)
class spell_moam_summon_mana_fiends : public SpellScript
{
    PrepareSpellScript(spell_moam_summon_mana_fiends);

    void HandleScript(SpellEffIndex /*effIndex*/)
    {
        const uint32 spellIds[3] = { SPELL_SUMMON_MANA_FIEND_1, SPELL_SUMMON_MANA_FIEND_2, SPELL_SUMMON_MANA_FIEND_3 };

        for (uint32 spellId : spellIds)
        {
            GetCaster()->CastSpell((Unit*)nullptr, spellId, true);
        }
    }

    void Register() override
    {
        OnEffectHitTarget += SpellEffectFn(spell_moam_summon_mana_fiends::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
    }
};

void AddSC_boss_moam()
{
    RegisterRuinsOfAhnQirajCreatureAI(boss_moam);
    RegisterSpellScript(spell_moam_mana_drain_filter);
    RegisterSpellScript(spell_moam_summon_mana_fiends);
}
<commit_msg>fix(Scripts/AqhQiraj): Increased aggro range for Moam. (#12947)<commit_after>/*
 * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by the
 * Free Software Foundation; either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program 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 Affero General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "Player.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "ruins_of_ahnqiraj.h"

enum Texts
{
    EMOTE_AGGRO                 = 0,
    EMOTE_MANA_FULL             = 1,
    EMOTE_STONE_PHASE           = 2
};

enum Spells
{
    SPELL_TRAMPLE               = 15550,
    SPELL_DRAIN_MANA_SERVERSIDE = 25676,
    SPELL_DRAIN_MANA            = 25671,
    SPELL_ARCANE_ERUPTION       = 25672,
    SPELL_SUMMON_MANA_FIENDS    = 25684,
    SPELL_SUMMON_MANA_FIEND_1   = 25681, // TARGET_DEST_CASTER_FRONT
    SPELL_SUMMON_MANA_FIEND_2   = 25682, // TARGET_DEST_CASTER_LEFT
    SPELL_SUMMON_MANA_FIEND_3   = 25683, // TARGET_DEST_CASTER_RIGHT
    SPELL_ENERGIZE              = 25685,

    SPELL_LARGE_OBSIDIAN_CHUNK  = 27630 //  Server-side
};

enum Events
{
    EVENT_SPELL_TRAMPLE         = 1,
    EVENT_SPELL_DRAIN_MANA      = 2,
    EVENT_STONE_PHASE           = 3,
    EVENT_STONE_PHASE_END       = 4
};

struct boss_moam : public BossAI
{
    boss_moam(Creature* creature) : BossAI(creature, DATA_MOAM) {}

    void InitializeAI() override
    {
        me->m_CombatDistance = 50.0f;
        Reset();
    }

    void Reset() override
    {
        _Reset();
        me->SetPower(POWER_MANA, 0);
        me->SetRegeneratingPower(false);
    }

    void EnterCombat(Unit* who) override
    {
        BossAI::EnterCombat(who);
        Talk(EMOTE_AGGRO);
        events.ScheduleEvent(EVENT_STONE_PHASE, 90s);
        events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 9s);
        events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 3s);
    }

    void JustDied(Unit* /*killer*/) override
    {
        _JustDied();
        DoCastAOE(SPELL_LARGE_OBSIDIAN_CHUNK, true);
    }

    void SummonedCreatureDies(Creature* /*creature*/, Unit* /*killer*/) override
    {
        if (!summons.IsAnyCreatureAlive() && me->HasAura(SPELL_ENERGIZE))
        {
            events.RescheduleEvent(EVENT_STONE_PHASE_END, 1s);
        }
    }

    void UpdateAI(uint32 diff) override
    {
        if (!UpdateVictim())
            return;

        events.Update(diff);

        if (me->GetPower(POWER_MANA) == me->GetMaxPower(POWER_MANA))
        {
            if (me->HasAura(SPELL_ENERGIZE))
            {
                me->RemoveAurasDueToSpell(SPELL_ENERGIZE);
                events.RescheduleEvent(EVENT_STONE_PHASE_END, 1s);
            }

            Talk(EMOTE_MANA_FULL);
            DoCastAOE(SPELL_ARCANE_ERUPTION);
        }

        while (uint32 eventId = events.ExecuteEvent())
        {
            switch (eventId)
            {
                case EVENT_STONE_PHASE:
                    Talk(EMOTE_STONE_PHASE);
                    DoCastAOE(SPELL_SUMMON_MANA_FIENDS);
                    DoCastSelf(SPELL_ENERGIZE);
                    events.CancelEvent(EVENT_SPELL_DRAIN_MANA);
                    events.ScheduleEvent(EVENT_STONE_PHASE_END, 90s);
                    break;
                case EVENT_STONE_PHASE_END:
                    me->RemoveAurasDueToSpell(SPELL_ENERGIZE);
                    events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 2s, 6s);
                    events.ScheduleEvent(EVENT_STONE_PHASE, 90s);
                    break;
                case EVENT_SPELL_DRAIN_MANA:
                    DoCastAOE(SPELL_DRAIN_MANA_SERVERSIDE);
                    events.ScheduleEvent(EVENT_SPELL_DRAIN_MANA, 2s, 6s);
                    break;
                case EVENT_SPELL_TRAMPLE:
                    DoCastAOE(SPELL_TRAMPLE);
                    events.ScheduleEvent(EVENT_SPELL_TRAMPLE, 15s);
                    break;
                default:
                    break;
            }
        }

        DoMeleeAttackIfReady();
    }
};

// 25676 - Drain Mana (server-side)
class spell_moam_mana_drain_filter : public SpellScript
{
    PrepareSpellScript(spell_moam_mana_drain_filter);

    void FilterTargets(std::list<WorldObject*>& targets)
    {
        targets.remove_if([&](WorldObject* target) -> bool
        {
            return !target->IsPlayer() || target->ToPlayer()->getPowerType() != POWER_MANA;
        });

        if (!targets.empty())
        {
            Acore::Containers::RandomResize(targets, 6);
        }
    }

    void HandleScript(SpellEffIndex /*effIndex*/)
    {
        if (Unit* caster = GetCaster())
        {
            caster->CastSpell(GetHitUnit(), SPELL_DRAIN_MANA, true);
        }
    }

    void Register() override
    {
        OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_moam_mana_drain_filter::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
        OnEffectHitTarget += SpellEffectFn(spell_moam_mana_drain_filter::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
    }
};

// 25684 - Summon Mana Fiends (server-side)
class spell_moam_summon_mana_fiends : public SpellScript
{
    PrepareSpellScript(spell_moam_summon_mana_fiends);

    void HandleScript(SpellEffIndex /*effIndex*/)
    {
        const uint32 spellIds[3] = { SPELL_SUMMON_MANA_FIEND_1, SPELL_SUMMON_MANA_FIEND_2, SPELL_SUMMON_MANA_FIEND_3 };

        for (uint32 spellId : spellIds)
        {
            GetCaster()->CastSpell((Unit*)nullptr, spellId, true);
        }
    }

    void Register() override
    {
        OnEffectHitTarget += SpellEffectFn(spell_moam_summon_mana_fiends::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
    }
};

void AddSC_boss_moam()
{
    RegisterRuinsOfAhnQirajCreatureAI(boss_moam);
    RegisterSpellScript(spell_moam_mana_drain_filter);
    RegisterSpellScript(spell_moam_summon_mana_fiends);
}
<|endoftext|>


<commit_before>#include "Controller.h"
#include "ConfigMessage.h"
#include "System/Config.h"
#include "Framework/Replication/ReplicationConfig.h"
#include "Framework/Replication/PaxosLease/PaxosLease.h"
#include "Application/Common/ContextTransport.h"
#include "Application/Common/ClientSession.h"
#include "Application/Common/ClusterMessage.h"

void Controller::Init()
{
    unsigned        numControllers;
    int64_t         nodeID;
    uint64_t        runID;
    const char*     str;
    Endpoint        endpoint;

    primaryLeaseTimeout.SetCallable(MFUNC(Controller, OnPrimaryLeaseTimeout));

    systemDatabase.Open(configFile.GetValue("database.dir", "db"), "system");
    REPLICATION_CONFIG->Init(systemDatabase.GetTable("system"));

    runID = REPLICATION_CONFIG->GetRunID();
    runID += 1;
    REPLICATION_CONFIG->SetRunID(runID);
    REPLICATION_CONFIG->Commit();

    nodeID = configFile.GetIntValue("nodeID", -1);
    if (nodeID < 0)
        ASSERT_FAIL();

    CONTEXT_TRANSPORT->SetSelfNodeID(nodeID);
    REPLICATION_CONFIG->SetNodeID(nodeID);

    CONTEXT_TRANSPORT->SetClusterContext(this);

    // connect to the controller nodes
    numControllers = (unsigned) configFile.GetListNum("controllers");
    for (nodeID = 0; nodeID < numControllers; nodeID++)
    {
        str = configFile.GetListValue("controllers", nodeID, "");
        endpoint.Set(str);
        CONTEXT_TRANSPORT->AddNode(nodeID, endpoint);
    }

    configState.Init();
    configContext.Init(this, numControllers, systemDatabase.GetTable("paxos"));
    CONTEXT_TRANSPORT->AddQuorumContext(&configContext);

    ReadConfigState();
}

void Controller::Shutdown()
{
    CONTEXT_TRANSPORT->Shutdown();
    REPLICATION_CONFIG->Shutdown();
    systemDatabase.Close();
}

int64_t Controller::GetMaster()
{
    return (int64_t) configContext.GetLeader();
}

uint64_t Controller::GetNodeID()
{
    return REPLICATION_CONFIG->GetNodeID();
}

ConfigState* Controller::GetConfigState()
{
    return &configState;
}

void Controller::OnLearnLease()
{
    bool updateListeners;

    updateListeners = false;
    if (!configState.hasMaster)
        updateListeners = true;

    configState.hasMaster = true;
    configState.masterID = GetMaster();

    if (updateListeners && (uint64_t) GetMaster() == GetNodeID())
        UpdateListeners();
}

void Controller::OnLeaseTimeout()
{
    ConfigMessage*  itMessage;
    ClientRequest*  itRequest;

    configState.hasMaster = false;
    configState.masterID = 0;

    for (itRequest = requests.First(); itRequest != NULL; itRequest = requests.First())
    {
        requests.Remove(itRequest);
        itRequest->response.NoService();
        itRequest->OnComplete();
    }
    assert(requests.GetLength() == 0);

    for (itRequest = listenRequests.First(); itRequest != NULL; itRequest = listenRequests.First())
    {
        listenRequests.Remove(itRequest);
        itRequest->response.NoService();
        itRequest->OnComplete();
    }
    assert(listenRequests.GetLength() == 0);

    for (itMessage = configMessages.First(); itMessage != NULL; itMessage = configMessages.Delete(itMessage));
    assert(configMessages.GetLength() == 0);
}

void Controller::OnAppend(ConfigMessage& message, bool ownAppend)
{
    ClusterMessage  clusterMessage;

    if (message.type == CONFIGMESSAGE_REGISTER_SHARDSERVER)
    {
        // tell ContextTransport that this connection has a new nodeID
        CONTEXT_TRANSPORT->SetConnectionNodeID(message.endpoint, message.nodeID);
        // tell the shard server
        clusterMessage.SetNodeID(message.nodeID);
        CONTEXT_TRANSPORT->SendClusterMessage(message.nodeID, clusterMessage);
    }

    configState.OnMessage(message);
    WriteConfigState();

    if (ownAppend)
    {
        assert(configMessages.GetLength() > 0);
        assert(configMessages.First()->type == message.type);
        if (configMessages.First()->fromClient)
            SendClientResponse(message);
        configMessages.Delete(configMessages.First());
    }

    if (configContext.IsLeader())
        UpdateListeners();
}

bool Controller::IsValidClientRequest(ClientRequest* request)
{
     return request->IsControllerRequest();
}

void Controller::OnClientRequest(ClientRequest* request)
{
    ConfigMessage*  message;

    if (request->type == CLIENTREQUEST_GET_MASTER)
    {
        if (configContext.IsLeaderKnown())
            request->response.Number(configContext.GetLeader());
        else
            request->response.NoService();

        request->OnComplete();
        return;
    }
    else if (request->type == CLIENTREQUEST_GET_CONFIG_STATE)
    {
        listenRequests.Append(request);
        request->response.GetConfigStateResponse(&configState);
        request->OnComplete(false);
        return;
    }

    message = new ConfigMessage;
    FromClientRequest(request, message);

    if (!configState.CompleteMessage(*message))
    {
        delete message;
        request->response.Failed();
        request->OnComplete();
        return;
    }

    requests.Append(request);
    configMessages.Append(message);
    TryAppend();
}

void Controller::OnClientClose(ClientSession* session)
{
    ClientRequest*  it;
    ClientRequest*  next;

    for (it = listenRequests.First(); it != NULL; it = next)
    {
        next = listenRequests.Next(it);
        if (it->session == session)
        {
            listenRequests.Remove(it);
            it->OnComplete();
        }
    }
}

void Controller::OnClusterMessage(uint64_t /*nodeID*/, ClusterMessage& message)
{
    if (!configContext.IsLeader())
        return;

    switch (message.type)
    {
        case CLUSTERMESSAGE_SET_NODEID:
            ASSERT_FAIL();
        case CLUSTERMESSAGE_SET_CONFIG_STATE:
            ASSERT_FAIL();
        case CLUSTERMESSAGE_REQUEST_LEASE:
            OnRequestLease(message);
            break;
        case CLUSTERMESSAGE_RECEIVE_LEASE:
            ASSERT_FAIL();
    }
}

void Controller::OnIncomingConnectionReady(uint64_t nodeID, Endpoint endpoint)
{
    ClusterMessage      clusterMessage;
    ConfigShardServer*  shardServer;

    // if it's a shard server, send the configState
    if (nodeID >= CONFIG_MIN_SHARD_NODE_ID)
    {
        // TODO: send shutdown message in case of bad configuration
        shardServer = configState.GetShardServer(nodeID);
        if (shardServer == NULL)
            return;

        if (shardServer->endpoint != endpoint)
        {
            Log_Message("Badly configured shard server trying to connect"
             ", nodeID: %" PRIu64
             ", endpoint: %s",
             nodeID, endpoint.ToString());

            return;
        }

        clusterMessage.SetConfigState(&configState);
        CONTEXT_TRANSPORT->SendClusterMessage(nodeID, clusterMessage);
    }
}

bool Controller::OnAwaitingNodeID(Endpoint endpoint)
{
    ConfigShardServer*              shardServer;
    ConfigState::ShardServerList*   shardServers;
    ClusterMessage                  clusterMessage;

    if (!configContext.IsLeader())
        return true; // drop connection

    // look for existing endpoint
    shardServers = &configState.shardServers;
    for (shardServer = shardServers->First(); shardServer != NULL; shardServer = shardServers->Next(shardServer))
    {
        if (shardServer->endpoint == endpoint)
        {
            // tell ContextTransport that this connection has a new nodeID
            CONTEXT_TRANSPORT->SetConnectionNodeID(endpoint, shardServer->nodeID);

            // tell the shard server
            clusterMessage.SetNodeID(shardServer->nodeID);
            CONTEXT_TRANSPORT->SendClusterMessage(shardServer->nodeID, clusterMessage);

            // send config state
            clusterMessage.SetConfigState(&configState);
            CONTEXT_TRANSPORT->SendClusterMessage(shardServer->nodeID, clusterMessage);
            return false;
        }
    }

    TryRegisterShardServer(endpoint);
    return false;
}

void Controller::TryAppend()
{
    if (!configContext.IsAppending())
        configContext.Append(configMessages.First());
}

void Controller::FromClientRequest(ClientRequest* request, ConfigMessage* message)
{
    message->fromClient = true;

    switch (request->type)
    {
        case CLIENTREQUEST_CREATE_QUORUM:
            message->type = CONFIGMESSAGE_CREATE_QUORUM;
            message->productionType = request->productionType;
            message->nodes = request->nodes;
            return;
        case CLIENTREQUEST_CREATE_DATABASE:
            message->type = CONFIGMESSAGE_CREATE_DATABASE;
            message->name.Wrap(request->name);
            message->productionType = request->productionType;
            return;
        case CLIENTREQUEST_RENAME_DATABASE:
            message->type = CONFIGMESSAGE_RENAME_DATABASE;
            message->databaseID = request->databaseID;
            message->name.Wrap(request->name);
            return;
        case CLIENTREQUEST_DELETE_DATABASE:
            message->type = CONFIGMESSAGE_DELETE_DATABASE;
            message->databaseID = request->databaseID;
            return;
        case CLIENTREQUEST_CREATE_TABLE:
            message->type = CONFIGMESSAGE_CREATE_TABLE;
            message->databaseID = request->databaseID;
            message->quorumID = request->quorumID;
            message->name.Wrap(request->name);
            return;
        case CLIENTREQUEST_RENAME_TABLE:
            message->type = CONFIGMESSAGE_RENAME_TABLE;
            message->databaseID = request->databaseID;
            message->tableID = request->tableID;
            message->name.Wrap(request->name);
            return;
        case CLIENTREQUEST_DELETE_TABLE:
            message->type = CONFIGMESSAGE_DELETE_TABLE;
            message->databaseID = request->databaseID;
            message->tableID = request->tableID;
            return;
        default:
            ASSERT_FAIL();
    }
}

void Controller::ToClientResponse(ConfigMessage* message, ClientResponse* response)
{
    switch (response->request->type)
    {
        case CLIENTREQUEST_CREATE_QUORUM:
            response->Number(message->quorumID);
            return;
        case CLIENTREQUEST_CREATE_DATABASE:
            response->Number(message->databaseID);
            return;
        case CLIENTREQUEST_RENAME_DATABASE:
            response->OK();
            return;
        case CLIENTREQUEST_DELETE_DATABASE:
            response->OK();
            return;
        case CLIENTREQUEST_CREATE_TABLE:
            response->Number(message->tableID);
            return;
        case CLIENTREQUEST_RENAME_TABLE:
            response->OK();
            return;
        case CLIENTREQUEST_DELETE_TABLE:
            response->OK();
            return;
        default:
            ASSERT_FAIL();
    }
}

void Controller::OnPrimaryLeaseTimeout()
{
    uint64_t        now;
    ConfigQuorum*   quorum;
    PrimaryLease*   itLease;

    now = EventLoop::Now();

    for (itLease = primaryLeases.First(); itLease != NULL; /* advanced in body */)
    {
        if (itLease->expireTime < now)
        {
            quorum = configState.GetQuorum(itLease->quorumID);
            quorum->hasPrimary = false;
            quorum->primaryID = 0;
            itLease = primaryLeases.Delete(itLease);
        }
        else
            break;
    }

    UpdatePrimaryLeaseTimer();
    UpdateListeners();
}

void Controller::TryRegisterShardServer(Endpoint& endpoint)
{
    ConfigMessage*      message;

    message = new ConfigMessage;
    message->fromClient = false;
    message->RegisterShardServer(0, endpoint);
    if (!configState.CompleteMessage(*message))
        ASSERT_FAIL();

    configMessages.Append(message);
    TryAppend();
}

void Controller::ReadConfigState()
{
    bool        ret;
    ReadBuffer  value;

    ret =  true;
    ret &= systemDatabase.GetTable("config")->Get(ReadBuffer("state"), value);
    ret &= configState.Read(value);
    if (!ret)
        Log_Message("Starting with empty database...");

    Log_Trace("%.*s", P(&value));
}

void Controller::WriteConfigState()
{
    configState.Write(configStateBuffer);
    systemDatabase.GetTable("config")->Set(ReadBuffer("state"), ReadBuffer(configStateBuffer));
    systemDatabase.Commit();
}

void Controller::SendClientResponse(ConfigMessage& message)
{
    ClientRequest* request;

    assert(requests.GetLength() > 0);

    request = requests.First();
    requests.Remove(request);

    ToClientResponse(&message, &request->response);
    request->OnComplete();

}

void Controller::OnRequestLease(ClusterMessage& message)
{
    uint64_t*       it;
    ConfigQuorum*   quorum;

    quorum = configState.GetQuorum(message.quorumID);

    if (quorum == NULL)
    {
        Log_Trace("nodeID " PRIu64 " requesting lease for non-existing quorum %" PRIu64 "",
         message.nodeID, message.quorumID);
        return;
    }

    if (quorum->hasPrimary)
    {
        if (quorum->primaryID == message.nodeID)
            ExtendPrimaryLease(*quorum, message);
        return;
    }

    for (it = quorum->activeNodes.First(); it != NULL; it = quorum->activeNodes.Next(it))
    {
        if (*it == message.nodeID)
            break;
    }

    if (it == NULL)
    {
        Log_Trace("nodeID " PRIu64 " requesting lease but not active member or quorum %" PRIu64 "",
         message.nodeID, message.quorumID);
        return;
    }

    AssignPrimaryLease(*quorum, message);
}

void Controller::AssignPrimaryLease(ConfigQuorum& quorum, ClusterMessage& message)
{
    unsigned        duration;
    PrimaryLease*   primaryLease;
    ClusterMessage  response;

    quorum.hasPrimary = true;
    quorum.primaryID = message.nodeID;

    primaryLease = new PrimaryLease;
    primaryLease->quorumID = quorum.quorumID;
    primaryLease->nodeID = quorum.primaryID;
    duration = MIN(message.duration, PAXOSLEASE_MAX_LEASE_TIME);
    primaryLease->expireTime = EventLoop::Now() + duration;
    primaryLeases.Add(primaryLease);

    UpdatePrimaryLeaseTimer();

    response.ReceiveLease(message.nodeID, message.quorumID, message.proposalID, duration);
    CONTEXT_TRANSPORT->SendClusterMessage(response.nodeID, response);
}

void Controller::ExtendPrimaryLease(ConfigQuorum& quorum, ClusterMessage& message)
{
    unsigned        duration;
    PrimaryLease*   it;
    ClusterMessage  response;

    duration = MIN(message.duration, PAXOSLEASE_MAX_LEASE_TIME);

    for (it = primaryLeases.First(); it != NULL; it = primaryLeases.Next(it))
    {
        if (it->quorumID == quorum.quorumID)
            break;
    }

    assert(it != NULL);

    primaryLeases.Remove(it);
    duration = MIN(message.duration, PAXOSLEASE_MAX_LEASE_TIME);
    it->expireTime = EventLoop::Now() + duration;
    primaryLeases.Add(it);
    UpdatePrimaryLeaseTimer();

    response.ReceiveLease(message.nodeID, message.quorumID, message.proposalID, duration);
    CONTEXT_TRANSPORT->SendClusterMessage(response.nodeID, response);
}

void Controller::UpdatePrimaryLeaseTimer()
{
    PrimaryLease* primaryLease;

    primaryLease = primaryLeases.First();
    if (!primaryLease)
        return;

    if (!primaryLeaseTimeout.IsActive() ||
     primaryLease->expireTime < primaryLeaseTimeout.GetExpireTime())
    {
        EventLoop::Remove(&primaryLeaseTimeout);
        primaryLeaseTimeout.SetExpireTime(primaryLease->expireTime);
        EventLoop::Add(&primaryLeaseTimeout);
    }
}

void Controller::UpdateListeners()
{
    ClientRequest*                  itRequest;
    ConfigShardServer*              itShardServer;
    ConfigState::ShardServerList*   shardServers;
    ClusterMessage                  message;

    // update clients
    for (itRequest = listenRequests.First(); itRequest != NULL; itRequest = listenRequests.Next(itRequest))
    {
        itRequest->response.GetConfigStateResponse(&configState);
        itRequest->OnComplete(false);
    }

    // update shard servers
    message.SetConfigState(&configState);
    shardServers = &configState.shardServers;
    for (itShardServer = shardServers->First();
     itShardServer != NULL;
     itShardServer = shardServers->Next(itShardServer))
    {
        CONTEXT_TRANSPORT->SendClusterMessage(itShardServer->nodeID, message);
    }
}
<commit_msg>Fixed bugs.<commit_after>#include "Controller.h"
#include "ConfigMessage.h"
#include "System/Config.h"
#include "Framework/Replication/ReplicationConfig.h"
#include "Framework/Replication/PaxosLease/PaxosLease.h"
#include "Application/Common/ContextTransport.h"
#include "Application/Common/ClientSession.h"
#include "Application/Common/ClusterMessage.h"

void Controller::Init()
{
    unsigned        numControllers;
    int64_t         nodeID;
    uint64_t        runID;
    const char*     str;
    Endpoint        endpoint;

    primaryLeaseTimeout.SetCallable(MFUNC(Controller, OnPrimaryLeaseTimeout));

    systemDatabase.Open(configFile.GetValue("database.dir", "db"), "system");
    REPLICATION_CONFIG->Init(systemDatabase.GetTable("system"));

    runID = REPLICATION_CONFIG->GetRunID();
    runID += 1;
    REPLICATION_CONFIG->SetRunID(runID);
    REPLICATION_CONFIG->Commit();

    nodeID = configFile.GetIntValue("nodeID", -1);
    if (nodeID < 0)
        ASSERT_FAIL();

    CONTEXT_TRANSPORT->SetSelfNodeID(nodeID);
    REPLICATION_CONFIG->SetNodeID(nodeID);

    CONTEXT_TRANSPORT->SetClusterContext(this);

    // connect to the controller nodes
    numControllers = (unsigned) configFile.GetListNum("controllers");
    for (nodeID = 0; nodeID < numControllers; nodeID++)
    {
        str = configFile.GetListValue("controllers", nodeID, "");
        endpoint.Set(str);
        CONTEXT_TRANSPORT->AddNode(nodeID, endpoint);
    }

    configState.Init();
    configContext.Init(this, numControllers, systemDatabase.GetTable("paxos"));
    CONTEXT_TRANSPORT->AddQuorumContext(&configContext);

    ReadConfigState();
}

void Controller::Shutdown()
{
    CONTEXT_TRANSPORT->Shutdown();
    REPLICATION_CONFIG->Shutdown();
    systemDatabase.Close();
}

int64_t Controller::GetMaster()
{
    return (int64_t) configContext.GetLeader();
}

uint64_t Controller::GetNodeID()
{
    return REPLICATION_CONFIG->GetNodeID();
}

ConfigState* Controller::GetConfigState()
{
    return &configState;
}

void Controller::OnLearnLease()
{
    bool updateListeners;

    updateListeners = false;
    if (!configState.hasMaster)
        updateListeners = true;

    configState.hasMaster = true;
    configState.masterID = GetMaster();

    if (updateListeners && (uint64_t) GetMaster() == GetNodeID())
        UpdateListeners();
}

void Controller::OnLeaseTimeout()
{
    ConfigMessage*  itMessage;
    ClientRequest*  itRequest;

    configState.hasMaster = false;
    configState.masterID = 0;

    for (itRequest = requests.First(); itRequest != NULL; itRequest = requests.First())
    {
        requests.Remove(itRequest);
        itRequest->response.NoService();
        itRequest->OnComplete();
    }
    assert(requests.GetLength() == 0);

    for (itRequest = listenRequests.First(); itRequest != NULL; itRequest = listenRequests.First())
    {
        listenRequests.Remove(itRequest);
        itRequest->response.NoService();
        itRequest->OnComplete();
    }
    assert(listenRequests.GetLength() == 0);

    for (itMessage = configMessages.First(); itMessage != NULL; itMessage = configMessages.Delete(itMessage));
    assert(configMessages.GetLength() == 0);
}

void Controller::OnAppend(ConfigMessage& message, bool ownAppend)
{
    ClusterMessage  clusterMessage;

    if (message.type == CONFIGMESSAGE_REGISTER_SHARDSERVER)
    {
        // tell ContextTransport that this connection has a new nodeID
        CONTEXT_TRANSPORT->SetConnectionNodeID(message.endpoint, message.nodeID);
        // tell the shard server
        clusterMessage.SetNodeID(message.nodeID);
        CONTEXT_TRANSPORT->SendClusterMessage(message.nodeID, clusterMessage);
    }

    configState.OnMessage(message);
    WriteConfigState();

    if (ownAppend)
    {
        assert(configMessages.GetLength() > 0);
        assert(configMessages.First()->type == message.type);
        if (configMessages.First()->fromClient)
            SendClientResponse(message);
        configMessages.Delete(configMessages.First());
    }

    if (configContext.IsLeader())
        UpdateListeners();
}

bool Controller::IsValidClientRequest(ClientRequest* request)
{
     return request->IsControllerRequest();
}

void Controller::OnClientRequest(ClientRequest* request)
{
    ConfigMessage*  message;

    if (request->type == CLIENTREQUEST_GET_MASTER)
    {
        if (configContext.IsLeaderKnown())
            request->response.Number(configContext.GetLeader());
        else
            request->response.NoService();

        request->OnComplete();
        return;
    }
    else if (request->type == CLIENTREQUEST_GET_CONFIG_STATE)
    {
        listenRequests.Append(request);
        request->response.GetConfigStateResponse(&configState);
        request->OnComplete(false);
        return;
    }

    message = new ConfigMessage;
    FromClientRequest(request, message);

    if (!configState.CompleteMessage(*message))
    {
        delete message;
        request->response.Failed();
        request->OnComplete();
        return;
    }

    requests.Append(request);
    configMessages.Append(message);
    TryAppend();
}

void Controller::OnClientClose(ClientSession* session)
{
    ClientRequest*  it;
    ClientRequest*  next;

    for (it = listenRequests.First(); it != NULL; it = next)
    {
        next = listenRequests.Next(it);
        if (it->session == session)
        {
            listenRequests.Remove(it);
            it->OnComplete();
        }
    }
}

void Controller::OnClusterMessage(uint64_t /*nodeID*/, ClusterMessage& message)
{
    if (!configContext.IsLeader())
        return;

    switch (message.type)
    {
        case CLUSTERMESSAGE_SET_NODEID:
            ASSERT_FAIL();
        case CLUSTERMESSAGE_SET_CONFIG_STATE:
            ASSERT_FAIL();
        case CLUSTERMESSAGE_REQUEST_LEASE:
            OnRequestLease(message);
            break;
        case CLUSTERMESSAGE_RECEIVE_LEASE:
            ASSERT_FAIL();
    }
}

void Controller::OnIncomingConnectionReady(uint64_t nodeID, Endpoint endpoint)
{
    ClusterMessage      clusterMessage;
    ConfigShardServer*  shardServer;

    // if it's a shard server, send the configState
    if (nodeID >= CONFIG_MIN_SHARD_NODE_ID)
    {
        // TODO: send shutdown message in case of bad configuration
        shardServer = configState.GetShardServer(nodeID);
        if (shardServer == NULL)
            return;

        if (shardServer->endpoint != endpoint)
        {
            Log_Message("Badly configured shard server trying to connect"
             ", nodeID: %" PRIu64
             ", endpoint: %s",
             nodeID, endpoint.ToString());

            return;
        }

        clusterMessage.SetConfigState(&configState);
        CONTEXT_TRANSPORT->SendClusterMessage(nodeID, clusterMessage);
    }
}

bool Controller::OnAwaitingNodeID(Endpoint endpoint)
{
    ConfigShardServer*              shardServer;
    ConfigState::ShardServerList*   shardServers;
    ClusterMessage                  clusterMessage;

    if (!configContext.IsLeader())
        return true; // drop connection

    // look for existing endpoint
    shardServers = &configState.shardServers;
    for (shardServer = shardServers->First(); shardServer != NULL; shardServer = shardServers->Next(shardServer))
    {
        if (shardServer->endpoint == endpoint)
        {
            // tell ContextTransport that this connection has a new nodeID
            CONTEXT_TRANSPORT->SetConnectionNodeID(endpoint, shardServer->nodeID);

            // tell the shard server
            clusterMessage.SetNodeID(shardServer->nodeID);
            CONTEXT_TRANSPORT->SendClusterMessage(shardServer->nodeID, clusterMessage);

            // send config state
            clusterMessage.SetConfigState(&configState);
            CONTEXT_TRANSPORT->SendClusterMessage(shardServer->nodeID, clusterMessage);
            return false;
        }
    }

    TryRegisterShardServer(endpoint);
    return false;
}

void Controller::TryAppend()
{
    if (!configContext.IsAppending())
        configContext.Append(configMessages.First());
}

void Controller::FromClientRequest(ClientRequest* request, ConfigMessage* message)
{
    message->fromClient = true;

    switch (request->type)
    {
        case CLIENTREQUEST_CREATE_QUORUM:
            message->type = CONFIGMESSAGE_CREATE_QUORUM;
            message->productionType = request->productionType;
            message->nodes = request->nodes;
            return;
        case CLIENTREQUEST_CREATE_DATABASE:
            message->type = CONFIGMESSAGE_CREATE_DATABASE;
            message->name.Wrap(request->name);
            message->productionType = request->productionType;
            return;
        case CLIENTREQUEST_RENAME_DATABASE:
            message->type = CONFIGMESSAGE_RENAME_DATABASE;
            message->databaseID = request->databaseID;
            message->name.Wrap(request->name);
            return;
        case CLIENTREQUEST_DELETE_DATABASE:
            message->type = CONFIGMESSAGE_DELETE_DATABASE;
            message->databaseID = request->databaseID;
            return;
        case CLIENTREQUEST_CREATE_TABLE:
            message->type = CONFIGMESSAGE_CREATE_TABLE;
            message->databaseID = request->databaseID;
            message->quorumID = request->quorumID;
            message->name.Wrap(request->name);
            return;
        case CLIENTREQUEST_RENAME_TABLE:
            message->type = CONFIGMESSAGE_RENAME_TABLE;
            message->databaseID = request->databaseID;
            message->tableID = request->tableID;
            message->name.Wrap(request->name);
            return;
        case CLIENTREQUEST_DELETE_TABLE:
            message->type = CONFIGMESSAGE_DELETE_TABLE;
            message->databaseID = request->databaseID;
            message->tableID = request->tableID;
            return;
        default:
            ASSERT_FAIL();
    }
}

void Controller::ToClientResponse(ConfigMessage* message, ClientResponse* response)
{
    switch (response->request->type)
    {
        case CLIENTREQUEST_CREATE_QUORUM:
            response->Number(message->quorumID);
            return;
        case CLIENTREQUEST_CREATE_DATABASE:
            response->Number(message->databaseID);
            return;
        case CLIENTREQUEST_RENAME_DATABASE:
            response->OK();
            return;
        case CLIENTREQUEST_DELETE_DATABASE:
            response->OK();
            return;
        case CLIENTREQUEST_CREATE_TABLE:
            response->Number(message->tableID);
            return;
        case CLIENTREQUEST_RENAME_TABLE:
            response->OK();
            return;
        case CLIENTREQUEST_DELETE_TABLE:
            response->OK();
            return;
        default:
            ASSERT_FAIL();
    }
}

void Controller::OnPrimaryLeaseTimeout()
{
    uint64_t        now;
    ConfigQuorum*   quorum;
    PrimaryLease*   itLease;

    now = EventLoop::Now();

    for (itLease = primaryLeases.First(); itLease != NULL; /* advanced in body */)
    {
        if (itLease->expireTime < now)
        {
            quorum = configState.GetQuorum(itLease->quorumID);
            quorum->hasPrimary = false;
            quorum->primaryID = 0;
            itLease = primaryLeases.Delete(itLease);
        }
        else
            break;
    }

    UpdatePrimaryLeaseTimer();
    UpdateListeners();
}

void Controller::TryRegisterShardServer(Endpoint& endpoint)
{
    ConfigMessage*      message;

    message = new ConfigMessage;
    message->fromClient = false;
    message->RegisterShardServer(0, endpoint);
    if (!configState.CompleteMessage(*message))
        ASSERT_FAIL();

    configMessages.Append(message);
    TryAppend();
}

void Controller::ReadConfigState()
{
    bool        ret;
    ReadBuffer  value;

    ret =  true;
    ret &= systemDatabase.GetTable("config")->Get(ReadBuffer("state"), value);
    ret &= configState.Read(value);
    if (!ret)
        Log_Message("Starting with empty database...");

    Log_Trace("%.*s", P(&value));
}

void Controller::WriteConfigState()
{
    configState.Write(configStateBuffer);
    systemDatabase.GetTable("config")->Set(ReadBuffer("state"), ReadBuffer(configStateBuffer));
    systemDatabase.Commit();
}

void Controller::SendClientResponse(ConfigMessage& message)
{
    ClientRequest* request;

    assert(requests.GetLength() > 0);

    request = requests.First();
    requests.Remove(request);

    ToClientResponse(&message, &request->response);
    request->OnComplete();

}

void Controller::OnRequestLease(ClusterMessage& message)
{
    uint64_t*       it;
    ConfigQuorum*   quorum;

    quorum = configState.GetQuorum(message.quorumID);

    if (quorum == NULL)
    {
        Log_Trace("nodeID " PRIu64 " requesting lease for non-existing quorum %" PRIu64 "",
         message.nodeID, message.quorumID);
        return;
    }

    if (quorum->hasPrimary)
    {
        if (quorum->primaryID == message.nodeID)
            ExtendPrimaryLease(*quorum, message);
        return;
    }

    for (it = quorum->activeNodes.First(); it != NULL; it = quorum->activeNodes.Next(it))
    {
        if (*it == message.nodeID)
            break;
    }

    if (it == NULL)
    {
        Log_Trace("nodeID " PRIu64 " requesting lease but not active member or quorum %" PRIu64 "",
         message.nodeID, message.quorumID);
        return;
    }

    AssignPrimaryLease(*quorum, message);
}

void Controller::AssignPrimaryLease(ConfigQuorum& quorum, ClusterMessage& message)
{
    unsigned        duration;
    PrimaryLease*   primaryLease;
    ClusterMessage  response;

    quorum.hasPrimary = true;
    quorum.primaryID = message.nodeID;

    primaryLease = new PrimaryLease;
    primaryLease->quorumID = quorum.quorumID;
    primaryLease->nodeID = quorum.primaryID;
    duration = MIN(message.duration, PAXOSLEASE_MAX_LEASE_TIME);
    primaryLease->expireTime = EventLoop::Now() + duration;
    primaryLeases.Add(primaryLease);

    UpdatePrimaryLeaseTimer();

    response.ReceiveLease(message.nodeID, message.quorumID, message.proposalID, duration);
    CONTEXT_TRANSPORT->SendClusterMessage(response.nodeID, response);
}

void Controller::ExtendPrimaryLease(ConfigQuorum& quorum, ClusterMessage& message)
{
    unsigned        duration;
    PrimaryLease*   it;
    ClusterMessage  response;

    duration = MIN(message.duration, PAXOSLEASE_MAX_LEASE_TIME);

    for (it = primaryLeases.First(); it != NULL; it = primaryLeases.Next(it))
    {
        if (it->quorumID == quorum.quorumID)
            break;
    }

    assert(it != NULL);

    primaryLeases.Remove(it);
    duration = MIN(message.duration, PAXOSLEASE_MAX_LEASE_TIME);
    it->expireTime = EventLoop::Now() + duration;
    primaryLeases.Add(it);
    UpdatePrimaryLeaseTimer();

    response.ReceiveLease(message.nodeID, message.quorumID, message.proposalID, duration);
    CONTEXT_TRANSPORT->SendClusterMessage(response.nodeID, response);
}

void Controller::UpdatePrimaryLeaseTimer()
{
    PrimaryLease* primaryLease;

    primaryLease = primaryLeases.First();
    if (!primaryLease)
        return;

    if (primaryLease->expireTime < primaryLeaseTimeout.GetExpireTime())
    {
        EventLoop::Remove(&primaryLeaseTimeout);
        primaryLeaseTimeout.SetExpireTime(primaryLease->expireTime);
        EventLoop::Add(&primaryLeaseTimeout);
    }
}

void Controller::UpdateListeners()
{
    ClientRequest*                  itRequest;
    ConfigShardServer*              itShardServer;
    ConfigState::ShardServerList*   shardServers;
    ClusterMessage                  message;

    // update clients
    for (itRequest = listenRequests.First(); itRequest != NULL; itRequest = listenRequests.Next(itRequest))
    {
        itRequest->response.GetConfigStateResponse(&configState);
        itRequest->OnComplete(false);
    }

    // update shard servers
    message.SetConfigState(&configState);
    shardServers = &configState.shardServers;
    for (itShardServer = shardServers->First();
     itShardServer != NULL;
     itShardServer = shardServers->Next(itShardServer))
    {
        CONTEXT_TRANSPORT->SendClusterMessage(itShardServer->nodeID, message);
    }
}
<|endoftext|>


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

/**
 * @file
 **/

#include "modules/planning/common/speed/speed_data.h"

#include <algorithm>
#include <utility>

#include "modules/common/math/linear_interpolation.h"
#include "modules/common/util/string_util.h"
#include "modules/common/util/util.h"
#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {

using apollo::common::SpeedPoint;

SpeedData::SpeedData(std::vector<SpeedPoint> speed_points)
    : std::vector<SpeedPoint>(speed_points) {
  std::sort(begin(), end(), [](const SpeedPoint& p1, const SpeedPoint& p2) {
    return p1.s() < p2.s();
  });
}

void SpeedData::AppendSpeedPoint(const double s, const double time,
                                 const double v, const double a,
                                 const double da) {
  if (!empty()) {
    CHECK(back().t() < time);
  }
  push_back(common::util::MakeSpeedPoint(s, time, v, a, da));
}

bool SpeedData::EvaluateByTime(const double t,
                               common::SpeedPoint* const speed_point) const {
  if (size() < 2) {
    return false;
  }
  if (!(front().t() < t + 1.0e-6 && t - 1.0e-6 < back().t())) {
    return false;
  }

  auto comp = [](const common::SpeedPoint& sp, const double t) {
    return sp.t() < t;
  };

  auto it_lower = std::lower_bound(begin(), end(), t, comp);
  if (it_lower == end()) {
    *speed_point = back();
  } else if (it_lower == begin()) {
    *speed_point = front();
  } else {
    const auto& p0 = *(it_lower - 1);
    const auto& p1 = *it_lower;
    double t0 = p0.t();
    double t1 = p1.t();

    common::SpeedPoint res;
    res.set_t(t);

    double s = common::math::lerp(p0.s(), t0, p1.s(), t1, t);
    res.set_s(s);

    if (p0.has_v() && p1.has_v()) {
      double v = common::math::lerp(p0.v(), t0, p1.v(), t1, t);
      res.set_v(v);
    }

    if (p0.has_a() && p1.has_a()) {
      double a = common::math::lerp(p0.a(), t0, p1.a(), t1, t);
      res.set_a(a);
    }

    if (p0.has_da() && p1.has_da()) {
      double da = common::math::lerp(p0.da(), t0, p1.da(), t1, t);
      res.set_da(da);
    }

    *speed_point = res;
  }
  return true;
}

double SpeedData::TotalTime() const {
  if (empty()) {
    return 0.0;
  }
  return back().t() - front().t();
}

void SpeedData::Clear() { clear(); }

std::string SpeedData::DebugString() const {
  const auto limit = std::min(
      size(), static_cast<size_t>(FLAGS_trajectory_point_num_for_debug));
  return apollo::common::util::StrCat(
      "[\n", apollo::common::util::PrintDebugStringIter(begin(),
                                                        begin() + limit, ",\n"),
      "]\n");
}

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

/**
 * @file
 **/

#include "modules/planning/common/speed/speed_data.h"

#include <algorithm>
#include <utility>

#include "modules/common/math/linear_interpolation.h"
#include "modules/common/util/string_util.h"
#include "modules/common/util/util.h"
#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {

using apollo::common::SpeedPoint;

SpeedData::SpeedData(std::vector<SpeedPoint> speed_points)
    : std::vector<SpeedPoint>(std::move(speed_points)) {
  std::sort(begin(), end(), [](const SpeedPoint& p1, const SpeedPoint& p2) {
    return p1.t() < p2.t();
  });
}

void SpeedData::AppendSpeedPoint(const double s, const double time,
                                 const double v, const double a,
                                 const double da) {
  if (!empty()) {
    CHECK(back().t() < time);
  }
  push_back(common::util::MakeSpeedPoint(s, time, v, a, da));
}

bool SpeedData::EvaluateByTime(const double t,
                               common::SpeedPoint* const speed_point) const {
  if (size() < 2) {
    return false;
  }
  if (!(front().t() < t + 1.0e-6 && t - 1.0e-6 < back().t())) {
    return false;
  }

  auto comp = [](const common::SpeedPoint& sp, const double t) {
    return sp.t() < t;
  };

  auto it_lower = std::lower_bound(begin(), end(), t, comp);
  if (it_lower == end()) {
    *speed_point = back();
  } else if (it_lower == begin()) {
    *speed_point = front();
  } else {
    const auto& p0 = *(it_lower - 1);
    const auto& p1 = *it_lower;
    double t0 = p0.t();
    double t1 = p1.t();

    common::SpeedPoint res;
    res.set_t(t);

    double s = common::math::lerp(p0.s(), t0, p1.s(), t1, t);
    res.set_s(s);

    if (p0.has_v() && p1.has_v()) {
      double v = common::math::lerp(p0.v(), t0, p1.v(), t1, t);
      res.set_v(v);
    }

    if (p0.has_a() && p1.has_a()) {
      double a = common::math::lerp(p0.a(), t0, p1.a(), t1, t);
      res.set_a(a);
    }

    if (p0.has_da() && p1.has_da()) {
      double da = common::math::lerp(p0.da(), t0, p1.da(), t1, t);
      res.set_da(da);
    }

    *speed_point = res;
  }
  return true;
}

double SpeedData::TotalTime() const {
  if (empty()) {
    return 0.0;
  }
  return back().t() - front().t();
}

void SpeedData::Clear() { clear(); }

std::string SpeedData::DebugString() const {
  const auto limit = std::min(
      size(), static_cast<size_t>(FLAGS_trajectory_point_num_for_debug));
  return apollo::common::util::StrCat(
      "[\n", apollo::common::util::PrintDebugStringIter(begin(),
                                                        begin() + limit, ",\n"),
      "]\n");
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */

#include <iostream>

#include "MQ/Queue.h"
#include "MQ/QueueManager.h"
#include "MQ/MQException.h"
#include "MQ/CommandServer.h"
#include "MQ/Message.h"
#include "MQ/PCF.h"

// When we get a MQRC_TRUNCATE..., we will try to enlarge the buffer.
// It is still possible to get MQRC_CONVERTED_MSG_TOO_BIG, but we really hope
// this buffer is large enough for all possible PCF answers.
#define REPLY_MESSAGE_LEN 8192

namespace MQ
{

CommandServer::CommandServer(QueueManager::Ptr qmgr, const std::string& modelQueue)
	: _qmgr(qmgr)
	, _commandQ(qmgr, qmgr->commandQueue())
	, _replyQ(qmgr, modelQueue)
{
	_commandQ.open(MQOO_OUTPUT);
	_replyQ.open(MQOO_INPUT_SHARED | MQOO_FAIL_IF_QUIESCING);
}

PCF::Ptr CommandServer::createCommand(MQLONG command) const
{
	return new PCF(command, _qmgr->zos());
}

// Throws MQException
void CommandServer::sendCommand(PCF::Ptr& command, PCF::Vector& response)
{
	response.clear();

	command->setReplyToQueue(_replyQ.name());
	_commandQ.put(*command, MQPMO_NO_SYNCPOINT);

	long wait = 600000;
	PCF::Ptr msgResponse;
	do
	{
		msgResponse = new PCF(_qmgr->zos());
		msgResponse->setCorrelationId(*command->getMessageId());
		msgResponse->buffer().resize(REPLY_MESSAGE_LEN, false);

		try
		{
			_replyQ.get(*msgResponse.get(), MQGMO_CONVERT | MQGMO_NO_SYNCPOINT, wait);
		}
		catch(MQException& mqe)
		{
			if ( mqe.reason() == MQRC_TRUNCATED_MSG_FAILED )
			{
				msgResponse->buffer().resize(msgResponse->dataLength(), false);
				msgResponse->clear();
				msgResponse->setCorrelationId(*command->getMessageId());
				_replyQ.get(*msgResponse.get(), MQGMO_CONVERT | MQGMO_NO_SYNCPOINT);
			}
			else
			{
				throw;
			}
		}
		wait = 1000;
		msgResponse->buffer().resize(msgResponse->dataLength());
		msgResponse->init();

		response.push_back(msgResponse);
	}
	while(! msgResponse->isLast());
}

}
<commit_msg>Add trace log for truncated messages<commit_after>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */

#include <iostream>

#include "MQ/Queue.h"
#include "MQ/QueueManager.h"
#include "MQ/MQException.h"
#include "MQ/CommandServer.h"
#include "MQ/Message.h"
#include "MQ/PCF.h"

// When we get a MQRC_TRUNCATE..., we will try to enlarge the buffer.
// It is still possible to get MQRC_CONVERTED_MSG_TOO_BIG, but we really hope
// this buffer is large enough for all possible PCF answers.
#define REPLY_MESSAGE_LEN 8192

namespace MQ
{

CommandServer::CommandServer(QueueManager::Ptr qmgr, const std::string& modelQueue)
	: _qmgr(qmgr)
	, _commandQ(qmgr, qmgr->commandQueue())
	, _replyQ(qmgr, modelQueue)
{
	_commandQ.open(MQOO_OUTPUT);
	_replyQ.open(MQOO_INPUT_SHARED | MQOO_FAIL_IF_QUIESCING);
}

PCF::Ptr CommandServer::createCommand(MQLONG command) const
{
	return new PCF(command, _qmgr->zos());
}

// Throws MQException
void CommandServer::sendCommand(PCF::Ptr& command, PCF::Vector& response)
{
	response.clear();

	command->setReplyToQueue(_replyQ.name());
	_commandQ.put(*command, MQPMO_NO_SYNCPOINT);

	long wait = 600000;
	PCF::Ptr msgResponse;
	do
	{
		msgResponse = new PCF(_qmgr->zos());
		msgResponse->setCorrelationId(*command->getMessageId());
		msgResponse->buffer().resize(REPLY_MESSAGE_LEN, false);

		try
		{
			_replyQ.get(*msgResponse.get(), MQGMO_CONVERT | MQGMO_NO_SYNCPOINT, wait);
		}
		catch(MQException& mqe)
		{
			if ( mqe.reason() == MQRC_TRUNCATED_MSG_FAILED )
			{
				Poco::Logger& logger = Poco::Logger::get("mq");
				if ( logger.trace() )
				{
					poco_trace_f2(logger, "Truncated message received. Actual size is %ld (> %d).", msgResponse->dataLength(), REPLY_MESSAGE_LEN);
				}

				msgResponse->buffer().resize(msgResponse->dataLength(), false);
				msgResponse->clear();
				msgResponse->setCorrelationId(*command->getMessageId());
				_replyQ.get(*msgResponse.get(), MQGMO_CONVERT | MQGMO_NO_SYNCPOINT);
			}
			else
			{
				throw;
			}
		}
		wait = 1000;
		msgResponse->buffer().resize(msgResponse->dataLength());
		msgResponse->init();

		response.push_back(msgResponse);
	}
	while(! msgResponse->isLast());
}

}
<|endoftext|>