<commit_before>#include "Runtime/World/CScriptCameraHint.hpp"

#include "Runtime/CStateManager.hpp"
#include "Runtime/World/CActorParameters.hpp"

#include "TCastTo.hpp" // Generated file, do not modify include path

namespace urde {

CScriptCameraHint::CScriptCameraHint(TUniqueId uid, std::string_view name, const CEntityInfo& info,
                                     const zeus::CTransform& xf, bool active, s32 priority,
                                     CBallCamera::EBallCameraBehaviour behaviour, u32 overrideFlags, float minDist,
                                     float maxDist, float backwardsDist, const zeus::CVector3f& lookAtOffset,
                                     const zeus::CVector3f& chaseLookAtOffset, const zeus::CVector3f& ballToCam,
                                     float fov, float attitudeRange, float azimuthRange, float anglePerSecond,
                                     float clampVelRange, float clampRotRange, float elevation, float interpolateTime,
                                     float clampVelTime, float controlInterpDur)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic),
         CActorParameters::None(), kInvalidUniqueId)
, xe8_priority(priority)
, xec_hint(overrideFlags, behaviour, minDist, maxDist, backwardsDist, lookAtOffset, chaseLookAtOffset, ballToCam, fov,
           attitudeRange, azimuthRange, anglePerSecond, clampVelRange, clampRotRange, elevation, interpolateTime,
           clampVelTime, controlInterpDur)
, x168_origXf(xf) {}

void CScriptCameraHint::Accept(IVisitor& visitor) { visitor.Visit(this); }

void CScriptCameraHint::InitializeInArea(CStateManager& mgr) {
  x164_delegatedCamera = kInvalidUniqueId;
  for (CEntity* ent : mgr.GetAllObjectList()) {
    for (const SConnection& conn : ent->GetConnectionList()) {
      if (mgr.GetIdForScript(conn.x8_objId) != GetUniqueId())
        continue;
      if (conn.x4_msg != EScriptObjectMessage::Increment && conn.x4_msg != EScriptObjectMessage::Decrement)
        continue;

      for (auto it = ent->GetConnectionList().begin(); it != ent->GetConnectionList().end(); ++it) {
        const SConnection& conn2 = *it;
        if (conn2.x4_msg != EScriptObjectMessage::Increment && conn2.x4_msg != EScriptObjectMessage::Decrement)
          continue;
        TUniqueId id = mgr.GetIdForScript(conn2.x8_objId);
        if (TCastToPtr<CPathCamera>(mgr.ObjectById(id)) || TCastToPtr<CScriptSpindleCamera>(mgr.ObjectById((id)))) {
          it = ent->GetConnectionList().erase(it);
          if (x164_delegatedCamera != id)
            x164_delegatedCamera = id;
          break;
        }
      }
      break;
    }
  }
}

void CScriptCameraHint::AddHelper(TUniqueId id) {
  auto search = std::find_if(x150_helpers.begin(), x150_helpers.end(), [id](TUniqueId tid) { return tid == id; });
  if (search == x150_helpers.end())
    x150_helpers.push_back(id);
}

void CScriptCameraHint::RemoveHelper(TUniqueId id) {
  auto search = std::find_if(x150_helpers.begin(), x150_helpers.end(), [id](TUniqueId tid) { return tid == id; });
  if (search != x150_helpers.end())
    x150_helpers.erase(search);
  else
    x150_helpers.pop_front();
}

void CScriptCameraHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
  switch (msg) {
  case EScriptObjectMessage::Deleted:
  case EScriptObjectMessage::Deactivate:
    mgr.GetCameraManager()->DeleteCameraHint(GetUniqueId(), mgr);
    break;
  case EScriptObjectMessage::InitializedInArea:
    InitializeInArea(mgr);
    break;
  default:
    break;
  }

  if (GetActive()) {
    switch (msg) {
    case EScriptObjectMessage::Increment:
      AddHelper(sender);
      mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr);
      x166_inactive = false;
      break;
    case EScriptObjectMessage::Decrement:
      RemoveHelper(sender);
      mgr.GetCameraManager()->AddInactiveCameraHint(GetUniqueId(), mgr);
      break;
    default:
      break;
    }
  }

  if (msg == EScriptObjectMessage::Follow) {
    if (!GetActive()) {
      if (TCastToConstPtr<CActor> act = mgr.GetObjectById(sender)) {
        zeus::CVector3f followerToThisFlat = x168_origXf.origin - act->GetTranslation();
        followerToThisFlat.z() = 0.f;
        if (followerToThisFlat.canBeNormalized())
          followerToThisFlat.normalize();
        else
          followerToThisFlat = act->GetTransform().basis[1];
        zeus::CVector3f target = act->GetTranslation() + followerToThisFlat;
        target.z() = x168_origXf.origin.z() + followerToThisFlat.z();
        SetTransform(zeus::lookAt(act->GetTranslation(), target));
      }
    }
    AddHelper(sender);
    mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr);
  }

  CActor::AcceptScriptMsg(msg, sender, mgr);
}

} // namespace urde
<commit_msg>CScriptCameraHint: Brace statements where applicable<commit_after>#include "Runtime/World/CScriptCameraHint.hpp"

#include "Runtime/CStateManager.hpp"
#include "Runtime/World/CActorParameters.hpp"

#include "TCastTo.hpp" // Generated file, do not modify include path

namespace urde {

CScriptCameraHint::CScriptCameraHint(TUniqueId uid, std::string_view name, const CEntityInfo& info,
                                     const zeus::CTransform& xf, bool active, s32 priority,
                                     CBallCamera::EBallCameraBehaviour behaviour, u32 overrideFlags, float minDist,
                                     float maxDist, float backwardsDist, const zeus::CVector3f& lookAtOffset,
                                     const zeus::CVector3f& chaseLookAtOffset, const zeus::CVector3f& ballToCam,
                                     float fov, float attitudeRange, float azimuthRange, float anglePerSecond,
                                     float clampVelRange, float clampRotRange, float elevation, float interpolateTime,
                                     float clampVelTime, float controlInterpDur)
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic),
         CActorParameters::None(), kInvalidUniqueId)
, xe8_priority(priority)
, xec_hint(overrideFlags, behaviour, minDist, maxDist, backwardsDist, lookAtOffset, chaseLookAtOffset, ballToCam, fov,
           attitudeRange, azimuthRange, anglePerSecond, clampVelRange, clampRotRange, elevation, interpolateTime,
           clampVelTime, controlInterpDur)
, x168_origXf(xf) {}

void CScriptCameraHint::Accept(IVisitor& visitor) { visitor.Visit(this); }

void CScriptCameraHint::InitializeInArea(CStateManager& mgr) {
  x164_delegatedCamera = kInvalidUniqueId;
  for (CEntity* ent : mgr.GetAllObjectList()) {
    for (const SConnection& conn : ent->GetConnectionList()) {
      if (mgr.GetIdForScript(conn.x8_objId) != GetUniqueId()) {
        continue;
      }
      if (conn.x4_msg != EScriptObjectMessage::Increment && conn.x4_msg != EScriptObjectMessage::Decrement) {
        continue;
      }

      for (auto it = ent->GetConnectionList().begin(); it != ent->GetConnectionList().end(); ++it) {
        const SConnection& conn2 = *it;
        if (conn2.x4_msg != EScriptObjectMessage::Increment && conn2.x4_msg != EScriptObjectMessage::Decrement) {
          continue;
        }

        const TUniqueId id = mgr.GetIdForScript(conn2.x8_objId);
        const auto* const obj = mgr.ObjectById(id);
        if (TCastToConstPtr<CPathCamera>(obj) || TCastToConstPtr<CScriptSpindleCamera>(obj)) {
          it = ent->GetConnectionList().erase(it);
          if (x164_delegatedCamera != id) {
            x164_delegatedCamera = id;
          }
          break;
        }
      }
      break;
    }
  }
}

void CScriptCameraHint::AddHelper(TUniqueId id) {
  const auto search =
      std::find_if(x150_helpers.cbegin(), x150_helpers.cend(), [id](TUniqueId tid) { return tid == id; });

  if (search != x150_helpers.end()) {
    return;
  }

  x150_helpers.push_back(id);
}

void CScriptCameraHint::RemoveHelper(TUniqueId id) {
  const auto search =
      std::find_if(x150_helpers.cbegin(), x150_helpers.cend(), [id](TUniqueId tid) { return tid == id; });

  if (search != x150_helpers.cend()) {
    x150_helpers.erase(search);
  } else {
    x150_helpers.pop_front();
  }
}

void CScriptCameraHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
  switch (msg) {
  case EScriptObjectMessage::Deleted:
  case EScriptObjectMessage::Deactivate:
    mgr.GetCameraManager()->DeleteCameraHint(GetUniqueId(), mgr);
    break;
  case EScriptObjectMessage::InitializedInArea:
    InitializeInArea(mgr);
    break;
  default:
    break;
  }

  if (GetActive()) {
    switch (msg) {
    case EScriptObjectMessage::Increment:
      AddHelper(sender);
      mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr);
      x166_inactive = false;
      break;
    case EScriptObjectMessage::Decrement:
      RemoveHelper(sender);
      mgr.GetCameraManager()->AddInactiveCameraHint(GetUniqueId(), mgr);
      break;
    default:
      break;
    }
  }

  if (msg == EScriptObjectMessage::Follow) {
    if (!GetActive()) {
      if (const TCastToConstPtr<CActor> act = mgr.GetObjectById(sender)) {
        zeus::CVector3f followerToThisFlat = x168_origXf.origin - act->GetTranslation();
        followerToThisFlat.z() = 0.f;
        if (followerToThisFlat.canBeNormalized()) {
          followerToThisFlat.normalize();
        } else {
          followerToThisFlat = act->GetTransform().basis[1];
        }
        zeus::CVector3f target = act->GetTranslation() + followerToThisFlat;
        target.z() = x168_origXf.origin.z() + followerToThisFlat.z();
        SetTransform(zeus::lookAt(act->GetTranslation(), target));
      }
    }
    AddHelper(sender);
    mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr);
  }

  CActor::AcceptScriptMsg(msg, sender, mgr);
}

} // namespace urde
<|endoftext|>


<commit_before>/**
 *
 *    OCTOBER 2012 SEBASTIEN GROS & MARIO ZANON
 *
 */

#include <acado_toolkit.hpp>
#include <ocp_export.hpp>

int main( int argc, char * const argv[] ){

	//======================================================================
	// PARSE THE INPUT ARGUMENTS:
	// ----------------------------------
	double IC[3];

	/* arguments are passed to the main function by string
	 *  there are 'int argc' arguments
	 *		the first one is the name of the program
	 *		the next ones are arguments passed in the call like
	 *			program number1 number2
	 *  in this stupid simple parser, we directly read doubles from the arguments
	 */

	int k=1;
	while (k < argc) {
		// load the i-th string argument passed to the main function
		char* input = argv[k];
		// parse the string to a double value
		IC[k-1] = atof(input);
		k++;
	}

	cout << "Initial Conditions" << endl;
	cout << "------------" << endl;
	for (k = 0; k < argc-1; ++k) {
		cout << k+1 << ":\t" << IC[k] << endl;
	}
	//======================================================================

	const int Ncvp  = (int)IC[0];       // = 50
	const double Tc = IC[1];       // = 10
    const int IntegratorSteps = (int)IC[2];// =  2 * 50

    const double n_XD = 8;
    const double n_U = 5;

    USING_NAMESPACE_ACADO

    DifferentialState Omega;    // Rotor speed
    DifferentialState xT;       // Nacelle fore-aft position
    DifferentialState dxT;      // Nacelle fore-aft speed

    DifferentialState theta;    // Pitch angle
    DifferentialState dtheta;   // Pitch rate
    DifferentialState Mg;       // Generator Torque

    DifferentialState Sigma_Omega;    // Dummy state to match the slack
    DifferentialState Sigma_Pow;    // Dummy state to match the slack

    // CONTROL :
    // -------------------------
	Control	    ddtheta;        // Pitch acceleration
    Control     dMg;            // Generator torqe rate
    Control     S_Omega;              // Slack variable
    Control     S_Pow;              // Slack variable

    Control     v0;             // LIDAR wind profile

    double Mgfactor = 1e4; //Scale generator torque

    //double v0 = 10;
    double PI = 3.141592653589793;
 // PARAMETERS :
    double rho = 1.23;
	//double omega = 2*PI;
    double R = 63;
    double eta = 0.95;
    double hH = 90;

    double mT = 347460;
    double mN = 240000;
    double mB = 17740;
    double mH = 56780;
    double xi = 0.7;
    double iratio = 0.010309278350515;
    double JH = 115926;
    double JB = 11776047;
    double JG = 534.116;
    double f0 = 0.32;
    double ds = 0.01;

    double mTe = mT/4 + mN + mH + 3*mB;
    double cT = 4*PI*mTe*ds*f0;
    double J = JH + 3*JB + JG/iratio/iratio;
    double kT = mTe*(2*PI*f0)*(2*PI*f0);

    IntermediateState   vrel   = v0 - dxT;   // Nacelle relative velocity wrt the wind field
    IntermediateState lambda = Omega*R/vrel; // Tip-speed ratio

// Interpolation of the look-up tables
//Cp interpolation

    float out[6];

    #include CpCt

    Cp1(theta,lambda,out);
    IntermediateState Cp         = out[0];
    IntermediateState dCpdtheta  = out[1];
    IntermediateState dCpdlambda = out[2];

    Ct1(theta,lambda,out);
    IntermediateState Ct         = out[0];
    IntermediateState dCtdtheta  = out[1];
    IntermediateState dCtdlambda = out[2];

    IntermediateState MA = 0.5*rho*PI*R*R*R*Cp*vrel*vrel/lambda;
    IntermediateState FA = 0.5*rho*PI*R*R*Ct*vrel*vrel;

//// THE EQUATIONS OF MOTION:
//// ---------------------------------------------------------------

    //IntermediateState Pel = 1e-6*eta*Mg*Omega/i;

    IntermediateState dOmega = (MA - Mgfactor*Mg/iratio)/J;   // Rotor acceleration
    IntermediateState ddxT = (FA - cT*dxT - kT*xT)/mTe;  // Tower acceleration

    double a_Omega = 1e-1;
    double a_Pow = 5e-2;

  // THE "RIGHT-HAND-SIDE" OF THE ODE:
// ---------------------------------------------------------------
   DifferentialEquation f;

    f  << dot(Omega)   ==  dOmega                             ;
    f  << dot(xT)	   ==  dxT                             ;
    f  << dot(dxT)     ==  ddxT                             ;

    f  << dot(theta)   ==  dtheta                            ;
    f  << dot(dtheta)  ==  ddtheta                            ;
    f  << dot(Mg)	   ==  dMg                            ;

  	f  << dot(Sigma_Omega) ==  S_Omega - a_Omega*Sigma_Omega                            ;
    f  << dot(Sigma_Pow)   ==  S_Pow - a_Pow*Sigma_Pow                            ;

    // DEFINE AN OPTIMAL CONTROL PROBLEM:
    // ----------------------------------
    OCP ocp( 0.0, Tc, Ncvp );

    ocp.subjectTo( f );

    // CONSTRAINTS:
    // ---------------------------------

    ocp.subjectTo(  0  <=  Mg <=  1.05*4.282138171017305   );
	ocp.subjectTo(  theta_min <= theta <=  theta_max   );

    ocp.subjectTo(  -7.0 <= dtheta <= 7.0    );

    ocp.subjectTo(   0   <= (Omega/0.837758040957278 - 1) + S_Omega );
    ocp.subjectTo(   (Omega/1.267109036947883 -1) - S_Omega <= 0  );

	//ocp.subjectTo(  0  <=  S_Omega  );
    //ocp.subjectTo(  0  <=  S_Pow  );

    IntermediateState  Pelec = (1e-6*eta*Mgfactor/iratio)*Mg*Omega;
    IntermediateState dPelec = (1e-6*eta*Mgfactor/iratio)*(dMg*Omega+Mg*dOmega);

    double Prated = 5;     // Rated power
    double Pmax = 1.01*Prated;  // Maximum steady-state power

    ocp.subjectTo(  (Pelec/Prated - 1) - S_Pow <= 0 );

    ocp.subjectTo( Sigma_Pow - (Pmax - Prated)/a_Pow <= 0 );

    Function h;
    Function hN;

    ExportVariable SS("SS", n_XD + n_U, n_XD + n_U, REAL);
    ExportVariable SSN("SSN", n_XD, n_XD, REAL);

    const double K = 1.823540394474115e+06;

    hN << 0.5*M*zeta*sqrt(v0*v0*v0); // Power optimization
    hN << dxT;                       // Nacelle fore-aft speed
    hN << 1e-3*v0*v0*v0*Sigma_Pow;   // Accumulated constraint violation

    h << 0.5*M*zeta*sqrt(v0*v0*v0);  // Power optimization
    h << dxT;                        // Nacelle fore-aft speed
    h << 1e-3*v0*v0*v0*Sigma_Pow;       // Accumulated constraint violation

    // Inputs
    h << ddtheta;                    // Pitch acceleration
    h << dMg;                        // Generator torqe rate

    h << dPelec;          // dPower/dt
    h << 1e-3*v0*v0*v0*S_Omega;         // Slack variable
    h << 1e-3*v0*v0*v0*S_Pow;           // Slack variable
    //h << v0;              // LIDAR wind profile

    ocp.minimizeLSQ(SS, h);
    ocp.minimizeLSQEndTerm(SSN, hN);

    // Other attempts, a bit artificial
    //h << dMg + a*Mg - Omega*(2*dOmega+a*Omega)*(iratio*K/Mgfactor);   // Generator torqe rate
    //h << dMg  - 2*Omega*dOmega*(iratio*K/Mgfactor);   // Generator torqe rate

	// EXPORT THE CODE:
	// ---------------------------------
	printf("EXPORTING LINUX/QPOASES CODE\n");
	OCPexport mpc( ocp );

    mpc.set( CG_HARDCODE_CONSTRAINT_VALUES, NO );
    mpc.set( MAX_NUM_QP_ITERATIONS,       1000              );

	mpc.set( HESSIAN_APPROXIMATION,       GAUSS_NEWTON    );
	mpc.set( DISCRETIZATION_TYPE,   MULTIPLE_SHOOTING );
	mpc.set( QP_SOLVER,             QP_QPOASES      );
	mpc.set( HOTSTART_QP,           YES              );

//	mpc.set( INTEGRATOR_TYPE,             INT_RK4         );
 	mpc.set( INTEGRATOR_TYPE,             INT_IRK_GL2     ); // Rien's shite
	mpc.set( NUM_INTEGRATOR_STEPS,        IntegratorSteps );

    //Options for implicit integrators
	mpc.set( IMPLICIT_INTEGRATOR_NUM_ITS, 3				);
	mpc.set( IMPLICIT_INTEGRATOR_NUM_ITS_INIT, 0		);
	//mpc.set( LINEAR_ALGEBRA_SOLVER,		  HOUSEHOLDER_QR );
	mpc.set( UNROLL_LINEAR_SOLVER,        NO	      );
	mpc.set( IMPLICIT_INTEGRATOR_MODE, IFTR );

	mpc.set(SPARSE_QP_SOLUTION, FULL_CONDENSING);

    mpc.set( GENERATE_MATLAB_INTERFACE, YES );

	mpc.set( CG_USE_C99,    YES              );

	mpc.exportCode( "code_export_MPC" );
	mpc.printDimensionsQP();

    return 0;
}

<commit_msg>minor update<commit_after>/**
 *
 *    OCTOBER 2012 SEBASTIEN GROS & MARIO ZANON
 *
 */

#include <acado_toolkit.hpp>
#include <ocp_export.hpp>

int main( int argc, char * const argv[] ){

	//======================================================================
	// PARSE THE INPUT ARGUMENTS:
	// ----------------------------------
	double IC[3];

	/* arguments are passed to the main function by string
	 *  there are 'int argc' arguments
	 *		the first one is the name of the program
	 *		the next ones are arguments passed in the call like
	 *			program number1 number2
	 *  in this stupid simple parser, we directly read doubles from the arguments
	 */

	int k=1;
	while (k < argc) {
		// load the i-th string argument passed to the main function
		char* input = argv[k];
		// parse the string to a double value
		IC[k-1] = atof(input);
		k++;
	}

	cout << "Initial Conditions" << endl;
	cout << "------------" << endl;
	for (k = 0; k < argc-1; ++k) {
		cout << k+1 << ":\t" << IC[k] << endl;
	}
	//======================================================================

	const int Ncvp  = 50;
	const double Tc =  10;
    const int IntegratorSteps = 2 * 50;

    const double n_XD = 6;
    const double n_U = 3;

    USING_NAMESPACE_ACADO

    DifferentialState Omega;    // Rotor speed
    DifferentialState xT;       // Nacelle fore-aft position
    DifferentialState dxT;      // Nacelle fore-aft speed

    DifferentialState theta;    // Pitch angle
    DifferentialState dtheta;   // Pitch rate
    DifferentialState Mg;       // Generator Torque

   // DifferentialState Sigma_Omega;    // Dummy state to match the slack
   // DifferentialState Sigma_Pow;    // Dummy state to match the slack

    // CONTROL :
    // -------------------------
	Control	    ddtheta;        // Pitch acceleration
    Control     dMg;            // Generator torqe rate
   // Control     S_Omega;              // Slack variable
   // Control     S_Pow;              // Slack variable

    Control     v0;             // LIDAR wind profile

    double Mgfactor = 1e4; //Scale generator torque

    //double v0 = 10;
    double PI = 3.141592653589793;
 // PARAMETERS :
    double rho = 1.23;
	//double omega = 2*PI;
    double R = 63;
    double eta = 0.95;
    double hH = 90;

    double mT = 347460;
    double mN = 240000;
    double mB = 17740;
    double mH = 56780;
    double xi = 0.7;
    double iratio = 0.010309278350515;
    double JH = 115926;
    double JB = 11776047;
    double JG = 534.116;
    double f0 = 0.32;
    double ds = 0.01;

    double mTe = mT/4 + mN + mH + 3*mB;
    double cT = 4*PI*mTe*ds*f0;
    double J = JH + 3*JB + JG/iratio/iratio;
    double kT = mTe*(2*PI*f0)*(2*PI*f0);

    IntermediateState   vrel   = v0 - dxT;   // Nacelle relative velocity wrt the wind field
    IntermediateState lambda = Omega*R/vrel; // Tip-speed ratio

// Interpolation of the look-up tables
//Cp interpolation

    float out[6];

    #include CpCt

    Cp1(theta,lambda,out);
    IntermediateState Cp         = out[0];
    IntermediateState dCp_dtheta  = out[1];
    IntermediateState dCp_dlambda = out[2];

    Ct1(theta,lambda,out);
    IntermediateState Ct         = out[0];
    IntermediateState dCt_dtheta  = out[1];
    IntermediateState dCt_dlambda = out[2];

    IntermediateState MA = 0.5*rho*PI*R*R*R*Cp*vrel*vrel/lambda;
    IntermediateState FA = 0.5*rho*PI*R*R*Ct*vrel*vrel;

//// THE EQUATIONS OF MOTION:
//// ---------------------------------------------------------------

    //IntermediateState Pel = 1e-6*eta*Mg*Omega/i;

    IntermediateState dOmega = (MA - Mgfactor*Mg/iratio)/J;   // Rotor acceleration
    IntermediateState ddxT = (FA - cT*dxT - kT*xT)/mTe;  // Tower acceleration

    double a_Omega = 1e-1;
    double a_Pow = 5e-2;

  // THE "RIGHT-HAND-SIDE" OF THE ODE:
// ---------------------------------------------------------------
   DifferentialEquation f;

    f  << dot(Omega)   ==  dOmega                             ;
    f  << dot(xT)	   ==  dxT                             ;
    f  << dot(dxT)     ==  ddxT                             ;

    f  << dot(theta)   ==  dtheta                            ;
    f  << dot(dtheta)  ==  ddtheta                            ;
    f  << dot(Mg)	   ==  dMg                            ;

  	//f  << dot(Sigma_Omega) ==  S_Omega - a_Omega*Sigma_Omega                       ;
    //f  << dot(Sigma_Pow)   ==  S_Pow - a_Pow*Sigma_Pow                            ;

    // DEFINE AN OPTIMAL CONTROL PROBLEM:
    // ----------------------------------
    OCP ocp( 0.0, Tc, Ncvp );

    ocp.subjectTo( f );

    // CONSTRAINTS:
    // ---------------------------------

    ocp.subjectTo(  0  <=  Mg <=  1.05*4.282138171017305   );
	ocp.subjectTo(  theta_min <= theta <=  theta_max   );

    ocp.subjectTo(  -7.0 <= dtheta <= 7.0    );

    ocp.subjectTo(   0   <= (Omega/0.837758040957278 - 1) + S_Omega );
    ocp.subjectTo(   (Omega/1.267109036947883 -1) - S_Omega <= 0  );

	//ocp.subjectTo(  0  <=  S_Omega  );
    //ocp.subjectTo(  0  <=  S_Pow  );

    IntermediateState  Pelec = (1e-6*eta*Mgfactor/iratio)*Mg*Omega;
    IntermediateState dPelec = (1e-6*eta*Mgfactor/iratio)*(dMg*Omega+Mg*dOmega);

    double Prated = 5;     // Rated power
    double Pmax = 1.01*Prated;  // Maximum steady-state power

    ocp.subjectTo(  (Pelec/Prated - 1) - S_Pow <= 0 );

    ocp.subjectTo( Sigma_Pow - (Pmax - Prated)/a_Pow <= 0 );

    Function h;
    Function hN;

    ExportVariable SS("SS", n_XD + n_U, n_XD + n_U, REAL);
    ExportVariable SSN("SSN", n_XD, n_XD, REAL);

    const double K = 1.823540394474115e+06;

    hN << 0.5*M*zeta*sqrt(v0*v0*v0); // Power optimization
    hN << dxT;                       // Nacelle fore-aft speed
    hN << 1e-3*v0*v0*v0*Sigma_Pow;   // Accumulated constraint violation

    h << 0.5*M*zeta*sqrt(v0*v0*v0);  // Power optimization
    h << dxT;                        // Nacelle fore-aft speed
    h << 1e-3*v0*v0*v0*Sigma_Pow;       // Accumulated constraint violation

    // Inputs
    h << ddtheta;                    // Pitch acceleration
    h << dMg;                        // Generator torqe rate

    h << dPelec;          // dPower/dt
    h << 1e-3*v0*v0*v0*S_Omega;         // Slack variable
    h << 1e-3*v0*v0*v0*S_Pow;           // Slack variable
    //h << v0;              // LIDAR wind profile

    ocp.minimizeLSQ(SS, h);
    ocp.minimizeLSQEndTerm(SSN, hN);

    // Other attempts, a bit artificial
    //h << dMg + a*Mg - Omega*(2*dOmega+a*Omega)*(iratio*K/Mgfactor);   // Generator torqe rate
    //h << dMg  - 2*Omega*dOmega*(iratio*K/Mgfactor);   // Generator torqe rate

	// EXPORT THE CODE:
	// ---------------------------------
	printf("EXPORTING LINUX/QPOASES CODE\n");
	OCPexport mpc( ocp );

    mpc.set( CG_HARDCODE_CONSTRAINT_VALUES, NO );
    mpc.set( MAX_NUM_QP_ITERATIONS,       1000              );

	mpc.set( HESSIAN_APPROXIMATION,       GAUSS_NEWTON    );
	mpc.set( DISCRETIZATION_TYPE,   MULTIPLE_SHOOTING );
	mpc.set( QP_SOLVER,             QP_QPOASES      );
	mpc.set( HOTSTART_QP,           YES              );

//	mpc.set( INTEGRATOR_TYPE,             INT_RK4         );
 	mpc.set( INTEGRATOR_TYPE,             INT_IRK_GL2     ); // Rien's shite
	mpc.set( NUM_INTEGRATOR_STEPS,        IntegratorSteps );

    //Options for implicit integrators
	mpc.set( IMPLICIT_INTEGRATOR_NUM_ITS, 3				);
	mpc.set( IMPLICIT_INTEGRATOR_NUM_ITS_INIT, 0		);
	//mpc.set( LINEAR_ALGEBRA_SOLVER,		  HOUSEHOLDER_QR );
	mpc.set( UNROLL_LINEAR_SOLVER,        NO	      );
	mpc.set( IMPLICIT_INTEGRATOR_MODE, IFTR );

	mpc.set(SPARSE_QP_SOLUTION, FULL_CONDENSING);

    mpc.set( GENERATE_MATLAB_INTERFACE, YES );

	mpc.set( CG_USE_C99,    YES              );

	mpc.exportCode( "code_export_MPC" );
	mpc.printDimensionsQP();

    return 0;
}

<|endoftext|>


<commit_before>//
// Printers for core types.
//
#include "../Lib.h"

#include <ostream>
#include <string>

namespace sge {

// Vector2 Printer
std::ostream &operator<< (std::ostream &os, const Vector2 &vec) {
    return os << "<Vector2 " << vec.x << " " << vec.y << ">";
}

// Vector3 Printer
std::ostream &operator<< (std::ostream &os, const Vector3 &vec) {
    return os << "<Vector3 " << vec.x << " " << vec.y << " " << vec.z << ">";
}

// Vector4 Printer
std::ostream &operator<< (std::ostream &os, const Vector4 &vec) {
    return os << "<Vector4 " << vec.x << " " << vec.y << " " << vec.z << " " << vec.w << ">";
}

// Quaternion Printer
std::ostream &operator<< (std::ostream &os, const Quaternion &quat) {
    return os << "<Quaternion (" << quat.i << " " << quat.j << " " << quat.k << ") " << quat.w << ">";
}

// Matrix2 Printer
std::ostream &operator<< (std::ostream &os, const Matrix2 &mat) {
    os << "<Matrix2 ";
    for (u8 i = 0; i < 2; ++i) {
        auto sep = "";
        os << "[";
        for (u8 j = 0; j < 2; ++j) {
            os << sep << mat[i][j];
            sep = " ";
        }
        os << "]";
    }
    os << ">";
    return os;
}

// Matrix3 Printer
std::ostream &operator<< (std::ostream &os, const Matrix3 &mat) {
    os << "<Matrix3 ";
    for (u8 i = 0; i < 4; ++i) {
        auto sep = "";
        os << "[";
        for (u8 j = 0; j < 4; ++j) {
            os << sep << mat[i][j];
            sep = " ";
        }
        os << "]";
    }
    os << ">";
    return os;
}

// Matrix4 Printer
std::ostream &operator<< (std::ostream &os, const Matrix4 &mat) {
    os << "<Matrix4 ";
    for (u8 i = 0; i < 4; ++i) {
        auto sep = "";
        os << "[";
        for (u8 j = 0; j < 4; ++j) {
            os << sep << mat[i][j];
            sep = " ";
        }
        os << "]";
    }
    os << ">";
    return os;
}

// Color Printer
std::ostream& operator<< (std::ostream &os, const Color &col) {
    return os << "<Color " << (unsigned)col.r << " " << (unsigned)col.g
              << " " << (unsigned)col.b << " " << (unsigned)col.a << ">";
}

// Vertex Printer
std::ostream& operator<< (std::ostream &os, const Vertex &vert) {
    return os << "<Vertex P=" << vert.position << " N=" << vert.normal
              << " T=" << vert.texCoord << " C=" << vert.color << ">";
}

// Transform Printer
std::ostream& operator<< (std::ostream &os, const Transform &tr) {
    Vector3 up = tr.Up();
    Vector3 f = tr.Forward();
    Vector3 r = tr.Right();
    bool uniScale = ((tr.scale.x == tr.scale.y) && (tr.scale.x == tr.scale.z));

    os << "<Transform P=" << tr.position
       << " O=[" << f.x << " " << f.y << " " << f.z
       << "|" << up.x << " " << up.y << " " << up.z
       << "|" << r.x << " " << r.y << " " << r.z
       << "] S=";

    if (uniScale) {
        os << tr.scale.x;
    } else {
        os << tr.scale;
    }
    os << ">";
    return os;
}

// Clock Printer
std::ostream& operator<< (std::ostream &os, const Clock &clock) {
    return os << "<Clock " << clock.Elapsed() << "ns (" << clock.DeltaSeconds() << "ds)>";
}

} /* namespace sge */
<commit_msg>Format output of Clock Printer<commit_after>//
// Printers for core types.
//
#include "../Lib.h"

#include <ostream>
#include <iomanip>
#include <string>

namespace sge {

// Vector2 Printer
std::ostream &operator<< (std::ostream &os, const Vector2 &vec) {
    return os << "<Vector2 " << vec.x << " " << vec.y << ">";
}

// Vector3 Printer
std::ostream &operator<< (std::ostream &os, const Vector3 &vec) {
    return os << "<Vector3 " << vec.x << " " << vec.y << " " << vec.z << ">";
}

// Vector4 Printer
std::ostream &operator<< (std::ostream &os, const Vector4 &vec) {
    return os << "<Vector4 " << vec.x << " " << vec.y << " " << vec.z << " " << vec.w << ">";
}

// Quaternion Printer
std::ostream &operator<< (std::ostream &os, const Quaternion &quat) {
    return os << "<Quaternion (" << quat.i << " " << quat.j << " " << quat.k << ") " << quat.w << ">";
}

// Matrix2 Printer
std::ostream &operator<< (std::ostream &os, const Matrix2 &mat) {
    os << "<Matrix2 ";
    for (u8 i = 0; i < 2; ++i) {
        auto sep = "";
        os << "[";
        for (u32 j = 0; j < 2; ++j) {
            os << sep << mat[i][j];
            sep = " ";
        }
        os << "]";
    }
    os << ">";
    return os;
}

// Matrix3 Printer
std::ostream &operator<< (std::ostream &os, const Matrix3 &mat) {
    os << "<Matrix3 ";
    for (u8 i = 0; i < 4; ++i) {
        auto sep = "";
        os << "[";
        for (u32 j = 0; j < 4; ++j) {
            os << sep << mat[i][j];
            sep = " ";
        }
        os << "]";
    }
    os << ">";
    return os;
}

// Matrix4 Printer
std::ostream &operator<< (std::ostream &os, const Matrix4 &mat) {
    os << "<Matrix4 ";
    for (u8 i = 0; i < 4; ++i) {
        auto sep = "";
        os << "[";
        for (u32 j = 0; j < 4; ++j) {
            os << sep << mat[i][j];
            sep = " ";
        }
        os << "]";
    }
    os << ">";
    return os;
}

// Color Printer
std::ostream& operator<< (std::ostream &os, const Color &col) {
    return os << "<Color " << (unsigned)col.r << " " << (unsigned)col.g
              << " " << (unsigned)col.b << " " << (unsigned)col.a << ">";
}

// Vertex Printer
std::ostream& operator<< (std::ostream &os, const Vertex &vert) {
    return os << "<Vertex P=" << vert.position << " N=" << vert.normal
              << " T=" << vert.texCoord << " C=" << vert.color << ">";
}

// Transform Printer
std::ostream& operator<< (std::ostream &os, const Transform &tr) {
    Vector3 up = tr.Up();
    Vector3 f = tr.Forward();
    Vector3 r = tr.Right();
    bool uniScale = ((tr.scale.x == tr.scale.y) && (tr.scale.x == tr.scale.z));

    os << "<Transform P=" << tr.position
       << " O=[" << f.x << " " << f.y << " " << f.z
       << "|" << up.x << " " << up.y << " " << up.z
       << "|" << r.x << " " << r.y << " " << r.z
       << "] S=";

    if (uniScale) {
        os << tr.scale.x;
    } else {
        os << tr.scale;
    }
    os << ">";
    return os;
}

// Clock Printer
std::ostream& operator<< (std::ostream &os, const Clock &clock) {
    u64 ns = clock.Elapsed();
    u32 ms = ns / 1000000;
    u32 hours = ms / (1000 * 60 * 60);
    u32 mins = (ms / (1000 * 60)) % 60;
    u32 sec = (ms / 1000) % 60;
    ms = ms % 1000;

    return os << std::setfill('0') << "<Clock "
        // HH:MM:SS
              << hours << ":" << std::setw(2) << mins << ":" << std::setw(2) << sec
        // :MS
              << ":" << std::setw(3) << ms
        // (Time Delta in seconds)
              << " (" << clock.DeltaSeconds() << "ds) "
        // Total elapsed time in nanoseconds.
              << ns << "ns>";
}

} /* namespace sge */
<|endoftext|>


<commit_before>/*

  Copyright (c) 2014, Michael Tesch
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.

  * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

  * Neither the name of Michael Tesch nor the names of other
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  https://github.com/tesch1/qt-google-analytics-collector

  to enable debugging messages, '#define GANALYTICS_DEBUG 1' before including this file
  to get super verbose debugging, '#define GANALYTICS_DEBUG 2'
*/
#include <unistd.h>
#include <map>
#include <QCoreApplication>
#include <QSettings>
#ifdef QT_GUI_LIB
#include <QApplication>
#include <QDesktopWidget>
#endif
#include <QUuid>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QUrlQuery>
#include <QDebug>
#include <QProcess>

/*!
 * send google tracking data according to
 * https://developers.google.com/analytics/devguides/collection/protocol/v1/reference
 */

#ifndef GANALYTICS_DEBUG
#define GANALYTICS_DEBUG 0
#endif

class GAnalytics : public QObject {
  Q_OBJECT
private:
public:
  GAnalytics(QCoreApplication * parent,
             QString trackingID,
             QString clientID = "",
             bool useGET = false)
    : QObject(parent), _qnam(this), _trackingID(trackingID), _clientID(clientID), _useGET(useGET), _isFail(false)
  {
    if (parent) {
      setAppName(parent->applicationName());
      setAppVersion(parent->applicationVersion());
#ifdef QT_GUI_LIB
      parent->dumpObjectTree();
#endif
    }
    if (!_clientID.size()) {
      // load client id from settings
      QSettings settings;
      if (!settings.contains("GAnalytics-cid")) {
        settings.setValue("GAnalytics-cid", QUuid::createUuid().toString());
      }
      _clientID = settings.value("GAnalytics-cid").toString();
    }
    connect(&_qnam, SIGNAL(finished(QNetworkReply *)), this, SLOT(postFinished(QNetworkReply *)));
#if QT_VERSION >= 0x040800
#if GANALYTICS_DEBUG
    if (!_qnam.networkAccessible())
      qDebug() << "error: network inaccessible\n";
#endif
#endif
  }

  ~GAnalytics() {
    // this generally happens after the event-loop is done, so no more network processing
#if GANALYTICS_DEBUG
    QList<QNetworkReply *> replies = _qnam.findChildren<QNetworkReply *>();
    for (QList<QNetworkReply *>::iterator it = replies.begin(); it != replies.end(); it++) {
      if ((*it)->isRunning())
        qDebug() << "~GAnalytics, request still running: " << (*it)->url().toString() << ", aborting.";
      //reply->deleteLater();
    }
#endif
  }

  // manual config of static fields
  void setClientID(QString clientID) { _clientID = clientID; }
  void setUserID(QString userID) { _userID = userID; }
  void setUserIPAddr(QString userIPAddr) { _userIPAddr = userIPAddr; }
  void setUserAgent(QString userAgent) { _userAgent = userAgent; }
  void setAppName(QString appName) { _appName = appName; }
  void setAppVersion(QString appVersion) { _appVersion = appVersion; }
  void setScreenResolution(QString screenResolution) { _screenResolution = screenResolution; }
  void setViewportSize(QString viewportSize) { _viewportSize = viewportSize; }
  void setUserLanguage(QString userLanguage) { _userLanguage = userLanguage; }
  QString getClientID() const { return _clientID; }
  QString getUserAgent() const { return _userAgent; }

  //
  // hit types
  //
  // - https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide
  //

public Q_SLOTS:

  // pageview
  void sendPageview(QString docHostname, QString page, QString title) const {
    QUrlQuery params = build_metric("pageview");
    params.addQueryItem("dh", docHostname);    // document hostname
    params.addQueryItem("dp", page);            // page
    params.addQueryItem("dt", title);           // title
    send_metric(params);
  }

  // event
  void sendEvent(QString eventCategory = "", QString eventAction = "",
                 QString eventLabel = "", int eventValue = 0) const {
    QUrlQuery params = build_metric("event");
    if (_appName.size()) params.addQueryItem("an", _appName); // mobile event app tracking
    if (_appVersion.size()) params.addQueryItem("av", _appVersion); // mobile event app tracking
    if (eventCategory.size()) params.addQueryItem("ec", eventCategory);
    if (eventAction.size()) params.addQueryItem("ea", eventAction);
    if (eventLabel.size()) params.addQueryItem("el", eventLabel);
    if (eventValue) params.addQueryItem("ev", QString::number(eventValue));
    send_metric(params);
  }

  // transaction
  void sendTransaction(QString transactionID, QString transactionAffiliation = "" /*...todo...*/) const {
    QUrlQuery params = build_metric("transaction");
    params.addQueryItem("ti", transactionID);
    if (transactionAffiliation.size()) params.addQueryItem("ta", transactionAffiliation);
    send_metric(params);
  }

  // item
  void sendItem(QString itemName) const {
    QUrlQuery params = build_metric("item");
    params.addQueryItem("in", itemName);
    //if (appName.size()) params.addQueryItem("an", appName);
    send_metric(params);
  }

  // social
  void sendSocial(QString socialNetwork, QString socialAction, QString socialActionTarget) const {
    QUrlQuery params = build_metric("social");
    params.addQueryItem("sn", socialNetwork);
    params.addQueryItem("sa", socialAction);
    params.addQueryItem("st", socialActionTarget);
    send_metric(params);
  }

  // exception
  void sendException(QString exceptionDescription, bool exceptionFatal = true) const {
    QUrlQuery params = build_metric("exception");
    if (exceptionDescription.size()) params.addQueryItem("exd", exceptionDescription);
    if (!exceptionFatal) params.addQueryItem("exf", "0");
    send_metric(params);
  }

  // timing
  void sendTiming(/* todo */) const {
    QUrlQuery params = build_metric("timing");
    //if (appName.size()) params.addQueryItem("an", appName);
    send_metric(params);
  }

  // appview
  void sendAppview(QString appName, QString appVersion = "", QString screenName = "") const {
    QUrlQuery params = build_metric("appview");
    if (_appName.size()) params.addQueryItem("an", _appName);
    else if (appName.size()) params.addQueryItem("an", appName);
    if (_appVersion.size()) params.addQueryItem("av", _appVersion);
    else if (appVersion.size()) params.addQueryItem("av", appVersion);
    if (screenName.size()) params.addQueryItem("cd", screenName);
    send_metric(params);
  }

  // custom dimensions / metrics
  // todo

  // experiment id / variant
  // todo

  //void startSession();
  void endSession() const {
    QUrlQuery params = build_metric("event");
    params.addQueryItem("sc", "end");
    send_metric(params);
  }

public:

  void generateUserAgentEtc() {
    QString locale = QLocale::system().name().toLower().replace("_", "-");
#ifdef __APPLE__
    QString machine = "Macintosh; Intel Mac OS X 10.9; ";
#endif
#ifdef __linux__
    QString machine = "X11; ";
    QProcess process;
    process.start("uname", QStringList() << "-sm");
    process.waitForFinished(-1); // wait forever until finished
    QString stdout = process.readAllStandardOutput();
    machine += stdout.simplified() + "; ";
#endif
#ifdef Q_WS_WIN
    QString machine = "Windows; ";
#endif
    _userAgent = "Mozilla/5.0 (" + machine + locale + ") GAnalytics/1.0 (Qt/" QT_VERSION_STR " )";
    _userLanguage = locale;
#ifdef QT_GUI_LIB
    QString geom = QString::number(QApplication::desktop()->screenGeometry().width())
      + "x" + QString::number(QApplication::desktop()->screenGeometry().height());
    _screenResolution = geom;
#endif
#if GANALYTICS_DEBUG > 1
    qDebug() << "User-Agent:" << _userAgent;
    qDebug() << "Language:" << _userLanguage;
    qDebug() << "Screen Resolution:" << _screenResolution;
#endif
  }

private Q_SLOTS:
  void postFinished(QNetworkReply * reply) {
    //qDebug() << "reply:" << reply->readAll().toHex();
    if (QNetworkReply::NoError != reply->error()) {
      qDebug() << "postFinished error: " << reply->errorString() << "\n";
    }
    else {
      int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
      //qDebug() << "response code: " << httpStatus;
      if (httpStatus < 200 || httpStatus > 299) {
#if GANALYTICS_DEBUG
        qDebug() << "response code: " << httpStatus;
#endif
        _isFail = true;
      }
    }
    reply->deleteLater();
  }
  void postError(QNetworkReply::NetworkError code) {
    qDebug() << "network error signal: " << code << "\n";
  }

private:
  GAnalytics(const GAnalytics &); // disable copy const constructor
  QUrlQuery build_metric(QString hitType) const {
    QUrlQuery params;
    // required in v1
    params.addQueryItem("v", "1" ); // version
    params.addQueryItem("tid", _trackingID);
    params.addQueryItem("cid", _clientID);
    params.addQueryItem("t", hitType);
    // optional
    if (_userID.size())
      params.addQueryItem("uid", _userID);
    if (_userIPAddr.size())
      params.addQueryItem("uip", _userIPAddr);
    if (_screenResolution.size())
      params.addQueryItem("sr", _screenResolution);
    if (_viewportSize.size())
      params.addQueryItem("vp", _viewportSize);
    if (_userLanguage.size())
      params.addQueryItem("ul", _userLanguage);
    //if (_userAgent.size())
    //  params.addQueryItem("ua", _userAgent);
    return params;
  }
  void send_metric(const QUrlQuery& params) const {
    // when google has err'd us, then stop sending events!
    if (_isFail)
      return;
    QUrl collect_url("http://www.google-analytics.com/collect");
    QNetworkRequest request;
    if (_userAgent.size())
      request.setRawHeader("User-Agent", _userAgent.toUtf8());
    QNetworkReply * reply;
    if (_useGET) {
      // add cache-buster "z" to params
      //params.addQueryItem("z", QString::number(qrand()) );
      collect_url.setQuery(params);
      request.setUrl(collect_url);
      reply = _qnam.get(request);
    }
    else {
      request.setUrl(collect_url);
      request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
      reply = _qnam.post(request, params.toString().toUtf8());
    }
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
            this, SLOT(postError(QNetworkReply::NetworkError)));
#if GANALYTICS_DEBUG > 1
    qDebug() << "GAnalytics sent: " << params.toString();
#endif
    reply->setParent(&_qnam);
  }
  mutable QNetworkAccessManager _qnam;
  QString _trackingID;
  QString _clientID;
  bool _useGET; // true=GET, false=POST
  QString _userID;

  // various parameters:
  bool _anonymizeIP;
  bool _cacheBust;
  //
  QString _userIPAddr;
  QString _userAgent;
  QString _appName;
  QString _appVersion;
#if 0 // todo
  // traffic sources
  QString _documentReferrer;
  QString _campaignName;
  QString _campaignSource;
  QString _campaignMedium;
  QString _campaignKeyword;
  QString _campaignContent;
  QString _campaignID;
  QString _adwordsID;
  QString _displayAdsID;
#endif
  // system info
  QString _screenResolution;
  QString _viewportSize;
  QString _userLanguage;
  // etc...

  // internal
  bool _isFail;
};

<commit_msg>Qt5 updates<commit_after>/*

  Copyright (c) 2014, Michael Tesch
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this
    list of conditions and the following disclaimer.

  * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution.

  * Neither the name of Michael Tesch nor the names of other
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  https://github.com/tesch1/qt-google-analytics-collector

  to enable debugging messages, '#define GANALYTICS_DEBUG 1' before including this file
  to get super verbose debugging, '#define GANALYTICS_DEBUG 2'
*/
#include <unistd.h>
#include <map>
#include <QSettings>
#include <QUuid>
#include <QScreen>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QUrlQuery>
#include <QDebug>
#include <QProcess>
#include <QGuiApplication>

/*!
 * send google tracking data according to
 * https://developers.google.com/analytics/devguides/collection/protocol/v1/reference
 */

#ifndef GANALYTICS_DEBUG
#define GANALYTICS_DEBUG 0
#endif

class GAnalytics : public QObject {
  Q_OBJECT
private:
public:
  GAnalytics(QCoreApplication * parent,
             QString trackingID,
             QString clientID = "",
             bool useGET = false)
    : QObject(parent), _qnam(this), _trackingID(trackingID), _clientID(clientID), _useGET(useGET), _isFail(false)
  {
    if (parent) {
      setAppName(parent->applicationName());
      setAppVersion(parent->applicationVersion());
    }
    if (!_clientID.size()) {
      // load client id from settings
      QSettings settings;
      if (!settings.contains("GAnalytics-cid")) {
        settings.setValue("GAnalytics-cid", QUuid::createUuid().toString());
      }
      _clientID = settings.value("GAnalytics-cid").toString();
    }
    connect(&_qnam, SIGNAL(finished(QNetworkReply *)), this, SLOT(postFinished(QNetworkReply *)));
#if QT_VERSION >= 0x040800
#if GANALYTICS_DEBUG
    if (!_qnam.networkAccessible())
      qDebug() << "error: network inaccessible\n";
#endif
#endif
  }

  ~GAnalytics() {
    // this generally happens after the event-loop is done, so no more network processing
#if GANALYTICS_DEBUG
    QList<QNetworkReply *> replies = _qnam.findChildren<QNetworkReply *>();
    for (QList<QNetworkReply *>::iterator it = replies.begin(); it != replies.end(); it++) {
      if ((*it)->isRunning())
        qDebug() << "~GAnalytics, request still running: " << (*it)->url().toString() << ", aborting.";
      //reply->deleteLater();
    }
#endif
  }

  // manual config of static fields
  void setClientID(QString clientID) { _clientID = clientID; }
  void setUserID(QString userID) { _userID = userID; }
  void setUserIPAddr(QString userIPAddr) { _userIPAddr = userIPAddr; }
  void setUserAgent(QString userAgent) { _userAgent = userAgent; }
  void setAppName(QString appName) { _appName = appName; }
  void setAppVersion(QString appVersion) { _appVersion = appVersion; }
  void setScreenResolution(QString screenResolution) { _screenResolution = screenResolution; }
  void setViewportSize(QString viewportSize) { _viewportSize = viewportSize; }
  void setUserLanguage(QString userLanguage) { _userLanguage = userLanguage; }
  QString getClientID() const { return _clientID; }
  QString getUserAgent() const { return _userAgent; }

  //
  // hit types
  //
  // - https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide
  //

public Q_SLOTS:

  // pageview
  void sendPageview(QString docHostname, QString page, QString title) const {
    QUrlQuery params = build_metric("pageview");
    params.addQueryItem("dh", docHostname);    // document hostname
    params.addQueryItem("dp", page);            // page
    params.addQueryItem("dt", title);           // title
    send_metric(params);
  }

  // event
  void sendEvent(QString eventCategory = "", QString eventAction = "",
                 QString eventLabel = "", int eventValue = 0) const {
    QUrlQuery params = build_metric("event");
    if (_appName.size()) params.addQueryItem("an", _appName); // mobile event app tracking
    if (_appVersion.size()) params.addQueryItem("av", _appVersion); // mobile event app tracking
    if (eventCategory.size()) params.addQueryItem("ec", eventCategory);
    if (eventAction.size()) params.addQueryItem("ea", eventAction);
    if (eventLabel.size()) params.addQueryItem("el", eventLabel);
    if (eventValue) params.addQueryItem("ev", QString::number(eventValue));
    send_metric(params);
  }

  // transaction
  void sendTransaction(QString transactionID, QString transactionAffiliation = "" /*...todo...*/) const {
    QUrlQuery params = build_metric("transaction");
    params.addQueryItem("ti", transactionID);
    if (transactionAffiliation.size()) params.addQueryItem("ta", transactionAffiliation);
    send_metric(params);
  }

  // item
  void sendItem(QString itemName) const {
    QUrlQuery params = build_metric("item");
    params.addQueryItem("in", itemName);
    //if (appName.size()) params.addQueryItem("an", appName);
    send_metric(params);
  }

  // social
  void sendSocial(QString socialNetwork, QString socialAction, QString socialActionTarget) const {
    QUrlQuery params = build_metric("social");
    params.addQueryItem("sn", socialNetwork);
    params.addQueryItem("sa", socialAction);
    params.addQueryItem("st", socialActionTarget);
    send_metric(params);
  }

  // exception
  void sendException(QString exceptionDescription, bool exceptionFatal = true) const {
    QUrlQuery params = build_metric("exception");
    if (exceptionDescription.size()) params.addQueryItem("exd", exceptionDescription);
    if (!exceptionFatal) params.addQueryItem("exf", "0");
    send_metric(params);
  }

  // timing
  void sendTiming(/* todo */) const {
    QUrlQuery params = build_metric("timing");
    //if (appName.size()) params.addQueryItem("an", appName);
    send_metric(params);
  }

  // appview
  void sendAppview(QString appName, QString appVersion = "", QString screenName = "") const {
    QUrlQuery params = build_metric("appview");
    if (_appName.size()) params.addQueryItem("an", _appName);
    else if (appName.size()) params.addQueryItem("an", appName);
    if (_appVersion.size()) params.addQueryItem("av", _appVersion);
    else if (appVersion.size()) params.addQueryItem("av", appVersion);
    if (screenName.size()) params.addQueryItem("cd", screenName);
    send_metric(params);
  }

  // custom dimensions / metrics
  // todo

  // experiment id / variant
  // todo

  //void startSession();
  void endSession() const {
    QUrlQuery params = build_metric("event");
    params.addQueryItem("sc", "end");
    send_metric(params);
  }

public:

  void generateUserAgentEtc() {
    QString locale = QLocale::system().name().toLower().replace("_", "-");
#ifdef __APPLE__
    QString machine = "Macintosh; Intel Mac OS X 10.9; ";
#endif
#ifdef __linux__
    QString machine = "X11; ";
    QProcess process;
    process.start("uname", QStringList() << "-sm");
    process.waitForFinished(-1); // wait forever until finished
    QString stdout = process.readAllStandardOutput();
    machine += stdout.simplified() + "; ";
#endif
#ifdef Q_WS_WIN
    QString machine = "Windows; ";
#endif
    _userAgent = "Mozilla/5.0 (" + machine + locale + ") GAnalytics/1.0 (Qt/" QT_VERSION_STR " )";
    _userLanguage = locale;
#ifdef QT_GUI_LIB
    QList<QScreen*> screens = QGuiApplication::screens();
    if (!screens.isEmpty())
    {
        QScreen* screen = screens.at(0);
        QRect rect = screen->geometry();

        _screenResolution = QString("%1x%2").arg(rect.width()).arg(rect.height());
    }
#endif
#if GANALYTICS_DEBUG > 1
    qDebug() << "User-Agent:" << _userAgent;
    qDebug() << "Language:" << _userLanguage;
    qDebug() << "Screen Resolution:" << _screenResolution;
#endif
  }

private Q_SLOTS:
  void postFinished(QNetworkReply * reply) {
    //qDebug() << "reply:" << reply->readAll().toHex();
    if (QNetworkReply::NoError != reply->error()) {
      qDebug() << "postFinished error: " << reply->errorString() << "\n";
    }
    else {
      int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
      //qDebug() << "response code: " << httpStatus;
      if (httpStatus < 200 || httpStatus > 299) {
#if GANALYTICS_DEBUG
        qDebug() << "response code: " << httpStatus;
#endif
        _isFail = true;
      }
    }
    reply->deleteLater();
  }
  void postError(QNetworkReply::NetworkError code) {
    qDebug() << "network error signal: " << code << "\n";
  }

private:
  GAnalytics(const GAnalytics &); // disable copy const constructor
  QUrlQuery build_metric(QString hitType) const {
    QUrlQuery params;
    // required in v1
    params.addQueryItem("v", "1" ); // version
    params.addQueryItem("tid", _trackingID);
    params.addQueryItem("cid", _clientID);
    params.addQueryItem("t", hitType);
    // optional
    if (_userID.size())
      params.addQueryItem("uid", _userID);
    if (_userIPAddr.size())
      params.addQueryItem("uip", _userIPAddr);
    if (_screenResolution.size())
      params.addQueryItem("sr", _screenResolution);
    if (_viewportSize.size())
      params.addQueryItem("vp", _viewportSize);
    if (_userLanguage.size())
      params.addQueryItem("ul", _userLanguage);
    //if (_userAgent.size())
    //  params.addQueryItem("ua", _userAgent);
    return params;
  }
  void send_metric(const QUrlQuery& params) const {
    // when google has err'd us, then stop sending events!
    if (_isFail)
      return;
    QUrl collect_url("http://www.google-analytics.com/collect");
    QNetworkRequest request;
    if (_userAgent.size())
      request.setRawHeader("User-Agent", _userAgent.toUtf8());
    QNetworkReply * reply;
    if (_useGET) {
      // add cache-buster "z" to params
      //params.addQueryItem("z", QString::number(qrand()) );
      collect_url.setQuery(params);
      request.setUrl(collect_url);
      reply = _qnam.get(request);
    }
    else {
      request.setUrl(collect_url);
      request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
      reply = _qnam.post(request, params.toString().toUtf8());
    }
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
            this, SLOT(postError(QNetworkReply::NetworkError)));
#if GANALYTICS_DEBUG > 1
    qDebug() << "GAnalytics sent: " << params.toString();
#endif
    reply->setParent(&_qnam);
  }
  mutable QNetworkAccessManager _qnam;
  QString _trackingID;
  QString _clientID;
  bool _useGET; // true=GET, false=POST
  QString _userID;

  // various parameters:
  bool _anonymizeIP;
  bool _cacheBust;
  //
  QString _userIPAddr;
  QString _userAgent;
  QString _appName;
  QString _appVersion;
#if 0 // todo
  // traffic sources
  QString _documentReferrer;
  QString _campaignName;
  QString _campaignSource;
  QString _campaignMedium;
  QString _campaignKeyword;
  QString _campaignContent;
  QString _campaignID;
  QString _adwordsID;
  QString _displayAdsID;
#endif
  // system info
  QString _screenResolution;
  QString _viewportSize;
  QString _userLanguage;
  // etc...

  // internal
  bool _isFail;
};

<|endoftext|>


<commit_before>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */
#include "RtfReader.h"
#include "Writer/OOXWriter.h"
#include "DestinationCommand.h"

#include "../../../Common/MS-LCID.h"

RtfReader::RtfReader(RtfDocument& oDocument, std::wstring sFilename ) : m_oDocument(oDocument), m_sFilename(sFilename)
{
	m_oState = ReaderStatePtr(new ReaderState());
	m_nFootnote = PROP_DEF;
	m_nDefFont = PROP_DEF;
	m_convertationManager = NULL;
}
bool RtfReader::Load()
{
	if (false == m_oLex.SetSource(m_sFilename)) return false;

	RtfNormalReader oNormalReader( m_oDocument, (*this) );
	oNormalReader.Parse( m_oDocument, (*this) );
	m_oLex.CloseSource();
    return true;
}
void RtfReader::PushState()
{
	ReaderStatePtr psaveNew = ReaderStatePtr(new ReaderState());
	psaveNew -> m_nUnicodeClean		= m_oState->m_nUnicodeClean;
	psaveNew -> m_oCharProp			= m_oState->m_oCharProp;
	psaveNew -> m_oParagraphProp	= m_oState->m_oParagraphProp;
	psaveNew -> m_oRowProperty		= m_oState->m_oRowProperty;
	psaveNew -> m_oCellProperty		= m_oState->m_oCellProperty;
	psaveNew -> m_oCurOldList		= m_oState->m_oCurOldList;
	//psaveNew -> m_oSectionProp	= m_oState->m_oSectionProp;
	psaveNew -> m_pSaveState		= m_oState;
	m_oState = psaveNew;

	if( PROP_DEF == m_oState->m_oCharProp.m_nFont )
		m_oState->m_oCharProp.m_nFont = m_nDefFont;
}
void RtfReader::PopState()
{
	if( 0 != m_oState->m_pSaveState )
		m_oState = m_oState->m_pSaveState;
}
//---------------------------------------------------------------------------------------------------------------------------------
bool RtfAbstractReader::Parse(RtfDocument& oDocument, RtfReader& oReader)
{
	NFileWriter::CBufferedFileWriter* poOldWriter = oReader.m_oLex.m_oFileWriter;
	oReader.m_oLex.m_oFileWriter = m_oFileWriter;

	int res = 0;
	m_oTok = oReader.m_oLex.NextCurToken();

	if (m_oTok.Type == m_oTok.None)
		m_oTok = oReader.m_oLex.NextToken();

	while (m_oTok.Type != RtfToken::Eof && false == m_bStopReader)
	{
		switch (m_oTok.Type)
		{
		case RtfToken::GroupStart:
		{
			ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);
			PushState(oReader);
		}break;
		case RtfToken::GroupEnd:
		{
			ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);

			PopState(oDocument, oReader);
		}break;
		case RtfToken::Keyword:
		{
			ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);
			if (m_oTok.Key == "u")
			{
				ExecuteText(oDocument, oReader, ExecuteTextInternal(oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter, m_nSkipChars));
				break;
			}
			else
			{
				if (true == m_bSkip)
				{
					if (false == ExecuteCommand(oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter))
						Skip(oDocument, oReader);
					m_bSkip = false;
				}
				else
					ExecuteCommand(oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter);
			}
			if (true == m_bCanStartNewReader)
				m_bCanStartNewReader = false;
		}break;
		case RtfToken::Control:
		{
			if (m_oTok.Key == "42")
				m_bSkip = true;
			if (m_oTok.Key == "39" && true == m_oTok.HasParameter)
			{
				oReader.m_oState->m_sCurText += m_oTok.Parameter;
				oReader.m_oState->m_bControlPresent = true;
			}
			if (m_oTok.Key == "32" && false == m_oTok.HasParameter)
			{
				oReader.m_oState->m_sCurText += " ";
				oReader.m_oState->m_bControlPresent = true;
			}
		}break;
		case RtfToken::Text:
		{
			oReader.m_oState->m_sCurText += m_oTok.Key;
		}break;

		}
		if (false == m_bStopReader)
			m_oTok = oReader.m_oLex.NextToken();
	}

	oReader.m_oLex.m_oFileWriter = poOldWriter;

	return true;
}
std::wstring RtfAbstractReader::ExecuteTextInternal(RtfDocument& oDocument, RtfReader& oReader, std::string & sKey, bool bHasPar, int nPar, int& nSkipChars)
{
	std::wstring sResult;

	if ("u" == sKey)
	{
		if (true == bHasPar)
			sResult += wchar_t(nPar);
	}
	else
	{
		std::string sCharString;
		if ("39" == sKey)
		{
			if (true == bHasPar)
				sCharString += (char)nPar;
		}
		else
			sCharString = sKey;

		sResult = ExecuteTextInternalCodePage(sCharString, oDocument, oReader);
	}
	ExecuteTextInternalSkipChars(sResult, oReader, sKey, nSkipChars);
	return sResult;
}
void RtfAbstractReader::ExecuteTextInternal2(RtfDocument& oDocument, RtfReader& oReader, std::string & sKey, int& nSkipChars)
{
	if (oReader.m_oState->m_sCurText.length() > 0)
	{
		std::string str;
		ExecuteTextInternalSkipChars(oReader.m_oState->m_sCurText, oReader, str, nSkipChars);

		std::wstring sResult = ExecuteTextInternalCodePage(oReader.m_oState->m_sCurText, oDocument, oReader);

		oReader.m_oState->m_sCurText.erase();
		oReader.m_oState->m_bControlPresent = false;

		if (false == sResult.empty())
		{
			ExecuteText(oDocument, oReader, sResult);
		}
	}
}
void RtfAbstractReader::ExecuteTextInternalSkipChars(std::string & sResult, RtfReader& oReader, std::string & sKey, int& nSkipChars)
{
	//удаляем символы вслед за юникодом
	if (nSkipChars > 0)
	{
		if (nSkipChars >= (int)sResult.length())
		{
			//nSkipChars -= nLength;//vedomost.rtf
			sResult.clear();
		}
		else
		{
			sResult = sResult.substr(nSkipChars);
		}
		nSkipChars = 0;
	}
	if ("u" == sKey)
	{
		//надо правильно установить m_nSkipChars по значению \ucN
		nSkipChars = oReader.m_oState->m_nUnicodeClean;
	}
}
void RtfAbstractReader::ExecuteTextInternalSkipChars(std::wstring & sResult, RtfReader& oReader, std::string & sKey, int& nSkipChars)
{
	//удаляем символы вслед за юникодом
	if (nSkipChars > 0)
	{
		if (nSkipChars >= (int)sResult.length())
		{
			//nSkipChars -= nLength;//vedomost.rtf
			sResult.clear();
		}
		else
		{
			sResult = sResult.substr(nSkipChars);
		}
		nSkipChars = 0;
	}
	if ("u" == sKey)
	{
		//надо правильно установить m_nSkipChars по значению \ucN
		nSkipChars = oReader.m_oState->m_nUnicodeClean;
	}
}
std::wstring RtfAbstractReader::ExecuteTextInternalCodePage( std::string& sCharString, RtfDocument& oDocument, RtfReader& oReader)
{
    std::wstring sResult;

    if( false == sCharString.empty())
    {
		if (sCharString == "*") return L"*";

        int nCodepage = -1;

        //применяем параметры codepage от текущего шрифта todo associated fonts.
        RtfFont oFont;
        if( true == oDocument.m_oFontTable.GetFont( oReader.m_oState->m_oCharProp.m_nFont, oFont ) && !m_bUseGlobalCodepage)
        {
            if( PROP_DEF != oFont.m_nCharset )
            {
                nCodepage = RtfUtility::CharsetToCodepage( oFont.m_nCharset );
            }
            else if( PROP_DEF != oFont.m_nCodePage )
            {
                nCodepage = oFont.m_nCodePage;
            }
        }
        //от настроек документа
        if( -1 == nCodepage && RtfDocumentProperty::cp_none != oDocument.m_oProperty.m_eCodePage )
        {
            switch ( oDocument.m_oProperty.m_eCodePage )
            {
            case RtfDocumentProperty::cp_ansi:
                {
                    if( PROP_DEF != oDocument.m_oProperty.m_nAnsiCodePage )
                    {
                        nCodepage = oDocument.m_oProperty.m_nAnsiCodePage;
                    }
                    else
                        nCodepage = CP_ACP;
                    break;
                }
            case RtfDocumentProperty::cp_mac:   nCodepage = CP_MACCP;   break; //?? todooo
            case RtfDocumentProperty::cp_pc:    nCodepage = 437;        break; //ms dos latin us
            case RtfDocumentProperty::cp_pca:   nCodepage = 850;        break; //ms dos latin eu
            }
        }
        //если ничего нет ставим ANSI или default from user
        if( -1 == nCodepage )
		{
            nCodepage = CP_ACP;
		}
		if (nCodepage == CP_ACP && oDocument.m_nUserLCID > 0)
		{
			nCodepage = msLCID2DefCodePage(oDocument.m_nUserLCID);
		}

        sResult = RtfUtility::convert_string_icu(sCharString.begin(), sCharString.end(), nCodepage);

		//if (!sCharString.empty() && sResult.empty())
		//{
		//	//code page not support in icu !!!
		//	sResult = RtfUtility::convert_string(sCharString.begin(), sCharString.end(), nCodepage); .. to UnicodeConverter
		//}
    }
    return sResult;
}
<commit_msg>fix bug #59322<commit_after>/*
 * (c) Copyright Ascensio System SIA 2010-2019
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */
#include "RtfReader.h"
#include "Writer/OOXWriter.h"
#include "DestinationCommand.h"

#include "../../../Common/MS-LCID.h"

RtfReader::RtfReader(RtfDocument& oDocument, std::wstring sFilename ) : m_oDocument(oDocument), m_sFilename(sFilename)
{
	m_oState = ReaderStatePtr(new ReaderState());
	m_nFootnote = PROP_DEF;
	m_nDefFont = PROP_DEF;
	m_convertationManager = NULL;
}
bool RtfReader::Load()
{
	if (false == m_oLex.SetSource(m_sFilename)) return false;

	RtfNormalReader oNormalReader( m_oDocument, (*this) );
	oNormalReader.Parse( m_oDocument, (*this) );
	m_oLex.CloseSource();
    return true;
}
void RtfReader::PushState()
{
	ReaderStatePtr psaveNew = ReaderStatePtr(new ReaderState());
	psaveNew -> m_nUnicodeClean		= m_oState->m_nUnicodeClean;
	psaveNew -> m_oCharProp			= m_oState->m_oCharProp;
	psaveNew -> m_oParagraphProp	= m_oState->m_oParagraphProp;
	psaveNew -> m_oRowProperty		= m_oState->m_oRowProperty;
	psaveNew -> m_oCellProperty		= m_oState->m_oCellProperty;
	psaveNew -> m_oCurOldList		= m_oState->m_oCurOldList;
	//psaveNew -> m_oSectionProp	= m_oState->m_oSectionProp;
	psaveNew -> m_pSaveState		= m_oState;
	m_oState = psaveNew;

	if( PROP_DEF == m_oState->m_oCharProp.m_nFont )
		m_oState->m_oCharProp.m_nFont = m_nDefFont;
}
void RtfReader::PopState()
{
	if( 0 != m_oState->m_pSaveState )
		m_oState = m_oState->m_pSaveState;
}
//---------------------------------------------------------------------------------------------------------------------------------
bool RtfAbstractReader::Parse(RtfDocument& oDocument, RtfReader& oReader)
{
	NFileWriter::CBufferedFileWriter* poOldWriter = oReader.m_oLex.m_oFileWriter;
	oReader.m_oLex.m_oFileWriter = m_oFileWriter;

	int res = 0;
	m_oTok = oReader.m_oLex.NextCurToken();

	if (m_oTok.Type == m_oTok.None)
		m_oTok = oReader.m_oLex.NextToken();

	while (m_oTok.Type != RtfToken::Eof && false == m_bStopReader)
	{
		switch (m_oTok.Type)
		{
		case RtfToken::GroupStart:
		{
			ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);
			PushState(oReader);
		}break;
		case RtfToken::GroupEnd:
		{
			ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);

			PopState(oDocument, oReader);
		}break;
		case RtfToken::Keyword:
		{
			ExecuteTextInternal2(oDocument, oReader, m_oTok.Key, m_nSkipChars);
			if (m_oTok.Key == "u")
			{
				ExecuteText(oDocument, oReader, ExecuteTextInternal(oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter, m_nSkipChars));
				break;
			}
			else
			{
				if (true == m_bSkip)
				{
					if (false == ExecuteCommand(oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter))
						Skip(oDocument, oReader);
					m_bSkip = false;
				}
				else
					ExecuteCommand(oDocument, oReader, m_oTok.Key, m_oTok.HasParameter, m_oTok.Parameter);
			}
			if (true == m_bCanStartNewReader)
				m_bCanStartNewReader = false;
		}break;
		case RtfToken::Control:
		{
			if (m_oTok.Key == "42")
				m_bSkip = true;
			if (m_oTok.Key == "39" && true == m_oTok.HasParameter)
			{
				oReader.m_oState->m_sCurText += m_oTok.Parameter;
				oReader.m_oState->m_bControlPresent = true;
			}
			if (m_oTok.Key == "32" && false == m_oTok.HasParameter)
			{
				oReader.m_oState->m_sCurText += " ";
				oReader.m_oState->m_bControlPresent = true;
			}
		}break;
		case RtfToken::Text:
		{
			oReader.m_oState->m_sCurText += m_oTok.Key;
		}break;

		}
		if (false == m_bStopReader)
			m_oTok = oReader.m_oLex.NextToken();
	}

	oReader.m_oLex.m_oFileWriter = poOldWriter;

	return true;
}
std::wstring RtfAbstractReader::ExecuteTextInternal(RtfDocument& oDocument, RtfReader& oReader, std::string & sKey, bool bHasPar, int nPar, int& nSkipChars)
{
	std::wstring sResult;

	if ("u" == sKey)
	{
		if (true == bHasPar)
			sResult += wchar_t(nPar);
	}
	else
	{
		std::string sCharString;
		if ("39" == sKey)
		{
			if (true == bHasPar)
				sCharString += (char)nPar;
		}
		else
			sCharString = sKey;

		sResult = ExecuteTextInternalCodePage(sCharString, oDocument, oReader);
	}
	ExecuteTextInternalSkipChars(sResult, oReader, sKey, nSkipChars);
	return sResult;
}
void RtfAbstractReader::ExecuteTextInternal2(RtfDocument& oDocument, RtfReader& oReader, std::string & sKey, int& nSkipChars)
{
	if (oReader.m_oState->m_sCurText.length() > 0)
	{
		std::string str;
		ExecuteTextInternalSkipChars(oReader.m_oState->m_sCurText, oReader, str, nSkipChars);

		std::wstring sResult = ExecuteTextInternalCodePage(oReader.m_oState->m_sCurText, oDocument, oReader);

		oReader.m_oState->m_sCurText.erase();
		oReader.m_oState->m_bControlPresent = false;

		if (false == sResult.empty())
		{
			ExecuteText(oDocument, oReader, sResult);
		}
	}
}
void RtfAbstractReader::ExecuteTextInternalSkipChars(std::string & sResult, RtfReader& oReader, std::string & sKey, int& nSkipChars)
{
	//удаляем символы вслед за юникодом
	if (nSkipChars > 0)
	{
		if (nSkipChars >= (int)sResult.length())
		{
			//nSkipChars -= nLength;//vedomost.rtf
			sResult.clear();
		}
		else
		{
			sResult = sResult.substr(nSkipChars);
		}
		nSkipChars = 0;
	}
	if ("u" == sKey)
	{
		//надо правильно установить m_nSkipChars по значению \ucN
		nSkipChars = oReader.m_oState->m_nUnicodeClean;
	}
}
void RtfAbstractReader::ExecuteTextInternalSkipChars(std::wstring & sResult, RtfReader& oReader, std::string & sKey, int& nSkipChars)
{
	//удаляем символы вслед за юникодом
	if (nSkipChars > 0)
	{
		if (nSkipChars >= (int)sResult.length())
		{
			//nSkipChars -= nLength;//vedomost.rtf
			sResult.clear();
		}
		else
		{
			sResult = sResult.substr(nSkipChars);
		}
		nSkipChars = 0;
	}
	if ("u" == sKey)
	{
		//надо правильно установить m_nSkipChars по значению \ucN
		nSkipChars = oReader.m_oState->m_nUnicodeClean;
	}
}
std::wstring RtfAbstractReader::ExecuteTextInternalCodePage( std::string& sCharString, RtfDocument& oDocument, RtfReader& oReader)
{
    std::wstring sResult;

    if( false == sCharString.empty())
    {
		if (sCharString == "*") return L"*";

        int nCodepage = -1;

        //применяем параметры codepage от текущего шрифта todo associated fonts.
        RtfFont oFont;
        if( true == oDocument.m_oFontTable.GetFont( oReader.m_oState->m_oCharProp.m_nFont, oFont ) && !m_bUseGlobalCodepage)
        {
            if( PROP_DEF != oFont.m_nCharset && oFont.m_nCharset > 1)
            {
                nCodepage = RtfUtility::CharsetToCodepage( oFont.m_nCharset );
            }
            else if( PROP_DEF != oFont.m_nCodePage )
            {
                nCodepage = oFont.m_nCodePage;
            }
        }
        //от настроек документа
        if( -1 == nCodepage && RtfDocumentProperty::cp_none != oDocument.m_oProperty.m_eCodePage )
        {
            switch ( oDocument.m_oProperty.m_eCodePage )
            {
            case RtfDocumentProperty::cp_ansi:
                {
                    if( PROP_DEF != oDocument.m_oProperty.m_nAnsiCodePage )
                    {
                        nCodepage = oDocument.m_oProperty.m_nAnsiCodePage;
                    }
                    else
                        nCodepage = CP_ACP;
                    break;
                }
            case RtfDocumentProperty::cp_mac:   nCodepage = CP_MACCP;   break; //?? todooo
            case RtfDocumentProperty::cp_pc:    nCodepage = 437;        break; //ms dos latin us
            case RtfDocumentProperty::cp_pca:   nCodepage = 850;        break; //ms dos latin eu
            }
        }
        //если ничего нет ставим ANSI или default from user
        if( -1 == nCodepage )
		{
            nCodepage = CP_ACP;
		}
		if (nCodepage == CP_ACP && oDocument.m_nUserLCID > 0)
		{
			nCodepage = msLCID2DefCodePage(oDocument.m_nUserLCID);
		}

        sResult = RtfUtility::convert_string_icu(sCharString.begin(), sCharString.end(), nCodepage);

		//if (!sCharString.empty() && sResult.empty())
		//{
		//	//code page not support in icu !!!
		//	sResult = RtfUtility::convert_string(sCharString.begin(), sCharString.end(), nCodepage); .. to UnicodeConverter
		//}
    }
    return sResult;
}
<|endoftext|>


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

#include "string_utils.h"

namespace gtx {

std::string TrimWhitespace(std::string str) {
  auto first_nonwhitespace_iter =
      std::find_if_not(str.begin(), str.end(), std::isspace);
  auto trimmed_leading = str.substr(first_nonwhitespace_iter - str.begin(),
                                    str.end() - first_nonwhitespace_iter);
  auto last_nonwhitespace_iter = std::find_if_not(
      trimmed_leading.rbegin(), trimmed_leading.rend(), std::isspace);
  return trimmed_leading.substr(
      0, trimmed_leading.rend() - last_nonwhitespace_iter);
}

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

#include "string_utils.h"

namespace gtx {

std::string TrimWhitespace(std::string str) {
  auto first_nonwhitespace_iter = std::find_if_not(
      str.begin(), str.end(), [](char c) { return std::isspace(c); });
  auto trimmed_leading = str.substr(first_nonwhitespace_iter - str.begin(),
                                    str.end() - first_nonwhitespace_iter);
  auto last_nonwhitespace_iter =
      std::find_if_not(trimmed_leading.rbegin(), trimmed_leading.rend(),
                       [](char c) { return std::isspace(c); });
  return trimmed_leading.substr(
      0, trimmed_leading.rend() - last_nonwhitespace_iter);
}

}  // namespace gtx
<|endoftext|>