text:
#include "NavParserThreadGroup.h"
#include "NavInterfaceFactory.h"
#include "NavRouteMessage.h"
#include "RouteRequest.h"
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "NavThread.h"
#include "ClientSettings.h"
#include "RoutePacket.h"
#include "UserData.h"
#include "ItemTypes.h"
#include "MC2CRC32.h"
#include "NavClientVersionStorage.h"
#include "TopRegionMatch.h"
#include "TopRegionRequest.h"
#include "NParam.h"
#include "NParamBlock.h"
#include "NavPacket.h"
#include <algorithm>
#include "sockets.h" // write
#include "FOBC.h"
#include "NavLatestNewsData.h"
#include "NavCategoriesData.h"
#include "NamedServerLists.h"
#include "DataBuffer.h"

NavParserThreadGroup::NavParserThreadGroup(
   const char* threadGroupName ,
   uint32 minNbrThreads, uint32 maxNbrThreads,
   uint32 queueFullFactor, uint32 queueOverFullFactor ):
   InterfaceParserThreadGroup( ServerTypes::NAVIGATOR,
                               threadGroupName,
                               minNbrThreads, maxNbrThreads,
                               queueFullFactor, queueOverFullFactor )
{
   //m_categoriesData belongs to ParserThreadGroup, but cannot be set
   //there as ParserTreadGroup doesn't know what type to use.
   m_categoriesData = new NavCategoriesDataHolder();

   m_simulatedRouteFileName = NULL;
   m_threadID = 0;
   m_alternativeServersList = NULL;
   m_alternativeServersListCRC = 0;
   m_longAlternativeServersList = NULL;
   m_longAlternativeServersListCRC = 0;
   m_httpAlternativeServersList = NULL;
   m_httpAlternativeServersListCRC = 0;
   m_forceRedirect = false;
   m_clientVersions = NULL;
   m_noUserTrack = false;
   m_latestNewsSearch = new SearchNavLatestNewsData();
}

NavParserThreadGroup::~NavParserThreadGroup() {
   delete m_clientVersions;
   delete [] m_simulatedRouteFileName;
   for ( latestNewsMap::iterator it = m_latestNews.begin() ;
         it != m_latestNews.end() ; ++it )
   {
      delete *it;
   }
   delete m_latestNewsSearch;
   delete m_categoriesData;
}

void
NavParserThreadGroup::handleDoneInterfaceRequest(
InterfaceRequest* ireply )
{
   static_cast< NavInterfaceFactory* > ( getFirstInterfaceFactory() )
      ->handleDoneInterfaceRequest( ireply );
}

ParserThreadHandle
NavParserThreadGroup::spawnThread() {
   return new NavThread( m_threadID++, this );
}

bool
NavParserThreadGroup::simulatedRouteFileName() {
   if ( m_simulatedRouteFileName != NULL ) {
      return true;
   } else {
      return false;
   }
}

void
NavParserThreadGroup::setSimulatedRouteFileName( const char *newFileName )
{
   if ( m_simulatedRouteFileName ) {
      delete [] m_simulatedRouteFileName;
   }
   if ( newFileName ) {
      m_simulatedRouteFileName = StringUtility::newStrDup( newFileName );
   } else {
      m_simulatedRouteFileName = NULL;
   }
}

bool
NavParserThreadGroup::saveRouteForSimulator( RouteRequest* rr,
                                             RouteReply* reply )
{
   if ( reply != NULL ) {
      mc2log << info << "SaveSimRoute: About to write (Nav)RouteReply "
             << "packet." << endl;
      int bufsize = 65536;
      byte buf[ bufsize ];
      if ( reply->convertToBytes( buf, bufsize ) == false ) {
         /* Failed ! */
         mc2log << error << "SaveSimRoute:  -"
                << "couldn't convert the (Nav)RouteReply to bytes" << endl;
      } else {
         int filenamelen = strlen( m_simulatedRouteFileName ) + 40;
         char* filename = new char[ filenamelen ];
         uint32 routeId = rr->getRouteID();
         uint32 routeTime = rr->getRouteCreateTime();
         sprintf( filename, "%s_routepack.%u-%u", m_simulatedRouteFileName,
                  routeTime, routeId );
         FILE* f = fopen( filename, "wb" );
         if ( f != NULL ) {
            if ( fwrite( buf, 1, reply->getLength(), f ) ==
                 reply->getLength() )
            {
               // DONE!
               mc2log << info << "SaveSimRoute: saved (Nav)RoutePacket "
                      << "as \"" << filename << "\"." << endl;
            } else {
               mc2log << error << "SaveSimRoute: -"
                      << "failed to write all (Nav)RoutePacket to "
                      << "\"" << filename << "\"." << endl;
            }

            fclose( f );
         } else {
            mc2log << error << "SaveSimRoute: -"
                   << "couldn't open \"" << filename << "\" for writing."
                   << endl;
         }

         delete [] filename;
      }
   }

   return saveMapRoute( m_simulatedRouteFileName, rr );
}

bool
NavParserThreadGroup::saveRouteForSimulator( NavReplyPacket* reply,
                                             RouteRequest *rr )
{
   if ( reply != NULL && reply->getParamBlock().getParam( 1105 ) != NULL )
   {
      // Save data to file.
      int filenamelen = strlen( m_simulatedRouteFileName ) + 40;
      char* filename = new char[ filenamelen ];
      char* filename2 = new char[ filenamelen ];
      RouteID routeID;
      const NParam* data = reply->getParamBlock().getParam( 1105 );
      bool t = true;
      if ( reply->getParamBlock().getParam( 1100 ) ) {
         routeID = RouteID( reply->getParamBlock().getParam( 1100 )
                            ->getString(t).c_str() );
      }

      sprintf( filename, "%s_nav.%u-%u", m_simulatedRouteFileName,
               routeID.getRouteIDNbr(), routeID.getCreationTime() );
      sprintf( filename2, "%s_nav", m_simulatedRouteFileName );
      mc2log << info << "SaveSimRoute: Will save data as \""
             << filename2 << "\" and \""
             << filename << "\"." << endl;
      int aflags = O_CREAT|O_TRUNC|O_WRONLY;
      int amode = S_IRWXU|S_IRGRP|S_IROTH;
      int fd = open( filename, aflags, amode );
      if ( fd < 0 ) {
         mc2log << warn << "SaveSimRoute: Error opening file: "
                << filename << " - "
                << strerror(errno) << endl;
      } else {
         int res = write( fd, data->getBuff(), data->getLength() );
         if ( res < 0 ) {
            mc2log << warn << "SaveSimRoute: Error writing to file: "
                   << filename << " - "
                   << strerror(errno) << endl;
         }
         if ( close( fd ) < 0 ) {
            mc2log << warn << "SaveSimRoute: Error closing file: "
                   << filename << " - "
                   << strerror(errno) << endl;
         }
      }

      fd = open( filename2, aflags, amode );
      if ( fd < 0 ) {
         mc2log << warn << "SaveSimRoute: Error opening file: "
                << filename2 << " - "
                << strerror(errno) << endl;
      } else {
         int res = write( fd, data->getBuff(), data->getLength() );
         if ( res < 0 ) {
            mc2log << warn << "SaveSimRoute: Error writing to file: "
                   << filename2 << " - "
                   << strerror(errno) << endl;
         }
         if ( close( fd ) < 0 ) {
            mc2log << warn << "SaveSimRoute: Error closing file: "
                   << filename2 << " - "
                   << strerror(errno) << endl;
         }
      }

      delete [] filename;
      delete [] filename2;
   } // End if have NavReply

   return saveMapRoute( m_simulatedRouteFileName, rr );
}

void
NavParserThreadGroup::setLatestNews( const char* latestNews ) {
   m_latestNewsMutex.lock();

   if ( latestNews != NULL ) {
      const ClientSettingStorage* storage = getClientSettingStorage();
      if ( storage == NULL ||
           storage->getClientSettings().empty() )
      {
         mc2log << fatal << "NavParserThreadGroup::setLatestNews "
                << "no clientSettings available. ClientSetting required. "
                << "Set clientSettings before calling setLatestNews."
                << endl;
         exit( 1 );
      }

      // client-type _ lang _ WFSubscr_t _ DaysLeft _ . ext
      //
      // client-type is the client type identificatin string.
      // lang is the iso-639-1 string for the language.
      // WFSubscr_t is the subscription type {t|s|g}.
      // DaysLeft is the number of days left, inf|0|7|14|30.
      // ext is the file type extension for the client-type, for settings.

      const char* clientType = NULL;
      const char* langStr = NULL;
      char WFSubscr_t[ 3 ] = { 't','s', 'g' };
      char WFSubscrCh = WFSubscr_t[ 0 ];
      char daysLeftStr[ 10 ];
      daysLeftStr[ 0 ] = '\0';
      const char* ext = NULL;
      char fileName[ 4096 ];
      NavLatestNewsData* latest = NULL;

      // for all client-types
      for ( ClientSettingStorage::client_setting_set::const_iterator it =
               getClientSettingStorage()->getClientSettings().begin() ;
            it != getClientSettingStorage()->getClientSettings().end() ;
            ++it )
      {
         if ( (*it)->getNoLatestNews() ) {
            continue;
         }
         // Set clientType
         clientType = (*it)->getClientType();
         // Set ext
         ext = (*it)->getImageExtension();
         bool printedError = false;

         // for all languages
         for ( uint32 lang = LangTypes::english/*0*/ ;
               lang < LangTypes::nbrLanguages; ++lang )
         {
            if ( ItemTypes::getLanguageTypeAsLanguageCode(
                    LangTypes::language_t( lang ) ) ==
                 StringTable::SMSISH_ENG )
            {
               // Not supported
               continue;
            }
            // Set langStr
            langStr = LangTypes::getLanguageAsISO639(
               LangTypes::language_t( lang ) );
            // for all WfSubscription types
            for ( uint32 wft = WFSubscriptionConstants::TRIAL/*0*/ ;
                  wft <= WFSubscriptionConstants::GOLD /*end*/ ; ++wft )
            {
               // Set WFSt
               WFSubscrCh = WFSubscr_t[ wft ];

               // for all days left
               // inf
               sprintf( fileName, "%s/%s_%s_%c_%s.%s", latestNews,
                        clientType, langStr, WFSubscrCh, "inf", ext );
//               mc2dbg << "Latest news file: " << fileName << endl;
               latest = new NavLatestNewsData(
                  fileName, clientType, LangTypes::language_t( lang ),
                  WFSubscriptionConstants::subscriptionsTypes( wft ),
                  MAX_UINT16, ext, this );
               if ( ! latest->loadFile() ) {
                  if ( !printedError ) {
                     mc2log << info << "NavParserThreadGroup::"
                            << "setLatestNews failed to load \""
                            << fileName << "\" skipping." << endl;
                     printedError = true;
                  }
                  delete latest;
               } else {
                  pair< latestNewsMap::iterator, bool > insRes =
                     m_latestNews.insert( latest );
                  if ( !insRes.second ) {
                     // Duplicate client-type or something like that
                     mc2dbg2 << "NavParserThreadGroup::"
                             << "setLatestNews duplicate \"" << fileName
                             << "\" not inserted." << endl;
                     delete latest;
                  }
               }

               // Some intervals
               for ( uint16 days = 0 ;
                     days < NavLatestNewsData::getNbrDaysLeftValues() ;
                     ++days )
               {
                  sprintf( fileName, "%s/%s_%s_%c_%u.%s", latestNews,
                           clientType, langStr, WFSubscrCh,
                           NavLatestNewsData::getDaysLeftValue( days ),
                           ext );

//                  mc2dbg << "Latest news file: " << fileName << endl;
                  latest = new NavLatestNewsData(
                     fileName, clientType, LangTypes::language_t( lang ),
                     WFSubscriptionConstants::subscriptionsTypes( wft ),
                     NavLatestNewsData::getDaysLeftValue( days ), ext,
                     this );
                  if ( ! latest->loadFile() ) {
                     if ( !printedError ) {
                        mc2log << info << "NavParserThreadGroup::"
                               << "setLatestNews failed to load \""
                               << fileName << "\" skipping." << endl;
                        printedError = true;
                     }
                     delete latest;
                  } else {
                     m_latestNews.insert( latest );
                  }
               }
            }

         }
      }
   } // End If not null argument

   m_latestNewsMutex.unlock();
}

bool
NavParserThreadGroup::getLatestNews(
   const char* clientType,
   LangTypes::language_t lang,
   WFSubscriptionConstants::subscriptionsTypes wfSubscriptionType,
   uint16 daysLeft,
   const char* imageExtension,
   byte*& latestNews,
   uint32& latestNewsLength )
{
   m_latestNewsMutex.lock();
   bool ok = true;

   daysLeft = NavLatestNewsData::getClosestDaysLeftValue( daysLeft );
   m_latestNewsSearch->setData( clientType, lang, wfSubscriptionType,
                                daysLeft, imageExtension );
   latestNewsMap::const_iterator findIt = m_latestNews.find(
      m_latestNewsSearch );
   m_latestNewsSearch->unSetData();

   if ( findIt != m_latestNews.end() ) {
      if ( !(*findIt)->recheckFile() ) {
         mc2log << warn << "NavParserThreadGroup::getLatestNews "
                << "recheckFile failed. Check \""
                << (*findIt)->getFilePatch() << "\"" << endl;
      }
      latestNews = new byte[ (*findIt)->getLastNewsLength() ];
      memcpy( latestNews, (*findIt)->getLastNews(),
              (*findIt)->getLastNewsLength() );
      latestNewsLength = (*findIt)->getLastNewsLength();
      ok = true;
   } else {
      latestNews = NULL;
      latestNewsLength = 0;
      ok = false;
   }

   m_latestNewsMutex.unlock();
   return ok;
}

bool
NavParserThreadGroup::getLatestNewsCRC(
   const char* clientType,
   LangTypes::language_t lang,
   WFSubscriptionConstants::subscriptionsTypes wfSubscriptionType,
   uint16 daysLeft,
   const char* imageExtension,
   uint32& crc )
{
   m_latestNewsMutex.lock();
   bool ok = true;

   daysLeft = NavLatestNewsData::getClosestDaysLeftValue( daysLeft );
   m_latestNewsSearch->setData( clientType, lang, wfSubscriptionType,
                                daysLeft, imageExtension );
   latestNewsMap::const_iterator findIt = m_latestNews.find(
      m_latestNewsSearch );
   m_latestNewsSearch->unSetData();

   if ( findIt != m_latestNews.end() ) {
      ok = true;
      crc = (*findIt)->getCRC();
   } else {
      crc = 0;
      ok = false;
   }

   m_latestNewsMutex.unlock();
   return ok;
}

void
NavParserThreadGroup::setAlternativeServersList(
   const char* alternativeServersList )
{
   m_alternativeServersList = alternativeServersList;
   if ( m_alternativeServersList != NULL ) {
      // Check alternativeServersList
      if ( strlen( m_alternativeServersList ) > 255 ) {
         mc2log << fatal << "NavParserThreadGroup::"
                << "setAlternativeServersList list too long "
                << strlen( m_alternativeServersList ) << " bytes max 255."
                << endl;
         exit( 1 );
      }
      m_alternativeServersListCRC = MC2CRC32::crc32(
         (byte*)m_alternativeServersList,
         strlen( m_alternativeServersList ) );

      if ( !replaceNamedServerList( NamedServerLists::DefaultGroup,
                                    NamedServerLists::NavServerShortType,
                                    m_alternativeServersList ) )
      {
         mc2log << fatal << "NavParserThreadGroup::"
                << "setAlternativeServersList list not ok " << endl;
         exit( 1 );
      }
   }
}

void
NavParserThreadGroup::setLongAlternativeServersList(
   const char* longAlternativeServersList )
{
   m_longAlternativeServersList = longAlternativeServersList;
   if ( m_longAlternativeServersList != NULL ) {
      // Check alternativeServersList
      m_longAlternativeServersListCRC = MC2CRC32::crc32(
         (byte*)m_longAlternativeServersList,
         strlen( m_longAlternativeServersList ) );

      if ( !replaceNamedServerList( NamedServerLists::DefaultGroup,
                                    NamedServerLists::NavServerType,
                                    m_longAlternativeServersList ) )
      {
         mc2log << fatal << "NavParserThreadGroup::"
                << "setLongAlternativeServersList list not ok " << endl;
         exit( 1 );
      }
   }
}

void
NavParserThreadGroup::setHttpAlternativeServersList(
   const char* httpAlternativeServersList )
{
   m_httpAlternativeServersList = httpAlternativeServersList;
   if ( m_httpAlternativeServersList != NULL ) {
      // Check alternativeServersList
      m_httpAlternativeServersListCRC = MC2CRC32::crc32(
         (byte*)m_httpAlternativeServersList,
         strlen( m_httpAlternativeServersList ) );

      if ( !replaceNamedServerList( NamedServerLists::DefaultGroup,
                                    NamedServerLists::HttpServerType,
                                    m_httpAlternativeServersList ) )
      {
        mc2log << fatal << "NavParserThreadGroup::"
                << "setHttpAlternativeServersList list not ok " << endl;
         exit( 1 );
      }
   }
}

void
NavParserThreadGroup::setCurrentVersion( const char* currentVersion ) {
   delete m_clientVersions;
   m_clientVersions = new NavClientVersionStorage();

   if ( currentVersion != NULL ) {
      // Check and add to client version list

      // A client entry:
      // Program version;Client type;Client type options;Resource version
      // Program version is majorbyte.minorbyte.minibyte like 1.1.23
      // Client type and Client type options is a string
      // Resource version is like Program version
      int pos = 0;
      int length = strlen( currentVersion );
      while ( pos < length ) {
         uint32 majorV = 0;
         uint32 minorV = 0;
         uint32 miniV = 0;
         char clientType[ 256 ];
         char clientTypeOptions[ 256 ];
         uint32 majorRV = 0;
         uint32 minorRV = 0;
         uint32 miniRV = 0;
         char remainder[ 512 ];
         uint32 elementSize = 0;
         bool dataOk = false;
         bool atEnd = false;

         if ( sscanf( currentVersion + pos,
                      "%u.%u.%u;%[^;];%[^;];%u.%u.%u" "%s",
                      &majorV, &minorV, &miniV, clientType,
                      clientTypeOptions, &majorRV, &minorRV, &miniRV,
                      remainder ) == 9 )
         {
            dataOk = true;
         } else if ( sscanf( currentVersion + pos,
                             "%u.%u.%u;%[^;];%[^;];%u.%u.%u",
                             &majorV, &minorV, &miniV, clientType,
                             clientTypeOptions, &majorRV, &minorRV,
                             &miniRV ) == 8 )
         {
            dataOk = true;
            atEnd = true;
         }

         if ( dataOk ) {
            // Add data to client version map/list
            m_clientVersions->addVersion(
               new NavClientVersion( clientType, clientTypeOptions,
                                     majorV, minorV, miniV,
                                     majorRV, minorRV, miniRV ) );

            const char* commaPos = strchr( currentVersion + pos, ',' );
            if ( commaPos != NULL ) {
               elementSize = strchr( currentVersion + pos, ',' ) -
                  (currentVersion + pos);
               pos += elementSize;
               pos++; // Skipp ','
            } else if ( atEnd ) {
               pos = length;
            } else {
              mc2log << fatal << "Client version list "
                     << "garbage after end, ',' not found! Error after "
                     << "this element: "
                     << (currentVersion + pos) << endl;
              exit( 1 );
            }
         } else {
            mc2log << fatal << "client version list "
                   << "currentVersion not valid! Error at: "
                   << (currentVersion + pos) << endl;
            exit( 1 );
         }

      }

   }
}

const NavClientVersion*
NavParserThreadGroup::getClientVersion( const char* clientType ) const {
   m_clientVersionMutex.lock();
   const NavClientVersion* cv = m_clientVersions->getVersion( clientType );
   m_clientVersionMutex.unlock();
   return cv;
}

int
NavParserThreadGroup::getTopRegionData( ParserThreadHandle thread,
                                        const UserUser* user,
                                        StringTable::languageCode lang,
                                        UserEnums::URType urmask,
                                        NParam& data )
{
   int res = 0;
   // Get a top region list.
   const TopRegionRequest* topReq = getTopRegionRequest( thread );

   // Check status of request, could be not ok return error
   if ( topReq == NULL || topReq->getStatus() != StringTable::OK ) {
      res = 1;
      if ( topReq == NULL ) {
         res = 2;
      } else if ( topReq->getStatus() == StringTable::TIMEOUT_ERROR ) {
         res = 2;
      } else if ( topReq->getStatus() ==
                  StringTable::INTERNAL_SERVER_ERROR )
      {
         res = 1;
      }
      return res;
   }

   LangTypes::language_t language =
      ItemTypes::getLanguageCodeAsLanguageType( lang );

   // Make sorted top region list
   ConstTopRegionMatchesVector sortedRegions;
   for ( uint32 i = 0 ; i < topReq->getNbrTopRegions() ; ++i ) {
      sortedRegions.push_back( topReq->getTopRegion( i ) );
   }
   // Sort the top regions
   std::sort( sortedRegions.begin(), sortedRegions.end(),
              topRegionMatchCompareLess( language ) );

   const TopRegionMatch* regionMatch = NULL;

   for ( uint32 i = 0 ; i < sortedRegions.size() ; ++i ) {
      regionMatch = sortedRegions[ i ];
      const char* regionName = regionMatch->getNames()->getBestName(
         language )->getName();
      if ( thread->checkUserRegionAccess(
              regionMatch->getID(), user, urmask ) )
      {
         data.addUint32( regionMatch->getID() );
         data.addUint32( regionMatch->getType() );
         data.addString( regionName, thread->clientUsesLatin1() );
      } // End if User has access to region
   }

   return res;
}

int
NavParserThreadGroup::getTopRegionCRC(
   ParserThreadHandle thread, const UserUser* user,
   StringTable::languageCode lang, UserEnums::URType urmask, uint32& crc )
{
   NParam data( 0 );
   int res = 0;

   res = getTopRegionData( thread, user, lang, urmask, data );
   if ( res == 0 ) {
      crc = MC2CRC32::crc32( data.getBuff(), data.getLength() );
   }

   return res;
}

const ClientSetting*
NavParserThreadGroup::getSetting( const NParamBlock& params,
                               ParserThreadHandle thread ) const
{
   MC2String clientType = "unknown";
   MC2String clientTypeOptions = "";
   if ( params.getParam( 4 ) != NULL ) {
      clientType = params.getParam( 4 )->getString(
         thread->clientUsesLatin1());
   }
   if ( params.getParam( 5 ) != NULL ) {
      clientTypeOptions = params.getParam( 5 )->getString(
         thread->clientUsesLatin1());
   }

   return getSetting( clientType.c_str(), clientTypeOptions.c_str() );
}

bool
NavParserThreadGroup::saveMapRoute( const char* fileName,
                                    RouteRequest* rr )
{
   RouteReplyPacket* rrp = NULL;
   uint32 dataLength;
   char *data;

   if ( rr != NULL && rr->getRouteReplyPacket() != NULL ) {
      rrp = const_cast< RouteReplyPacket* >( rr->getRouteReplyPacket() );
      dataLength = RouteReplyPacket::getMaxSimDataLength(rrp);

      if ( dataLength <= 0 ) {
         mc2log << warn << "NPTG::saveMapRoute: No data for simulate "
                << "route!" << endl;
         return false;
      }
      mc2log << info << "NPTG::saveMapRoute: got " << dataLength
             << " bytes of data." << endl;
      data = new char[ dataLength + 1 ];

      if ( !data ) {
         mc2log << warn << "NPTG::saveMapRoute: Failed to allocate data"
                << endl;
         return false;
      }
      mc2log << info << "NPTG::saveMapRoute: Allocated data, saving "
             << "route..." << endl;

      /* Get data for simulation. */
      RouteReplyPacket::printSimulateRouteData( rrp, data, dataLength );

      /* Save data to file. */
      int filenamelen = strlen( fileName ) + 20;
      char* idfilename = new char[ filenamelen ];
      uint32 routeId = rr->getRouteID();
      uint32 routeTime = rr->getRouteCreateTime();
      sprintf( idfilename, "%s.%u-%u", fileName,
               routeTime, routeId );
      mc2log << info << "NPTG::saveMapRoute: Will save data as \""
             << fileName << "\" and \""
             << idfilename << "\"." << endl;
      int aflags = O_CREAT|O_TRUNC|O_WRONLY;
      int amode = S_IRWXU|S_IRGRP|S_IROTH;
      int writelen = strlen( data );
      int fd = open( idfilename, aflags, amode );
      if ( fd < 0 ) {
         mc2log << warn << "NPTG::saveMapRoute: Error opening file: "
                << idfilename << " - "
                << strerror(errno) << endl;
      } else {
         int res = write( fd, data, writelen );
         if ( res < 0 ) {
            mc2log << warn << "NPTG::saveMapRoute: Error writing to file: "
                   << idfilename << " - "
                   << strerror(errno) << endl;
         }
         if ( close( fd ) < 0 ) {
            mc2log << warn << "NPTG::saveMapRoute: Error closing file: "
                   << idfilename << " - "
                   << strerror(errno) << endl;
         }
      }

      fd = open( fileName, aflags, amode );
      if ( fd < 0 ) {
         mc2log << warn << "NPTG::saveMapRoute: Error opening file: "
                << fileName << " - "
                << strerror(errno) << endl;
      } else {
         int res = write( fd, data, writelen );
         if ( res < 0 ) {
            mc2log << warn << "NPTG::saveMapRoute: Error writing to file: "
                   << fileName << " - "
                   << strerror(errno) << endl;
         }
         if (close (fd) < 0) {
            mc2log << warn << "NPTG::saveMapRoute: Error closing file: "
                   << fileName << " - "
                   << strerror(errno) << endl;
         }
      }

      delete[] idfilename;
      delete[] data;
   } // End if have route and reply

   return true;
}


text:
from .action import ApiAction
from smsapi.responses import ApiResponse

class AddAction(ApiAction):

    def set_name(self, name):
        self._data['add'] = name

    def execute(self):
        result = self.proxy.execute(self.uri, self._data)
        return ApiResponse(result)

class StatusAction(ApiAction):

    def set_name(self, name):
        self._data['status'] = name

    def execute(self):
        result = self.proxy.execute(self.uri, self._data)
        return ApiResponse(result)

class DeleteAction(ApiAction):

    def set_name(self, name):
        self._data['delete'] = name

    def execute(self):
        result = self.proxy.execute(self.uri, self._data)
        return ApiResponse(result)

class ListAction(ApiAction):

    def execute(self):
        self._data['list'] = 1

        result = self.proxy.execute(self.uri, self._data)
        return ApiResponse(result)

class SetDefaultAction(ApiAction):

    def set_name(self, name):
        self._data['default'] = name

    def execute(self):
        result = self.proxy.execute(self.uri, self._data)
        return ApiResponse(result)

redpajama_set_name: RedPajamaGithub


text:
using UnityEngine;
using System.Collections;

public class Spawner2 : MonoBehaviour {
	float spawn = 10;
	float endTime = 10;
	float Tps = 2;

	void Update () {
		if(Time.time >= endTime || Global.Choice == 1){
			GameObject Enemy = Instantiate(Resources.Load("Enem"),transform.position,transform.rotation) as GameObject;
			Global.Round++;
			endTime += Tps;
			Global.Choice = 0;
		}
	}
}


text:
<?php

/**
 * @generate-class-entries static
 * @generate-function-entries
 */

namespace MongoDB\BSON;

interface TimestampInterface
{
    /** @tentative-return-type */
    public function getTimestamp(): int;

    /** @tentative-return-type */
    public function getIncrement(): int;

    /** @tentative-return-type */
    public function __toString(): string;
}


text:
A test console app that, when run before and after the hour mark throws error

We're trying to figure out the issue with .NET and CloudFlare where a cached certificate before the turn of the hour throws a TLS error on the first subsequent call after the hour


text:
package tail

import (
	"bytes"
	"testing"
	"time"

	"github.com/influxdata/telegraf/internal"
	"github.com/stretchr/testify/assert"
)

func TestMultilineConfigOK(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        ".*",
		MatchWhichLine: Previous,
	}

	_, err := c.NewMultiline()

	assert.NoError(t, err, "Configuration was OK.")
}

func TestMultilineConfigError(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        "\xA0",
		MatchWhichLine: Previous,
	}

	_, err := c.NewMultiline()

	assert.Error(t, err, "The pattern was invalid")
}

func TestMultilineConfigTimeoutSpecified(t *testing.T) {
	duration, _ := time.ParseDuration("10s")
	c := &MultilineConfig{
		Pattern:        ".*",
		MatchWhichLine: Previous,
		Timeout:        &internal.Duration{Duration: duration},
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")

	assert.Equal(t, duration, m.config.Timeout.Duration)
}

func TestMultilineConfigDefaultTimeout(t *testing.T) {
	duration, _ := time.ParseDuration("5s")
	c := &MultilineConfig{
		Pattern:        ".*",
		MatchWhichLine: Previous,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")

	assert.Equal(t, duration, m.config.Timeout.Duration)
}

func TestMultilineIsEnabled(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        ".*",
		MatchWhichLine: Previous,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")

	isEnabled := m.IsEnabled()

	assert.True(t, isEnabled, "Should have been enabled")
}

func TestMultilineIsDisabled(t *testing.T) {
	c := &MultilineConfig{
		MatchWhichLine: Previous,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")

	isEnabled := m.IsEnabled()

	assert.False(t, isEnabled, "Should have been disabled")
}

func TestMultilineFlushEmpty(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        "^=>",
		MatchWhichLine: Previous,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")
	var buffer bytes.Buffer

	text := m.Flush(&buffer)

	assert.Empty(t, text)
}

func TestMultilineFlush(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        "^=>",
		MatchWhichLine: Previous,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")
	var buffer bytes.Buffer
	buffer.WriteString("foo")

	text := m.Flush(&buffer)

	assert.Equal(t, "foo", text)
	assert.Zero(t, buffer.Len())
}

func TestMultiLineProcessLinePrevious(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        "^=>",
		MatchWhichLine: Previous,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")
	var buffer bytes.Buffer

	text := m.ProcessLine("1", &buffer)
	assert.Empty(t, text)
	assert.NotZero(t, buffer.Len())

	text = m.ProcessLine("=>2", &buffer)
	assert.Empty(t, text)
	assert.NotZero(t, buffer.Len())

	text = m.ProcessLine("=>3", &buffer)
	assert.Empty(t, text)
	assert.NotZero(t, buffer.Len())

	text = m.ProcessLine("4", &buffer)
	assert.Equal(t, "1=>2=>3", text)
	assert.NotZero(t, buffer.Len())

	text = m.ProcessLine("5", &buffer)
	assert.Equal(t, "4", text)
	assert.Equal(t, "5", buffer.String())
}

func TestMultiLineProcessLineNext(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        "=>$",
		MatchWhichLine: Next,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")
	var buffer bytes.Buffer

	text := m.ProcessLine("1=>", &buffer)
	assert.Empty(t, text)
	assert.NotZero(t, buffer.Len())

	text = m.ProcessLine("2=>", &buffer)
	assert.Empty(t, text)
	assert.NotZero(t, buffer.Len())

	text = m.ProcessLine("3=>", &buffer)
	assert.Empty(t, text)
	assert.NotZero(t, buffer.Len())

	text = m.ProcessLine("4", &buffer)
	assert.Equal(t, "1=>2=>3=>4", text)
	assert.Zero(t, buffer.Len())

	text = m.ProcessLine("5", &buffer)
	assert.Equal(t, "5", text)
	assert.Zero(t, buffer.Len())
}

func TestMultiLineMatchStringWithInvertMatchFalse(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        "=>$",
		MatchWhichLine: Next,
		InvertMatch:    false,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")

	matches1 := m.matchString("t=>")
	matches2 := m.matchString("t")

	assert.True(t, matches1)
	assert.False(t, matches2)
}

func TestMultiLineMatchStringWithInvertTrue(t *testing.T) {
	c := &MultilineConfig{
		Pattern:        "=>$",
		MatchWhichLine: Next,
		InvertMatch:    true,
	}
	m, err := c.NewMultiline()
	assert.NoError(t, err, "Configuration was OK.")

	matches1 := m.matchString("t=>")
	matches2 := m.matchString("t")

	assert.False(t, matches1)
	assert.True(t, matches2)
}

func TestMultilineWhat(t *testing.T) {
	var w1 MultilineMatchWhichLine
	w1.UnmarshalTOML([]byte(`"previous"`))
	assert.Equal(t, Previous, w1)

	var w2 MultilineMatchWhichLine
	w2.UnmarshalTOML([]byte(`previous`))
	assert.Equal(t, Previous, w2)

	var w3 MultilineMatchWhichLine
	w3.UnmarshalTOML([]byte(`'previous'`))
	assert.Equal(t, Previous, w3)

	var w4 MultilineMatchWhichLine
	w4.UnmarshalTOML([]byte(`"next"`))
	assert.Equal(t, Next, w4)

	var w5 MultilineMatchWhichLine
	w5.UnmarshalTOML([]byte(`next`))
	assert.Equal(t, Next, w5)

	var w6 MultilineMatchWhichLine
	w6.UnmarshalTOML([]byte(`'next'`))
	assert.Equal(t, Next, w6)

	var w7 MultilineMatchWhichLine
	err := w7.UnmarshalTOML([]byte(`nope`))
	assert.Equal(t, MultilineMatchWhichLine(-1), w7)
	assert.Error(t, err)
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Grabacr07.KanColleViewer.Composition
{
	/// <summary>
	/// プラグインの主機能を [ツール] タブに表示させるためのメンバーを公開します。
	/// </summary>
	public interface IToolPlugin : IPlugin
	{
		string ToolName { get; }

		object GetToolView();
	}
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.jueb.agent</groupId>
    <artifactId>agent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <description>agent</description>
    <properties>
        <java.version>1.8</java.version>
        <skipAssembly>true</skipAssembly>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.sun</groupId>
            <artifactId>tools</artifactId>
            <version>1.8.0</version>
            <scope>system</scope>
            <systemPath>${env.JAVA_HOME}/lib/tools.jar</systemPath>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <archive>
<!--                        <manifest>-->
<!--                            <addClasspath>true</addClasspath>-->
<!--                        </manifest>-->
                        <manifestEntries>
                            <Agent-Class>JavaAgent</Agent-Class>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


text:
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace ForieroEngine.MIDIUnified.Plugins
{
	public interface IMidiDevice
	{
        bool Initialized();

        int ConnectDevice (int deviceIndex, bool editor = false);

		void DisconnectDevice (int deviceId, bool editor = false);

		void DisconnectDevices (bool editor = false);

		string GetDeviceName (int deviceIndex);

		int GetDeviceCount ();
	}

	public interface IMidiEditorDevice
	{
		int GetConnectedDeviceCount ();

		int GetConnectedDeviceId (int connectedDeviceIndex);

		string GetConnectedDeviceName (int connectedDeviceIndex);

		bool GetConnectedDeviceIsEditor (int connectedDeviceIndex);
	}

	public interface IMidiINDevice : IMidiDevice
	{
		int PopMessage (out MidiMessage midiMessage, bool editor = false);
	}

	public interface IMidiOUTDevice : IMidiDevice
	{
		int SendMessage (byte command, byte data1, byte data2, bool editor = false);

		int SendData (byte[] data, bool editor = false);
	}

	public interface ISynthPlugin
	{

	}
}


text:
namespace arc {

class AdbSideloadingAvailabilityDelegateImpl
    : public AdbSideloadingAvailabilityDelegate {
 public:
  AdbSideloadingAvailabilityDelegateImpl();

  // Not copyable or movable
  AdbSideloadingAvailabilityDelegateImpl(
      const AdbSideloadingAvailabilityDelegateImpl&) = delete;
  AdbSideloadingAvailabilityDelegateImpl& operator=(
      const AdbSideloadingAvailabilityDelegateImpl&) = delete;

  ~AdbSideloadingAvailabilityDelegateImpl() override;

  void SetProfile(Profile* profile);

  void CanChangeAdbSideloading(
      base::OnceCallback<void(bool can_change_adb_sideloading)> callback)
      override;

 private:
  // Unowned pointer. Keeps current profile.
  Profile* profile_ = nullptr;
};

}  // namespace arc

#endif  // CHROME_BROWSER_ASH_ARC_SESSION_ADB_SIDELOADING_AVAILABILITY_DELEGATE_IMPL_H_


text:
'use strict';

/**
 * @ngdoc function
 * @name amApp.controller:DefinitionTabsCtrl
 * @description
 * # DefinitionTabsCtrl
 * Controller of the amApp
 */
angular.module('amApp')
    .controller('DefinitionTabsCtrl', function ($scope, Definition, definition) {

        $scope.definition = definition;

        $scope.definition.properties.forEach(function(property, index){
            if(property.$ref !== null && typeof property.$ref !== 'object'){
                Definition.one(property.$ref).get().then(function(data){
                    $scope.definition.properties[index].$ref = data;
                });
            }
        });

        $scope.tabData   = [
            {
                heading: 'Details',
                route: 'definition.tab.detail'
            },
            {
                heading: 'Properties',
                route: 'definition.tab.properties'
            },
            {
                heading: 'Sample',
                route: 'definition.tab.sample'
            },
            {
                heading: 'Resources',
                route: 'definition.tab.resources'
            }
        ];
    });


text:
int main(int, char**) noexcept
{
    gorc::std_output_stream os;

    std::string str = "Hello, World!\n";
    os.write(str.data(), str.size());

    return 0;
}


text:
namespace CocosSharp
{
    /// <summary>
    /// @brief CCTransitionFadeUp:
    /// Fade the tiles of the outgoing scene from the bottom to the top.
    /// </summary>
    public class CCTransitionFadeUp : CCTransitionFadeTR
    {
        protected override CCFiniteTimeAction CreateAction(CCGridSize size)
        {
            return new CCFadeOutUpTiles(Duration, size);
        }

        #region Constructors

        public CCTransitionFadeUp(float t, CCScene scene) : base(t, scene)
        {
        }

        #endregion Constructors
    }
}


text:
<?php

// No direct access
defined('_HZEXEC_') or die();

/**
 * Tags plugin class for publications
 */
class plgTagsPublications extends \Hubzero\Plugin\Plugin
{
	/**
	 * Affects constructor behavior. If true, language files will be loaded automatically.
	 *
	 * @var  boolean
	 */
	protected $_autoloadLanguage = true;

	/**
	 * Constructor
	 *
	 * @param   object  &$subject  The object to observe
	 * @param   array   $config    An optional associative array of configuration settings.
	 * @return  void
	 */
	public function __construct(&$subject, $config)
	{
		parent::__construct($subject, $config);

		include_once Component::path('com_publications') . DS . 'tables' . DS . 'category.php';
		include_once Component::path('com_publications') . DS . 'tables' . DS . 'publication.php';
	}

	/**
	 * Retrieve records for items tagged with specific tags
	 *
	 * @param   array    $tags        Tags to match records against
	 * @param   mixed    $limit       SQL record limit
	 * @param   integer  $limitstart  SQL record limit start
	 * @param   string   $sort        The field to sort records by
	 * @param   mixed    $areas       An array or string of areas that should retrieve records
	 * @return  mixed    Returns integer when counting records, array when retrieving records
	 */
	public function onTagView($tags, $limit=0, $limitstart=0, $sort='', $areas=null)
	{
		$response = array(
			'name'     => $this->_name,
			'title'    => Lang::txt('PLG_TAGS_PUBLICATIONS'),
			'total'    => 0,
			'results'  => null,
			'sql'      => '',
			'children' => array()
		);

		$database = App::get('db');
		$rt = new \Components\Publications\Tables\Category($database);
		foreach ($rt->getCategories() as $category)
		{
			$response['children'][$category->url_alias] = array(
				'name'     => $category->url_alias,
				'title'    => $category->name,
				'total'    => 0,
				'results'  => null,
				'sql'      => '',
				'id'       => $category->id
			);
		}

		if (empty($tags))
		{
			return $response;
		}

		$ids = array();
		foreach ($tags as $tag)
		{
			$ids[] = $tag->get('id');
		}

		// Instantiate some needed objects
		$rr = new \Components\Publications\Tables\Publication($database);

		// Build query
		$filters = array();
		$filters['tags'] = $ids;
		$filters['now'] = Date::toSql();
		$filters['sortby'] = ($sort) ? $sort : 'ranking';
		$filters['authorized'] = false;

		$filters['usergroups'] = \Hubzero\User\Helper::getGroups((int)User::get('id', 0), 'all');

		$filters['select'] = 'count';

		foreach ($response['children'] as $k => $t)
		{
			$filters['category'] = $t['id'];

			// Execute a count query for each area/category
			$database->setQuery($this->_buildPluginQuery($filters));
			$response['children'][$k]['total'] = $database->loadResult();
			$response['total'] += $response['children'][$k]['total'];
		}

		if ($areas && ($areas == $response['name'] || isset($response['children'][$areas])))
		{
			$filters['select']     = 'records';
			$filters['limit']      = $limit;
			$filters['limitstart'] = $limitstart;
			$filters['sortby']     = ($sort) ? $sort : 'date';

			// Check the area of return. If we are returning results for a specific area/category
			// we'll need to modify the query a bit
			if (isset($response['children'][$areas]))
			{
				$filters['category'] = $response['children'][$areas]['id'];

				$database->setQuery($this->_buildPluginQuery($filters));
				$response['children'][$areas]['results'] = $database->loadObjectList();
			}
			else
			{
				unset($filters['category']);

				$database->setQuery($this->_buildPluginQuery($filters));
				$response['results'] = $database->loadObjectList();
			}
		}
		else
		{
			$filters['select']     = 'records';
			$filters['limit']      = 'all';
			$filters['limitstart'] = $limitstart;
			$filters['sortby']     = ($sort) ? $sort : 'date';

			// Check the area of return. If we are returning results for a specific area/category
			// we'll need to modify the query a bit
			if (isset($response['children'][$areas]))
			{
				$filters['category'] = $response['children'][$areas]['id'];

				$response['children'][$key]['sql'] = $this->_buildPluginQuery($filters);
			}
			else
			{
				unset($filters['category']);
				$response['sql'] = $this->_buildPluginQuery($filters);
			}
		}

		return $response;
	}

	/**
	 * Build a database query
	 *
	 * @param   array   $filters  Options for building the query
	 * @return  string  SQL
	 */
	private function _buildPluginQuery($filters=array())
	{
		$database = App::get('db');

		include_once \Component::path('com_publications') . DS . 'tables' . DS . 'category.php';
		$rt = new \Components\Publications\Tables\Category($database);

		if (isset($filters['select']) && $filters['select'] == 'count')
		{
			if (isset($filters['tags']))
			{
				$query = "SELECT count(f.id) FROM (SELECT r.id, COUNT(DISTINCT t.tagid) AS uniques ";
			}
			else
			{
				$query = "SELECT count(DISTINCT r.id) ";
			}
		}
		else
		{
			$query = "SELECT DISTINCT r.id, V.title, V.version_number as alias,
					V.abstract as itext, V.id as ftext, V.state AS state, V.created, V.created_by,
					V.modified, V.published_up as publish_up, V.published_down as publish_down,
					CONCAT('index.php?option=com_publications&id=', r.id) AS href, 'publications' AS section ";
			if (isset($filters['tags']))
			{
				$query .= ", COUNT(DISTINCT t.tagid) AS uniques ";
			}
			$query .= ", V.params, r.rating AS rcount, r.category AS data1, rt.name AS data2, r.ranking data3 ";
		}
		$query .= "FROM #__publication_versions as V, #__publications AS r ";
		$query .= "LEFT JOIN " . $rt->getTableName() . " AS rt ON r.category=rt.id";
		if (isset($filters['tag']))
		{
			$query .= ", #__tags_object AS t, #__tags AS tg ";
		}
		if (isset($filters['tags']))
		{
			$query .= ", #__tags_object AS t ";
		}
		$query .= "WHERE V.publication_id=r.id AND V.state=1 AND V.main = 1 ";
		if (isset($filters['tag']))
		{
			$query .= "AND t.objectid=r.id AND t.tbl='publications' AND t.tagid=tg.id AND (tg.tag='" . $filters['tag'] . "' OR tg.alias='" . $filters['tag'] . "') ";
		}
		if (isset($filters['tags']))
		{
			$ids = implode(',', $filters['tags']);
			$query .= "AND t.objectid=r.id AND t.tbl='publications' AND t.tagid IN (" . $ids . ") ";
		}
		if (isset($filters['category']) && $filters['category'] != '') {
			$query .= "AND r.category=" . $filters['category'] . " ";
		}

		if (isset($filters['tags']))
		{
			$query .= " GROUP BY r.id, V.id, V.version_number, V.title, V.abstract HAVING uniques=" . count($filters['tags']) . " ";
		}
		if (isset($filters['select']) && $filters['select'] != 'count')
		{
			if (isset($filters['sortby']))
			{
				if (isset($filters['groupby']))
				{
					$query .= "GROUP BY r.id ";
				}
				$query .= "ORDER BY ";
				switch ($filters['sortby'])
				{
					case 'title':
						$query .= 'title ASC, publish_up DESC';
						break;
					case 'rating':
						$query .= "rating DESC, times_rated DESC";
						break;
					case 'ranking':
						$query .= "ranking DESC";
						break;
					case 'relevance':
						$query .= "relevance DESC";
						break;
					case 'users':
					case 'usage':
						$query .= "users DESC";
						break;
					case 'jobs':
						$query .= "jobs DESC";
						break;
					case 'date':
					default:
						$query .= 'publish_up DESC';
						break;
				}
			}
			if (isset($filters['limit']) && $filters['limit'] != 'all')
			{
				$query .= " LIMIT " . $filters['limitstart'] . "," . $filters['limit'];
			}
		}
		if (isset($filters['select']) && $filters['select'] == 'count')
		{
			if (isset($filters['tags']))
			{
				$query .= ") AS f";
			}
		}

		return $query;
	}

	/**
	 * Static method for formatting results
	 *
	 * @param   object  $row  Database row
	 * @return  string  HTML
	 */
	public static function out($row)
	{
		include_once Component::path('com_publications') . DS . 'tables' . DS . 'author.php';
		require_once Component::path('com_publications') . DS . 'helpers' . DS . 'html.php';

		$row->href = Route::url('index.php?option=com_publications&id=' . $row->id);

		$database = App::get('db');

		// Get version authors
		$pa = new \Components\Publications\Tables\Author($database);
		$authors = $pa->getAuthors($row->ftext);

		// Get the component params
		$config = Component::params('com_publications');

		$row->rating   = $row->rcount;
		$row->category = $row->data1;
		$row->area     = $row->data2;
		$row->ranking  = $row->data3;

		// Set the display date
		switch ($config->get('show_date'))
		{
			case 0:
				$thedate = '';
				break;
			case 1:
				$thedate = Date::of($row->created)->toLocal(Lang::txt('DATE_FORMAT_HZ1'));
				break;
			case 2:
				$thedate = Date::of($row->modified)->toLocal(Lang::txt('DATE_FORMAT_HZ1'));
				break;
			case 3:
				$thedate = Date::of($row->publish_up)->toLocal(Lang::txt('DATE_FORMAT_HZ1'));
				break;
		}

		if (strstr($row->href, 'index.php'))
		{
			$row->href = Route::url($row->href);
		}

		// Start building the HTML
		$html  = "\t".'
' . "\n";
		$html .= "\t\t" . '
href . '/?v=' . $row->alias . '">'
			. stripslashes($row->title) . '
' . "\n";

		$html .= "\t\t" . '
' . $thedate . ' | ' . $row->area;
		if ($authors)
		{
			$html .= ' | ' . Lang::txt('PLG_TAGS_PUBLICATIONS_CONTRIBUTORS') . ' ' . stripslashes(\Components\Publications\Helpers\Html::showContributors($authors, true, false));
		}
		$html .= '
' . "\n";
		if ($row->itext)
		{
			$html .= "\t\t" . '
' . \Hubzero\Utility\Str::truncate(\Hubzero\Utility\Sanitize::stripAll(stripslashes($row->itext)), 200) . '
' . "\n";
		}

		$html .= "\t\t" . '
' . Request::base() . trim($row->href . '/?v=' . $row->alias, '/') . '
' . "\n";
		$html .= "\t" . '
'."\n";

		// Return output
		return $html;
	}
}


text:
import HTML5Video from 'clappr'
import shaka from 'shaka-player'

export default class DashShaka extends HTML5Video {
  constructor(options) {
    super(options)
    this.setup()
  }

  setup() {
    shaka.polyfill.installAll()

    this.player = new shaka.player.Player(this.el)
    this.player.load(new shaka.player.DashVideoSource(this.options.src))
  }
}

DashShaka.canPlay = function(resource, mimeType) {
  var resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || []
  return "mpd" === resourceParts[1]
}


text:
/**
 * Created by mattbaker on 12/7/13.
 */

var GeoJSON = (function(){

    var earthquakes = [];

    return {
        loadEarthquakeData: function(time, magnitude){
            var url = 'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/'+time+'_'+magnitude+'.geojsonp';
            $.ajax({
                url:url,
                crossDomain:true,
                dataType: 'jsonp',
                jsonp: false,
                cache:true,
                jsonpCallback: 'eqfeed_callback',
                beforeSend: function(){
                    $(document).trigger('getEarthquakeData_start', { message: 'Getting data from USGS ('+url+')' });
                },
                error: function(j,status,error){
                    $(document).trigger('getEarthquakeData_error', { message: 'Error data from USGS: '+error });
                },
                success: function(data,status,xhr){
                    var featuresArray = data.features;
                    for (var i= 0, l=featuresArray.length; i<l;i++){
                      earthquakes.push({
                          lng:featuresArray[i].geometry.coordinates[0],
                          lat:featuresArray[i].geometry.coordinates[1],
                          depth:featuresArray[i].geometry.coordinates[2],
                          magnitude:featuresArray[i].properties.mag,
                          title:featuresArray[i].properties.place
                      });
                    }
                    $(document).trigger('getEarthquakeData_success', { message: 'Earthquake data received successfully.', earthquakes:earthquakes });
                }
            });
        }
    };

})();


text:
package com.vmware.vim25;

/**
@author Steve Jin (sjin@vmware.com)
*/

public class ArrayOfKeyValue
{
  public KeyValue[] KeyValue;

  public KeyValue[] getKeyValue()
  {
    return this.KeyValue;
  }

  public KeyValue getKeyValue(int i)
  {
    return this.KeyValue[i];
  }

  public void setKeyValue(KeyValue[] KeyValue)
  {
    this.KeyValue=KeyValue;
  }
}


text:
<?xml version="1.0"?>
<package>
  <name>rsv_balance_rqt</name>
  <version>0.0.1</version>
  <description>RQT interface for setting operation mode of the balance platform.</description>

  <maintainer email="vmatos@robosavvy.com">Vitor Matos</maintainer>
  <license>BSD</license>
  <url type="website">http://wiki.ros.org/Robots/RoboSavvyBalance</url>
  <url type="repository">https://github.com/robosavvy/rsv_balance_desktop</url>
  <author email="vmatos@robosavvy.com">Vitor Matos</author>

  <buildtool_depend>catkin</buildtool_depend>

  <build_depend>rsv_balance_msgs</build_depend>
  <build_depend>roslint</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>rqt_gui</build_depend>
  <build_depend>rqt_gui_py</build_depend>

  <run_depend>rsv_balance_msgs</run_depend>
  <run_depend>python-rospkg</run_depend>
  <run_depend>rospy</run_depend>
  <run_depend>rqt_gui</run_depend>
  <run_depend>rqt_gui_py</run_depend>
  <run_depend>rqt_py_common</run_depend>
  <run_depend>rosservice</run_depend>

  <export>
    <rqt_gui plugin="${prefix}/plugin.xml"/>
  </export>
</package>


text:
package com.allanbank.mongodb.client.state;

import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import com.allanbank.mongodb.MongoClientConfiguration;
import com.allanbank.mongodb.MongoDbException;
import com.allanbank.mongodb.client.ClusterType;
import com.allanbank.mongodb.client.connection.Connection;
import com.allanbank.mongodb.client.connection.proxy.ProxiedConnectionFactory;
import com.allanbank.mongodb.client.message.IsMaster;
import com.allanbank.mongodb.client.message.ReplicaSetStatus;
import com.allanbank.mongodb.client.message.Reply;
import com.allanbank.mongodb.util.IOUtils;
import com.allanbank.mongodb.util.log.Log;
import com.allanbank.mongodb.util.log.LogFactory;

/**
 * ClusterPinger pings each of the connections in the cluster and updates the
 * latency of the server from this client.
 *
 * @api.no This class is NOT part of the drivers API. This class may be
 *         mutated in incompatible ways between any two releases of the driver.
 * @copyright 2012-2014, Allanbank Consulting, Inc., All Rights Reserved
 */
public class ClusterPinger
        implements Runnable, Closeable {

    /** The default interval between ping sweeps in seconds. */
    public static final int DEFAULT_PING_INTERVAL_SECONDS = 600;

    /** The logger for the {@link ClusterPinger}. */
    protected static final Log LOG = LogFactory.getLog(ClusterPinger.class);

    /**
     * The logger for the metrics:
     * {@value MongoClientConfiguration#METRICS_LOGGER_NAME}.
     */
    protected static final Log METRICS_LOG = LogFactory
            .getLog(MongoClientConfiguration.METRICS_LOGGER_NAME);

    /** Instance of the inner class containing the ping logic. */
    private static final Pinger PINGER = new Pinger();

    /**
     * Pings the server and suppresses all exceptions.
     *
     * @param server
     *            The address of the server. Used for logging.
     * @param conn
     *            The connection to ping.
     * @return True if the ping worked, false otherwise.
     */
    public static boolean ping(final Server server, final Connection conn) {
        return PINGER.ping(server, conn);
    }

    /** The state of the clusters. */
    private final List<Cluster> myClusters;

    /** The configuration for the connections. */
    private final MongoClientConfiguration myConfig;

    /** The factory for creating connections to the servers. */
    private final ProxiedConnectionFactory myConnectionFactory;

    /** The units for the ping sweep intervals. */
    private volatile TimeUnit myIntervalUnits;

    /** The interval for a ping sweep across all of the servers. */
    private volatile int myPingSweepInterval;

    /** The thread that is pinging the servers for latency. */
    private final Thread myPingThread;

    /** The flag to stop the ping thread. */
    private volatile boolean myRunning;

    /**
     * Creates a new ClusterPinger.
     *
     * @param cluster
     *            The state of the cluster.
     * @param factory
     *            The factory for creating connections to the servers.
     * @param config
     *            The configuration for the connections.
     */
    public ClusterPinger(final Cluster cluster,
            final ProxiedConnectionFactory factory,
            final MongoClientConfiguration config) {
        super();

        myConnectionFactory = factory;
        myConfig = config;
        myRunning = true;

        myClusters = new CopyOnWriteArrayList<Cluster>();
        myClusters.add(cluster);

        myIntervalUnits = TimeUnit.SECONDS;
        myPingSweepInterval = DEFAULT_PING_INTERVAL_SECONDS;

        myPingThread = myConfig.getThreadFactory().newThread(this);
        myPingThread.setDaemon(true);
        myPingThread.setName("MongoDB Pinger");
        myPingThread.setPriority(Thread.MIN_PRIORITY);
    }

    /**
     * Adds a new cluster to the set of tracked clusters.
     *
     * @param cluster
     *            A new cluster to the set of tracked clusters.
     */
    public void addCluster(final Cluster cluster) {
        myClusters.add(cluster);
    }

    /**
     * {@inheritDoc}
     *

     * Overridden to close the pinger.
     *

     */
    @Override
    public void close() {
        myRunning = false;
        myPingThread.interrupt();

        // Log the final metrics.
        logMetrics();
    }

    /**
     * Returns the units for the ping sweep intervals.
     *
     * @return The units for the ping sweep intervals.
     */
    public TimeUnit getIntervalUnits() {
        return myIntervalUnits;
    }

    /**
     * Returns the interval for a ping sweep across all of the servers..
     *
     * @return The interval for a ping sweep across all of the servers..
     */
    public int getPingSweepInterval() {
        return myPingSweepInterval;
    }

    /**
     * Performs a single sweep through the servers sending a ping with a
     * callback to set the latency and tags for each server.
     *

     * This method will not return until at least 50% of the servers have
     * replied (which may be a failure) to the initial ping.
     *

     *
     * @param cluster
     *            The cluster of servers to ping.
     */
    public void initialSweep(final Cluster cluster) {
        final List<Server> servers = cluster.getServers();
        final List<Future<Reply>> replies = new ArrayList<Future<Reply>>(
                servers.size());
        final List<Connection> connections = new ArrayList<Connection>(
                servers.size());
        try {
            for (final Server server : servers) {
                // Ping the current server.
                final String name = server.getCanonicalName();
                Connection conn = null;
                try {
                    conn = myConnectionFactory.connect(server, myConfig);

                    // Use a isMaster request to measure latency. It is
                    // a best case since it does not require any locks.
                    final Future<Reply> reply = PINGER.pingAsync(
                            cluster.getType(), server, conn);
                    replies.add(reply);
                }
                catch (final IOException e) {
                    LOG.info("Could not ping '{}': {}", name, e.getMessage());
                }
                finally {
                    if (conn != null) {
                        connections.add(conn);
                        conn.shutdown(false);
                    }
                }
            }

            long now = System.currentTimeMillis();
            final long deadline = now
                    + Math.max(5000, myConfig.getConnectTimeout());
            while ((now < deadline) && !replies.isEmpty()) {
                final Iterator<Future<Reply>> iter = replies.iterator();
                while (iter.hasNext() && (now < deadline)) {
                    Future<Reply> future = iter.next();
                    try {
                        if (future != null) {
                            // Pause...
                            future.get(deadline - now, TimeUnit.MILLISECONDS);
                        }

                        // A good reply or we could not connect to the server.
                        iter.remove();
                    }
                    catch (final ExecutionException e) {
                        // We got a reply. Its a failure but its a reply.
                        iter.remove();
                    }
                    catch (final TimeoutException e) {
                        // No reply yet.
                        future = null;
                    }
                    catch (final InterruptedException e) {
                        // No reply yet.
                        future = null;
                    }

                    now = System.currentTimeMillis();
                }
            }
        }
        finally {
            for (final Connection conn : connections) {
                IOUtils.close(conn);
            }
        }
    }

    /**
     * {@inheritDoc}
     *

     * Overridden to periodically wake-up and ping the servers. At first this
     * will occur fairly often but eventually degrade to once every 5 minutes.
     *

     */
    @Override
    public void run() {
        while (myRunning) {
            try {
                final Map<Server, ClusterType> servers = extractAllServers();

                final long interval = getIntervalUnits().toMillis(
                        getPingSweepInterval());
                final long perServerSleep = servers.isEmpty() ? interval
                        : interval / servers.size();

                // Sleep a little before starting. We do it first to give
                // tests time to finish without a sweep in the middle
                // causing confusion and delay.
                Thread.sleep(TimeUnit.MILLISECONDS.toMillis(perServerSleep));

                startSweep();
                logMetrics();

                for (final Map.Entry<Server, ClusterType> entry : servers
                        .entrySet()) {
                    // Ping the current server.
                    final Server server = entry.getKey();
                    final String name = server.getCanonicalName();
                    Connection conn = null;
                    try {
                        myPingThread.setName("MongoDB Pinger - " + name);

                        conn = myConnectionFactory.connect(server, myConfig);

                        PINGER.pingAsync(entry.getValue(), server, conn);

                        // Sleep a little between the servers.
                        Thread.sleep(TimeUnit.MILLISECONDS
                                .toMillis(perServerSleep));
                    }
                    catch (final IOException e) {
                        LOG.info("Could not ping '{}': {}", name,
                                e.getMessage());
                    }
                    finally {
                        myPingThread.setName("MongoDB Pinger - Idle");
                        if (conn != null) {
                            conn.shutdown(true);
                        }
                    }

                }
            }
            catch (final InterruptedException ok) {
                LOG.debug("Pinger interrupted.");
            }
        }
    }

    /**
     * Sets the value of units for the ping sweep intervals.
     *
     * @param intervalUnits
     *            The new value for the units for the ping sweep intervals.
     */
    public void setIntervalUnits(final TimeUnit intervalUnits) {
        myIntervalUnits = intervalUnits;
    }

    /**
     * Sets the interval for a ping sweep across all of the servers..
     *
     * @param pingSweepInterval
     *            The new value for the interval for a ping sweep across all of
     *            the servers..
     */
    public void setPingSweepInterval(final int pingSweepInterval) {
        myPingSweepInterval = pingSweepInterval;
    }

    /**
     * Starts the background pinger.
     */
    public void start() {
        myPingThread.start();
    }

    /**
     * Stops the background pinger. Equivalent to {@link #close()}.
     */
    public void stop() {
        close();
    }

    /**
     * Starts the background pinger.
     */
    public void wakeUp() {
        myPingThread.interrupt();
    }

    /**
     * Extension point to notify derived classes that a new sweep is starting.
     */
    protected void startSweep() {
        // Nothing.
    }

    /**
     * Extracts the complete list of servers in all clusters.
     *
     * @return The complete list of servers across all clusters.
     */
    private Map<Server, ClusterType> extractAllServers() {
        final Map<Server, ClusterType> servers = new HashMap<Server, ClusterType>();

        for (final Cluster cluster : myClusters) {
            for (final Server server : cluster.getServers()) {
                servers.put(server, cluster.getType());
            }
        }

        return Collections.unmodifiableMap(servers);
    }

    /**
     * Logs the current metrics.
     */
    private void logMetrics() {
        // Log the metrics.
        final java.util.logging.Level level = java.util.logging.Level
                .parse(String.valueOf(myConfig.getMetricsLogLevel()));
        if (METRICS_LOG.isEnabled(level)) {
            METRICS_LOG.log(level, "{}", myConnectionFactory.getMetrics());
        }
    }

    /**
     * Pinger provides logic to ping servers.
     *
     * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
     */
    protected static final class Pinger {
        /**
         * Pings the server and suppresses all exceptions. Updates the server
         * state with a latency and the tags found in the response, if any.
         *
         * @param server
         *            The server to update with the results of the ping. If
         *            false is returned then the state will not
         *            have been updated. Passing null for the state
         *            is allowed.
         * @param conn
         *            The connection to ping.
         * @return True if the ping worked, false otherwise.
         */
        public boolean ping(final Server server, final Connection conn) {
            try {
                final Future<Reply> future = pingAsync(ClusterType.STAND_ALONE,
                        server, conn);

                // Wait for the reply.
                if (future != null) {
                    future.get(1, TimeUnit.MINUTES);

                    return true;
                }
            }
            catch (final ExecutionException e) {
                LOG.info(e, "Could not ping '{}': {}",
                        server.getCanonicalName(), e.getMessage());
            }
            catch (final TimeoutException e) {
                LOG.info(e, "'{}' might be a zombie - not receiving "
                        + "a response to ping: {}", server.getCanonicalName(),
                        e.getMessage());
            }
            catch (final InterruptedException e) {
                LOG.info(e, "Interrupted pinging '{}': {}",
                        server.getCanonicalName(), e.getMessage());
            }

            return false;
        }

        /**
         * Pings the server and suppresses all exceptions. Returns a future that
         * can be used to determine if a response has been received. The future
         * will update the {@link Server} latency and tags if found.
         *
         * @param type
         *            The type of cluster to ping.
         * @param server
         *            The server to update with the results of the ping. If
         *            false is returned then the state will not
         *            have been updated. Passing null for the state
         *            is allowed.
         * @param conn
         *            The connection to ping.
         * @return A {@link Future} that will be updated once the reply is
         *         received.
         */
        public Future<Reply> pingAsync(final ClusterType type,
                final Server server, final Connection conn) {
            try {
                final ServerUpdateCallback future = new ServerUpdateCallback(
                        server);

                conn.send(new IsMaster(), future);
                if (type == ClusterType.REPLICA_SET) {
                    conn.send(new ReplicaSetStatus(), new ServerUpdateCallback(
                            server));
                }

                return future;
            }
            catch (final MongoDbException e) {
                LOG.info("Could not ping '{}': {}", server, e.getMessage());
            }
            return null;
        }
    }
}


text:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
//import java.awt.event.ActionEvent;
//import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
//import java.awt.event.KeyListener;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.*;
import java.util.ArrayList;

/*
 * Classe Avatar
 * Representa o Personagem controlado pelo jogador.
 *
 *
 * */
public class Avatar extends JPanel{

	//Imagem base para retirar os quadros na animação do personagem
	private BufferedImage img;

	//Arraylist de imagens isoladas para as animações
	private ArrayList<BufferedImage> sprites;

	//Objeto que anima imagens alocadas no ArrayList sprites
	private Animator animator;

	//Estados so avatar
	private boolean upKey, downKey, leftKey, rightKey, idle = false;

	//Informações para organizar as animações
	private int spriteRow = 0;
	private int startSpriteAnim = 0;
	private int stopSpriteAnim = 0;

	/*
	 	x =  Posição do boneco em X
	 	y =  Posição do boneco em y
	 	vx = Deslocamento do boneco em x
	 	vy = Deslocamento do boneco em y
	*/
	private static int x = 0,y = 0, vx = 0, vy = 0;

	//Referência para o objeto "pai" do Avatar
	private TelaGamePlay tgp;

	//Construtor
	public Avatar(TelaGamePlay t){
		this.tgp = t;

		//Montando os Sprites
		// Carregando a imagem base
		try{
			this.img = this.tgp.loader.loadImage("images/sprite_5.png");
		}catch(IOException ex){
			System.out.println("Erro carregando Sprite Avatar");
		}

		this.sprites = new ArrayList<BufferedImage>();

		//Isolando os sprites
		SpriteSheet sprite = new SpriteSheet(this.img);
		for(int y=0 ; y<8 ; y++){
			for( int x=0 ; x<4 ; x++){
				this.sprites.add( sprite.grabSprite( 64*x, 64*y, 64, 64 ) );
			}
		}

		//Instanciando/configurando o Animator
		this.animator = new Animator(this.sprites);
		this.animator.setSpeed(75);
		this.animator.play();
	}

	public void paint(Graphics g){
		//desenhando o boneco
		super.paint(g);
		g.drawImage(this.animator.sprite, x, y, 64, 64, null);
	}

	public void update(){
		//Atualiza o avatar
		this.updateMovement();

		//Atualiza o quadro da animação do Avatar
		this.animator.updateWithConstraint(System.currentTimeMillis(), this.startSpriteAnim , this.stopSpriteAnim);
	}

	//bloqueia a movimentação do Avatar
	//	Chamado quando o jogo termina
	public void noMotion(){
		this.upKey = false;
		this.downKey = false;
		this.leftKey = false;
		this.rightKey = false;
		this.idle = false;

	}

	public void keyPressed(KeyEvent e){
		//Através dos eventos dos teclados alteramos os estados possíveis do Avatar
		int tecla = e.getKeyCode();

		if(tecla == KeyEvent.VK_LEFT){
			this.leftKey = true;
		}
		if(tecla == KeyEvent.VK_RIGHT){
			this.rightKey = true;
		}
		if(tecla == KeyEvent.VK_UP){
			this.upKey = true;
		}
		if(tecla == KeyEvent.VK_DOWN){
			this.downKey = true;
		}
	}

	public void keyReleased(KeyEvent e){
		int tecla = e.getKeyCode();

		if(tecla == KeyEvent.VK_LEFT){
			this.leftKey = false;
		}
		if(tecla == KeyEvent.VK_RIGHT){
			this.rightKey = false;
		}
		if(tecla == KeyEvent.VK_UP){
			this.upKey = false;
		}
		if(tecla == KeyEvent.VK_DOWN){
			this.downKey = false;
		}
	}

	private void updateMovement(){
		//A cada estado do Avatar mudamos:
		// 1 - os valores do deslocamento
		if(this.upKey){
			this.vy = -1;
		}
		else if(this.downKey){
			this.vy = 1;
		}
		else{
			this.vy = 0;
		}

		if(this.leftKey){
			this.vx = -1;
		}
		else if(this.rightKey){
			this.vx = 1;
		}
		else{
			this.vx = 0;
		}

		// 2 - A "linha" da sequencia de imagens que faz a animação, de acordo com o a direçnao do deslocamento do Avatar
		if( this.upKey && this.leftKey ){
			this.spriteRow = 6;
		}
		else if( this.upKey && this.rightKey ){
			this.spriteRow = 7;
		}
		else if( this.downKey && this.leftKey ){
			this.spriteRow = 5;
		}
		else if( this.downKey && this.rightKey ){
			this.spriteRow = 4;
		}
		else if(this.upKey)		this.spriteRow = 3;
		else if(this.downKey)	this.spriteRow = 0;
		else if(this.leftKey)	this.spriteRow = 1;
		else if(this.rightKey)	this.spriteRow = 2;

		// 3 - Atualização das informações para o Animator
		if( !this.upKey   &&
			!this.downKey &&
			!this.leftKey &&
			!this.rightKey ){
			this.startSpriteAnim = this.spriteRow*4;
			this.stopSpriteAnim = this.spriteRow*4;

			this.animator.setStart(this.spriteRow*4);
			this.animator.setStop(this.spriteRow*4);
			}
		else{
			this.startSpriteAnim = this.spriteRow*4;
			this.stopSpriteAnim = this.spriteRow*4+3;

			this.animator.setStart(this.spriteRow*4);
			this.animator.setStop(this.spriteRow*4+3);
		}

		// 4 - Atualização da posição do Avatar
		this.x += this.vx;
		this.y += this.vy;

		// 5 - Limites de deslocamento do Avatar
		if( this.x < 0) this.x = 0;
		else if( this.x+64 > TelaGamePlay.WIDTH ) this.x = TelaGamePlay.WIDTH-64;

		if(this.y < 0)this.y = 0;
		else if(this.y+64 > TelaGamePlay.HEIGHT) this.y = TelaGamePlay.HEIGHT-64;

	}

	//coordenadas x e y do avatar
	public int getX(){
		return x;
	}
	public int getY(){
		return y;
	}

}


text:
import { Iterable, Iterator } from '../Iterable';
import { Mapper } from '../Sequence';
export declare class MappingIterable<T, R> implements Iterable<R> {
    private source;
    private mapper;
    constructor(source: Iterable<T>, mapper: Mapper<T, R>);
    iterate(): Iterator<R>;
}


text:
The MIT License (MIT)

Copyright (C) 2013-2015 David McCuskey. All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

--]]

--====================================================================--
--== DMC Corona Library : DMC Kozy
--====================================================================--

-- Semantic Versioning Specification: http://semver.org/

local VERSION = "1.0.1"

--====================================================================--
--== DMC Corona Library Config
--====================================================================--

--====================================================================--
--== Support Functions

local Utils = {} -- make copying from lua_utils easier

function Utils.extend( fromTable, toTable )

	function _extend( fT, tT )

		for k,v in pairs( fT ) do

			if type( fT[ k ] ) == "table" and
				type( tT[ k ] ) == "table" then

				tT[ k ] = _extend( fT[ k ], tT[ k ] )

			elseif type( fT[ k ] ) == "table" then
				tT[ k ] = _extend( fT[ k ], {} )

			else
				tT[ k ] = v
			end
		end

		return tT
	end

	return _extend( fromTable, toTable )
end

--====================================================================--
--== Configuration

local dmc_lib_data, dmc_lib_info

-- boot dmc_corona with boot script or
-- setup basic defaults if it doesn't exist
--
if false == pcall( function() require( 'dmc_corona_boot' ) end ) then
	_G.__dmc_corona = {
		dmc_corona={},
	}
end

dmc_lib_data = _G.__dmc_corona

--====================================================================--
--== DMC Kozy
--====================================================================--

--====================================================================--
--== Configuration

dmc_lib_data.dmc_kozy = dmc_lib_data.dmc_kozy or {}

local DMC_KOZY_DEFAULTS = {
	make_global=false,
	print_warnings=true,

	-- G1 deprecated methods
	activate_zeroone_alpha=true,
	activate_anchor=true,
	activate_fillcolor=true,
	activate_strokecolor=true,
}

local dmc_kozy_data = Utils.extend( dmc_lib_data.dmc_kozy, DMC_KOZY_DEFAULTS )

--====================================================================--
--== Setup, Constants

-- reference to the native object
local _DISPLAY = _G.display
local _NATIVE = _G.native

local dkd = dmc_kozy_data -- make shorter reference

local Display, Native

--====================================================================--
--== Support Functions

-- translateRGBToHDR()
-- translates RGB color sequence to equivalent HDR values
--
local function translateRGBToHDR( ... )
	-- print( 'translateRGBToHDR' )

	local args = { ... }
	local color, alpha
	local default_alpha = 255

	if dkd.activate_zeroone_alpha then default_alpha = 1 end

	-- print(  args[1], args[2], args[3], args[4], args[5] )

	if type( args[2] ) == 'number' then
		-- regular RGB
		if args[3] == nil then
			-- greyscale
			args[3] = args[2]
			args[4] = args[2]
			args[5] = default_alpha
		elseif args[4] == nil then
			-- greyscale with alpha
			args[3] = args[2]
			args[4] = args[2]
			args[5] = args[3]
		elseif args[5] == nil then
			-- RGB, no alpha
			args[5] = default_alpha
		end
		if dkd.activate_zeroone_alpha then
			alpha = args[5]
		else
			alpha = args[5]/255
		end

		color = { args[2]/255, args[3]/255, args[4]/255, alpha }

	elseif type( args[2] ) == 'table' and args[2].type=='gradient' then

		-- gradient RGB

		t = args[2].color1
		if not t[4] then
			alpha = 1
		elseif dkd.activate_zeroone_alpha then
			alpha = t[4]
		else
			alpha = t[4]/255
		end
		args[2].color1 = { t[1]/255, t[2]/255, t[3]/255, alpha }

		t = args[2].color2
		if not t[4] then
			alpha = 1
		elseif dkd.activate_zeroone_alpha then
			alpha = t[4]
		else
			alpha = t[4]/255
		end
		args[2].color2 = { t[1]/255, t[2]/255, t[3]/255, alpha }

		color = { args[2] }

	elseif type( args[2] ) == 'string' and args[2]:sub(1,1) == '#' then
		local hex = args[2]:gsub("#","")
		color = {
			tonumber("0x"..hex:sub(1,2))/255,
			tonumber("0x"..hex:sub(3,4))/255,
			tonumber("0x"..hex:sub(5,6))/255
		}

	elseif type( args[2] ) == 'string' then

		-- named color
		color = NAMED_COLORS and NAMED_COLORS[ args[2] ]
		if not color then
			color = { 1, 1, 1 }
			print('\n')
			print( 'ERROR dmc_kolor: named color not found', tostring( args[2] ) )
			print('\n')
		end
		color[4] = args[3]

	else
		print('\n')
		print( 'ERROR dmc_kolor: invalid RGB color type', type( args[2] ) )
		print('\n')
	end

	-- print( color[1], color[2], color[3], color[4] )

	return color
end

-- addSetAnchor()
-- imbue object with setReferencePoint magic
--
local function addSetAnchor( o )
	-- print( 'addSetAnchor' )

	function createClosure( obj )
		local f = function( ... )
			local args = {...}
			local x, y

			if type( args[2] ) == 'table' then
				x, y = unpack( args[2] )
			end
			if type( args[2] ) == 'number' then
				x = args[2]
			end
			if type( args[3] ) == 'number' then
				y = args[3]
			end

			obj.anchorX = x
			obj.anchorY = y
		end
		return f
	end

	local f = createClosure( o )
	o.setReferencePoint = f
	o.setAnchor = f
end

-- addSetFillColor()
-- imbue object with setFillColor / setTextColor magic
--
local function addSetFillColor( o )
	-- print( 'addSetFillColor' )

	function createClosure( obj, translate )
		local f = function( ... )
			-- print( 'DMC Kompatible :DISPLAY COLOR\n')
			local args = { ... }
			-- print(  args[1], args[2], args[3], args[4] )
			local color = translate( ... )
			obj:_setFillColor( unpack( color ) )
		end
		return f
	end

	o._setFillColor = o.setFillColor -- save original version
	o.setFillColor = createClosure( o, translateRGBToHDR )

end

-- addSetStrokeColor()
-- imbue object with strokeColor magic
--
local function addSetStrokeColor( o )
	-- print( 'addSetStrokeColor' )

	function createClosure( obj, translate )
		-- print('createClosure stroke')
		local f = function( ... )
			local color = translate( ... )
			obj:_setStrokeColor( unpack( color ) )
		end
		return f
	end

	o._setStrokeColor = o.setStrokeColor -- save original version
	o.setStrokeColor = createClosure( o, translateRGBToHDR )

end

--====================================================================--
--== Display Class Setup
--====================================================================--

Display = {}
Display.NAME = "DMC Kozy Display"

Display.super = _DISPLAY
setmetatable( Display, { __index=Display.super } )

--== Config ==--

Display.TopLeftReferencePoint = { 0, 0 }
Display.TopCenterReferencePoint = { 0.5, 0 }
Display.TopRightReferencePoint = { 1, 0 }
Display.CenterLeftReferencePoint = { 0, 0.5 }
Display.CenterReferencePoint = { 0.5, 0.5 }
Display.CenterRightReferencePoint = { 1, 0.5 }
Display.BottomLeftReferencePoint = { 0, 1 }
Display.BottomCenterReferencePoint = { 0.5, 1 }
Display.BottomRightReferencePoint = { 1, 1 }

--== Corona Display API ==--

function Display.newCircle( ... )
	-- print( 'dmc_kozy.newCircle' )

	local o = Display.super.newCircle( ... )
	local p

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end
	if dkd.activate_strokecolor then
		addSetStrokeColor( o )
	end

	return o
end

function Display.newContainer( ... )
	-- print( 'dmc_kozy.newContainer' )

	local o = Display.super.newContainer( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end

	return o
end

function Display.newGroup( ... )
	-- print( 'dmc_kozy.newGroup' )

	local o = Display.super.newGroup( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end

	return o
end

function Display.newImage( ... )
	-- print( 'dmc_kozy.newImage' )

	local o = Display.super.newImage( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end

	return o
end

function Display.newImageRect( ... )
	-- print( 'dmc_kozy.newImageRect' )

	local o = Display.super.newImageRect( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end

	return o
end

function Display.newLine( ... )
	-- print( 'dmc_kozy.newLine' )

	local o = Display.super.newLine( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_strokecolor then
		-- print( 'start', o.setStrokeColor )
		addSetStrokeColor( o )
		-- print( o.setStrokeColor )
	end

	return o
end

function Display.newPolygon( ... )
	-- print( 'dmc_kozy.newPolygon' )

	local o = Display.super.newPolygon( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_strokecolor then
		addSetStrokeColor( o )
	end

	return o
end

function Display.newRect( ... )
	-- print( 'dmc_kozy.newRect' )

	local o = Display.super.newRect( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end
	if dkd.activate_strokecolor then
		addSetStrokeColor( o )
	end

	return o
end

function Display.newRoundedRect( ... )
	-- print( 'dmc_kozy.newRoundedRect' )

	local o = Display.super.newRoundedRect( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end
	if dkd.activate_strokecolor then
		addSetStrokeColor( o )
	end

	return o
end

function Display.newSprite( ... )
	-- print( 'dmc_kozy.newSprite' )

	local o = Display.super.newSprite( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end

	return o
end

function Display.newText( ... )
	-- print( 'dmc_kozy.newText' )

	local o = Display.super.newText( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end

	return o
end

--====================================================================--
--== Native Class Setup
--====================================================================--

Native = {}
Native.NAME = "DMC Kozy Native"

Native.super = _NATIVE
setmetatable( Native, { __index=Native.super } )

--== Corona Native API ==--

function Native.newText( ... )
	-- print( 'dmc_kozy.newText' )

	local o = Native.super.newText( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end

	return o
end

function Native.newTextBox( ... )
	-- print( 'dmc_kozy.newTextBox' )

	local o = Native.super.newTextBox( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end

	return o
end

function Native.newTextField( ... )
	-- print( 'dmc_kozy.newTextField' )

	local o = Native.super.newTextField( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end

	return o
end

function Native.newWebView( ... )
	-- print( 'dmc_kozy.newWebView' )

	local o = Native.super.newWebView( ... )

	if dkd.activate_anchor then
		addSetAnchor( o )
	end
	if dkd.activate_fillcolor then
		addSetFillColor( o )
	end

	return o
end

function Native.setKeyboardFocus( obj )
	-- print( 'dmc_kozy.setKeyboardFocus', obj )

	if obj~=nil and obj.__is_dmc and obj.setKeyboardFocus then
		obj:setKeyboardFocus()
	else
		Native.super.setKeyboardFocus( obj )
	end
end

--====================================================================--
--== Final Setup
--====================================================================--

--== Make Global

if dkd.make_global then
	_G.display = Display
	_G.native = Native
end

-- return function so we can return two values
return function() return Display, Native end


text:
var	RouteSchemaManager = require('./RouteSchemaManager');

var ZSchemaErrors = require('z-schema-errors');
var Hoek = require('hoek');
var Boom = require('boom');
var capitalize = require('capitalize');

var baseMessage = '{part} parameters validation error:';

var errorReporters = ['headers', 'query', 'path', 'payload', 'response'].reduce(function(current, part){
	current[part] = ZSchemaErrors.init({
		contextMessage: baseMessage.replace('{part}', capitalize(part))
	});

	return current;
}, {});

var RequestValidator = function(plugin, options) {
	options = options || {};
	var configuredErrorReporters = Hoek.applyToDefaults(errorReporters, options.errorReporters || {});
	var routeSchemaManager = new RouteSchemaManager({ pluginName: options.pluginName, log: options.log }),
		log = options.log || function(){},

		onRequest = function(request, reply) {
			// hand routes for this server to schema manager so it can compile the schemas for each route
			// this method will not attempt to compile them more than once, so this is safe to call on every request
			try {
				var connectionsWithTable = request.server.table();

				connectionsWithTable.forEach(function(cwt){
					routeSchemaManager.initializeRoutes(cwt.info.uri, cwt.table);
				});
			}
			catch (error){
				log('error', 'Unable to compile and validate schemas', error);
				return reply(error);
			}

			reply.continue();
		},

		onPreHandler = function(request, reply) {
			var report,
				parts = ['path', 'query', 'headers', 'payload'];

			for (var i = 0; i < parts.length; i++){
				var capitalizedParts = capitalize(parts[i]);
				report = routeSchemaManager['validate' + capitalizedParts](request);

				if (!report.valid){
					return reply(Boom.badRequest(configuredErrorReporters[parts[i]].extractMessage(report)));
				}
			}

			reply.continue();
		},

		onPostHandler = function(request, reply) {
			var report, errorMessages;

			// if route config contains a schema for the respose, and sample rate is greater than 0, validate it
			if (request.route.plugins &&
				request.route.plugins[options.pluginName] &&
				request.route.plugins[options.pluginName].response &&
				request.route.plugins[options.pluginName].response.schema &&
				request.route.plugins[options.pluginName].response.sample !== 0 &&
				request.route.plugins[options.pluginName].response.sample !== false) {

				// if sampling is enabled and the random sample value is greater than the defined sample rate, don't validate
				if (request.route.plugins[options.pluginName].response.sample) {
					var currentSample = Math.ceil((Math.random() * 100));
					if (currentSample > request.route.plugins[options.pluginName].response.sample) {
						return reply.continue();
					}
				}

				if (request.response.isBoom) {
					return reply.continue();
				}

				report = routeSchemaManager.validateResponse(request);
				if (!report.valid) {
					errorMessages = configuredErrorReporters['response'].extractMessage(report);

					if (request.route.plugins[options.pluginName].response.failAction === 'log') {
						request.log(['validation', 'error'], errorMessages);
						return reply.continue();
					}
					return reply(Boom.internal(errorMessages));
				}
			}
			reply.continue();
		};

	// hook for compiling all schemas for all routes (one time)
	plugin.ext('onRequest', onRequest);
	// hook for validating request payload, query params, and path params
	plugin.ext('onPreHandler', onPreHandler);
	// hook for validating response payload
	plugin.ext('onPostHandler', onPostHandler);

};

module.exports = RequestValidator;