kosovnn / local_RC 2ss_boulder_edit+new(id=name+date)

// ==UserScript==
// @name     local_RC 2ss_boulder_edit+new(id=name+date)
// @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt
// @version  2
// @grant    GM.xmlHttpRequest
// @require  https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
//// @match    https://rc.crags.ru/spots/17/sectors/36/routes/*
//// @match    http://rc.crags.ru/spots/17/sectors/36/routes/*
// @match    http://staging.rovingclimbers.ru/spots/17/sectors/36/routes/*
// @match    https://staging.rovingclimbers.ru/spots/17/sectors/36/routes/*
// ==/UserScript==
// ==/UserScript==
let SERVER;//="http://staging.rovingclimbers.ru";
const SECT_ID=36;//северная стена трудность
const GS_MAX_NUMBER=300;// в северной стене не больше, чем столько трасс
const KIND="boulder";
const Y_LEFT=0.946;//0.001* количество пикселей по горизонтали на схеме (на самом деле важно только отношение)
const X_TOP=0.669;//0.001* количество пикселей по вертикали на схеме
const MIN=1.5;//диаметр кружочка (точнее чуть больше) в процентах по горизонтали*Y_LEFT=в процентах по вертикали*X_TOP
//const URL_GOOGLE_SPREADSHEET="https://spreadsheets.google.com/feeds/cells/1joxwmdCoP4wSaZvimDD0RbSpdxMNQvfanXxTA_RwOu8/1/public/values?alt=json";
//https://docs.google.com/spreadsheets/d/e/2PACX-1vTGWk7LBkpL5PCc7KS9Y3GyxtQ_nulmENbeq95DZFnB-AMbIN9WmCjc4e6rLQ2HYi_pInr8rwmFSqZW/pubhtml
//https://docs.google.com/spreadsheets/d/e/2PACX-1vRJgXpN0CxEllB57VpQhuyPaxt9aj21DFUpRmgMsSPQ-L321dQihXB93h_k4igyyRTXGvvrMd9RWGBD/pubhtml
//const URL_GOOGLE_SPREADSHEET_POSITION="https://spreadsheets.google.com/feeds/cells/1joxwmdCoP4wSaZvimDD0RbSpdxMNQvfanXxTA_RwOu8/3/public/values?alt=json";
const URL_GOOGLE_SPREADSHEET="https://spreadsheets.google.com/feeds/cells/1w_rwuJLGzLgZvUNH4Sh4VRThY2RzMRiyMvCVzYSdT4o/1/public/values?alt=json";
const URL_GOOGLE_SPREADSHEET_POSITION="https://spreadsheets.google.com/feeds/cells/1w_rwuJLGzLgZvUNH4Sh4VRThY2RzMRiyMvCVzYSdT4o/3/public/values?alt=json";
let URL_FOR_JSON;//=SERVER+"/api/v1/sectors/"+SECT_ID+"/routes";
let URL_FOR_REQUEST;//=SERVER+"/api/v1/routes/";//+id трассы
let POSITION;
let begin_find_new_route=2;
//Эта функция забивает значения в переменную POSITION где расположены углы скалодрома, какой номер у трассы там и т.д.
// В дальнейшем используется для вычисления координат всех трасс
function set_positiondata(){
  console.log("POSITION");
  POSITION=[];/*=[{p:{x:73,y:11},num:1,len:5,side:-1}, //и т.д. x- координата в процентах сверху, y- координата в процентах слева,
                                                        //num номер трассы, для которой задаются координаты
                                                        //len количество трасс в промежутке от этой точки до следующей
                                                        //side в какую сторону сдвигать сначала влево или вправо
                                                        //все данные хранятся в отдельной вкладке гугл-таблицы
              ];*/
  
  $.getJSON(URL_GOOGLE_SPREADSHEET_POSITION, function(values) {
    //console.log("данные для расположения");
    let tableDataPosition={};
     let data = values.feed.entry;
    //console.log(data.length);
    
     for (let i = 0; i < data.length; i++) {//здесь они добавляются
        let cell = data[i]["gs$cell"];
        let row = cell.row;
        let col = cell.col;
        let val = cell["$t"];
        tableDataPosition[row] = tableDataPosition[row] || {};
        tableDataPosition[row][col] = val;
     };
    //console.log(tableDataPosition);
         // Получить значение из ячейки (row, col) или пустую строку, если значение в ячейке не определено.
     function getCellValuePosition(row, col) {
        return (tableDataPosition[row] || {})[col] || "";
        }
   console.log(getCellValuePosition(1,1));
   for (let i = 1; getCellValuePosition(i,1)!=""; i++)
     POSITION.push({
       p:{
         x:Number(getCellValuePosition(i,1)),
         y:Number(getCellValuePosition(i,2))
        },
       v:{
         x:Number(getCellValuePosition(i,4)),
         y:Number(getCellValuePosition(i,5)),
       }
     })
     
  });
}
function normVect(a){// длина вектора (обратите внимание, не стандартная метрика, а сжатая с разной степенью по вертикали и горизонтали)
  return Math.sqrt((a.x*X_TOP)*(a.x*X_TOP)+(a.y*Y_LEFT)*(a.y*Y_LEFT));
}
function sumVect(a,b){//сложение векторов
  return {x:(a.x+b.x), y:(a.y+b.y)};
}
function multNumVect(mul,a){
  return {x:mul*a.x, y:mul*a.y};
}
function normalizeVect(a){
  return multNumVect(1/normVect(a),a);
}
function rotate(a){//поворот против часовой стрелки на 90 градусов
  let c={x:(-a.y*Y_LEFT/X_TOP),y:a.x*X_TOP/Y_LEFT};
  //console.log(c);
  //console.log("rotated");
  return c;
}
//Вычисляем координаты трассы.
function calculate_coord_absolute(POSITION,route_num){
  let num_of_sector=(route_num%100-route_num%10)/10;
  console.log("num_of_sector");
  console.log(num_of_sector);
  let vector_segment=normalizeVect(POSITION[num_of_sector].v);
  console.log("vector_segment");
  console.log(vector_segment);
  let n=(route_num%10000-route_num%100)/100-1;
  
  let n_straight=Math.round(n/2)*2;//каждая вторая трасса будет прямо на отрезке (соединяющем точки), а остальные сдвигаются вправо или влево. Это номер ближайшей вниз.
  let side=n%2;//чередует 0,1,0,1,0,1,0,1 
  //console.log("side "+side+" straight "+straight);
  let result;
  //let lambda=number_in_segment/total_in_segment;
//  let lambda=number_in_segment/N/step;
//    let lambda_straight=n_straight/N;
  result=sumVect(POSITION[num_of_sector].p,multNumVect(n*MIN/2,vector_segment));
  console.log("result");
  console.log(result);
  //let x=1/2*MIN;
  let y=Math.sqrt(3)/2*MIN;
  //let correction=sumVect(multNumVect(straight*x,vector_segment),multNumVect(straight*y,rotate(vector_segment)));//это насколько надо сдвинуться
  let correction=multNumVect(side*y,rotate(vector_segment));//это насколько надо сдвинуться 
  console.log("correction");
  console.log(correction);
    //console.log(result);
  result=sumVect(result,correction);
  console.log(result);
  let tr_vect=rotate(vector_segment);
  tr_vect=multNumVect((MIN*(route_num%10)*2),tr_vect);
  result=sumVect(result,tr_vect);
  return result; 
}

(function (window, undefined) {  
  // Сначала определяем скрипт запустился на страничке с трассой или при создании новой трассы
    let id_route;
    let current_url=document.URL;
    let b=current_url.split("/");
    console.log(b);
    if (b[b.length-1]=="")
        b.splice(-1,1);
    if (b[b.length-1]=="new")
        id_route=""
    else
        if (b[b.length-1]=="edit")
           id_route=b[b.length-2]
        else id_route=b[b.length-1];
    b=current_url.split(".ru/");
    SERVER=b[0]+".ru";
    console.log("SERVER "+SERVER);
    console.log("id_route "+id_route);
    URL_FOR_JSON=SERVER+"/api/v1/sectors/"+SECT_ID+"/routes";
    URL_FOR_REQUEST=SERVER+"/api/v1/routes/";
    let tableData = {};//сюда будут добавлены значения из гугл-таблицы.

    function theRealFunction(){
      console.log(URL_FOR_JSON);
     //В случае удачной загрузки данных из нужной гугл-странички
     $.getJSON(URL_GOOGLE_SPREADSHEET, function(values) {
      $.getJSON(URL_FOR_JSON, function(valuesRC) {

         set_positiondata();
         //console.log(POSITION);
         let lengthRC=valuesRC.payload.length;
         let data = values.feed.entry;
         for (let i = 0; i < data.length; i++) {//здесь они добавляются
            let cell = data[i]["gs$cell"];
            let row = cell.row;
            let col = cell.col;
            let val = cell["$t"];
            tableData[row] = tableData[row] || {};
            tableData[row][col] = val;
         };
         // Получить значение из ячейки (row, col) или пустую строку, если значение в ячейке не определено.
         function getCellValue(row, col) {
            return (tableData[row] || {})[col] || "";
           //return 1111;//это затычка на случай проблем с гугл-таблицей
            }
         // Получить номер строки в гугл-таблице (а точнее куда это скопировано) с данным именем(номером), сектором и датой накрутки
         function getNumRow(name,sect,date){
           let num_row = 1;
           //console.log(name);
           //console.log(getCellValue(6,2));
           
           do {
             num_row++;
            } while ((name!=getCellValue(num_row,2)||(date!=getCellValue(num_row,11))||(sect!=getCellValue(num_row,11))) && (num_row<GS_MAX_NUMBER));
           if (num_row==GS_MAX_NUMBER) {
             num_row=-1;
             console.log("Трасса в гугл-таблице с именем '"+name+" и датой накрутки"+date+"' не найдена. Такого быть не должно или она удалена.");
             };
           return num_row;
         }
         // Получить номер строки в данных RC, с данным id
         function getNumRowRC(id){
          var num_row_rc=-1;
          console.log("id"+id); 
          console.log(valuesRC.payload[6].id); 
           for (let num_row_rc = 0; num_row_rc < lengthRC; num_row_rc++) 
            if (valuesRC.payload[num_row_rc].id==id) 
              return num_row_rc;
          console.log("Трасса в RC не внесена, а у нее есть id. Такого быть не должно.");
          return -1;
         }
         // Получить номер строки в данных RC, с данным именем и датой накрутки
         function getNumRowRCbyName(name,date){
//          var num_row_rc=-1;
           for (let num_row_rc = 0; num_row_rc < lengthRC; num_row_rc++) 
            if ((valuesRC.payload[num_row_rc].name==name) && (valuesRC.payload[num_row_rc].installed_at==date)) 
              return num_row_rc;
          console.log("Трасса в RC с именем "+name+" и датой накрутки "+name+" не найдена. Надо ее внести.");
          return -1;
         }
         // Получить id трассы в данных RC, по номеру строки
         function getIdRCbyNum(num_row_rc){
          if (num_row_rc!=-1)
            return valuesRC.payload[num_row_rc].id;
          return -1;
         }
         // Получить id трассы в данных RC, с данным именем и датой накрутки
         function getIdRCbyName(name,date){
          return getIdRCbyNum(getNumRowRCbyName(name,date));
         }
         // Ищем строку в гугл-таблице, которая еще не внесена в RC
         function findNewNumRow(lengthRC,num_row_gs){//второе число с какой строчки начинать искать новые трассы.
           let new_num_row_gs=-1;
           //let num_row_gs=2;
           do {
             let num_row_rc;
             //console.log("findNewNumRow");
             for (num_row_rc = 0; num_row_rc < lengthRC; num_row_rc++) {
               if (valuesRC.payload[num_row_rc].name==getCellValue(num_row_gs,2)){
                 num_row_rc = lengthRC+1;
               };
             };
             if (num_row_rc==lengthRC+2){
               num_row_gs++;
               //alert("Совпало");
             } else {
               console.log("findNewNumRow "+getCellValue(num_row_gs,2)+".");
               console.log("findNewNumRow "+getCellValue(num_row_gs,2)+".");
               
               if ((getCellValue(num_row_gs,2)=="")||(getCellValue(num_row_gs,13)!=""))//имя пустое или трасса скручена
                 num_row_gs++
               else new_num_row_gs=num_row_gs;
             };
           } while ((num_row_gs<GS_MAX_NUMBER)&&(new_num_row_gs==-1));
           return new_num_row_gs;
         }
         // Возвращаем объект со всей информацией, которая есть про трассу.
         function getInfGS(num_row,coord){
           //console.log("route_inf_gs");
           let route_inf_gs;
           //console.log(route_inf_gs);
           route_inf_gs={
            route:{   
              sector_id: SECT_ID, //35 для трудности в северной стене
              kind:KIND,
              number:	getCellValue(num_row,1),//Номер трассы --- мой сложный номер
              name: getCellValue(num_row,2),// имя трассы --- сектор точка номер
              category:	getCellValue(num_row,3),// категория
              description: getCellValue(num_row,7),//описание
              installed_at:	getCellValue(num_row,11),//накручено
              author_id:	getCellValue(num_row,10),//id рутсеттера
//1-черные,2-зеленые,3-красные,4-синие,5-фиолетовые, 6-желтые,
//7-темно-розовые, 8-розовые,9-белые,10-бирюзовые, 11-оранжевые, 12-серые
              installed_until:getCellValue(num_row,13),//дата, когда скручена
              mark:{colors:{holds:getCellValue(num_row,12)}},// код цвета
            },
            data:{position:{top:	coord.x,left:	coord.y}}, //координаты на схеме
//            }
            };
//           alert(route_inf_gs["installed_until"]);
//           if (route_inf_gs["installed_until"]===undefined){
//             delete route_inf_gs["installed_until"];
//           }
//           console.log();
//           
           if (route_inf_gs["route"]["author_id"]=="0"){
             delete route_inf_gs["route"]["author_id"];
             //console.log(route_inf_gs);
             //alert(getCellValue(num_row,20));
             //route_inf_gs["route"]["description"]="Рутсеттер: "+getCellValue(num_row,20)+". "+route_inf_gs["route"]["description"];// добавляем в описание рутсеттера           
           }
           console.log("route_inf_gs");
           console.log(route_inf_gs);
//           alert(JSON.stringify(route_inf_gs));
           return route_inf_gs;
         }
         // Дописывем информацию о цветах зацепок, положения стрелочек (чтобы они не стерлись при перезаписи), убираем когда скручено
         function correction_of_existing(route_inf_correction,num_row_rc,coord){
           if (valuesRC.payload[num_row_rc]["data"]){
             route_inf_correction["data"]=valuesRC.payload[num_row_rc]["data"];
             route_inf_correction["data"]["position"]={top:coord.x,left:coord.y};
           };
           if (valuesRC.payload[num_row_rc]["mark"]){
             let a=route_inf_correction["route"]["mark"]["colors"]["holds"];
             route_inf_correction["route"]["mark"]=valuesRC.payload[num_row_rc]["mark"];
             route_inf_correction["route"]["mark"]["colors"]["holds"]=a;
           };  
           if (route_inf_correction["route"]["installed_until"]==""){
             delete route_inf_correction["route"]["installed_until"];
           }
           return route_inf_correction;
         }
         //пересчитываем все данные по строчкам с begin по end
         function recalculate(begin,end){
           let tempstring="";
           for (let num_row=begin;num_row<=end;num_row++){
             let coord=calculate_coord_absolute(POSITION,getCellValue(num_row,1));
             let route_inf_correction=getInfGS(num_row,coord);
             let num_row_rc=getNumRowRCbyName(getCellValue(num_row,2),getCellValue(num_row,11));
             let id_current_route=getIdRCbyNum(num_row_rc);
             if (id_current_route!=-1){
              route_inf_correction=correction_of_existing(route_inf_correction,num_row_rc,coord);
              GM.xmlHttpRequest({
                url:URL_FOR_REQUEST+id_current_route,
                method: 'PATCH',
                headers: {'Content-Type': 'application/json;charset=utf-8'},
                data: JSON.stringify(route_inf_correction),
                onload: function(response) {console.log("GM.xmlHttpRequest response");console.log(response);}
              });
             }

           }
         }
         //Создаем трассы с begin по end 
        function setnew(begin,end){
           let tempstring="";
           for (let num_row=begin;num_row<=end;num_row++){
             let coord=calculate_coord_absolute(POSITION,getCellValue(num_row,1));
             let route_inf_correction=getInfGS(num_row,coord);
             delete route_inf_correction["route"]["installed_until"];
             //let num_row_rc=getNumRowRCbyName(getCellValue(num_row,2),getCellValue(num_row,11));
             //let id_current_route=getIdRCbyNum(num_row_rc);
             //if (id_current_route!=-1){
             //route_inf_correction=correction_of_existing(route_inf_correction,num_row_rc,coord);
              GM.xmlHttpRequest({
                     url:URL_FOR_REQUEST,
                     method: 'POST',
                     headers: {'Content-Type': 'application/json;charset=utf-8'},
                     data: JSON.stringify(route_inf_correction),
                     onload: function(response) {console.log("GM.xmlHttpRequest response");console.log(response);}
              });
             //}

           }
         }
         // Помечаем в RC скрученными все, что отмечено скрученным в гугл-таблице
         function uninstall(begin,end){
//           let tempstring="";
           for (let num_row=begin;num_row<=end;num_row++){
             if (getCellValue(num_row,13)!=""){
               let id_current_route=getIdRCbyName(getCellValue(num_row,2),getCellValue(num_row,11));
			         if (id_current_route!=-1){
                alert("Для трассы "+getCellValue(num_row,2)+" c датой накрутки "+getCellValue(num_row,11)+" с id "+id_current_route+" будет установлена дата скрутки "+getCellValue(num_row,13));
                GM.xmlHttpRequest({
                  url:URL_FOR_REQUEST+id_current_route,
                  method: 'PATCH',
                  headers: {'Content-Type': 'application/json;charset=utf-8'},
                  data: JSON.stringify({route:{installed_until:getCellValue(num_row,13)}}),
                  onload: function(response) {
                    //console.log("GM.xmlHttpRequest response");console.log(response);
                  }
                });
//                tempstring=tempstring+"fetch('"+URL_FOR_REQUEST+id_current_route+"', {method: 'PATCH',headers: {'Content-Type': 'application/json;charset=utf-8'}, body: '"; 
//                tempstring=tempstring+JSON.stringify({route:{installed_until:getCellValue(num_row,13)}})+"'});\n";
               }
             }
           }
//           console.log(tempstring);
         }
        //помечаем скрученными трассы, которые отсутствуют в гугл-таблице (в дату, которая аргумент)
		    function correct(date){
		      for (num_row_rc = 0; num_row_rc < lengthRC; num_row_rc++) 
			     if (getNumRow(valuesRC.payload[num_row_rc].name,valuesRC.payload[num_row_rc].installed_at)==-1){
             alert("Нет в гугл-таблице сведений о трассе "+JSON.stringify(valuesRC.payload[num_row_rc]) +". Если нажмете ок, то пометим, что она скручена в дату "+date+".");				
			       GM.xmlHttpRequest({
                  url:URL_FOR_REQUEST+valuesRC.payload[num_row_rc].id,
                  method: 'PATCH',
                  headers: {'Content-Type': 'application/json;charset=utf-8'},
                  data: JSON.stringify({route:{installed_until:date}}),
                  onload: function(response) {console.log("GM.xmlHttpRequest response");console.log(response);}
                });
           }
          alert("В гугл таблице есть сведения обо всех трассах в RC.");
         }
         //Добавляем информацию в зависимости от того, что написано в строчке. 
         //Если ничего, то обновляем информацию о трассе (или если это добавление трассы, то добавляем новую)
         function addGS(newDiv,newInput){
          if (newInput.value!=""){
            let a=newInput.value.split("/");
            if (a[0]=="r")
              recalculate(Number(a[1]),Number(a[2]));
		        if (a[0]=="u")
              if (a.length==1)
                uninstall(2,300)
              else
                uninstall(Number(a[1]),Number(a[2]));
            if (a[0]=="c")
              correct((a[1]));
            if (a[0]=="n")
              setnew(Number(a[1]),Number(a[2]));
          }
          else{ 
           let num_row_rc;
           let num_row;
           if (id_route==""){
             num_row=findNewNumRow(lengthRC,begin_find_new_route);
             console.log(num_row);
           }
           else{
             console.log('"'+id_route+'"');
             console.log(getNumRowRC(id_route));
             
             num_row_rc=getNumRowRC(id_route);
             num_row=getNumRow(valuesRC.payload[num_row_rc].name,valuesRC.payload[num_row_rc].installed_at);
           };
           console.log(begin_find_new_route);
           console.log(num_row+" num_row");
           console.log(newDiv.innerHTML+(newDiv.innerHTML==""));
           if ((newDiv.innerHTML=="")||(newDiv.innerHTML=="Новая трасса добавлена. Но это не точно.")||(newDiv.innerHTML=="Новых трасс нет.")){
             if (num_row==-1) {
               newDiv.innerHTML="Новых трасс нет.";
             }
             else{
               if (id_route==""){
                 newDiv.innerHTML="Новая трасса в гугл таблице "+getCellValue(num_row,2)+" в строке "+num_row+".";
                 
               }
               else 
                 newDiv.innerHTML="";
               let coord=calculate_coord_absolute(POSITION,getCellValue(num_row,1));
               for (let i = 1; i < 8; i++) newDiv.innerHTML = newDiv.innerHTML+" "+getCellValue(num_row,i);
               newDiv.innerHTML = newDiv.innerHTML+". top:"+coord.x+", left:"+coord.y+". Для того, чтобы загрузить данные, нажмите еще раз на кнопку.";
             }
           }
           else {
             let coord=calculate_coord_absolute(POSITION,getCellValue(num_row,1));
             let route_inf_correction = getInfGS(num_row,coord);
             if (id_route!=""){
              console.log("route_inf_correction:");
              console.log(route_inf_correction);
                console.log("2 route_inf_correction:");
                console.log(route_inf_correction);
                console.log(num_row_rc); 
              route_inf_correction=correction_of_existing(route_inf_correction,num_row_rc,coord);
              console.log("route_inf_correction:");  
              console.log(route_inf_correction);  
              let aa=JSON.stringify(route_inf_correction);
              console.log(aa+" "+URL_FOR_REQUEST+id_route);
              GM.xmlHttpRequest({
                url:URL_FOR_REQUEST+id_route,
                method: 'PATCH',
                headers: {'Content-Type': 'application/json;charset=utf-8'},
                data: JSON.stringify(route_inf_correction),
                onload: function(response) {console.log("GM.xmlHttpRequest response");console.log(response);}
              });
             } else {
               console.log(route_inf_correction);
               console.log(route_inf_correction);
               if (route_inf_correction.name!=""){
                 console.log(getNumRowRCbyName(route_inf_correction.route.name,route_inf_correction.route.installed_at));
                 if (getNumRowRCbyName(route_inf_correction.route.name,route_inf_correction.route.installed_at)==-1){
                   let aa=JSON.stringify(route_inf_correction);
                   console.log(aa+" NEW "+num_row);
                   begin_find_new_route=num_row+1;
                   GM.xmlHttpRequest({
                     url:URL_FOR_REQUEST,
                     method: 'POST',
                     headers: {'Content-Type': 'application/json;charset=utf-8'},
                     data: JSON.stringify(route_inf_correction),
                     onload: function(response) {console.log("GM.xmlHttpRequest response");console.log(response);}
                   });
                   console.log(route_inf_correction);
                   newDiv.innerHTML="Новая трасса добавлена. Но это не точно.";
                 } else alert("ТРАССА С ТАКИМ ИМЕНЕМ И ДАТОЙ НАКРУТКИ УЖЕ ЕСТЬ.");
               } else alert("ПЫТАЮТСЯ ВНЕСТИ ТРАССУ С ПУСТЫМ ИМЕНЕМ.");
                   
             };
//*/          
           };
          };
         }
         // Добавление кнопки с добавлением данных
         function addGSBtn(ele,num_child) {
            let newDiv = document.createElement("div");
            let btn = document.createElement("button");
            let newInput = document.createElement("input");
            ele.appendChild(btn);
            newDiv.innerHTML = "";         
            let newInput_result=ele.appendChild(newInput);
            let newDiv_result=ele.appendChild(newDiv);
            //btn.innerHTML = "Добавить данные из таблицы";
            btn.innerHTML = `При нажатии на кнопку загрузятся данные из гугл таблицы и вычислятся координаты.
                             Если ничего не писать, то обновятся данные о трассе (если это просмотр трассы) но после второго нажатия на кнопку.
                             Или добавится новая трасса (если это добавление трассы) после второго нажатия на кнопку, но там будет понятно. 
                             И можно много трасс добавлять. 
                             ('u'-скрутит скрученные трассы) \n
                             ('u/2/13'- скрутит скрученные трассы с 2 по 13 строчки)\n 
                             ('r/2/13'- пересчитает все данные с 2 по 13 строчки)\n
                             ('c/21-05-2021' пометит все отстутствующие в гугл-таблице трассы скрученными в эту дату)`;
            btn.className = "GBtn";
            //btn.onclick=() => {alert(1);};
            btn.onclick=() =>{addGS(newDiv_result,newInput_result);};
            //btn.onclick=() =>{recalculate(2,185);};
           
            //console.log(ele.childNodes[num_child+1]);
             
         }
       var num_div_cat;
       //console.log("jhsdbcjjbds"); 
       var elements_div=document.getElementsByTagName("div");
        
      for (let i = 0; i < elements_div.length; i++){
         if (elements_div[i].innerText){
           //console.log(elements_div[i].innerText+" "+i);
           if ((elements_div[i]["innerText"]=="Сложность:")||elements_div[i]["innerText"]=="Категория:"){
             num_div_cat=i;
             //console.log(i)
           }
         }
       };
 
        
       //console.log(num_div_cat); 
       //td = routeN[2].parentNode;
       //addGSBtn(td,5);
       td = elements_div[num_div_cat];
       addGSBtn(td,0);
       //alert(getCellValue(4,5));
      });
     });
    }
  setTimeout(theRealFunction, 5000); //Кстати, это уменьшает количество выдаваемых ошибок, так как страничка дозагружается за 10 секунд.
})(window);
//})();