{
	UNUSED(a_Dt);
	UNUSED(a_Chunk);
	if (!m_ShouldExecute)
	{
		return false;
	}

	m_ShouldExecute = false;
	Execute();
	return true;
}

// CommandBlockEntity.cpp

// Implements the cCommandBlockEntity class representing a single command block in the world

#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules
#include "CommandBlockEntity.h"

#include "../CommandOutput.h"
#include "../Root.h"
#include "../Server.h"  // ExecuteConsoleCommand()
#include "../ChatColor.h"
#include "../World.h"
#include "../ClientHandle.h"

cCommandBlockEntity::cCommandBlockEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
	Super(a_BlockType, a_BlockMeta, a_Pos, a_World),
	m_ShouldExecute(false),
	m_Result(0)
{
	ASSERT(a_BlockType == E_BLOCK_COMMAND_BLOCK);
}

bool cCommandBlockEntity::UsedBy(cPlayer * a_Player)
{
	// Nothing to do
	UNUSED(a_Player);
	return true;
}

void cCommandBlockEntity::SetCommand(const AString & a_Cmd)
{
	m_Command = a_Cmd;
}

void cCommandBlockEntity::SetLastOutput(const AString & a_LastOut)
{
	m_LastOutput = a_LastOut;
}

void cCommandBlockEntity::SetResult(const NIBBLETYPE a_Result)
{
	m_Result = a_Result;
}

const AString & cCommandBlockEntity::GetCommand(void) const
{
	return m_Command;
}

const AString & cCommandBlockEntity::GetLastOutput(void) const
{
	return m_LastOutput;
}

NIBBLETYPE cCommandBlockEntity::GetResult(void) const
{
	return m_Result;
}

void cCommandBlockEntity::Activate(void)
{
	m_ShouldExecute = true;
}

void cCommandBlockEntity::CopyFrom(const cBlockEntity & a_Src)
{
	Super::CopyFrom(a_Src);
	auto & src = static_cast<const cCommandBlockEntity &>(a_Src);
	m_Command = src.m_Command;
	m_LastOutput = src.m_LastOutput;
	m_Result = src.m_Result;
	m_ShouldExecute = src.m_ShouldExecute;
}

bool cCommandBlockEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)

void cCommandBlockEntity::SendTo(cClientHandle & a_Client)
{
	a_Client.SendUpdateBlockEntity(*this);
}

void cCommandBlockEntity::Execute()
{
	ASSERT(m_World != nullptr);  // Execute should not be called before the command block is attached to a world

	if (!m_World->AreCommandBlocksEnabled())
	{
		return;
	}

	if (m_Command.empty())
	{
		return;
	}

	class CommandBlockOutCb :
		public cLogCommandDeleteSelfOutputCallback
	{
		cCommandBlockEntity * m_CmdBlock;

	public:
		CommandBlockOutCb(cCommandBlockEntity * a_CmdBlock) : m_CmdBlock(a_CmdBlock) {}

		virtual void Out(const AString & a_Text) override
		{
			// Overwrite field
			m_CmdBlock->SetLastOutput(cClientHandle::FormatChatPrefix(m_CmdBlock->GetWorld()->ShouldUseChatPrefixes(), "SUCCESS", cChatColor::Green, cChatColor::White) + a_Text);
		}
	};

	AString RealCommand = m_Command;

	// Remove leading slash if it exists, since console commands don't use them
	if (RealCommand[0] == '/')
	{
		RealCommand = RealCommand.substr(1, RealCommand.length());
	}

	// Administrator commands are not executable by command blocks:
	if (
		(RealCommand != "stop") &&
		(RealCommand != "restart") &&
		(RealCommand != "kick") &&
		(RealCommand != "ban") &&
		(RealCommand != "ipban")
	)
	{
		cServer * Server = cRoot::Get()->GetServer();
		LOGD("cCommandBlockEntity: Executing command %s", m_Command.c_str());
		Server->QueueExecuteConsoleCommand(RealCommand, *new CommandBlockOutCb(this));
	}
	else
	{
		SetLastOutput(cClientHandle::FormatChatPrefix(GetWorld()->ShouldUseChatPrefixes(), "FAILURE", cChatColor::Rose, cChatColor::White) + "Adminstration commands can not be executed");
		LOGD("cCommandBlockEntity: Prevented execution of administration command %s", m_Command.c_str());
	}

	// TODO 2014-01-18 xdot: Update the signal strength.
	m_Result = 0;
}


{
	ossimImageHandler::getPropertyNames(propertyNames);
	propertyNames.push_back("file_type");
}

// See top level LICENSE.txt file.
// Author: Ken Melero
// Description: This class give the capability to access tiles from an
//              ADRG file.

#include <ossim/imaging/ossimAdrgTileSource.h>
#include <ossim/imaging/ossimAdrgHeader.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimCommon.h>
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/base/ossimTrace.h>
#include <ossim/base/ossimKeywordlist.h>
#include <ossim/base/ossimEllipsoid.h>
#include <ossim/base/ossimDatum.h>
#include <ossim/base/ossimUnitTypeLut.h>
#include <ossim/base/ossimStringProperty.h>
#include <ossim/base/ossimContainerProperty.h>
#include <ossim/imaging/ossimImageDataFactory.h>
#include <ossim/imaging/ossimImageGeometry.h>
#include <ossim/imaging/ossimTiffTileSource.h>
#include <ossim/imaging/ossimU8ImageData.h>
#include <ossim/projection/ossimMapProjection.h>
#include <ossim/projection/ossimEquDistCylProjection.h>
#include <ossim/projection/ossimProjectionFactoryRegistry.h>
#include <iostream>

RTTI_DEF1(ossimAdrgTileSource, "ossimAdrgTileSource", ossimImageHandler)

// Static trace for debugging
static ossimTrace traceDebug("ossimAdrgTileSource:debug");

// NOTE:  Currently this tilesource is hard-coded to access tiles
//        from the ZDR image file. This will change as I wrote support
//        data classes for all the ADRG image files: ZDR, overview,
//        and legend support data.  Next step in development will
//        be to put in flags to access overview and legend image files.

using namespace std;

// Public Constructor:
ossimAdrgTileSource::ossimAdrgTileSource()
   :
      ossimImageHandler(),
      m_Tile(0),
      m_TileBuffer(0),
      m_FileStr(),
      m_AdrgHeader(0)
{
   // Construction not complete.  Users should call "open" method.
}

ossimAdrgTileSource::~ossimAdrgTileSource()
{
   if(m_AdrgHeader)
   {
      delete m_AdrgHeader;
      m_AdrgHeader = 0;
   }
   if (m_TileBuffer)
   {
      delete [] m_TileBuffer;
      m_TileBuffer = 0;
   }

   close();
}

ossimRefPtr<ossimImageData> ossimAdrgTileSource::getTile(
   const ossimIrect& rect,
   ossim_uint32 resLevel)
{
   if (m_Tile.valid())
   {
      // Image rectangle must be set prior to calling getTile.
      m_Tile->setImageRectangle(rect);

      if ( getTile( m_Tile.get(), resLevel ) == false )
      {
         if (m_Tile->getDataObjectStatus() != OSSIM_NULL)
         {
            m_Tile->makeBlank();
         }
      }
   }

   return m_Tile;
}

bool ossimAdrgTileSource::getTile(ossimImageData* result,
                                  ossim_uint32 resLevel)
{
   bool status = false;

   // Not open, this tile source bypassed, or invalid res level,
   // return a blank tile.
   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
       result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
   {
      result->ref();  // Increment ref count.

      // Check for overview tile.  Some overviews can contain r0 so always
      // call even if resLevel is 0.  Method returns true on success, false
      // on error.
      status = getOverviewTile(resLevel, result);

      if (!status) // Did not get an overview tile.
      {
         status = true;

         ossimIrect tile_rect = result->getImageRectangle();

         ossimIrect image_rect = getImageRectangle(resLevel);

         result->makeBlank();

         // See if any point of the requested tile is in the image.
         if ( tile_rect.intersects(image_rect) )
         {
            ossimIrect clip_rect = tile_rect.clipToRect(image_rect);

            // Load the tile buffer with data from the adrg.
            status = fillBuffer(tile_rect, clip_rect, result);

            if (status)
            {
               result->validate();
            }
         }
      }

      result->unref();  // Decrement ref count.
   }

   return status;
}

// Private Method:
bool ossimAdrgTileSource::fillBuffer(const ossimIrect& /* tile_rect */,
                                     const ossimIrect& clip_rect,
                                     ossimImageData* tile)
{
   // Shift the upper left corner of the "clip_rect" to the an even chunk
   ossimIpt tileOrigin = clip_rect.ul();
   adjustToStartOfTile(tileOrigin);

   // Calculate the number of tiles needed in the line/sample directions.
   ossim_int32 size_in_x = clip_rect.lr().x - tileOrigin.x + 1;
   ossim_int32 size_in_y = clip_rect.lr().y - tileOrigin.y + 1;

   ossim_int32 tiles_in_x_dir = size_in_x / ADRG_TILE_WIDTH  +
      (size_in_x % ADRG_TILE_WIDTH  ? 1 : 0);
   ossim_int32 tiles_in_y_dir = size_in_y / ADRG_TILE_HEIGHT +
      (size_in_y % ADRG_TILE_HEIGHT ? 1 : 0);

   ossimIpt ulTilePt = tileOrigin;

   // Chunk loop in line direction.
   for (ossim_int32 y=0; y<tiles_in_y_dir; y++)
   {
      ulTilePt.x = tileOrigin.x;

      // Tile loop in sample direction.
      for (ossim_int32 x=0; x<tiles_in_x_dir; x++)
      {
         ossimIrect adrg_tile_rect(ulTilePt.x,
                                   ulTilePt.y,
                                   ulTilePt.x + ADRG_TILE_WIDTH- 1,
                                   ulTilePt.y + ADRG_TILE_HEIGHT - 1);

         if (adrg_tile_rect.intersects(clip_rect))
         {
            ossimIrect tile_clip_rect = clip_rect.clipToRect(adrg_tile_rect);

            // Some point in the chip intersect the tile so grab the
            ossim_int32 row = (ossim_int32) ulTilePt.y / ADRG_TILE_HEIGHT;
            ossim_int32 col = (ossim_int32) ulTilePt.x / ADRG_TILE_WIDTH;
            ossim_int32 tileOffset = m_AdrgHeader->tim(row, col);

            if(tileOffset != 0)
            {
               // Get the data.
               int seek_position = (tileOffset - 1) * 49152 + 2048;
               int band;

               // seek to start of chip
               m_FileStr.seekg(seek_position, ios::beg);
               for (band=0; band<3; band++)
               {
                  // Read the chip from the ccf file into the chunk buffer.
                  // This will get all the bands.  Bands are interleaved by
                  if (!m_FileStr.read((char*)m_TileBuffer,
                                       ADRG_TILE_SIZE))
                  {
                     theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
                     return false;
                  }

                  tile->loadBand(m_TileBuffer,
                                 adrg_tile_rect,
                                 tile_clip_rect,
                                 band);

               } // End of band loop.

            } // End of if (tileOffset != 0)

         } // End of if (adrg_tile_rect.intersects(clip_rect))

         ulTilePt.x += ADRG_TILE_WIDTH;

      }  // End of tile loop in the sample direction.

      ulTilePt.y += ADRG_TILE_HEIGHT;

   }  // End of tile loop in the line direction.

   return true;
}

ossim_uint32 ossimAdrgTileSource::getNumberOfOutputBands()const
{
   return getNumberOfInputBands();
}

// Public Method:
ossimIrect
ossimAdrgTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const
{
   return ossimIrect(0,                         // upper left x
                     0,                         // upper left y
                     getNumberOfSamples(reduced_res_level) - 1,  // lower right x
                     getNumberOfLines(reduced_res_level)   - 1); // lower right y
}

void ossimAdrgTileSource::close()
{
   if(m_AdrgHeader)
   {
      delete m_AdrgHeader;
      m_AdrgHeader = 0;
   }
   if(m_FileStr.is_open())
   {
      m_FileStr.close();
   }
   m_Tile = 0;
}

// Public method:
bool ossimAdrgTileSource::open()
{
   static const char MODULE[] = "ossimAdrgTileSource::open";

   if(traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << MODULE << "Entered..."<<std::endl;
   }
   if(isOpen())
   {
      close();
   }
   if(m_AdrgHeader)
   {
      delete m_AdrgHeader;
      m_AdrgHeader = 0;
   }
   // Instantiate support data class to parse header file.
   m_AdrgHeader = new ossimAdrgHeader(theImageFile);

   if (m_AdrgHeader->errorStatus() == ossimErrorCodes::OSSIM_ERROR)
   {
      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_WARN)
            << MODULE << " Error in ossimAdrg header detected." << std::endl;
      }

      close();
      return false;
   }

   m_FileStr.open(m_AdrgHeader->imageFile().c_str(),
                   ios::in | ios::binary);

   // Check the file pointer.
   if(!m_FileStr)
   {
      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_WARN) << MODULE << "\nCannot open:  "
              << m_AdrgHeader->imageFile().c_str() << std::endl;
      }
      close();

      return false;
   }

   if(traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << MODULE
         << "File is opened -> "<< m_AdrgHeader->imageFile()<<std::endl;
   }

   // allow the base handler to check for other overrides
   completeOpen();
   // Allocate memory.
   m_Tile      = ossimImageDataFactory::instance()->create(this, this);
   m_Tile->initialize();
   m_TileBuffer  = new ossim_uint8[ADRG_TILE_SIZE];

   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "\nminLon:   " << m_AdrgHeader->minLon()
         << "\nminLond:  " << m_AdrgHeader->minLongitude()
         << "\nminLat:   " << m_AdrgHeader->minLat()
         << "\nminLatd:  " << m_AdrgHeader->minLatitude()
         << "\nmaxLon:   " << m_AdrgHeader->maxLon()
         << "\nmaxLond:  " << m_AdrgHeader->maxLongitude()
         << "\nmaxLat:   " << m_AdrgHeader->maxLat()
         << "\nmaxLatd:  " << m_AdrgHeader->maxLatitude()
         << std::endl;
   }

   return true;
}

// Public method:
bool ossimAdrgTileSource::saveState(ossimKeywordlist& kwl,
                                    const char* prefix) const
{
   // Currently nothing to do here.
   return ossimImageHandler::saveState(kwl, prefix);
}

// Public method:
bool ossimAdrgTileSource::loadState(const ossimKeywordlist& kwl,
                                    const char* prefix)
{
   if (ossimImageHandler::loadState(kwl, prefix))
   {
      if (open())
      {
         return true;
      }
   }

   return false;
}

// Public method:
ossimRefPtr<ossimImageGeometry> ossimAdrgTileSource::getImageGeometry()
{
   if ( !theGeometry )
   {
      // Check for external geom:
      theGeometry = getExternalImageGeometry();

      if ( !theGeometry )
      {
         // origin of latitude
         ossim_float64 originLatitude = (m_AdrgHeader->maxLatitude() +
                                         m_AdrgHeader->minLatitude()) / 2.0;

         // central meridian.
         ossim_float64 centralMeridian = (m_AdrgHeader->maxLongitude() +
                                          m_AdrgHeader->minLongitude()) / 2.0;

         // Compute the pixel size in latitude and longitude direction.  This will
         // be full image extents divided by full image lines and samples.

         // Samples in full image (used to compute degPerPixelX).
         ossim_float64 samples = m_AdrgHeader->samples();

         // Lines in full image (used to compute degPerPixelX).
         ossim_float64 lines = m_AdrgHeader->lines();

         // Degrees in latitude direction of the full image.
         ossim_float64 degrees_in_lat_dir = m_AdrgHeader->maxLatitude() -
            m_AdrgHeader->minLatitude();

         // Degrees in longitude direction of the full image.
         ossim_float64 degrees_in_lon_dir = m_AdrgHeader->maxLongitude() -
            m_AdrgHeader->minLongitude();

         ossim_float64 degPerPixelY = degrees_in_lat_dir / lines;
         ossim_float64 degPerPixelX = degrees_in_lon_dir / samples;

         // The tie is determined with the following assumptions that need to be
         // 1) Rows and columns start at 1.
         // 2) The min / max latitudes longitudes go to the edge of the pixel.
         // 3) Latitude decreases by degPerPixelY with each line.
         // 4) Longitude increases by degPerPixelX with each sample.
         ossim_float64 ul_lat = (m_AdrgHeader->maxLatitude() -
                                 ( (m_AdrgHeader->startRow() - 1) *
                                   degPerPixelY ) - ( degPerPixelY * 0.5 ) );
         ossim_float64 ul_lon = (m_AdrgHeader->minLongitude() +
                                 ( (m_AdrgHeader->startCol() -1) *
                                   degPerPixelX ) +  ( degPerPixelX * 0.5 ) );

         // projection type
         ossimKeywordlist kwl;
         const char* prefix = 0;
         kwl.add(prefix,
                 ossimKeywordNames::TYPE_KW,
                 "ossimEquDistCylProjection",
                 true);

         kwl.add(prefix,
                 ossimKeywordNames::DATUM_KW,
                 "WGE",
                 true);

         // origin latitude
         kwl.add(prefix,
                 ossimKeywordNames::ORIGIN_LATITUDE_KW,
                 originLatitude,
                 true);

         // central meridin
         kwl.add(prefix,
                 ossimKeywordNames::CENTRAL_MERIDIAN_KW,
                 centralMeridian,
                 true);

         // Save the tie point.
         kwl.add(prefix,
                 ossimKeywordNames::TIE_POINT_XY_KW,
                 ossimDpt(ul_lon, ul_lat).toString().c_str(),
                 true);
         kwl.add(prefix,
                 ossimKeywordNames::TIE_POINT_UNITS_KW,
                 ossimUnitTypeLut::instance()->getEntryString(OSSIM_DEGREES),
                 true);

         // Save the scale.
         kwl.add(prefix,
                 ossimKeywordNames::TIE_POINT_LAT_KW,
                 ul_lat,
                 true);

         kwl.add(prefix,
                 ossimKeywordNames::TIE_POINT_LON_KW,
                 ul_lon,
                 true);

         // Save the scale.
         kwl.add(prefix,
                 ossimKeywordNames::PIXEL_SCALE_XY_KW,
                 ossimDpt(degPerPixelX, degPerPixelY).toString().c_str(),
                 true);
         kwl.add(prefix,
                 ossimKeywordNames::PIXEL_SCALE_UNITS_KW,
                 ossimUnitTypeLut::instance()->getEntryString(OSSIM_DEGREES),
                 true);

         // lines
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_LINES_KW,
                 getNumberOfLines());

         // samples
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_SAMPLES_KW,
                 getNumberOfSamples());

         // res sets
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_REDUCED_RES_SETS_KW,
                 getNumberOfDecimationLevels());

         // bands
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_INPUT_BANDS_KW,
                 getNumberOfInputBands());

         // bands
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_OUTPUT_BANDS_KW,
                 getNumberOfOutputBands());

         if (traceDebug())
         {
            ossimNotify(ossimNotifyLevel_DEBUG)
               << "\nminLon:             " << m_AdrgHeader->minLon()
               << "\nminLond:            " << m_AdrgHeader->minLongitude()
               << "\nminLat:             " << m_AdrgHeader->minLat()
               << "\nminLatd:            " << m_AdrgHeader->minLatitude()
               << "\nmaxLon:             " << m_AdrgHeader->maxLon()
               << "\nmaxLond:            " << m_AdrgHeader->maxLongitude()
               << "\nmaxLat:             " << m_AdrgHeader->maxLat()
               << "\nmaxLatd:            " << m_AdrgHeader->maxLatitude()
               << "\nstartRow:           " << m_AdrgHeader->startRow()
               << "\nstartCol:           " << m_AdrgHeader->startCol()
               << "\nstopRow:            " << m_AdrgHeader->stopRow()
               << "\nstopCol:            " << m_AdrgHeader->stopCol()
               << "\nfull image lines:   " << lines
               << "\nfull image samples: " << samples
               << "\nkwl:\n"               << kwl
               << std::endl;
         }

         ossimProjection* new_proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
         theGeometry = new ossimImageGeometry;
         theGeometry->setProjection(new_proj);  // assumes management of projection instance

      } // matches (after getExternalImageGeometry()):  if ( !theGeometry )

      // Set image things the geometry object should know about.
      initImageParameters( theGeometry.get() );

   } // matches: if ( !theGeometry )

   return theGeometry;
}

// Public method:
ossimScalarType ossimAdrgTileSource::getOutputScalarType() const
{
  return OSSIM_UCHAR;
}

// Public method:
ossim_uint32 ossimAdrgTileSource::getTileWidth() const
{
   return ( m_Tile.valid() ? m_Tile->getWidth() : 0 );
}

// Public method:
ossim_uint32 ossimAdrgTileSource::getTileHeight() const
{
   return ( m_Tile.valid() ? m_Tile->getHeight() : 0 );
}

// Public method:
ossim_uint32 ossimAdrgTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const
{
   if ( (reduced_res_level == 0) && m_AdrgHeader )
   {
      return (m_AdrgHeader->stopRow() - m_AdrgHeader->startRow()) + 1;
   }
   else if (theOverview.valid())
   {
      return theOverview->getNumberOfLines(reduced_res_level);
   }

   return 0;
}

// Public method:
ossim_uint32 ossimAdrgTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const
{
   if ( (reduced_res_level == 0) && m_AdrgHeader )
   {
      return (m_AdrgHeader->stopCol() - m_AdrgHeader->startCol()) + 1;
   }
   else if (theOverview.valid())
   {
      return theOverview->getNumberOfSamples(reduced_res_level);
   }

   return 0;
}

ossim_uint32 ossimAdrgTileSource::getImageTileWidth() const
{
   return ADRG_TILE_WIDTH;
}

ossim_uint32 ossimAdrgTileSource::getImageTileHeight() const
{
   return ADRG_TILE_HEIGHT;
}

ossimRefPtr<ossimProperty> ossimAdrgTileSource::getProperty(const ossimString& name)const
{
   if(name == "file_type")
   {
      return new ossimStringProperty(name, "ADRG");
   }

   return ossimImageHandler::getProperty(name);
}

void ossimAdrgTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const

ossimString ossimAdrgTileSource::getShortName()const
{
   return ossimString("adrg");
}

ossimString ossimAdrgTileSource::getLongName()const
{
   return ossimString("adrg reader");
}

ossim_uint32 ossimAdrgTileSource::getNumberOfInputBands() const
{
   ossim_uint32 bands = 1;
   if ( m_AdrgHeader )
   {
      bands = m_AdrgHeader->numberOfBands();
   }
   return bands;
}

bool ossimAdrgTileSource::isOpen()const
{
   return (m_AdrgHeader!=0);
}

void ossimAdrgTileSource::adjustToStartOfTile(ossimIpt& pt) const
{
   pt.x &= 0xffffff80;
   pt.y &= 0xffffff80;
}


bool ossimAdrgTileSource::saveState(ossimKeywordlist& kwl,
                                    const char* prefix) const
{
   // Currently nothing to do here.
   return ossimImageHandler::saveState(kwl, prefix);
}

// See top level LICENSE.txt file.
// Author: Ken Melero
// Description: This class give the capability to access tiles from an
//              ADRG file.

#include <ossim/imaging/ossimAdrgTileSource.h>
#include <ossim/imaging/ossimAdrgHeader.h>
#include <ossim/base/ossimConstants.h>
#include <ossim/base/ossimCommon.h>
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/base/ossimTrace.h>
#include <ossim/base/ossimKeywordlist.h>
#include <ossim/base/ossimEllipsoid.h>
#include <ossim/base/ossimDatum.h>
#include <ossim/base/ossimUnitTypeLut.h>
#include <ossim/base/ossimStringProperty.h>
#include <ossim/base/ossimContainerProperty.h>
#include <ossim/imaging/ossimImageDataFactory.h>
#include <ossim/imaging/ossimImageGeometry.h>
#include <ossim/imaging/ossimTiffTileSource.h>
#include <ossim/imaging/ossimU8ImageData.h>
#include <ossim/projection/ossimMapProjection.h>
#include <ossim/projection/ossimEquDistCylProjection.h>
#include <ossim/projection/ossimProjectionFactoryRegistry.h>
#include <iostream>

RTTI_DEF1(ossimAdrgTileSource, "ossimAdrgTileSource", ossimImageHandler)

// Static trace for debugging
static ossimTrace traceDebug("ossimAdrgTileSource:debug");

// NOTE:  Currently this tilesource is hard-coded to access tiles
//        from the ZDR image file. This will change as I wrote support
//        data classes for all the ADRG image files: ZDR, overview,
//        and legend support data.  Next step in development will
//        be to put in flags to access overview and legend image files.

using namespace std;

// Public Constructor:
ossimAdrgTileSource::ossimAdrgTileSource()
   :
      ossimImageHandler(),
      m_Tile(0),
      m_TileBuffer(0),
      m_FileStr(),
      m_AdrgHeader(0)
{
   // Construction not complete.  Users should call "open" method.
}

ossimAdrgTileSource::~ossimAdrgTileSource()
{
   if(m_AdrgHeader)
   {
      delete m_AdrgHeader;
      m_AdrgHeader = 0;
   }
   if (m_TileBuffer)
   {
      delete [] m_TileBuffer;
      m_TileBuffer = 0;
   }

   close();
}

ossimRefPtr<ossimImageData> ossimAdrgTileSource::getTile(
   const ossimIrect& rect,
   ossim_uint32 resLevel)
{
   if (m_Tile.valid())
   {
      // Image rectangle must be set prior to calling getTile.
      m_Tile->setImageRectangle(rect);

      if ( getTile( m_Tile.get(), resLevel ) == false )
      {
         if (m_Tile->getDataObjectStatus() != OSSIM_NULL)
         {
            m_Tile->makeBlank();
         }
      }
   }

   return m_Tile;
}

bool ossimAdrgTileSource::getTile(ossimImageData* result,
                                  ossim_uint32 resLevel)
{
   bool status = false;

   // Not open, this tile source bypassed, or invalid res level,
   // return a blank tile.
   if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
       result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
   {
      result->ref();  // Increment ref count.

      // Check for overview tile.  Some overviews can contain r0 so always
      // call even if resLevel is 0.  Method returns true on success, false
      // on error.
      status = getOverviewTile(resLevel, result);

      if (!status) // Did not get an overview tile.
      {
         status = true;

         ossimIrect tile_rect = result->getImageRectangle();

         ossimIrect image_rect = getImageRectangle(resLevel);

         result->makeBlank();

         // See if any point of the requested tile is in the image.
         if ( tile_rect.intersects(image_rect) )
         {
            ossimIrect clip_rect = tile_rect.clipToRect(image_rect);

            // Load the tile buffer with data from the adrg.
            status = fillBuffer(tile_rect, clip_rect, result);

            if (status)
            {
               result->validate();
            }
         }
      }

      result->unref();  // Decrement ref count.
   }

   return status;
}

// Private Method:
bool ossimAdrgTileSource::fillBuffer(const ossimIrect& /* tile_rect */,
                                     const ossimIrect& clip_rect,
                                     ossimImageData* tile)
{
   // Shift the upper left corner of the "clip_rect" to the an even chunk
   ossimIpt tileOrigin = clip_rect.ul();
   adjustToStartOfTile(tileOrigin);

   // Calculate the number of tiles needed in the line/sample directions.
   ossim_int32 size_in_x = clip_rect.lr().x - tileOrigin.x + 1;
   ossim_int32 size_in_y = clip_rect.lr().y - tileOrigin.y + 1;

   ossim_int32 tiles_in_x_dir = size_in_x / ADRG_TILE_WIDTH  +
      (size_in_x % ADRG_TILE_WIDTH  ? 1 : 0);
   ossim_int32 tiles_in_y_dir = size_in_y / ADRG_TILE_HEIGHT +
      (size_in_y % ADRG_TILE_HEIGHT ? 1 : 0);

   ossimIpt ulTilePt = tileOrigin;

   // Chunk loop in line direction.
   for (ossim_int32 y=0; y<tiles_in_y_dir; y++)
   {
      ulTilePt.x = tileOrigin.x;

      // Tile loop in sample direction.
      for (ossim_int32 x=0; x<tiles_in_x_dir; x++)
      {
         ossimIrect adrg_tile_rect(ulTilePt.x,
                                   ulTilePt.y,
                                   ulTilePt.x + ADRG_TILE_WIDTH- 1,
                                   ulTilePt.y + ADRG_TILE_HEIGHT - 1);

         if (adrg_tile_rect.intersects(clip_rect))
         {
            ossimIrect tile_clip_rect = clip_rect.clipToRect(adrg_tile_rect);

            // Some point in the chip intersect the tile so grab the
            ossim_int32 row = (ossim_int32) ulTilePt.y / ADRG_TILE_HEIGHT;
            ossim_int32 col = (ossim_int32) ulTilePt.x / ADRG_TILE_WIDTH;
            ossim_int32 tileOffset = m_AdrgHeader->tim(row, col);

            if(tileOffset != 0)
            {
               // Get the data.
               int seek_position = (tileOffset - 1) * 49152 + 2048;
               int band;

               // seek to start of chip
               m_FileStr.seekg(seek_position, ios::beg);
               for (band=0; band<3; band++)
               {
                  // Read the chip from the ccf file into the chunk buffer.
                  // This will get all the bands.  Bands are interleaved by
                  if (!m_FileStr.read((char*)m_TileBuffer,
                                       ADRG_TILE_SIZE))
                  {
                     theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
                     return false;
                  }

                  tile->loadBand(m_TileBuffer,
                                 adrg_tile_rect,
                                 tile_clip_rect,
                                 band);

               } // End of band loop.

            } // End of if (tileOffset != 0)

         } // End of if (adrg_tile_rect.intersects(clip_rect))

         ulTilePt.x += ADRG_TILE_WIDTH;

      }  // End of tile loop in the sample direction.

      ulTilePt.y += ADRG_TILE_HEIGHT;

   }  // End of tile loop in the line direction.

   return true;
}

ossim_uint32 ossimAdrgTileSource::getNumberOfOutputBands()const
{
   return getNumberOfInputBands();
}

// Public Method:
ossimIrect
ossimAdrgTileSource::getImageRectangle(ossim_uint32 reduced_res_level) const
{
   return ossimIrect(0,                         // upper left x
                     0,                         // upper left y
                     getNumberOfSamples(reduced_res_level) - 1,  // lower right x
                     getNumberOfLines(reduced_res_level)   - 1); // lower right y
}

void ossimAdrgTileSource::close()
{
   if(m_AdrgHeader)
   {
      delete m_AdrgHeader;
      m_AdrgHeader = 0;
   }
   if(m_FileStr.is_open())
   {
      m_FileStr.close();
   }
   m_Tile = 0;
}

// Public method:
bool ossimAdrgTileSource::open()
{
   static const char MODULE[] = "ossimAdrgTileSource::open";

   if(traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << MODULE << "Entered..."<<std::endl;
   }
   if(isOpen())
   {
      close();
   }
   if(m_AdrgHeader)
   {
      delete m_AdrgHeader;
      m_AdrgHeader = 0;
   }
   // Instantiate support data class to parse header file.
   m_AdrgHeader = new ossimAdrgHeader(theImageFile);

   if (m_AdrgHeader->errorStatus() == ossimErrorCodes::OSSIM_ERROR)
   {
      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_WARN)
            << MODULE << " Error in ossimAdrg header detected." << std::endl;
      }

      close();
      return false;
   }

   m_FileStr.open(m_AdrgHeader->imageFile().c_str(),
                   ios::in | ios::binary);

   // Check the file pointer.
   if(!m_FileStr)
   {
      theErrorStatus = ossimErrorCodes::OSSIM_ERROR;
      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_WARN) << MODULE << "\nCannot open:  "
              << m_AdrgHeader->imageFile().c_str() << std::endl;
      }
      close();

      return false;
   }

   if(traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << MODULE
         << "File is opened -> "<< m_AdrgHeader->imageFile()<<std::endl;
   }

   // allow the base handler to check for other overrides
   completeOpen();
   // Allocate memory.
   m_Tile      = ossimImageDataFactory::instance()->create(this, this);
   m_Tile->initialize();
   m_TileBuffer  = new ossim_uint8[ADRG_TILE_SIZE];

   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "\nminLon:   " << m_AdrgHeader->minLon()
         << "\nminLond:  " << m_AdrgHeader->minLongitude()
         << "\nminLat:   " << m_AdrgHeader->minLat()
         << "\nminLatd:  " << m_AdrgHeader->minLatitude()
         << "\nmaxLon:   " << m_AdrgHeader->maxLon()
         << "\nmaxLond:  " << m_AdrgHeader->maxLongitude()
         << "\nmaxLat:   " << m_AdrgHeader->maxLat()
         << "\nmaxLatd:  " << m_AdrgHeader->maxLatitude()
         << std::endl;
   }

   return true;
}

// Public method:

// Public method:
bool ossimAdrgTileSource::loadState(const ossimKeywordlist& kwl,
                                    const char* prefix)
{
   if (ossimImageHandler::loadState(kwl, prefix))
   {
      if (open())
      {
         return true;
      }
   }

   return false;
}

// Public method:
ossimRefPtr<ossimImageGeometry> ossimAdrgTileSource::getImageGeometry()
{
   if ( !theGeometry )
   {
      // Check for external geom:
      theGeometry = getExternalImageGeometry();

      if ( !theGeometry )
      {
         // origin of latitude
         ossim_float64 originLatitude = (m_AdrgHeader->maxLatitude() +
                                         m_AdrgHeader->minLatitude()) / 2.0;

         // central meridian.
         ossim_float64 centralMeridian = (m_AdrgHeader->maxLongitude() +
                                          m_AdrgHeader->minLongitude()) / 2.0;

         // Compute the pixel size in latitude and longitude direction.  This will
         // be full image extents divided by full image lines and samples.

         // Samples in full image (used to compute degPerPixelX).
         ossim_float64 samples = m_AdrgHeader->samples();

         // Lines in full image (used to compute degPerPixelX).
         ossim_float64 lines = m_AdrgHeader->lines();

         // Degrees in latitude direction of the full image.
         ossim_float64 degrees_in_lat_dir = m_AdrgHeader->maxLatitude() -
            m_AdrgHeader->minLatitude();

         // Degrees in longitude direction of the full image.
         ossim_float64 degrees_in_lon_dir = m_AdrgHeader->maxLongitude() -
            m_AdrgHeader->minLongitude();

         ossim_float64 degPerPixelY = degrees_in_lat_dir / lines;
         ossim_float64 degPerPixelX = degrees_in_lon_dir / samples;

         // The tie is determined with the following assumptions that need to be
         // 1) Rows and columns start at 1.
         // 2) The min / max latitudes longitudes go to the edge of the pixel.
         // 3) Latitude decreases by degPerPixelY with each line.
         // 4) Longitude increases by degPerPixelX with each sample.
         ossim_float64 ul_lat = (m_AdrgHeader->maxLatitude() -
                                 ( (m_AdrgHeader->startRow() - 1) *
                                   degPerPixelY ) - ( degPerPixelY * 0.5 ) );
         ossim_float64 ul_lon = (m_AdrgHeader->minLongitude() +
                                 ( (m_AdrgHeader->startCol() -1) *
                                   degPerPixelX ) +  ( degPerPixelX * 0.5 ) );

         // projection type
         ossimKeywordlist kwl;
         const char* prefix = 0;
         kwl.add(prefix,
                 ossimKeywordNames::TYPE_KW,
                 "ossimEquDistCylProjection",
                 true);

         kwl.add(prefix,
                 ossimKeywordNames::DATUM_KW,
                 "WGE",
                 true);

         // origin latitude
         kwl.add(prefix,
                 ossimKeywordNames::ORIGIN_LATITUDE_KW,
                 originLatitude,
                 true);

         // central meridin
         kwl.add(prefix,
                 ossimKeywordNames::CENTRAL_MERIDIAN_KW,
                 centralMeridian,
                 true);

         // Save the tie point.
         kwl.add(prefix,
                 ossimKeywordNames::TIE_POINT_XY_KW,
                 ossimDpt(ul_lon, ul_lat).toString().c_str(),
                 true);
         kwl.add(prefix,
                 ossimKeywordNames::TIE_POINT_UNITS_KW,
                 ossimUnitTypeLut::instance()->getEntryString(OSSIM_DEGREES),
                 true);

         // Save the scale.
         kwl.add(prefix,
                 ossimKeywordNames::TIE_POINT_LAT_KW,
                 ul_lat,
                 true);

         kwl.add(prefix,
                 ossimKeywordNames::TIE_POINT_LON_KW,
                 ul_lon,
                 true);

         // Save the scale.
         kwl.add(prefix,
                 ossimKeywordNames::PIXEL_SCALE_XY_KW,
                 ossimDpt(degPerPixelX, degPerPixelY).toString().c_str(),
                 true);
         kwl.add(prefix,
                 ossimKeywordNames::PIXEL_SCALE_UNITS_KW,
                 ossimUnitTypeLut::instance()->getEntryString(OSSIM_DEGREES),
                 true);

         // lines
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_LINES_KW,
                 getNumberOfLines());

         // samples
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_SAMPLES_KW,
                 getNumberOfSamples());

         // res sets
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_REDUCED_RES_SETS_KW,
                 getNumberOfDecimationLevels());

         // bands
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_INPUT_BANDS_KW,
                 getNumberOfInputBands());

         // bands
         kwl.add(prefix,
                 ossimKeywordNames::NUMBER_OUTPUT_BANDS_KW,
                 getNumberOfOutputBands());

         if (traceDebug())
         {
            ossimNotify(ossimNotifyLevel_DEBUG)
               << "\nminLon:             " << m_AdrgHeader->minLon()
               << "\nminLond:            " << m_AdrgHeader->minLongitude()
               << "\nminLat:             " << m_AdrgHeader->minLat()
               << "\nminLatd:            " << m_AdrgHeader->minLatitude()
               << "\nmaxLon:             " << m_AdrgHeader->maxLon()
               << "\nmaxLond:            " << m_AdrgHeader->maxLongitude()
               << "\nmaxLat:             " << m_AdrgHeader->maxLat()
               << "\nmaxLatd:            " << m_AdrgHeader->maxLatitude()
               << "\nstartRow:           " << m_AdrgHeader->startRow()
               << "\nstartCol:           " << m_AdrgHeader->startCol()
               << "\nstopRow:            " << m_AdrgHeader->stopRow()
               << "\nstopCol:            " << m_AdrgHeader->stopCol()
               << "\nfull image lines:   " << lines
               << "\nfull image samples: " << samples
               << "\nkwl:\n"               << kwl
               << std::endl;
         }

         ossimProjection* new_proj = ossimProjectionFactoryRegistry::instance()->createProjection(kwl);
         theGeometry = new ossimImageGeometry;
         theGeometry->setProjection(new_proj);  // assumes management of projection instance

      } // matches (after getExternalImageGeometry()):  if ( !theGeometry )

      // Set image things the geometry object should know about.
      initImageParameters( theGeometry.get() );

   } // matches: if ( !theGeometry )

   return theGeometry;
}

// Public method:
ossimScalarType ossimAdrgTileSource::getOutputScalarType() const
{
  return OSSIM_UCHAR;
}

// Public method:
ossim_uint32 ossimAdrgTileSource::getTileWidth() const
{
   return ( m_Tile.valid() ? m_Tile->getWidth() : 0 );
}

// Public method:
ossim_uint32 ossimAdrgTileSource::getTileHeight() const
{
   return ( m_Tile.valid() ? m_Tile->getHeight() : 0 );
}

// Public method:
ossim_uint32 ossimAdrgTileSource::getNumberOfLines(ossim_uint32 reduced_res_level) const
{
   if ( (reduced_res_level == 0) && m_AdrgHeader )
   {
      return (m_AdrgHeader->stopRow() - m_AdrgHeader->startRow()) + 1;
   }
   else if (theOverview.valid())
   {
      return theOverview->getNumberOfLines(reduced_res_level);
   }

   return 0;
}

// Public method:
ossim_uint32 ossimAdrgTileSource::getNumberOfSamples(ossim_uint32 reduced_res_level) const
{
   if ( (reduced_res_level == 0) && m_AdrgHeader )
   {
      return (m_AdrgHeader->stopCol() - m_AdrgHeader->startCol()) + 1;
   }
   else if (theOverview.valid())
   {
      return theOverview->getNumberOfSamples(reduced_res_level);
   }

   return 0;
}

ossim_uint32 ossimAdrgTileSource::getImageTileWidth() const
{
   return ADRG_TILE_WIDTH;
}

ossim_uint32 ossimAdrgTileSource::getImageTileHeight() const
{
   return ADRG_TILE_HEIGHT;
}

ossimRefPtr<ossimProperty> ossimAdrgTileSource::getProperty(const ossimString& name)const
{
   if(name == "file_type")
   {
      return new ossimStringProperty(name, "ADRG");
   }

   return ossimImageHandler::getProperty(name);
}

void ossimAdrgTileSource::getPropertyNames(std::vector<ossimString>& propertyNames)const
{
	ossimImageHandler::getPropertyNames(propertyNames);
	propertyNames.push_back("file_type");
}

ossimString ossimAdrgTileSource::getShortName()const
{
   return ossimString("adrg");
}

ossimString ossimAdrgTileSource::getLongName()const
{
   return ossimString("adrg reader");
}

ossim_uint32 ossimAdrgTileSource::getNumberOfInputBands() const
{
   ossim_uint32 bands = 1;
   if ( m_AdrgHeader )
   {
      bands = m_AdrgHeader->numberOfBands();
   }
   return bands;
}

bool ossimAdrgTileSource::isOpen()const
{
   return (m_AdrgHeader!=0);
}

void ossimAdrgTileSource::adjustToStartOfTile(ossimIpt& pt) const
{
   pt.x &= 0xffffff80;
   pt.y &= 0xffffff80;
}


void setup(){
    ///Bind Gui
    bindGLV();
    ///Add Variables to GUI
    gui(amt,"amt",-100,100)(bReset,"bReset")(bShaded,"bShaded");
    gui(p,"p",0,10)(q,"q",0,10);

    mColor.set(1,1,1);

  }

  /*-----------------------------------------------------------------------------
   *  Draw Routines
   *-----------------------------------------------------------------------------*/
  void onDraw(){

      ps.bShadedOutput = bShaded;

      //0. a and c are at 90 degrees, must find b...
      auto a = Vec::x;
      auto c = Vec::y;

      auto xy = Biv::xy;

      // employ the spherical trig cosine rule ...
      // cos a = cos b cos c + sin b sin c cos A
      // A = acos( ( cos a - cos b cos c ) / sin b sin c
      // so if ta, tb, and tc represent the angles between vectors on a sphere
      // find amt to rotate planes and then intersect them ...
      double tb = PIOVERTWO;
      double ta = PI/(int)p;
      double tc = -PI/(int)q;

      double ca = cos(ta);
      double sa = sin(ta);
      double cb = cos(tb);
      double sb = sin(tb);
      double cc = cos(tc);
      double sc = sin(tc);

      //rotate yz and xz planes by polar angles
      // @todo note that since we know tb, the equation could be simplified
      double tA = acos( (ca-(cb*cc))/(sb*sc) );
      double tC = acos( (cc-(ca*cb))/(sa*sb) );

      //2. ... to rotate the yx plane ...
      auto bivA = xy.rot( a.duale() * tC / 2.0 );
      auto bivC = xy.rot( c.duale() * tA / 2.0 );

      //3. ... and find b via coincidence of planes ...
      auto b = -(bivA.duale() ^ bivC.duale()).duale().unit();

      if (bReset){
       DrawB(bivA,1,1,0,1);
       Draw(b,0,1,0);
       DrawB(bivC,0,1,1,1);
       Draw(c,0,0,1);
       DrawB(Biv::xy,1,0,1,1);
       Draw(a,1,0,0);

      } else{

       Draw(Biv::xy,.2,.2,.2);
       Draw(bivA,1,1,0);
       Draw(bivC,0,1,1);
      }

      Draw(a,1,0,0);
      Draw(b,0,1,0);
      Draw(c,0,0,1);

  }

};

int main(){

  MyApp app;
  app.start();

  return 0;

}


int minstrBaseIdx(Opcode opc) {
  return opcodeHasFlags(opc, MInstrProp) ? 0 :
         opcodeHasFlags(opc, MInstrElem) ? 0 :
         bad_value<int>();
}

/*
   +----------------------------------------------------------------------+
   | HipHop for PHP                                                       |
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
   +----------------------------------------------------------------------+
*/
#include "hphp/runtime/vm/jit/minstr-effects.h"

#include "hphp/runtime/vm/jit/frame-state.h"

namespace HPHP { namespace jit {

namespace {

template<typename T> T bad_value() { not_reached(); }

Opcode canonicalOp(Opcode op) {
  if (op == ElemUX || op == UnsetElem)     return UnsetElem;
  if (op == SetRange || op == SetRangeRev) return SetRange;

  return opcodeHasFlags(op, MInstrProp) ? SetProp
       : opcodeHasFlags(op, MInstrElem) ? SetElem
       : bad_value<Opcode>();
}

void getBaseType(Opcode rawOp, bool predict,
                 Type& baseType, bool& baseValChanged) {
  always_assert(baseType <= TCell);
  auto const op = canonicalOp(rawOp);

  if ((op == SetElem || op == SetProp) &&
      baseType.maybe(TNull | TBool | TStr)) {
    if (predict && baseType.maybe(TStr)) {
      /* If the output type will be used as a prediction and not as fact, we
       * can be optimistic here. Assume no promotion for string bases and
       * an exception otherwise */
      baseType = TStr;
    } else if (baseType <= TStr && rawOp == SetNewElem) {
      /* new-elem to string will always raise, empty or not */
      baseType = TBottom;
    } else if (baseType.maybe(TNull | TBool)) {
      /* we used to promote falsey things to array or an instance of stdClass,
       * now these always raise, except a base of `true` gets coerced to null */
      baseType -= TNull;
    }

    if (baseType != TBottom) baseValChanged = true;
  }

  if ((op == SetElem || op == SetRange || op == UnsetElem) &&
      baseType.maybe(TArrLike | TStr | TClsMeth)) {
    /* Member operations never cause us to lose the vanilla bit. */
    auto const vanilla = baseType.arrSpec().vanilla();

    /* Modifying an array or string element, even when COW doesn't kick in,
     * produces a new SSATmp for the base. StaticArr/StaticStr may be promoted
     * to CountedArr/CountedStr. */
    baseValChanged = true;

    if (baseType.maybe(TVec)) baseType |= TCountedVec;
    if (baseType.maybe(TDict)) baseType |= TCountedDict;
    if (baseType.maybe(TKeyset)) baseType |= TCountedKeyset;
    if (baseType.maybe(TStr)) baseType |= TCountedStr;
    if (baseType.maybe(TClsMeth)) baseType |= TCountedVec;

    if (vanilla) baseType = baseType.narrowToVanilla();
  }
}

}

// minstrBaseIdx returns the src index for inst's base operand.

bool MInstrEffects::supported(Opcode op) {
  return opcodeHasFlags(op, MInstrProp | MInstrElem);
}
bool MInstrEffects::supported(const IRInstruction* inst) {
  return supported(inst->op());
}

MInstrEffects::MInstrEffects(const Opcode rawOp, const Type origBase) {
  // Note: MInstrEffects wants to manipulate pointer types in some situations
  // for historical reasons.  We'll eventually change that.
  bool const is_ptr = origBase <= TLvalToCell;
  auto const basePtr = is_ptr ? origBase.ptrKind() : Ptr::Bottom;
  baseType = origBase.derefIfPtr();

  baseTypeChanged = baseValChanged = false;

  getBaseType(rawOp, false, baseType, baseValChanged);

  baseType = is_ptr ? baseType.lval(basePtr) : baseType;
  baseTypeChanged = baseType != origBase;
  baseValChanged = baseValChanged || (baseTypeChanged && baseType != TBottom);
}

}}


cplus/github/walkccc/LeetCode/solutions/1901. Find a Peak Element II/1901.cpp

while (l < r) {
      const int m = l + (r - l) / 2;
      if (*max_element(begin(mat[m]), end(mat[m])) >=
          *max_element(begin(mat[m + 1]), end(mat[m + 1])))
        r = m;
      else
        l = m + 1;
    }

class Solution {
 public:
  vector<int> findPeakGrid(vector<vector<int>>& mat) {
    int l = 0;
    int r = mat.size() - 1;

    return {l, getMaxIndex(mat[l])};
  }

 private:
  int getMaxIndex(const vector<int>& A) {
    pair<int, int> res{0, A[0]};
    for (int i = 1; i < A.size(); ++i)
      if (A[i] > res.second)
        res = {i, A[i]};
    return res.first;
  }
};


while (cin >> N) {
    best = 0;

    for (int i = 1; i <= N; i++) {
      cin >> time >> distance;

      if (distance / time > best) {
        best = distance / time;
        cout << i << endl;
      }
    }
  }

#include <iostream>

using namespace std;

int main() {
  int N;
  double best, time, distance;


OnnxPrediction::OnnxPrediction(std::wstring& onnx_model_file, Ort::Env& env)
    : raw_model{nullptr},
      ptr_session{std::make_unique<Ort::Session>(env, onnx_model_file.c_str(), empty_session_option)},
      input_names(ptr_session->GetInputCount()),
      output_names(ptr_session->GetOutputCount()) {
  init();
}

#include "OnnxPrediction.h"
#include "onnxruntime_session_options_config_keys.h"

#include <vector>

// Uses the onnxruntime to load the model
// into a session.

// Uses the onnx to seri
OnnxPrediction::OnnxPrediction(onnx::ModelProto& onnx_model, Ort::Env& env) {
  raw_model = std::shared_ptr<void>(alloc.Alloc(onnx_model.ByteSizeLong()), [this](void* ptr) {
    this->GetAllocator().Free(ptr);
  });

  onnx_model.SerializeToArray(raw_model.get(), static_cast<int>(onnx_model.ByteSizeLong()));

  ptr_session = std::make_unique<Ort::Session>(env,
                                               static_cast<void*>(raw_model.get()),
                                               onnx_model.ByteSizeLong(),
                                               empty_session_option);

  // TODO Use reserve instead of resize
  input_names.resize(ptr_session->GetInputCount());
  output_names.resize(ptr_session->GetOutputCount());

  init();
}

OnnxPrediction::OnnxPrediction(const std::vector<char>& model_data, Ort::Env& env) {
  Ort::SessionOptions so;
  so.AddConfigEntry(kOrtSessionOptionsConfigLoadModelFormat, "ORT");
  ptr_session = std::make_unique<Ort::Session>(env,
                                               model_data.data(),
                                               model_data.size(),
                                               so);

  // TODO Use reserve instead of resize
  input_names.resize(ptr_session->GetInputCount());
  output_names.resize(ptr_session->GetOutputCount());

  init();
}

// OnnxPrediction console output format
// prints the output data.
std::wostream& operator<<(std::wostream& out, OnnxPrediction& pred) {
  auto pretty_print = [&out](auto ptr, Ort::Value& val) {
    out << L"[";
    std::wstring msg = L"";
    for (int i = 0; i < val.GetTensorTypeAndShapeInfo().GetElementCount(); i++) {
      out << msg << ptr[i];
      msg = L", ";
    }
    out << L"]\n";
  };

  size_t index{0};
  for (auto& val : pred.output_values) {
    out << pred.output_names[index++] << L" = ";
    pred.ProcessOutputData(pretty_print, val);
  }

  return out;
}

// Used to Generate data for predict
void GenerateDataForInputTypeTensor(OnnxPrediction& predict,
                                    size_t input_index, const std::string& input_name,
                                    ONNXTensorElementDataType elem_type, size_t elem_count, size_t seed) {
  (void)input_name;
  (void)input_index;

  auto pretty_print = [&input_name](auto raw_data) {
    Logger::testLog << input_name << L" = ";
    Logger::testLog << L"[";
    std::wstring msg = L"";
    for (int i = 0; i < raw_data.size(); i++) {
      Logger::testLog << msg << raw_data[i];
      msg = L", ";
    }
    Logger::testLog << L"]\n";
  };

  if (elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT) {
    auto raw_data = GenerateRandomData(0.0f, elem_count, seed);
    predict << std::move(raw_data);
  } else if (elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32) {
    int32_t initial = 0;
    auto raw_data = GenerateRandomData(initial, elem_count, seed);
    predict << std::move(raw_data);
  } else {
    throw std::exception("only floats are implemented");
  }
}

// Run the prediction
void OnnxPrediction::RunInference() {
  Logger::testLog << L"inference starting " << Logger::endl;
  Logger::testLog.flush();

  try {
    ptr_session->Run(run_options,
                     input_names.data(), input_values.data(),
                     input_values.size(), output_names.data(), output_values.data(),
                     output_names.size());
  } catch (...) {
    Logger::testLog << L"Something went wrong in inference " << Logger::endl;
    Logger::testLog.flush();
    throw;
  }

  Logger::testLog << L"inference completed " << Logger::endl;
  Logger::testLog.flush();
}

// Print the output values of the prediction.
void OnnxPrediction::PrintOutputValues() {
  Logger::testLog << L"output data:\n";
  Logger::testLog << *this;
  Logger::testLog << Logger::endl;
}

// Common initilization amongst constructors
void OnnxPrediction::init() {
  // Initialize model input names
  for (int i = 0; i < ptr_session->GetInputCount(); i++) {
    // TODO Use push_back on input_names instead of assignment
    input_names[i] = ptr_session->GetInputName(i, alloc);
    input_values.emplace_back(nullptr);
  }

  // Initialize model output names
  for (int i = 0; i < ptr_session->GetOutputCount(); i++) {
    // TODO Use push_back on output_names instead of assignment
    output_names[i] = ptr_session->GetOutputName(i, alloc);
    output_values.emplace_back(nullptr);
  }
}

// Get the allocator used by the runtime
Ort::AllocatorWithDefaultOptions& OnnxPrediction::GetAllocator() {
  return alloc;
}

void OnnxPrediction::SetupInput(
    InputGeneratorFunctionType GenerateData,
    size_t seed) {
  Logger::testLog << L"input data:\n";
  for (int i = 0; i < ptr_session->GetInputCount(); i++) {
    auto inputType = ptr_session->GetInputTypeInfo(i);

    if (inputType.GetONNXType() == ONNX_TYPE_TENSOR) {
      auto elem_type = inputType.GetTensorTypeAndShapeInfo().GetElementType();
      auto elem_count = inputType.GetTensorTypeAndShapeInfo().GetElementCount();

      // This can be any generic function to generate inputs
      GenerateData(*this, i, std::string(input_names[i]), elem_type, elem_count, seed);

      // Update the seed in a predicatable way to get other values for different inputs
      seed++;
    } else {
      std::cout << "Unsupported \n";
    }
  }
  Logger::testLog << Logger::endl;
}


try {
    ptr_session->Run(run_options,
                     input_names.data(), input_values.data(),
                     input_values.size(), output_names.data(), output_values.data(),
                     output_names.size());
  } catch (...) {
    Logger::testLog << L"Something went wrong in inference " << Logger::endl;
    Logger::testLog.flush();
    throw;
  }

#include "OnnxPrediction.h"
#include "onnxruntime_session_options_config_keys.h"

#include <vector>

// Uses the onnxruntime to load the model
// into a session.
OnnxPrediction::OnnxPrediction(std::wstring& onnx_model_file, Ort::Env& env)
    : raw_model{nullptr},
      ptr_session{std::make_unique<Ort::Session>(env, onnx_model_file.c_str(), empty_session_option)},
      input_names(ptr_session->GetInputCount()),
      output_names(ptr_session->GetOutputCount()) {
  init();
}

// Uses the onnx to seri
OnnxPrediction::OnnxPrediction(onnx::ModelProto& onnx_model, Ort::Env& env) {
  raw_model = std::shared_ptr<void>(alloc.Alloc(onnx_model.ByteSizeLong()), [this](void* ptr) {
    this->GetAllocator().Free(ptr);
  });

  onnx_model.SerializeToArray(raw_model.get(), static_cast<int>(onnx_model.ByteSizeLong()));

  ptr_session = std::make_unique<Ort::Session>(env,
                                               static_cast<void*>(raw_model.get()),
                                               onnx_model.ByteSizeLong(),
                                               empty_session_option);

  // TODO Use reserve instead of resize
  input_names.resize(ptr_session->GetInputCount());
  output_names.resize(ptr_session->GetOutputCount());

  init();
}

OnnxPrediction::OnnxPrediction(const std::vector<char>& model_data, Ort::Env& env) {
  Ort::SessionOptions so;
  so.AddConfigEntry(kOrtSessionOptionsConfigLoadModelFormat, "ORT");
  ptr_session = std::make_unique<Ort::Session>(env,
                                               model_data.data(),
                                               model_data.size(),
                                               so);

  // TODO Use reserve instead of resize
  input_names.resize(ptr_session->GetInputCount());
  output_names.resize(ptr_session->GetOutputCount());

  init();
}

// OnnxPrediction console output format
// prints the output data.
std::wostream& operator<<(std::wostream& out, OnnxPrediction& pred) {
  auto pretty_print = [&out](auto ptr, Ort::Value& val) {
    out << L"[";
    std::wstring msg = L"";
    for (int i = 0; i < val.GetTensorTypeAndShapeInfo().GetElementCount(); i++) {
      out << msg << ptr[i];
      msg = L", ";
    }
    out << L"]\n";
  };

  size_t index{0};
  for (auto& val : pred.output_values) {
    out << pred.output_names[index++] << L" = ";
    pred.ProcessOutputData(pretty_print, val);
  }

  return out;
}

// Used to Generate data for predict
void GenerateDataForInputTypeTensor(OnnxPrediction& predict,
                                    size_t input_index, const std::string& input_name,
                                    ONNXTensorElementDataType elem_type, size_t elem_count, size_t seed) {
  (void)input_name;
  (void)input_index;

  auto pretty_print = [&input_name](auto raw_data) {
    Logger::testLog << input_name << L" = ";
    Logger::testLog << L"[";
    std::wstring msg = L"";
    for (int i = 0; i < raw_data.size(); i++) {
      Logger::testLog << msg << raw_data[i];
      msg = L", ";
    }
    Logger::testLog << L"]\n";
  };

  if (elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT) {
    auto raw_data = GenerateRandomData(0.0f, elem_count, seed);
    predict << std::move(raw_data);
  } else if (elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32) {
    int32_t initial = 0;
    auto raw_data = GenerateRandomData(initial, elem_count, seed);
    predict << std::move(raw_data);
  } else {
    throw std::exception("only floats are implemented");
  }
}

// Run the prediction
void OnnxPrediction::RunInference() {
  Logger::testLog << L"inference starting " << Logger::endl;
  Logger::testLog.flush();

  Logger::testLog << L"inference completed " << Logger::endl;
  Logger::testLog.flush();
}

// Print the output values of the prediction.
void OnnxPrediction::PrintOutputValues() {
  Logger::testLog << L"output data:\n";
  Logger::testLog << *this;
  Logger::testLog << Logger::endl;
}

// Common initilization amongst constructors
void OnnxPrediction::init() {
  // Initialize model input names
  for (int i = 0; i < ptr_session->GetInputCount(); i++) {
    // TODO Use push_back on input_names instead of assignment
    input_names[i] = ptr_session->GetInputName(i, alloc);
    input_values.emplace_back(nullptr);
  }

  // Initialize model output names
  for (int i = 0; i < ptr_session->GetOutputCount(); i++) {
    // TODO Use push_back on output_names instead of assignment
    output_names[i] = ptr_session->GetOutputName(i, alloc);
    output_values.emplace_back(nullptr);
  }
}

// Get the allocator used by the runtime
Ort::AllocatorWithDefaultOptions& OnnxPrediction::GetAllocator() {
  return alloc;
}

void OnnxPrediction::SetupInput(
    InputGeneratorFunctionType GenerateData,
    size_t seed) {
  Logger::testLog << L"input data:\n";
  for (int i = 0; i < ptr_session->GetInputCount(); i++) {
    auto inputType = ptr_session->GetInputTypeInfo(i);

    if (inputType.GetONNXType() == ONNX_TYPE_TENSOR) {
      auto elem_type = inputType.GetTensorTypeAndShapeInfo().GetElementType();
      auto elem_count = inputType.GetTensorTypeAndShapeInfo().GetElementCount();

      // This can be any generic function to generate inputs
      GenerateData(*this, i, std::string(input_names[i]), elem_type, elem_count, seed);

      // Update the seed in a predicatable way to get other values for different inputs
      seed++;
    } else {
      std::cout << "Unsupported \n";
    }
  }
  Logger::testLog << Logger::endl;
}