//+------------------------------------------------------------------+
//|                                              blTelegramToMT4.mq4 |
//|                                  Copyright 2025, MQL Development |
//|                                  https://www.mqldevelopment.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MQL Development"
#property link      "https://www.mqldevelopment.com/"
#property version   "2.0"
#property strict

#define buy "buy"
#define sell "sell"
#define MaxOrders 10000

struct msgDetails
  {
   int               msgid;
   ulong             tickt;
                     msgDetails()
     {
      msgid       = -1;
      tickt       = -1;
     }
  };

msgDetails od[MaxOrders];

input       string               Settings              = " ------------- General Settings ------------- ";   //_
input       int                  magic_no              = 333;                                                // Magic no
input       string               symbolMatch           = "GOLD:XAUUSD,BitCoin:BTCUSD";                       // Symbol Mapping (Telegram:MT4)
input       string               suffix                = "";                                                 // Account Suffix
input       string               prefix                = "";                                                 // Account Prefix
input       double               lotSize               = 0.1;                                                // Lot Size
input       double               partialClose          = 20;                                                 // Partial Closing %

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
// Global Variables
string      url1      = "http://127.0.0.1"; // "http://myapp.local";
string      header    = "Content-Type: application/json\r\nAccept: application/json\r\n";

string symbolChart[];
string symbolSnd[];
string symbolsListUserInput[];
uchar  sym1[];
uchar  sym2[];
int last_message_id = INT_MIN;
int OnInit()
  {
//--- create timer

   ushort u_sep = StringGetCharacter(",",0);
   StringSplit(symbolMatch,u_sep,symbolsListUserInput);
   ArrayResize(symbolChart,0);
   ArrayResize(symbolSnd,0);

   for(int i = 0; i < ArraySize(symbolsListUserInput); i++)
     {

      string str = symbolsListUserInput[i];

      int index  = StringFind(str,":");
      int index2 = StringLen(str);

      ArrayResize(sym1,0);
      ArrayResize(sym2,0);

      for(int j = 0; j < index; j++)
        {
         ArrayResize(sym1,ArraySize(sym1)+1);
         sym1[j] = uchar(str[j]);
        }

      int k = 0;

      for(int j = index + 1 ; j < index2; j++)
        {
         ArrayResize(sym2,ArraySize(sym2)+1);
         sym2[k] = uchar(str[j]);
         k++;
        }

      ArrayResize(symbolChart,ArraySize(symbolChart)+1);
      ArrayResize(symbolSnd,ArraySize(symbolSnd)+1);

      symbolChart[i] = CharArrayToString(sym1);
      symbolSnd[i]   = CharArrayToString(sym2);

     }

   string jsonString = GET_function(url1 + "/get-latest-message-id", header);
   StringReplace(jsonString,"},", "*");
   last_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;

   string message = getJsonStringValue(jsonString, "message");

   if(last_message_id != INT_MIN)
     {
      Print(" latest_message_id = ",last_message_id);
      Print(" result found against get-latest-message-id = ",message);
     }

   EventSetTimer(1);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   if(last_message_id == INT_MIN)
     {

      string jsonString = GET_function(url1 + "/get-latest-message-id", header);
      StringReplace(jsonString,"},", "*");
      last_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;


      if(last_message_id != INT_MIN)
        {

         string message = getJsonStringValue(jsonString, "message");

         if(last_message_id != INT_MIN)
           {
            Print(" latest_message_id = ",last_message_id);
            Print(" result found against get-latest-message-id = ",message);
           }
         execute_functionality_on_new_message(last_message_id);

        }

     }
   else
     {
      string jsonString = GET_function(url1 + "/get-latest-message-id", header);
      StringReplace(jsonString,"},", "*");
      int latest_message_id = (int)getJsonStringValue(jsonString, "id") != 0 ? (int)getJsonStringValue(jsonString, "id") : INT_MIN;

      if(last_message_id != latest_message_id)
        {
         for(int i = latest_message_id; i > last_message_id; i--)
           {
            execute_functionality_on_new_message(i);
           }
         last_message_id = latest_message_id;
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string  GET_function(string url,string headers)
  {

   string result_string = NULL;
   int timeout          = 10;  // Set the timeout value in seconds

   char result[],data[];
   string resultHeaders;
   int res = WebRequest("GET",url,headers,timeout,data,result,resultHeaders);

   if(res == 200)
     {
      result_string = CharArrayToString(result);
     }
   else
     {
      Print("content GETT: ", result_string," Error: ",GetLastError(), " res: ",res);
     }

   return result_string;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool checkExistingTrade(int message_id)
  {
   for(int i=0; i < MaxOrders; i++)
     {
      if(od[i].msgid == message_id)
        {
         return true;
        }
     }
   return false;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string getJsonStringValue(string json,string key,int addUp,string endSign)
  {
   int indexStart = StringFind(json,key)+StringLen(key)+addUp;
   int indexEnd   = StringFind(json,endSign,indexStart);
   return StringSubstr(json,indexStart,indexEnd-indexStart);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string getJsonStringValue(string json, string key)
  {
   int start = StringFind(json, "\""+key+"\"");
   if(start == -1)
      return "";

// Find colon after key
   int colon = StringFind(json, ":", start);
   if(colon == -1)
      return "";

// Find next comma or closing brace
   int endComma = StringFind(json, ",", colon);
   int endBrace = StringFind(json, "}", colon);
   int end = (endComma != -1 && (endComma < endBrace || endBrace == -1)) ? endComma : endBrace;
   if(end == -1)
      end = StringLen(json);

   string value = trim(StringSubstr(json, colon+1, end-colon-1));
// remove quotes if exist
   StringReplace(value, "\"", "");
   return value;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string trim(string text)
  {
   StringTrimLeft(text);
   StringTrimRight(text);
   return text;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void execute_functionality_on_new_message(int i)
  {

   string url = url1 + "/get-message/" + IntegerToString(i);
   string jsonString = GET_function(url, header);
   StringReplace(jsonString,"},", "*");

   string message = getJsonStringValue(jsonString,"message",4,"\"");

   int group_message_id = (int)getJsonStringValue(jsonString, "message_id");

   StringToLower(message);
   StringReplace(message,"~","#");

   if(checkExistingTrade(group_message_id) == false)
     {

      string isReplyValue = getJsonStringValue(jsonString, "is_reply");
      StringReplace(isReplyValue," ","");

      if(isReplyValue == "True")
        {

         int reply_to_msg_id = (int)getJsonStringValue(jsonString, "reply_to_msg_id");
         message = getJsonStringValue(jsonString, "message");
         StringToLower(message);

         Print(" ================ Replied Message found of message_id ================ ",reply_to_msg_id);
         Print(" ================ Message: ================ ",message);

         int ticket = getTicket(reply_to_msg_id);

         if(ticket != -1)
           {
            if(StringFind(message,"set") != -1 && StringFind(message,"stop") != -1 && StringFind(message,"loss") != -1 && StringFind(message,"entry") != -1)
              {

               if(OrderSelect(ticket,SELECT_BY_TICKET))
                 {

                  bool result = OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice(),OrderTakeProfit(),0,clrNONE);

                  if(result)
                    {
                     Print("Order Sl Modify to Open Price ", ticket);
                    }
                  else
                    {
                     Print("Error in Modify order SL : ", GetLastError()," Setting SL at: ",OrderOpenPrice()," price: ",OrderClosePrice());
                    }
                 }
              }

            if(StringFind(message,"take") != -1 && StringFind(message,"some") != -1 && StringFind(message,"partial") != -1 && StringFind(message,"profit") != -1)
              {

               if(OrderSelect(ticket,SELECT_BY_TICKET))
                 {

                  double lot = NormalizeDouble(OrderLots()*(partialClose/100),2);

                  bool result = OrderClose(ticket,lot,OrderClosePrice(),10, clrNONE);

                  if(result)
                    {
                     Print("Partially closed ", lot, " lots from order ", ticket);



                     for(int j = OrdersTotal()-1; j>=0; j--)
                       {
                        if(OrderSelect(j, SELECT_BY_POS))
                          {
                           if(OrderComment() != "")
                             {
                              string ticketToBeReplace = OrderComment();
                              StringReplace(ticketToBeReplace,"from #","");

                              if(int(ticketToBeReplace) == ticket)
                                {
                                 findAndreplaceTicketFromStructure(OrderTicket(),reply_to_msg_id);
                                }
                             }
                          }
                       }


                    }
                  else
                    {
                     Print("Error closing partial order: ", GetLastError()," lot = ",lot," OrderLots() = ",OrderLots());
                    }
                 }
              }

           }


        }

      else
        {
         if(checkExistingTrade(group_message_id) == false)
           {
            Print(" --------------- New Trade Message Found ----------------- ", " Message Id: ", group_message_id);
            StringReplace(message,"~","#");
            StringReplace(message,"##", "#");
            StringToLower(message);
            message = removeExtraSpaces(message);
            Print("Message is ",message);

            string result[];
            string tempResult[];
            int indexTemp = 0;

            StringSplit(message,'#',tempResult);

            for(int j=0; j<ArraySize(tempResult); j++)
              {
               //result[i] = StringTrimLeft(result[i]);
               //result[i] = StringTrimRight(result[i]);
               //Print("Temp Result : ", tempResult[i], " index is: ", i);
               if(HasAlphanumeric(tempResult[j]))
                 {
                  //Print(" contains alphanumeric characters.");
                  ArrayResize(result,ArraySize(result)+1);
                  result[indexTemp] = tempResult[j];
                  indexTemp++;
                 }
               else
                 {
                  //Print(" does not contain alphanumeric characters.");
                  //ArrayResize(indexToDelete,ArraySize(indexToDelete)+1);
                  //indexToDelete[indexTemp] = i;
                  //indexTemp++;
                 }
              }

            int ticket = -1;

            message(result,message,group_message_id,ticket);
            pendingMessage(result,message,group_message_id,ticket);

            addtoMessageStructure(group_message_id,message,ticket);

           }
        }
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void findAndreplaceTicketFromStructure(int ticketToBeReplace,int reply_to_msg_id)
  {
   for(int i=0; i < MaxOrders; i++)
     {
      if(od[i].msgid == reply_to_msg_id)
        {

         od[i].tickt = ticketToBeReplace;

         Print("codeOrder is partially closed so update Ticket ",ticketToBeReplace);
         break;
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int getTicket(int reply_to_msg_id)
  {
   for(int i=0; i < MaxOrders; i++)
     {
      if(od[i].msgid == reply_to_msg_id)
        {
         return int(od[i].tickt);
        }
     }
   return -1;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void message(string &result[], string message, int message_id,int & tickt)
  {
   string lineOne[]; // = result[0];
   int lineIndex = 0;
   string direction = "";
   int direction_index = -1;
   string symbol = "";

   if(ArraySize(result) >= 1)
     {
      StringSplit(result[0], ' ', lineOne);
      if(StringFind(result[0], "now", 0) != -1)
         if(((StringFind(result[0], "buy", 0) != -1) || (StringFind(result[0], "sell", 0) != -1)))
           {
            Print(" ------------------------------- Active Message ---------------------------------- ");
            for(int i=0; i<ArraySize(lineOne); i++)
              {
               if(HasAlphanumeric(lineOne[i]))
                 {
                  ArrayResize(lineOne,ArraySize(lineOne)+1);
                  lineOne[lineIndex] = lineOne[i];
                  Print("Direction and Symbol: ", lineOne[lineIndex], " index is: ", lineIndex);

                  if(lineOne[lineIndex] == buy || lineOne[lineIndex] == sell)
                    {
                     direction = lineOne[lineIndex];
                     direction_index = lineIndex;
                     //Print(" Direction is: ", direction, " Direction Index: ", direction_index);
                    }
                  lineIndex++;
                 }
              }
            if(ArraySize(lineOne) >= 2)
              {
               if(direction_index == 0)
                 {
                  symbol = lineOne[1];
                  StringToUpper(symbol);

                  //Print(" This is Message format One (1). Where Direction is: ", direction, " Symbol: ", symbol);
                 }
               else
                  if(direction_index > 0)
                    {
                     symbol = lineOne[0];
                     StringToUpper(symbol);

                     //Print(" This is Message format One (1). Where Direction is: ", direction, " Symbol: ", symbol);
                    }
              }
            symbol = symbolMapping(symbol);

            double sl = 0;
            double tp = 0; // = result[0];
            for(int i=0 ; i < ArraySize(result); i++)
              {
               // result[i] = StringTrimLeft(result[i]);
               // result[i] = StringTrimRight(result[i]);
               // Print("Result : ", result[i], " index is: ", i);
               if((StringFind(result[i], "sl", 0) != -1))
                 {
                  string tempSl[];
                  StringReplace(result[i],":", " ");
                  result[i] = trimString(result[i]);
                  result[i] = spaceRemove(result[i]);
                  //Print(" Sl String: ", result[i]);
                  StringSplit(result[i], ' ', tempSl);
                  if(ArraySize(tempSl) >= 2)
                     sl = (double) tempSl[ArraySize(tempSl) - 1];
                  Print("Sl : ", sl);
                 }
               if((StringFind(result[i], "tp", 0) != -1))
                 {
                  Print("Tp : ", result[i], " index is: ", i);
                  string tempTp[];
                  StringReplace(result[i],":", " ");
                  result[i] = trimString(result[i]);
                  result[i] = spaceRemove(result[i]);
                  Print("Tp After String Replace : ", result[i], " index is: ", i);
                  StringSplit(result[i], ' ', tempTp);
                  //double tp = (double) tempTp[1];
                  for(int j=0 ; j < ArraySize(tempTp); j++)
                    {
                     Print(" Data is: ", tempTp[j]);
                    }
                  if(ArraySize(tempTp) >= 2)
                     tp = (double) tempTp[ArraySize(tempTp) - 1];
                  Print("Tp : ", tp);
                 }
              }
            Print("Side:", direction, " Symbol: ", symbol, " Tp: ", tp, " Sl: ", sl, " Message Id: ", message_id);

            if(direction == buy)
              {
               tickt = placeBuyTrade(symbol, OP_BUY, SymbolInfoDouble(symbol, SYMBOL_ASK), tp, sl, message_id, lotSize);
              }

            if(direction == sell)
              {
               tickt = placeSellTrade(symbol, OP_SELL, SymbolInfoDouble(symbol, SYMBOL_BID), tp, sl, message_id, lotSize);
              }
           }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void pendingMessage(string &result[], string message, int message_id,int & tickt)
  {
   string lineOne[]; // = result[0];
   int lineIndex = 0;
   string direction = "";
   int direction_index = -1;
   string symbol = "";

   if(ArraySize(result) >= 1)
     {
      StringSplit(result[0], ' ', lineOne);
      if(StringFind(result[0], "limit", 0) != -1)
         if(((StringFind(result[0], "buy", 0) != -1) || (StringFind(result[0], "sell", 0) != -1)))
           {
            Print(" ------------------------------- Pending Message ---------------------------------- ");
            for(int i=0; i<ArraySize(lineOne); i++)
              {
               if(HasAlphanumeric(lineOne[i]))
                 {
                  ArrayResize(lineOne,ArraySize(lineOne)+1);
                  lineOne[lineIndex] = lineOne[i];
                  Print("Direction and Symbol: ", lineOne[lineIndex], " index is: ", lineIndex);

                  if(lineOne[lineIndex] == buy || lineOne[lineIndex] == sell)
                    {
                     direction = lineOne[lineIndex];
                     direction_index = lineIndex;
                     //Print(" Direction is: ", direction, " Direction Index: ", direction_index);
                    }
                  lineIndex++;
                 }
              }
            if(ArraySize(lineOne) >= 2)
              {
               if(direction_index == 0)
                 {
                  symbol = lineOne[1];
                  StringToUpper(symbol);

                  //Print(" This is Message format One (1). Where Direction is: ", direction, " Symbol: ", symbol);
                 }
               else
                  if(direction_index > 0)
                    {
                     symbol = lineOne[0];
                     StringToUpper(symbol);

                     //Print(" This is Message format One (1). Where Direction is: ", direction, " Symbol: ", symbol);
                    }
              }
            symbol = symbolMapping(symbol);

            double price = 0;
            double sl = 0;
            double tp = 0; // = result[0];
            for(int i=0 ; i < ArraySize(result); i++)
              {
               // result[i] = StringTrimLeft(result[i]);
               // result[i] = StringTrimRight(result[i]);
               // Print("Result : ", result[i], " index is: ", i);
               if((StringFind(result[i], "open", 0) != -1))
                 {
                  string tempOpen[];
                  StringReplace(result[i],":", " ");
                  result[i] = trimString(result[i]);
                  result[i] = spaceRemove(result[i]);
                  //Print(" Sl String: ", result[i]);
                  StringSplit(result[i], ' ', tempOpen);
                  if(ArraySize(tempOpen) >= 2)
                     price = (double) tempOpen[ArraySize(tempOpen) - 1];
                  Print("Open : ", price);
                 }
               if((StringFind(result[i], "sl", 0) != -1))
                 {
                  string tempSl[];
                  StringReplace(result[i],":", " ");
                  result[i] = trimString(result[i]);
                  result[i] = spaceRemove(result[i]);
                  //Print(" Sl String: ", result[i]);
                  StringSplit(result[i], ' ', tempSl);
                  if(ArraySize(tempSl) >= 2)
                     sl = (double) tempSl[ArraySize(tempSl) - 1];
                  Print("Sl : ", sl);
                 }
               if((StringFind(result[i], "tp", 0) != -1))
                 {
                  Print("Tp : ", result[i], " index is: ", i);
                  string tempTp[];
                  StringReplace(result[i],":", " ");
                  result[i] = trimString(result[i]);
                  result[i] = spaceRemove(result[i]);
                  Print("Tp After String Replace : ", result[i], " index is: ", i);
                  StringSplit(result[i], ' ', tempTp);
                  //double tp = (double) tempTp[1];
                  for(int j=0 ; j < ArraySize(tempTp); j++)
                    {
                     Print(" Data is: ", tempTp[j]);
                    }
                  if(ArraySize(tempTp) >= 2)
                     tp = (double) tempTp[ArraySize(tempTp) - 1];
                  Print("Tp : ", tp);
                 }
              }
            ENUM_ORDER_TYPE pending_side = 0;
            if(direction == buy)
              {
               if(price > SymbolInfoDouble(symbol, SYMBOL_ASK))
                 {
                  pending_side = OP_BUYSTOP;
                 }
               else
                 {
                  pending_side = OP_BUYLIMIT;
                 }
              }
            if(direction == sell)
              {
               if(price < SymbolInfoDouble(symbol, SYMBOL_BID))
                 {
                  pending_side = OP_SELLSTOP;
                 }
               else
                 {
                  pending_side = OP_SELLLIMIT;
                 }
              }
            Print("Side:", direction, " Type: ", pending_side, " Symbol: ", symbol, " Tp: ", tp, " Sl: ", sl, " Message Id: ", message_id);

            if(direction == buy)
              {
               tickt = placeBuyTrade(symbol, pending_side, price, tp, sl, message_id, lotSize);
              }

            if(direction == sell)
              {
               tickt = placeSellTrade(symbol, pending_side, price, tp, sl, message_id, lotSize);
              }
           }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int placeBuyTrade(string symbol, ENUM_ORDER_TYPE orderType, double priceIs,double tp,double sl, int messageId, double lot_size)
  {

   double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
   double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
   double buySl  = sl;
   double buyTp  = tp;


   int ticket = OrderSend(symbol, orderType, lot_size, priceIs, 3, buySl, buyTp, "Buy Trade Placed.", magic_no, 0, clrBlue);
   Print("Buy order Print: Stop Loss: ", buySl, " Take profit: ", buyTp);
   if(ticket < 0)
     {
      Print("Buy Order Failed ", GetLastError());
     }
   else
     {
      Print(" Buy Order Is Placed Sucessfully ");
     }

   return ticket;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int placeSellTrade(string symbol, ENUM_ORDER_TYPE orderType, double priceIs,double tp,double sl, int messageId, double lot_size)
  {

   double ask = SymbolInfoDouble(symbol,SYMBOL_ASK);
   double bid = SymbolInfoDouble(symbol,SYMBOL_BID);
   double sellSl = sl;
   double sellTp = tp;

   int ticket = OrderSend(symbol, orderType, lot_size, priceIs, 3, sellSl, sellTp, "Sell Trade Placed.", magic_no, 0, clrRed);
   if(ticket < 0)
     {
      Print("Sell Order Failed ", GetLastError());
     }
   else
     {
      Print(" Sell Order Is Placed Sucessfully ");
     }
   return ticket;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void addtoMessageStructure(int message_id,string message,ulong ticket)
  {
   for(int i=0; i < MaxOrders; i++)
     {
      if(od[i].msgid == -1)
        {
         od[i].msgid = message_id;
         od[i].tickt = ticket;
         StringToLower(message);
         Print(" Message ID ",message_id,"  of Message = ",message," Having Ticket ",ticket," is added To Structure :: ");
         break;
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string trimString(string inputt)
  {
// Remove spaces from the left and right sides
   int startt = 0;
   int end = StringLen(inputt) - 1;

// Find the first non-space character
   while(startt <= end && StringGetCharacter(inputt, startt) == ' ')
      startt++;

// Find the last non-space character
   while(end >= startt && StringGetCharacter(inputt, end) == ' ')
      end--;

// Extract the substring without leading or trailing spaces
   return StringSubstr(inputt, startt, end - startt + 1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string spaceRemove(string inputt)
  {
   int len = StringLen(inputt);
   string out = "";
   bool inSpace = false;

   for(int i = 0; i < len; i++)
     {
      ushort ch = StringGetCharacter(inputt, i);
      // treat space, tab, CR, LF as whitespace
      bool isSpace = (ch == 32 || ch == 9 || ch == 10 || ch == 13);

      if(isSpace)
        {
         // mark that we are inside a whitespace run, but don't append yet
         inSpace = true;
         continue;
        }

      // when we hit a non-space after whitespace, add a single space (if out not empty)
      if(inSpace && StringLen(out) > 0)
         out += " ";

      // append the non-space character (use substr to preserve unicode chars)
      out += StringSubstr(inputt, i, 1);

      inSpace = false;
     }

   return(out);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string removeExtraSpaces(string str)
  {
   string result = "";
   int len = StringLen(str);
   bool lastWasSpace = false;

   for(int i = 0; i < len; i++)
     {
      string currentChar = StringSubstr(str, i, 1);

      if(currentChar == " ")
        {
         // Skip adding this space if the last character was also a space
         if(lastWasSpace)
            continue;

         lastWasSpace = true;
        }
      else
        {
         lastWasSpace = false;
        }

      result += currentChar;
     }

   return result;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool HasAlphanumeric(string str)
  {
//Print("String Length: ", StringLen(str));
   for(int i = 0; i <= StringLen(str); i++)
     {
      //Print("Here ", StringLen(str));
      if(IsAlphanumeric((char)str[i]))
        {
         return true;
         break;
        }
     }
   return false;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool IsAlphanumeric(char c)
  {
   if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
      return true;
   return false;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string symbolMapping(string symbol)
  {
   for(int k = 0; k < ArraySize(symbolChart); k++)
     {
      StringToUpper(symbolChart[k]);
      if(symbol == symbolChart[k])
        {
         symbol = symbolSnd[k];
        }
     }
   symbol = prefix + symbol + suffix;
   return symbol;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
