mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-09-01 11:39:18 +02:00
Merge remote-tracking branch 'tmj-fstate/mover_in_c++' into mover_in_c++
This commit is contained in:
@@ -867,7 +867,8 @@ public:
|
||||
/*
|
||||
int BrakeStatus = b_off; //0 - odham, 1 - ham., 2 - uszk., 4 - odluzniacz, 8 - antyposlizg, 16 - uzyte EP, 32 - pozycja R, 64 - powrot z R
|
||||
*/
|
||||
bool EmergencyBrakeFlag = false; /*hamowanie nagle*/
|
||||
bool AlarmChainFlag = false; // manual emergency brake
|
||||
bool RadioStopFlag = false; /*hamowanie nagle*/
|
||||
int BrakeDelayFlag = 0; /*nastawa opoznienia ham. osob/towar/posp/exp 0/1/2/4*/
|
||||
int BrakeDelays = 0; /*nastawy mozliwe do uzyskania*/
|
||||
int BrakeOpModeFlag = 0; /*nastawa trybu pracy PS/PN/EP/MED 1/2/4/8*/
|
||||
@@ -1024,7 +1025,7 @@ public:
|
||||
bool IncBrakeLevel(); // wersja na użytek AI
|
||||
bool DecBrakeLevel();
|
||||
bool ChangeCab(int direction);
|
||||
bool CurrentSwitch(int direction);
|
||||
bool CurrentSwitch(bool const State);
|
||||
void UpdateBatteryVoltage(double dt);
|
||||
double ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, const TLocation &NewLoc, TRotation &NewRot); //oblicza przesuniecie pojazdu
|
||||
double FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, const TLocation &NewLoc, TRotation &NewRot); //oblicza przesuniecie pojazdu - wersja zoptymalizowana
|
||||
@@ -1082,7 +1083,8 @@ public:
|
||||
bool IncManualBrakeLevel(int CtrlSpeed);
|
||||
bool DecManualBrakeLevel(int CtrlSpeed);
|
||||
bool DynamicBrakeSwitch(bool Switch);
|
||||
bool EmergencyBrakeSwitch(bool Switch);
|
||||
bool RadiostopSwitch(bool Switch);
|
||||
bool AlarmChainSwitch( bool const State );
|
||||
bool AntiSlippingBrake(void);
|
||||
bool BrakeReleaser(int state);
|
||||
bool SwitchEPBrake(int state);
|
||||
@@ -1109,6 +1111,8 @@ public:
|
||||
double Adhesive(double staticfriction);
|
||||
double TractionForce(double dt);
|
||||
double FrictionForce(double R, int TDamage);
|
||||
double BrakeForceR(double ratio, double velocity);
|
||||
double BrakeForceP(double press, double velocity);
|
||||
double BrakeForce(const TTrackParam &Track);
|
||||
double CouplerForce(int CouplerN, double dt);
|
||||
void CollisionDetect(int CouplerN, double dt);
|
||||
|
||||
@@ -692,13 +692,13 @@ bool TMoverParameters::ChangeCab(int direction)
|
||||
return false;
|
||||
};
|
||||
|
||||
bool TMoverParameters::CurrentSwitch(int direction)
|
||||
{ // rozruch wysoki (true) albo niski (false)
|
||||
// rozruch wysoki (true) albo niski (false)
|
||||
bool
|
||||
TMoverParameters::CurrentSwitch(bool const State) {
|
||||
// Ra: przeniosłem z Train.cpp, nie wiem czy ma to sens
|
||||
if (MaxCurrentSwitch(direction != 0))
|
||||
{
|
||||
if (MaxCurrentSwitch(State)) {
|
||||
if (TrainType != dt_EZT)
|
||||
return (MinCurrentSwitch(direction != 0));
|
||||
return (MinCurrentSwitch(State));
|
||||
}
|
||||
// TBD, TODO: split off shunt mode toggle into a separate command? It doesn't make much sense to have these two together like that
|
||||
// dla 2Ls150
|
||||
@@ -706,14 +706,14 @@ bool TMoverParameters::CurrentSwitch(int direction)
|
||||
&& ( true == ShuntModeAllow )
|
||||
&& ( ActiveDir == 0 ) ) {
|
||||
// przed ustawieniem kierunku
|
||||
ShuntMode = ( direction != 0 );
|
||||
ShuntMode = State;
|
||||
return true;
|
||||
}
|
||||
// for SM42/SP42
|
||||
if( ( EngineType == DieselElectric )
|
||||
&& ( true == ShuntModeAllow )
|
||||
&& ( MainCtrlPos == 0 ) ) {
|
||||
ShuntMode = ( direction != 0 );
|
||||
ShuntMode = State;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1082,7 +1082,7 @@ void TMoverParameters::CollisionDetect(int CouplerN, double dt)
|
||||
EventFlag = true;
|
||||
|
||||
if ((coupler.CouplingFlag & ctrain_pneumatic) == ctrain_pneumatic)
|
||||
EmergencyBrakeFlag = true; // hamowanie nagle - zerwanie przewodow hamulcowych
|
||||
AlarmChainFlag = true; // hamowanie nagle - zerwanie przewodow hamulcowych
|
||||
coupler.CouplingFlag = 0;
|
||||
|
||||
switch (CouplerN) // wyzerowanie flag podlaczenia ale ciagle sa wirtualnie polaczone
|
||||
@@ -2188,7 +2188,7 @@ void TMoverParameters::SecuritySystemCheck(double dt)
|
||||
// obsady
|
||||
// poza tym jest zdefiniowany we wszystkich 3 członach EN57
|
||||
if ((!Radio))
|
||||
EmergencyBrakeSwitch(false);
|
||||
RadiostopSwitch(false);
|
||||
|
||||
if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0) &&
|
||||
(Battery)) // Ra: EZT ma teraz czuwak w rozrządczym
|
||||
@@ -2259,7 +2259,7 @@ void TMoverParameters::SecuritySystemCheck(double dt)
|
||||
}
|
||||
else if (!Battery)
|
||||
{ // wyłączenie baterii deaktywuje sprzęt
|
||||
EmergencyBrakeSwitch(false);
|
||||
RadiostopSwitch(false);
|
||||
// SecuritySystem.Status = 0; //deaktywacja czuwaka
|
||||
}
|
||||
}
|
||||
@@ -2623,7 +2623,7 @@ bool TMoverParameters::DecBrakeLevelOld(void)
|
||||
bool TMoverParameters::IncLocalBrakeLevel(int CtrlSpeed)
|
||||
{
|
||||
bool IBL;
|
||||
if ((LocalBrakePos < LocalBrakePosNo) /*and (BrakeCtrlPos<1)*/)
|
||||
if ((LocalBrakePos < LocalBrakePosNo) /*and (BrakeCtrlPos<1)*/)
|
||||
{
|
||||
while ((LocalBrakePos < LocalBrakePosNo) && (CtrlSpeed > 0))
|
||||
{
|
||||
@@ -2777,34 +2777,49 @@ bool TMoverParameters::DynamicBrakeSwitch(bool Switch)
|
||||
// Q: 20160711
|
||||
// włączenie / wyłączenie hamowania awaryjnego
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::EmergencyBrakeSwitch(bool Switch)
|
||||
bool TMoverParameters::RadiostopSwitch(bool Switch)
|
||||
{
|
||||
bool EBS;
|
||||
if ((BrakeSystem != Individual) && (BrakeCtrlPosNo > 0))
|
||||
{
|
||||
if ((!EmergencyBrakeFlag) && Switch)
|
||||
{
|
||||
EmergencyBrakeFlag = Switch;
|
||||
if( ( BrakeSystem != Individual )
|
||||
&& ( BrakeCtrlPosNo > 0 ) ) {
|
||||
|
||||
if( ( true == Switch )
|
||||
&& ( false == RadioStopFlag ) ) {
|
||||
RadioStopFlag = Switch;
|
||||
EBS = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((abs(V) < 0.1) &&
|
||||
(Switch == false)) // odblokowanie hamulca bezpieczenistwa tylko po zatrzymaniu
|
||||
{
|
||||
EmergencyBrakeFlag = Switch;
|
||||
else {
|
||||
if( ( Switch == false )
|
||||
&& ( std::abs( V ) < 0.1 ) ) {
|
||||
// odblokowanie hamulca bezpieczenistwa tylko po zatrzymaniu
|
||||
RadioStopFlag = Switch;
|
||||
EBS = true;
|
||||
}
|
||||
else
|
||||
else {
|
||||
EBS = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
EBS = false; // nie ma hamulca bezpieczenstwa gdy nie ma hamulca zesp.
|
||||
else {
|
||||
// nie ma hamulca bezpieczenstwa gdy nie ma hamulca zesp.
|
||||
EBS = false;
|
||||
}
|
||||
|
||||
return EBS;
|
||||
}
|
||||
|
||||
bool TMoverParameters::AlarmChainSwitch( bool const State ) {
|
||||
|
||||
bool stateswitched { false };
|
||||
|
||||
if( AlarmChainFlag != State ) {
|
||||
// simple routine for the time being
|
||||
AlarmChainFlag = State;
|
||||
stateswitched = true;
|
||||
}
|
||||
return stateswitched;
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Q: 20160710
|
||||
// hamowanie przeciwpoślizgowe
|
||||
@@ -3282,12 +3297,19 @@ void TMoverParameters::UpdatePipePressure(double dt)
|
||||
Pipe2->Flow(dpMainValve);
|
||||
}
|
||||
|
||||
// if(EmergencyBrakeFlag)and(BrakeCtrlPosNo=0)then //ulepszony hamulec bezp.
|
||||
if ((EmergencyBrakeFlag) || (TestFlag(SecuritySystem.Status, s_SHPebrake)) ||
|
||||
(TestFlag(SecuritySystem.Status, s_CAebrake)) ||
|
||||
(s_CAtestebrake == true) ||
|
||||
(TestFlag(EngDmgFlag, 32)) /* or (not Battery)*/) // ulepszony hamulec bezp.
|
||||
dpMainValve = dpMainValve + PF(0, PipePress, 0.15) * dt;
|
||||
// ulepszony hamulec bezp.
|
||||
if( ( true == RadioStopFlag )
|
||||
|| ( true == AlarmChainFlag )
|
||||
|| ( true == TestFlag( SecuritySystem.Status, s_SHPebrake ) )
|
||||
|| ( true == TestFlag( SecuritySystem.Status, s_CAebrake ) )
|
||||
/*
|
||||
// NOTE: disabled because 32 is 'load destroyed' flag, what does this have to do with emergency brake?
|
||||
// (if it's supposed to be broken coupler, such event sets alarmchainflag instead when appropriate)
|
||||
|| ( true == TestFlag( EngDmgFlag, 32 ) )
|
||||
*/
|
||||
|| ( true == s_CAtestebrake ) ) {
|
||||
dpMainValve = dpMainValve + PF( 0, PipePress, 0.15 ) * dt;
|
||||
}
|
||||
// 0.2*Spg
|
||||
Pipe->Flow(-dpMainValve);
|
||||
Pipe->Flow(-(PipePress)*0.001 * dt);
|
||||
@@ -3766,6 +3788,41 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
|
||||
//};
|
||||
}
|
||||
|
||||
double TMoverParameters::BrakeForceR(double ratio, double velocity)
|
||||
{
|
||||
double press = 0;
|
||||
if (MBPM>2)
|
||||
{
|
||||
press = MaxBrakePress[1] + (MaxBrakePress[3] - MaxBrakePress[1]) * std::min(1.0, (TotalMass - Mass) / (MBPM - Mass));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MaxBrakePress[1] > 0.1)
|
||||
{
|
||||
press = MaxBrakePress[LoadFlag];
|
||||
}
|
||||
else
|
||||
{
|
||||
press = MaxBrakePress[3];
|
||||
if (DynamicBrakeType == dbrake_automatic)
|
||||
ratio = ratio + (1.5 - ratio)*std::min(1.0, Vel*0.02);
|
||||
if ((BrakeDelayFlag&bdelay_R) && (BrakeMethod%128 != bp_Cosid) && (BrakeMethod % 128 != bp_D1) && (BrakeMethod % 128 != bp_D2) && (Power<1) && (velocity<40))
|
||||
ratio = ratio / 2;
|
||||
}
|
||||
|
||||
}
|
||||
return BrakeForceP(press*ratio, velocity);
|
||||
}
|
||||
|
||||
double TMoverParameters::BrakeForceP(double press, double velocity)
|
||||
{
|
||||
double BFP = 0;
|
||||
double K = (((press * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj) * BrakeRigEff;
|
||||
K *= static_cast<double>(BrakeCylNo) / (NAxles * std::max(1, NBpA));
|
||||
BFP = Hamulec->GetFC(velocity, K)*K*(NAxles * std::max(1, NBpA)) * 1000;
|
||||
return BFP;
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Q: 20160713
|
||||
// oblicza siłę na styku koła i szyny
|
||||
@@ -3809,7 +3866,7 @@ double TMoverParameters::BrakeForce(const TTrackParam &Track)
|
||||
Ntotal = u * BrakeRigEff;
|
||||
else
|
||||
{
|
||||
u = (BrakePress * P2FTrans) * BrakeCylMult[0] - BrakeSlckAdj;
|
||||
u = ((BrakePress * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj;
|
||||
if (u * (2.0 - BrakeRigEff) < Ntotal) // histereza na nacisku klockow
|
||||
Ntotal = u * (2.0 - BrakeRigEff);
|
||||
}
|
||||
@@ -3863,6 +3920,9 @@ double TMoverParameters::FrictionForce(double R, int TDamage)
|
||||
return FF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// *************************************************************************************************
|
||||
// Q: 20160713
|
||||
// Oblicza przyczepność
|
||||
@@ -3971,17 +4031,17 @@ double TMoverParameters::CouplerForce(int CouplerN, double dt)
|
||||
|
||||
// blablabla
|
||||
// ABu: proby znalezienia problemu ze zle odbijajacymi sie skladami
|
||||
//***if (Couplers[CouplerN].CouplingFlag=ctrain_virtual) and (newdist>0) then
|
||||
//if (Couplers[CouplerN].CouplingFlag=ctrain_virtual) and (newdist>0) then
|
||||
if ((Couplers[CouplerN].CouplingFlag == ctrain_virtual) && (Couplers[CouplerN].CoupleDist > 0))
|
||||
{
|
||||
CF = 0; // kontrola zderzania sie - OK
|
||||
ScanCounter++;
|
||||
if ((newdist > MaxDist) || ((ScanCounter > MaxCount) && (newdist > MinDist)))
|
||||
//***if (tempdist>MaxDist) or ((ScanCounter>MaxCount)and(tempdist>MinDist)) then
|
||||
//if (tempdist>MaxDist) or ((ScanCounter>MaxCount)and(tempdist>MinDist)) then
|
||||
{ // zerwij kontrolnie wirtualny sprzeg
|
||||
// Connected.Couplers[CNext].Connected:=nil; //Ra: ten podłączony niekoniecznie jest
|
||||
// wirtualny
|
||||
Couplers[CouplerN].Connected = NULL;
|
||||
// Couplers[CouplerN].Connected = NULL;
|
||||
ScanCounter = static_cast<int>(Random(500.0)); // Q: TODO: cy dobrze przetlumaczone?
|
||||
// WriteLog(FloatToStr(ScanCounter));
|
||||
}
|
||||
@@ -4612,36 +4672,26 @@ double TMoverParameters::TractionForce(double dt)
|
||||
else
|
||||
tmp = 4; // szybkie malenie, powolne wzrastanie
|
||||
}
|
||||
// if SlippingWheels then begin PosRatio:=0; tmp:=10; SandDoseOn;
|
||||
// end;//przeciwposlizg
|
||||
|
||||
// if(Flat)then //PRZECIWPOŚLIZG
|
||||
dmoment = eimv[eimv_Fful];
|
||||
// else
|
||||
// dmoment:=eimc[eimc_p_F0]*0.99;
|
||||
// NOTE: the commands to operate the sandbox are likely to conflict with other similar ai decisions
|
||||
// TODO: gather these in single place so they can be resolved together
|
||||
if ((abs((PosRatio + 9.66 * dizel_fill) * dmoment * 100) >
|
||||
0.95 * Adhesive(RunningTrack.friction) * TotalMassxg))
|
||||
{
|
||||
if( ( std::abs( ( PosRatio + 9.66 * dizel_fill ) * dmoment * 100 ) > 0.95 * Adhesive( RunningTrack.friction ) * TotalMassxg ) ) {
|
||||
PosRatio = 0;
|
||||
tmp = 4;
|
||||
Sandbox( true, range::local );
|
||||
} // przeciwposlizg
|
||||
if ((abs((PosRatio + 9.80 * dizel_fill) * dmoment * 100) >
|
||||
0.95 * Adhesive(RunningTrack.friction) * TotalMassxg))
|
||||
{
|
||||
if( ( std::abs( ( PosRatio + 9.80 * dizel_fill ) * dmoment * 100 ) > 0.95 * Adhesive( RunningTrack.friction ) * TotalMassxg ) ) {
|
||||
PosRatio = 0;
|
||||
tmp = 9;
|
||||
} // przeciwposlizg
|
||||
if( ( SlippingWheels ) ) {
|
||||
PosRatio = 0;
|
||||
tmp = 9;
|
||||
Sandbox( true, range::local );
|
||||
} // przeciwposlizg
|
||||
if ((SlippingWheels))
|
||||
{
|
||||
// PosRatio = -PosRatio * 0; // serio -0 ???
|
||||
PosRatio = 0;
|
||||
tmp = 9;
|
||||
Sandbox( true, range::local );
|
||||
} // przeciwposlizg
|
||||
else {
|
||||
// switch sandbox off
|
||||
Sandbox( false, range::local );
|
||||
}
|
||||
|
||||
dizel_fill += Max0R(Min0R(PosRatio - dizel_fill, 0.1), -0.1) * 2 *
|
||||
(tmp /*2{+4*byte(PosRatio<dizel_fill)*/) *
|
||||
@@ -8238,7 +8288,7 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
}
|
||||
else if (Command == "Emergency_brake")
|
||||
{
|
||||
if (EmergencyBrakeSwitch(floor(CValue1) == 1)) // YB: czy to jest potrzebne?
|
||||
if (RadiostopSwitch(floor(CValue1) == 1)) // YB: czy to jest potrzebne?
|
||||
OK = true;
|
||||
else
|
||||
OK = false;
|
||||
|
||||
@@ -2372,6 +2372,11 @@ double TFV4aM::GetPos(int i)
|
||||
return pos_table[i];
|
||||
}
|
||||
|
||||
double TFV4aM::GetCP()
|
||||
{
|
||||
return TP;
|
||||
}
|
||||
|
||||
double TFV4aM::LPP_RP(double pos) // cisnienie z zaokraglonej pozycji;
|
||||
{
|
||||
int const i_pos = 2 + std::floor( pos ); // zaokraglone w dol
|
||||
|
||||
@@ -551,7 +551,7 @@ class TFV4aM : public TDriverHandle {
|
||||
void SetReductor(double nAdj)/*override*/;
|
||||
double GetSound(int i)/*override*/;
|
||||
double GetPos(int i)/*override*/;
|
||||
|
||||
double GetCP();
|
||||
inline TFV4aM() :
|
||||
TDriverHandle()
|
||||
{}
|
||||
|
||||
@@ -48,40 +48,30 @@ std::string Now() {
|
||||
return converter.str();
|
||||
}
|
||||
|
||||
bool TestFlag(int Flag, int Value)
|
||||
{
|
||||
if ((Flag & Value) == Value)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
bool SetFlag( int &Flag, int const Value ) {
|
||||
|
||||
bool SetFlag(int &Flag, int Value) {
|
||||
|
||||
if (Value > 0)
|
||||
{
|
||||
if ((Flag & Value) == 0)
|
||||
{
|
||||
if( Value > 0 ) {
|
||||
if( false == TestFlag( Flag, Value ) ) {
|
||||
Flag |= Value;
|
||||
return true; // true, gdy było wcześniej 0 i zostało ustawione
|
||||
}
|
||||
}
|
||||
else if (Value < 0)
|
||||
{
|
||||
Value = abs(Value);
|
||||
if ((Flag & Value) == Value)
|
||||
{
|
||||
Flag &= ~Value; // Value jest ujemne, czyli zerowanie flagi
|
||||
return true; // true, gdy było wcześniej 1 i zostało wyzerowane
|
||||
}
|
||||
else if( Value < 0 ) {
|
||||
// Value jest ujemne, czyli zerowanie flagi
|
||||
return ClearFlag( Flag, -Value );
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnSetFlag(int &Flag, int Value)
|
||||
{
|
||||
Flag &= ~Value;
|
||||
return true;
|
||||
bool ClearFlag( int &Flag, int const Value ) {
|
||||
|
||||
if( true == TestFlag( Flag, Value ) ) {
|
||||
Flag &= ~Value;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline double Random(double a, double b)
|
||||
@@ -124,14 +114,14 @@ std::string DWE(std::string s) /*Delete After Equal sign*/
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string ExchangeCharInString( std::string const &Source, char const &From, char const &To )
|
||||
std::string ExchangeCharInString( std::string const &Source, char const From, char const To )
|
||||
{
|
||||
std::string replacement; replacement.reserve( Source.size() );
|
||||
std::for_each(Source.cbegin(), Source.cend(), [&](char const idx) {
|
||||
if( idx != From ) { replacement += idx; }
|
||||
else {
|
||||
if( To != NULL ) { replacement += To; } }
|
||||
} );
|
||||
std::for_each(
|
||||
std::begin( Source ), std::end( Source ),
|
||||
[&](char const idx) {
|
||||
if( idx != From ) { replacement += idx; }
|
||||
else { replacement += To; } } );
|
||||
|
||||
return replacement;
|
||||
}
|
||||
|
||||
@@ -63,9 +63,9 @@ inline double BorlandTime()
|
||||
std::string Now();
|
||||
|
||||
/*funkcje logiczne*/
|
||||
bool TestFlag(int Flag, int Value);
|
||||
bool SetFlag( int & Flag, int Value);
|
||||
bool UnSetFlag(int &Flag, int Value);
|
||||
inline bool TestFlag( int const Flag, int const Value ) { return ( ( Flag & Value ) == Value ); }
|
||||
bool SetFlag( int &Flag, int const Value);
|
||||
bool ClearFlag(int &Flag, int const Value);
|
||||
|
||||
bool FuzzyLogic(double Test, double Threshold, double Probability);
|
||||
/*jesli Test>Threshold to losowanie*/
|
||||
@@ -75,7 +75,7 @@ bool FuzzyLogicAI(double Test, double Threshold, double Probability);
|
||||
/*operacje na stringach*/
|
||||
std::string DUE(std::string s); /*Delete Until Equal sign*/
|
||||
std::string DWE(std::string s); /*Delete While Equal sign*/
|
||||
std::string ExchangeCharInString(std::string const &s, const char &aim, const char &target); // zamienia jeden znak na drugi
|
||||
std::string ExchangeCharInString( std::string const &Source, char const From, char const To ); // zamienia jeden znak na drugi
|
||||
std::vector<std::string> &Split(const std::string &s, char delim, std::vector<std::string> &elems);
|
||||
std::vector<std::string> Split(const std::string &s, char delim);
|
||||
//std::vector<std::string> Split(const std::string &s);
|
||||
|
||||
Reference in New Issue
Block a user