Page 1 of 1

Very strange error when closing all databases

Posted: Sun Aug 26, 2018 5:17 am
by Eugene Lutsenko
Very strange error when closing all databases:
<<<===############################################### line 49587
If you log out and immediately start this mode, everything works fine. But if you do something before that in the system, and then run it, then this error occurs, but not always.

Code: Select all

************************************************************************************************************************************
******** 4.1.9. Подготовка результатов распознавания в форме CSV-файлов в стандарте http://kaggle.com. 
******** Данный режим предполагает, что: 1) в модели 2 класса; 2) результаты распознавания во всех моделях уже получены в режиме 3.5
************************************************************************************************************************************
FUNCTION F4_1_9()

   Running(.T.)

   **********************************************************************
   ******* Провести проверки на:
   ******* - наличие приложения;
   ******* - 2 класса в модели;
   ******  - наличие результатов распознавания во всех моделях;
   ******  - числовой результат распознавания;
   ******* с выдачей соответствующих сообщение.
   ******* Если все нормально - переход на выполнение.
   ******* Спросить сколько знаков после запятой включать.
   ******* Сообщить о том, что возможно нужно поменять название 1-го поля
   **********************************************************************

   ***********************************************
   ******* Провести проверки на наличие приложения
   ***********************************************

   PUBLIC M_PathAppl := "", M_NameAppl := "", mFlagErr := .F., mFlagAppl :=.F.

   IF .NOT. FILE("Appls.dbf")

      mFlagErr = .T.                                // Выдать сообщение об ошибке и вернуться в главное меню
      aMess := {}
      AADD(aMess, L('Отсутствует текущее приложение !'))
      AADD(aMess, L('Надо создать его в режиме 2.3.2.2,'))
      AADD(aMess, L('1.3, 2.3.2.1 или в другом!'))
      LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
      **************************************************************
      ***** БД, открытые перед запуском главного меню
      ***** Восстанавливать их после выхода из функций главного меню
      **************************************************************
      CLOSE ALL
      DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
      USE PathGrAp EXCLUSIVE NEW
      USE Appls    EXCLUSIVE NEW
      USE Users    EXCLUSIVE NEW
      Running(.F.)
      RETURN NIL
   ELSE

      CLOSE ALL
      USE Appls EXCLUSIVE NEW
      SELECT Appls
      
      DBGOTOP()
      DO WHILE .NOT. EOF()
         IF LEN(ALLTRIM(By_default)) > 0
            REPLACE By_default WITH "W"
            M_PathAppl = UPPER(ALLTRIM(Path_Appl))  // Путь на текущее приложение
            M_NameAppl = ALLTRIM(Name_Appl)             
            mFlagAppl =.T.                          // Текущее приложение существует, его имя: M_NameAppl, путь на него: M_PathAppl
            EXIT
         ENDIF
         DBSKIP(1)
      ENDDO
   ENDIF

   IF mFlagAppl =.F.                                // Текущего приложения не существует
      mFlagErr = .T.                                // Выдать сообщение об ошибке и вернуться в главное меню
      aMess := {}
      AADD(aMess, L('Отсутствует текущее приложение !'))
      AADD(aMess, L('Надо создать его в режиме 2.3.2.2,'))
      AADD(aMess, L('1.3, 2.3.2.1 или в другом!'))
      LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
      **************************************************************
      ***** БД, открытые перед запуском главного меню
      ***** Восстанавливать их после выхода из функций главного меню
      **************************************************************
      CLOSE ALL
      DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
      USE PathGrAp EXCLUSIVE NEW
      USE Appls    EXCLUSIVE NEW
      USE Users    EXCLUSIVE NEW
      Running(.F.)
      RETURN NIL
   ENDIF
   
   **********************************************
   ******* Провести проверки на 2 класса в модели
   **********************************************

   DIRCHANGE(M_PathAppl)      // Путь на текущее приложение

   CLOSE ALL                                        // <<<===############################################### line 49587
   USE Classes EXCLUSIVE NEW;N_Cls = RECCOUNT()

   IF N_Cls <> 2
      mFlagErr = .T.                                // Выдать сообщение об ошибке и вернуться в главное меню
      aMess := {}
      AADD(aMess, L('В приложении:'))
      AADD(aMess, L(' '))
      AADD(aMess, L('Наименование:')+' '+M_NameAppl)
      AADD(aMess, L('Путь:')+' '+M_PathAppl)
      AADD(aMess, L(' '))
      AADD(aMess, ALLTRIM(STR(N_Cls))+' '+L('классов.'))
      AADD(aMess, L('А должно быть 2 (на Каггл бинарное распознавание)'))
      LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
      **************************************************************
      ***** БД, открытые перед запуском главного меню
      ***** Восстанавливать их после выхода из функций главного меню
      **************************************************************
      CLOSE ALL
      DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
      USE PathGrAp EXCLUSIVE NEW
      USE Appls    EXCLUSIVE NEW
      USE Users    EXCLUSIVE NEW
      Running(.F.)
      RETURN NIL
   ENDIF

   ******************************************************************************
   ******* Провести проверки на наличие результатов распознавания во всех моделях
   ******************************************************************************

   Ar_Model := {"Abs","Prc1","Prc2","Inf1","Inf2","Inf3","Inf4","Inf5","Inf6","Inf7" }
   
   aRsp2   := {}
   
   FOR mNumModel = 1 TO LEN(Ar_Model)

       mNameRsp2i = 'Rsp2i_'+Ar_Model[mNumModel]
       mNameRsp2k = 'Rsp2k_'+Ar_Model[mNumModel]    // #####################

       mFlagRsp2 = .F.

       USE (mNameRsp2i) EXCLUSIVE NEW;mReccount_i = RECCOUNT()
       USE (mNameRsp2k) EXCLUSIVE NEW;mReccount_k = RECCOUNT()

       IF (.NOT. FILE(mNameRsp2i+'.dbf') .OR. .NOT. FILE(mNameRsp2k+'.dbf') ) .OR. mReccount_i * mReccount_k = 0 

          mFlagErr = .T.                            // Выдать сообщение об ошибке и вернуться в главное меню
          aMess := {}
          AADD(aMess, L('В приложении:'))
          AADD(aMess, L(' '))
          AADD(aMess, L('Наименование:')+' '+M_NameAppl)
          AADD(aMess, L('Путь:')+' '+M_PathAppl)
          AADD(aMess, L(' '))
          AADD(aMess, L('нет результатов распознавания во всех моделях и со всеми инт.критериями.'))
          AADD(aMess, L(' '))
          AADD(aMess, L('Надо провести распознавание в режиме 3.5.'))
          LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
          **************************************************************
          ***** БД, открытые перед запуском главного меню
          ***** Восстанавливать их после выхода из функций главного меню
          **************************************************************
          CLOSE ALL
          DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
          USE PathGrAp EXCLUSIVE NEW
          USE Appls    EXCLUSIVE NEW
          USE Users    EXCLUSIVE NEW
          Running(.F.)
          RETURN NIL
       ENDIF
   NEXT

   ****************************************************************************
   ******* Провести проверки на то, что результат распознавания является числом
   ****************************************************************************

   CLOSE ALL
   USE Classes EXCLUSIVE NEW;N_Cls = RECCOUNT()
   SELECT Classes

   DBGOTOP()
   DO WHILE .NOT. EOF()
      IF AT('{', Name_cls) * AT('}', Name_cls) = 0
         mFlagErr = .T.                            // Выдать сообщение об ошибке и вернуться в главное меню
         aMess := {}
         AADD(aMess, L('В приложении:'))
         AADD(aMess, L(' '))
         AADD(aMess, L('Наименование:')+' '+M_NameAppl)
         AADD(aMess, L('Путь:')+' '+M_PathAppl)
         AADD(aMess, L(' '))
         AADD(aMess, L('классы должны быть интервальными числовыми значениями'))
         AADD(aMess, L('(классификационная шкала должна быть числовой!)'))
         LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
         **************************************************************
         ***** БД, открытые перед запуском главного меню
         ***** Восстанавливать их после выхода из функций главного меню
         **************************************************************
         CLOSE ALL
         DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
         USE PathGrAp EXCLUSIVE NEW
         USE Appls    EXCLUSIVE NEW
         USE Users    EXCLUSIVE NEW
         Running(.F.)
         RETURN NIL
      ENDIF
      DBSKIP(1)
   ENDDO
   
   ******************************************************
   ******* Спросить сколько знаков после запятой включать
   ******************************************************

   mDeci = 1
   @0,0 DCSAY L('Задайте число знаков после запятой: ') GET mDeci PICTURE "##" SAYSIZE 0
   DCREAD GUI FIT ADDBUTTONS TITLE L('4.1.9. Подготовка результатов для http://kaggle.com')
   mDeci = IF(mDeci<=15,mDeci,15)

   oScr := DC_WaitOn(L('4.1.9. Подготовка результатов распознавания в форме CSV-файлов в стандарте http://kaggle.com'))     

   CLOSE ALL
   USE Classes EXCLUSIVE NEW;N_Cls = RECCOUNT()

   IF N_Cls = 2

      SELECT Classes
      mNameCls1 = ALLTRIM(Name_cls)
      DBSKIP(1)
      mNameCls2 = ALLTRIM(Name_cls)

      ***** Структура создаваемой базы ***********
       
      CLOSE ALL
      
      Ar_Model := {"Abs","Prc1","Prc2","Inf1","Inf2","Inf3","Inf4","Inf5","Inf6","Inf7" }
      
      aRsp2   := {}
      aKaggle := {}
      
      FOR mNumModel = 1 TO LEN(Ar_Model)

          mNameRsp2i = 'Rsp2i_'+Ar_Model[mNumModel]
          mNameRsp2k = 'Rsp2k_'+Ar_Model[mNumModel]              // #####################

          IF FILE(mNameRsp2i+'.dbf') .AND.;
             FILE(mNameRsp2k+'.dbf')
      
             AADD(aRsp2  , mNameRsp2i)
             AADD(aRsp2  , mNameRsp2k)
             
             AADD(aKaggle, 'Kaggle_'+Ar_Model[mNumModel]+'i')
             AADD(aKaggle, 'Kaggle_'+Ar_Model[mNumModel]+'k')
      
          ENDIF
      NEXT

      IF LEN(aRsp2) > 0

         mMaxLen = -999
         
         FOR ik = 1 TO LEN(aRsp2)
         
             CLOSE ALL
             USE (aRsp2[ik]) EXCLUSIVE NEW
             SELECT (aRsp2[ik])
             DBGOTOP()
             DO WHILE .NOT. EOF()
                mMaxLen = MAX(mMaxLen, LEN(ALLTRIM(Name_obj)))
                DBSKIP(1)
             ENDDO
         
         NEXT

         aStructure := { { "id"       , "C",mMaxLen, 0},;    // 1 id фрагмента текста из тестовой выборки
                         { "Prob"     , "N",     15, 7},;    // 2 Итоговая релевантность текстового фрагмента с истинным классом для каггла (предполагается, что модель дает истинных решений больше, чем ложных)
                         { "Prob1"    , "N",     15, 7},;    // 3 Релевантность текстового фрагмента с классом 1 = mKorr1 - mKorr2
                         { "Prob2"    , "N",     15, 7},;    // 4 Релевантность текстового фрагмента с классом 2 = mKorr2 - mKorr1
                         { "UrSx_Cls1", "N",     15, 7},;    // 5 Ур.сходства с классом 1, который дает система Эйдос
                         { "UrSx_Cls2", "N",     15, 7} }    // 6 Ур.сходства с классом 2, который дает система Эйдос
         
         FOR mNumModel = 1 TO LEN(Ar_Model)
         
             mNameRsp2i = 'Rsp2i_'+Ar_Model[mNumModel]
             mNameRsp2k = 'Rsp2k_'+Ar_Model[mNumModel]       // ################
         
             IF FILE(mNameRsp2i+'.dbf') .AND.;
                FILE(mNameRsp2k+'.dbf')

                DbCreate( 'Kaggle_'+Ar_Model[mNumModel]+'i', aStructure )
                DbCreate( 'Kaggle_'+Ar_Model[mNumModel]+'k', aStructure )
         
             ENDIF
         
         NEXT
         
         FOR ik = 1 TO LEN(aRsp2)
         
             CLOSE ALL
             USE (aRsp2[ik]) EXCLUSIVE NEW
             INDEX ON STR(Kod_obj,15) TO (aRsp2[ik])
             
             CLOSE ALL
             USE (aRsp2[ik])   INDEX (aRsp2[ik]) EXCLUSIVE NEW
             USE (aKaggle[ik]) EXCLUSIVE NEW
             
             mKorr1Max = -9999                 // Max.знач.ур.сходства с классом 1
             mKorr1Min = +9999                 // Min.знач.ур.сходства с классом 1
         
             mKorr2Max = -9999                 // Max.знач.ур.сходства с классом 2
             mKorr2Min = +9999                 // Min.знач.ур.сходства с классом 2
         
             mClass1Sum = 0
             mClass2Sum = 0
             
             SELECT (aRsp2[ik])
             DBGOTOP()
             
             mIdErr = ''                       // Отсутствующие id
             mIdOld = VAL(Name_obj)
             
             DO WHILE .NOT. EOF()
             
                mID    = ALLTRIM(Name_obj)
         
                mKorr1 = Korr
                DBSKIP(1)
                mKorr2 = Korr
         
                mClass1Sum = mClass1Sum + mKorr1
                mClass2Sum = mClass2Sum + mKorr2
             
                // mKorr1 уровень сходства с классом: "есть описание суицида"
                // mKorr2 уровень сходства с классом: "нет  описания суицида"
             
                SELECT (aKaggle[ik])
                APPEND BLANK
         
                mProb1 = mKorr1 - mKorr2
                mProb2 = mKorr2 - mKorr1
         
                REPLACE id        WITH mID
                REPLACE prob1     WITH mProb1
                REPLACE prob2     WITH mProb2
         
                REPLACE UrSx_Cls1 WITH mKorr1
                REPLACE UrSx_Cls2 WITH mKorr2
         
                mKorr1Max =    MAX(mKorr1Max, mProb1)
                mKorr1Min =    MIN(mKorr1Min, mProb1)
             
                mKorr2Max =    MAX(mKorr2Max, mProb2)
                mKorr2Min =    MIN(mKorr2Min, mProb2)

                SELECT (aRsp2[ik])
                DBSKIP(1)
         
*               **** Сделать проверку на пропуски в id и вставлять пустые записи при пропусках ЭТО ДЕЛАТЬ НЕ НАДО #####
*               mNameObj = ALLTRIM(Name_obj)
*               mIdNew = VAL(mNameObj)               // ############## НЕ ЧИСЛО ###################
*               IF mIdNew - mIdOld > 1
*                  mIdErr = mIdErr + ALLTRIM(STR(mIdNew - 1, 15)) + ' '
*                  SELECT (aKaggle[ik])
*                  APPEND BLANK
*                  REPLACE id        WITH ALLTRIM(STR(mIdNew - 1,15))                // ###########
*                  REPLACE prob1     WITH 0
*                  REPLACE prob2     WITH 0
*                  REPLACE UrSx_Cls1 WITH 0
*                  REPLACE UrSx_Cls2 WITH 0
*                  SELECT (aRsp2[ik])
*               ENDIF
*               mIdOld = mIdNew
             
             ENDDO
             
             StrFile(mIdErr, 'Id_Error.txt')                                         // Запись текстового файла с пропущенными id
             
             ****** Сделать нормировку prob к 1-0
         
             SELECT (aKaggle[ik])
             DBGOTOP()
             DO WHILE .NOT. EOF()
                IF mClass1Sum > mClass2Sum                                           // Предполагаем, что классификатор дает истинных решений больше, чем ложных, т.е. "не с точностью наоборот"
                   REPLACE Prob WITH (Prob1 - mKorr1Min) / (mKorr1Max - mKorr1Min)
                ELSE
                   REPLACE Prob WITH (Prob2 - mKorr2Min) / (mKorr2Max - mKorr2Min)
                ENDIF
                DBSKIP(1)
             ENDDO

         NEXT
         
         CLOSE ALL

         IF .F.                  // ####################################

            DC_Impl(oScr)                                                   

            aMess := {}
            AADD(aMess, L('РЕЗУЛЬТАТЫ БИНАРНОЙ КЛАССИФИКАЦИИ В БАЗАХ:'))
            AADD(aMess, L(' '))
            AADD(aMess, L('Интегральный критерий: "Сумма знаний":'))
            FOR j=1 TO LEN(aKaggle) STEP 2
                AADD(aMess, ALLTRIM(aKaggle[j])+'.dbf')
            NEXT
            AADD(aMess, L(' '))
            AADD(aMess, L('Интегральный критерий: "Резонанс знаний":'))
            FOR j=2 TO LEN(aKaggle) STEP 2
                AADD(aMess, ALLTRIM(aKaggle[j])+'.dbf')
            NEXT
            AADD(aMess, L(' '))
            AADD(aMess, L('Все эти базы данных открываются в MS Excel.'))
            AADD(aMess, L(' '))
            AADD(aMess, L('Смысл полей баз данных: "Kaggle_#_###.dbf":'))
            AADD(aMess, L('- id: id фрагмента текста из тестовой выборки;'))
            AADD(aMess, L('- Prob: Итоговая релевантность текстового фрагмента с истинным классом для каггла;'))
            AADD(aMess, L('            где:'))
            AADD(aMess,   '            Prob = (Prob1 - Korr1Min) / (Korr1Max - Korr1Min);')
            AADD(aMess,   '            Prob = (Prob2 - Korr2Min) / (Korr2Max - Korr2Min);')
            AADD(aMess,   '            Korr1Max = MAX(Korr1Max, Prob1);')
            AADD(aMess,   '            Korr1Min = MIN(Korr1Min, Prob1);')
            AADD(aMess,   '            Korr2Max = MAX(Korr2Max, Prob2);')
            AADD(aMess,   '            Korr2Min = MIN(Korr2Min, Prob2);')
            AADD(aMess, L('- Prob1 = UrSx_Cls1 - UrSx_Cls2: Релевантность текстового фрагмента с классом 1;'))
            AADD(aMess, L('- Prob2 = UrSx_Cls2 - UrSx_Cls1: Релевантность текстового фрагмента с классом 2;'))
            AADD(aMess, L('- UrSx_Cls1: Уровень сходства с классом 1, который дает система Эйдос;'))
            AADD(aMess, L('- UrSx_Cls2: Уровень сходства с классом 2, который дает система Эйдос;'))
            AADD(aMess, L(' '))
            AADD(aMess, L('Если модель работает "не с точностью до наоборот", то по итогам классификации;'))
            AADD(aMess, L('можно предположить, что истинными являются решения о принадлежности к классу:;'))
            AADD(aMess, IF(mClass1Sum > mClass2Sum, '"'+mNameCls1+'"', '"'+mNameCls2+'".'))
            
            LB_Warning(aMess, L('(C) System "Aidos-X++"' ))

         ENDIF
      ENDIF
   ENDIF

   mCountF = ADIR("Kaggle_*.DBF")                            // Кол-во TXT-файлов
   IF mCountF > 0

      PRIVATE aFileName[mCountF], aFileSize[mCountF]            // Имена и размеры файлов
      
      ADIR("Kaggle_*.DBF", aFileName, aFileSize)
      
      FOR ff=1 TO mCountF
      
          mFileName = SUBSTR(aFileName[ff], 1, AT('.',aFileName[ff])-1)
      
          CLOSE ALL
          USE (mFileName) EXCLUSIVE NEW
          SELECT (mFileName)
      
          ********** Открыть процесс печати выходной формы
          set device to printer
          set printer on
          set printer to (mFileName+'.csv')
          set console off
      
          ??'SK_ID_CURR,TARGET'
      
          DBGOTOP()
          DO WHILE .NOT. EOF()
          
             ?ALLTRIM(ID)+','+ALLTRIM(STR(ROUND(PROB,mDeci)))
      
             DBSKIP(1)
          
          ENDDO
      
          ********** Закрыть процесс печати выходной формы
          Set device to screen
          Set printer off
          Set printer to
          Set console on
      
      NEXT

      DC_Impl(oScr)                                                   
      
      aMess := {}
      AADD(aMess,L('4.1.9. Подготовка результатов распознавания в форме CSV-файлов в стандарте http://kaggle.com завершена успешно!'))
      AADD(aMess,L(''))
      AADD(aMess,L('Результаты распознавания находятся в папке: "'+M_PathAppl+'" в файлах:'))
      AADD(aMess,L(''))
      AADD(aMess,L('Kaggle_Inf1i.csv'))
      AADD(aMess,L('Kaggle_Inf2i.csv'))
      AADD(aMess,L('Kaggle_Inf3i.csv'))
      AADD(aMess,L('Kaggle_Inf4i.csv'))
      AADD(aMess,L('Kaggle_Inf5i.csv'))
      AADD(aMess,L('Kaggle_Inf6i.csv'))
      AADD(aMess,L('Kaggle_Inf7i.csv'))
      AADD(aMess,L('Kaggle_Prc1i.csv'))
      AADD(aMess,L('Kaggle_Prc2i.csv'))
      AADD(aMess,L(''))
      AADD(aMess,L('Kaggle_Inf1k.csv'))
      AADD(aMess,L('Kaggle_Inf2k.csv'))
      AADD(aMess,L('Kaggle_Inf3k.csv'))
      AADD(aMess,L('Kaggle_Inf4k.csv'))
      AADD(aMess,L('Kaggle_Inf5k.csv'))
      AADD(aMess,L('Kaggle_Inf6k.csv'))
      AADD(aMess,L('Kaggle_Inf7k.csv'))
      AADD(aMess,L('Kaggle_Prc1k.csv'))
      AADD(aMess,L('Kaggle_Prc2k.csv'))
      AADD(aMess,L(''))
      AADD(aMess,L('Проверьте наименование полей в CSV-файлах'))
      LB_Warning(aMess)

   ENDIF

   DC_Impl(oScr)                                                   

   **************************************************************
   ***** БД, открытые перед запуском главного меню
   ***** Восстанавливать их после выхода из функций главного меню
   **************************************************************
   CLOSE ALL
   DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
   USE PathGrAp EXCLUSIVE NEW
   USE Appls    EXCLUSIVE NEW
   USE Users    EXCLUSIVE NEW
   Running(.F.)

RETURN NIL
[/size]

Re: Very strange error when closing all databases

Posted: Thu Oct 04, 2018 5:40 pm
by digitsoft
Hello You can tell me how much record has that DBF since uo had that error and always does it when it has more than a million records

Eugene Lutsenko wrote:Very strange error when closing all databases:
<<<===############################################### line 49587
If you log out and immediately start this mode, everything works fine. But if you do something before that in the system, and then run it, then this error occurs, but not always.

Code: Select all

************************************************************************************************************************************
******** 4.1.9. Подготовка результатов распознавания в форме CSV-файлов в стандарте http://kaggle.com. 
******** Данный режим предполагает, что: 1) в модели 2 класса; 2) результаты распознавания во всех моделях уже получены в режиме 3.5
************************************************************************************************************************************
FUNCTION F4_1_9()

   Running(.T.)

   **********************************************************************
   ******* Провести проверки на:
   ******* - наличие приложения;
   ******* - 2 класса в модели;
   ******  - наличие результатов распознавания во всех моделях;
   ******  - числовой результат распознавания;
   ******* с выдачей соответствующих сообщение.
   ******* Если все нормально - переход на выполнение.
   ******* Спросить сколько знаков после запятой включать.
   ******* Сообщить о том, что возможно нужно поменять название 1-го поля
   **********************************************************************

   ***********************************************
   ******* Провести проверки на наличие приложения
   ***********************************************

   PUBLIC M_PathAppl := "", M_NameAppl := "", mFlagErr := .F., mFlagAppl :=.F.

   IF .NOT. FILE("Appls.dbf")

      mFlagErr = .T.                                // Выдать сообщение об ошибке и вернуться в главное меню
      aMess := {}
      AADD(aMess, L('Отсутствует текущее приложение !'))
      AADD(aMess, L('Надо создать его в режиме 2.3.2.2,'))
      AADD(aMess, L('1.3, 2.3.2.1 или в другом!'))
      LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
      **************************************************************
      ***** БД, открытые перед запуском главного меню
      ***** Восстанавливать их после выхода из функций главного меню
      **************************************************************
      CLOSE ALL
      DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
      USE PathGrAp EXCLUSIVE NEW
      USE Appls    EXCLUSIVE NEW
      USE Users    EXCLUSIVE NEW
      Running(.F.)
      RETURN NIL
   ELSE

      CLOSE ALL
      USE Appls EXCLUSIVE NEW
      SELECT Appls
      
      DBGOTOP()
      DO WHILE .NOT. EOF()
         IF LEN(ALLTRIM(By_default)) > 0
            REPLACE By_default WITH "W"
            M_PathAppl = UPPER(ALLTRIM(Path_Appl))  // Путь на текущее приложение
            M_NameAppl = ALLTRIM(Name_Appl)             
            mFlagAppl =.T.                          // Текущее приложение существует, его имя: M_NameAppl, путь на него: M_PathAppl
            EXIT
         ENDIF
         DBSKIP(1)
      ENDDO
   ENDIF

   IF mFlagAppl =.F.                                // Текущего приложения не существует
      mFlagErr = .T.                                // Выдать сообщение об ошибке и вернуться в главное меню
      aMess := {}
      AADD(aMess, L('Отсутствует текущее приложение !'))
      AADD(aMess, L('Надо создать его в режиме 2.3.2.2,'))
      AADD(aMess, L('1.3, 2.3.2.1 или в другом!'))
      LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
      **************************************************************
      ***** БД, открытые перед запуском главного меню
      ***** Восстанавливать их после выхода из функций главного меню
      **************************************************************
      CLOSE ALL
      DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
      USE PathGrAp EXCLUSIVE NEW
      USE Appls    EXCLUSIVE NEW
      USE Users    EXCLUSIVE NEW
      Running(.F.)
      RETURN NIL
   ENDIF
   
   **********************************************
   ******* Провести проверки на 2 класса в модели
   **********************************************

   DIRCHANGE(M_PathAppl)      // Путь на текущее приложение

   CLOSE ALL                                        // <<<===############################################### line 49587
   USE Classes EXCLUSIVE NEW;N_Cls = RECCOUNT()

   IF N_Cls <> 2
      mFlagErr = .T.                                // Выдать сообщение об ошибке и вернуться в главное меню
      aMess := {}
      AADD(aMess, L('В приложении:'))
      AADD(aMess, L(' '))
      AADD(aMess, L('Наименование:')+' '+M_NameAppl)
      AADD(aMess, L('Путь:')+' '+M_PathAppl)
      AADD(aMess, L(' '))
      AADD(aMess, ALLTRIM(STR(N_Cls))+' '+L('классов.'))
      AADD(aMess, L('А должно быть 2 (на Каггл бинарное распознавание)'))
      LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
      **************************************************************
      ***** БД, открытые перед запуском главного меню
      ***** Восстанавливать их после выхода из функций главного меню
      **************************************************************
      CLOSE ALL
      DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
      USE PathGrAp EXCLUSIVE NEW
      USE Appls    EXCLUSIVE NEW
      USE Users    EXCLUSIVE NEW
      Running(.F.)
      RETURN NIL
   ENDIF

   ******************************************************************************
   ******* Провести проверки на наличие результатов распознавания во всех моделях
   ******************************************************************************

   Ar_Model := {"Abs","Prc1","Prc2","Inf1","Inf2","Inf3","Inf4","Inf5","Inf6","Inf7" }
   
   aRsp2   := {}
   
   FOR mNumModel = 1 TO LEN(Ar_Model)

       mNameRsp2i = 'Rsp2i_'+Ar_Model[mNumModel]
       mNameRsp2k = 'Rsp2k_'+Ar_Model[mNumModel]    // #####################

       mFlagRsp2 = .F.

       USE (mNameRsp2i) EXCLUSIVE NEW;mReccount_i = RECCOUNT()
       USE (mNameRsp2k) EXCLUSIVE NEW;mReccount_k = RECCOUNT()

       IF (.NOT. FILE(mNameRsp2i+'.dbf') .OR. .NOT. FILE(mNameRsp2k+'.dbf') ) .OR. mReccount_i * mReccount_k = 0 

          mFlagErr = .T.                            // Выдать сообщение об ошибке и вернуться в главное меню
          aMess := {}
          AADD(aMess, L('В приложении:'))
          AADD(aMess, L(' '))
          AADD(aMess, L('Наименование:')+' '+M_NameAppl)
          AADD(aMess, L('Путь:')+' '+M_PathAppl)
          AADD(aMess, L(' '))
          AADD(aMess, L('нет результатов распознавания во всех моделях и со всеми инт.критериями.'))
          AADD(aMess, L(' '))
          AADD(aMess, L('Надо провести распознавание в режиме 3.5.'))
          LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
          **************************************************************
          ***** БД, открытые перед запуском главного меню
          ***** Восстанавливать их после выхода из функций главного меню
          **************************************************************
          CLOSE ALL
          DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
          USE PathGrAp EXCLUSIVE NEW
          USE Appls    EXCLUSIVE NEW
          USE Users    EXCLUSIVE NEW
          Running(.F.)
          RETURN NIL
       ENDIF
   NEXT

   ****************************************************************************
   ******* Провести проверки на то, что результат распознавания является числом
   ****************************************************************************

   CLOSE ALL
   USE Classes EXCLUSIVE NEW;N_Cls = RECCOUNT()
   SELECT Classes

   DBGOTOP()
   DO WHILE .NOT. EOF()
      IF AT('{', Name_cls) * AT('}', Name_cls) = 0
         mFlagErr = .T.                            // Выдать сообщение об ошибке и вернуться в главное меню
         aMess := {}
         AADD(aMess, L('В приложении:'))
         AADD(aMess, L(' '))
         AADD(aMess, L('Наименование:')+' '+M_NameAppl)
         AADD(aMess, L('Путь:')+' '+M_PathAppl)
         AADD(aMess, L(' '))
         AADD(aMess, L('классы должны быть интервальными числовыми значениями'))
         AADD(aMess, L('(классификационная шкала должна быть числовой!)'))
         LB_Warning(aMess, L('(C) System "Aidos-X++"' ))
         **************************************************************
         ***** БД, открытые перед запуском главного меню
         ***** Восстанавливать их после выхода из функций главного меню
         **************************************************************
         CLOSE ALL
         DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
         USE PathGrAp EXCLUSIVE NEW
         USE Appls    EXCLUSIVE NEW
         USE Users    EXCLUSIVE NEW
         Running(.F.)
         RETURN NIL
      ENDIF
      DBSKIP(1)
   ENDDO
   
   ******************************************************
   ******* Спросить сколько знаков после запятой включать
   ******************************************************

   mDeci = 1
   @0,0 DCSAY L('Задайте число знаков после запятой: ') GET mDeci PICTURE "##" SAYSIZE 0
   DCREAD GUI FIT ADDBUTTONS TITLE L('4.1.9. Подготовка результатов для http://kaggle.com')
   mDeci = IF(mDeci<=15,mDeci,15)

   oScr := DC_WaitOn(L('4.1.9. Подготовка результатов распознавания в форме CSV-файлов в стандарте http://kaggle.com'))     

   CLOSE ALL
   USE Classes EXCLUSIVE NEW;N_Cls = RECCOUNT()

   IF N_Cls = 2

      SELECT Classes
      mNameCls1 = ALLTRIM(Name_cls)
      DBSKIP(1)
      mNameCls2 = ALLTRIM(Name_cls)

      ***** Структура создаваемой базы ***********
       
      CLOSE ALL
      
      Ar_Model := {"Abs","Prc1","Prc2","Inf1","Inf2","Inf3","Inf4","Inf5","Inf6","Inf7" }
      
      aRsp2   := {}
      aKaggle := {}
      
      FOR mNumModel = 1 TO LEN(Ar_Model)

          mNameRsp2i = 'Rsp2i_'+Ar_Model[mNumModel]
          mNameRsp2k = 'Rsp2k_'+Ar_Model[mNumModel]              // #####################

          IF FILE(mNameRsp2i+'.dbf') .AND.;
             FILE(mNameRsp2k+'.dbf')
      
             AADD(aRsp2  , mNameRsp2i)
             AADD(aRsp2  , mNameRsp2k)
             
             AADD(aKaggle, 'Kaggle_'+Ar_Model[mNumModel]+'i')
             AADD(aKaggle, 'Kaggle_'+Ar_Model[mNumModel]+'k')
      
          ENDIF
      NEXT

      IF LEN(aRsp2) > 0

         mMaxLen = -999
         
         FOR ik = 1 TO LEN(aRsp2)
         
             CLOSE ALL
             USE (aRsp2[ik]) EXCLUSIVE NEW
             SELECT (aRsp2[ik])
             DBGOTOP()
             DO WHILE .NOT. EOF()
                mMaxLen = MAX(mMaxLen, LEN(ALLTRIM(Name_obj)))
                DBSKIP(1)
             ENDDO
         
         NEXT

         aStructure := { { "id"       , "C",mMaxLen, 0},;    // 1 id фрагмента текста из тестовой выборки
                         { "Prob"     , "N",     15, 7},;    // 2 Итоговая релевантность текстового фрагмента с истинным классом для каггла (предполагается, что модель дает истинных решений больше, чем ложных)
                         { "Prob1"    , "N",     15, 7},;    // 3 Релевантность текстового фрагмента с классом 1 = mKorr1 - mKorr2
                         { "Prob2"    , "N",     15, 7},;    // 4 Релевантность текстового фрагмента с классом 2 = mKorr2 - mKorr1
                         { "UrSx_Cls1", "N",     15, 7},;    // 5 Ур.сходства с классом 1, который дает система Эйдос
                         { "UrSx_Cls2", "N",     15, 7} }    // 6 Ур.сходства с классом 2, который дает система Эйдос
         
         FOR mNumModel = 1 TO LEN(Ar_Model)
         
             mNameRsp2i = 'Rsp2i_'+Ar_Model[mNumModel]
             mNameRsp2k = 'Rsp2k_'+Ar_Model[mNumModel]       // ################
         
             IF FILE(mNameRsp2i+'.dbf') .AND.;
                FILE(mNameRsp2k+'.dbf')

                DbCreate( 'Kaggle_'+Ar_Model[mNumModel]+'i', aStructure )
                DbCreate( 'Kaggle_'+Ar_Model[mNumModel]+'k', aStructure )
         
             ENDIF
         
         NEXT
         
         FOR ik = 1 TO LEN(aRsp2)
         
             CLOSE ALL
             USE (aRsp2[ik]) EXCLUSIVE NEW
             INDEX ON STR(Kod_obj,15) TO (aRsp2[ik])
             
             CLOSE ALL
             USE (aRsp2[ik])   INDEX (aRsp2[ik]) EXCLUSIVE NEW
             USE (aKaggle[ik]) EXCLUSIVE NEW
             
             mKorr1Max = -9999                 // Max.знач.ур.сходства с классом 1
             mKorr1Min = +9999                 // Min.знач.ур.сходства с классом 1
         
             mKorr2Max = -9999                 // Max.знач.ур.сходства с классом 2
             mKorr2Min = +9999                 // Min.знач.ур.сходства с классом 2
         
             mClass1Sum = 0
             mClass2Sum = 0
             
             SELECT (aRsp2[ik])
             DBGOTOP()
             
             mIdErr = ''                       // Отсутствующие id
             mIdOld = VAL(Name_obj)
             
             DO WHILE .NOT. EOF()
             
                mID    = ALLTRIM(Name_obj)
         
                mKorr1 = Korr
                DBSKIP(1)
                mKorr2 = Korr
         
                mClass1Sum = mClass1Sum + mKorr1
                mClass2Sum = mClass2Sum + mKorr2
             
                // mKorr1 уровень сходства с классом: "есть описание суицида"
                // mKorr2 уровень сходства с классом: "нет  описания суицида"
             
                SELECT (aKaggle[ik])
                APPEND BLANK
         
                mProb1 = mKorr1 - mKorr2
                mProb2 = mKorr2 - mKorr1
         
                REPLACE id        WITH mID
                REPLACE prob1     WITH mProb1
                REPLACE prob2     WITH mProb2
         
                REPLACE UrSx_Cls1 WITH mKorr1
                REPLACE UrSx_Cls2 WITH mKorr2
         
                mKorr1Max =    MAX(mKorr1Max, mProb1)
                mKorr1Min =    MIN(mKorr1Min, mProb1)
             
                mKorr2Max =    MAX(mKorr2Max, mProb2)
                mKorr2Min =    MIN(mKorr2Min, mProb2)

                SELECT (aRsp2[ik])
                DBSKIP(1)
         
*               **** Сделать проверку на пропуски в id и вставлять пустые записи при пропусках ЭТО ДЕЛАТЬ НЕ НАДО #####
*               mNameObj = ALLTRIM(Name_obj)
*               mIdNew = VAL(mNameObj)               // ############## НЕ ЧИСЛО ###################
*               IF mIdNew - mIdOld > 1
*                  mIdErr = mIdErr + ALLTRIM(STR(mIdNew - 1, 15)) + ' '
*                  SELECT (aKaggle[ik])
*                  APPEND BLANK
*                  REPLACE id        WITH ALLTRIM(STR(mIdNew - 1,15))                // ###########
*                  REPLACE prob1     WITH 0
*                  REPLACE prob2     WITH 0
*                  REPLACE UrSx_Cls1 WITH 0
*                  REPLACE UrSx_Cls2 WITH 0
*                  SELECT (aRsp2[ik])
*               ENDIF
*               mIdOld = mIdNew
             
             ENDDO
             
             StrFile(mIdErr, 'Id_Error.txt')                                         // Запись текстового файла с пропущенными id
             
             ****** Сделать нормировку prob к 1-0
         
             SELECT (aKaggle[ik])
             DBGOTOP()
             DO WHILE .NOT. EOF()
                IF mClass1Sum > mClass2Sum                                           // Предполагаем, что классификатор дает истинных решений больше, чем ложных, т.е. "не с точностью наоборот"
                   REPLACE Prob WITH (Prob1 - mKorr1Min) / (mKorr1Max - mKorr1Min)
                ELSE
                   REPLACE Prob WITH (Prob2 - mKorr2Min) / (mKorr2Max - mKorr2Min)
                ENDIF
                DBSKIP(1)
             ENDDO

         NEXT
         
         CLOSE ALL

         IF .F.                  // ####################################

            DC_Impl(oScr)                                                   

            aMess := {}
            AADD(aMess, L('РЕЗУЛЬТАТЫ БИНАРНОЙ КЛАССИФИКАЦИИ В БАЗАХ:'))
            AADD(aMess, L(' '))
            AADD(aMess, L('Интегральный критерий: "Сумма знаний":'))
            FOR j=1 TO LEN(aKaggle) STEP 2
                AADD(aMess, ALLTRIM(aKaggle[j])+'.dbf')
            NEXT
            AADD(aMess, L(' '))
            AADD(aMess, L('Интегральный критерий: "Резонанс знаний":'))
            FOR j=2 TO LEN(aKaggle) STEP 2
                AADD(aMess, ALLTRIM(aKaggle[j])+'.dbf')
            NEXT
            AADD(aMess, L(' '))
            AADD(aMess, L('Все эти базы данных открываются в MS Excel.'))
            AADD(aMess, L(' '))
            AADD(aMess, L('Смысл полей баз данных: "Kaggle_#_###.dbf":'))
            AADD(aMess, L('- id: id фрагмента текста из тестовой выборки;'))
            AADD(aMess, L('- Prob: Итоговая релевантность текстового фрагмента с истинным классом для каггла;'))
            AADD(aMess, L('            где:'))
            AADD(aMess,   '            Prob = (Prob1 - Korr1Min) / (Korr1Max - Korr1Min);')
            AADD(aMess,   '            Prob = (Prob2 - Korr2Min) / (Korr2Max - Korr2Min);')
            AADD(aMess,   '            Korr1Max = MAX(Korr1Max, Prob1);')
            AADD(aMess,   '            Korr1Min = MIN(Korr1Min, Prob1);')
            AADD(aMess,   '            Korr2Max = MAX(Korr2Max, Prob2);')
            AADD(aMess,   '            Korr2Min = MIN(Korr2Min, Prob2);')
            AADD(aMess, L('- Prob1 = UrSx_Cls1 - UrSx_Cls2: Релевантность текстового фрагмента с классом 1;'))
            AADD(aMess, L('- Prob2 = UrSx_Cls2 - UrSx_Cls1: Релевантность текстового фрагмента с классом 2;'))
            AADD(aMess, L('- UrSx_Cls1: Уровень сходства с классом 1, который дает система Эйдос;'))
            AADD(aMess, L('- UrSx_Cls2: Уровень сходства с классом 2, который дает система Эйдос;'))
            AADD(aMess, L(' '))
            AADD(aMess, L('Если модель работает "не с точностью до наоборот", то по итогам классификации;'))
            AADD(aMess, L('можно предположить, что истинными являются решения о принадлежности к классу:;'))
            AADD(aMess, IF(mClass1Sum > mClass2Sum, '"'+mNameCls1+'"', '"'+mNameCls2+'".'))
            
            LB_Warning(aMess, L('(C) System "Aidos-X++"' ))

         ENDIF
      ENDIF
   ENDIF

   mCountF = ADIR("Kaggle_*.DBF")                            // Кол-во TXT-файлов
   IF mCountF > 0

      PRIVATE aFileName[mCountF], aFileSize[mCountF]            // Имена и размеры файлов
      
      ADIR("Kaggle_*.DBF", aFileName, aFileSize)
      
      FOR ff=1 TO mCountF
      
          mFileName = SUBSTR(aFileName[ff], 1, AT('.',aFileName[ff])-1)
      
          CLOSE ALL
          USE (mFileName) EXCLUSIVE NEW
          SELECT (mFileName)
      
          ********** Открыть процесс печати выходной формы
          set device to printer
          set printer on
          set printer to (mFileName+'.csv')
          set console off
      
          ??'SK_ID_CURR,TARGET'
      
          DBGOTOP()
          DO WHILE .NOT. EOF()
          
             ?ALLTRIM(ID)+','+ALLTRIM(STR(ROUND(PROB,mDeci)))
      
             DBSKIP(1)
          
          ENDDO
      
          ********** Закрыть процесс печати выходной формы
          Set device to screen
          Set printer off
          Set printer to
          Set console on
      
      NEXT

      DC_Impl(oScr)                                                   
      
      aMess := {}
      AADD(aMess,L('4.1.9. Подготовка результатов распознавания в форме CSV-файлов в стандарте http://kaggle.com завершена успешно!'))
      AADD(aMess,L(''))
      AADD(aMess,L('Результаты распознавания находятся в папке: "'+M_PathAppl+'" в файлах:'))
      AADD(aMess,L(''))
      AADD(aMess,L('Kaggle_Inf1i.csv'))
      AADD(aMess,L('Kaggle_Inf2i.csv'))
      AADD(aMess,L('Kaggle_Inf3i.csv'))
      AADD(aMess,L('Kaggle_Inf4i.csv'))
      AADD(aMess,L('Kaggle_Inf5i.csv'))
      AADD(aMess,L('Kaggle_Inf6i.csv'))
      AADD(aMess,L('Kaggle_Inf7i.csv'))
      AADD(aMess,L('Kaggle_Prc1i.csv'))
      AADD(aMess,L('Kaggle_Prc2i.csv'))
      AADD(aMess,L(''))
      AADD(aMess,L('Kaggle_Inf1k.csv'))
      AADD(aMess,L('Kaggle_Inf2k.csv'))
      AADD(aMess,L('Kaggle_Inf3k.csv'))
      AADD(aMess,L('Kaggle_Inf4k.csv'))
      AADD(aMess,L('Kaggle_Inf5k.csv'))
      AADD(aMess,L('Kaggle_Inf6k.csv'))
      AADD(aMess,L('Kaggle_Inf7k.csv'))
      AADD(aMess,L('Kaggle_Prc1k.csv'))
      AADD(aMess,L('Kaggle_Prc2k.csv'))
      AADD(aMess,L(''))
      AADD(aMess,L('Проверьте наименование полей в CSV-файлах'))
      LB_Warning(aMess)

   ENDIF

   DC_Impl(oScr)                                                   

   **************************************************************
   ***** БД, открытые перед запуском главного меню
   ***** Восстанавливать их после выхода из функций главного меню
   **************************************************************
   CLOSE ALL
   DIRCHANGE(Disk_dir)                          // Перейти в папку с исполнимым модулем системы
   USE PathGrAp EXCLUSIVE NEW
   USE Appls    EXCLUSIVE NEW
   USE Users    EXCLUSIVE NEW
   Running(.F.)

RETURN NIL
[/size]

Re: Very strange error when closing all databases

Posted: Thu Oct 04, 2018 10:56 pm
by Auge_Ohr
Eugene Lutsenko wrote:Very strange error when closing all databases:

If you log out and immediately start this mode, everything works fine. But if you do something before that in the system, and then run it, then this error occurs, but not always.
did you use RELATION ?

Re: Very strange error when closing all databases

Posted: Thu Oct 04, 2018 11:46 pm
by Eugene Lutsenko
Records are significantly less than a million. I do not use Relation as a command, but I do something similar myself

Re: Very strange error when closing all databases

Posted: Thu Oct 04, 2018 11:51 pm
by skiman
Hi,

Maybe this can help.

Code: Select all

Function CLoseAll()
***********************
LOCAL bError , aWorkareas , x, y

bError := ErrorBlock( {|e| Break(e)} )
aWorkAreas := workspacelist()
y := len(aWorkAreas)

for x = 1 to y
  BEGIN SEQUENCE
    (aWorkAreas[x])->(DbClearRelation())
    (aWorkAreas[x])->(DbCloseArea())
  ENDSEQUENCE
next
ErrorBlock(bError)
bError   := nil
Return nil

Re: Very strange error when closing all databases

Posted: Fri Oct 05, 2018 12:10 am
by Eugene Lutsenko
Thank you very much! Definitely try. I think I understand your function. Sometimes the user just needs to wait a little and then everything will work? And Your function allows you not to wait, and she is waiting for the completion of processes?

Re: Very strange error when closing all databases

Posted: Fri Oct 05, 2018 5:24 am
by Victorio
I have similar problem , error Base/8021 Unknown{Invalid symbol for alias, DbSetIndex
One of mine user have this often, but I can not simulate it. I mean, problem is with slow or busy network od server disk which close and save database and again open it in exclusive mode.
Database is not very large but have FPT file (Visual Foxpro format).
Now I put sleep half second if problem stay. Better solution is from Jimmy, because sometime need more time maybe seconds to save data to disk.

Code: Select all

	                
                SELECT 67
  	        use &nazovdbf67 ALIAS TEMPPRVC EXCLUSIVE
               	zap
                pack
		set default to &cestatemp
		index on CLV*100000+PCS*10+CDE TAG PV1 
		index on CLV*100000+PCS*10 TAG PV2
		index on CLV*100000+CDE TAG PV3
		set default to &cestahlprg
		close TEMPPRVC
		sleep(50)                              // <==  here I put this for test if problem solved
       	        SELECT 67
               	use &nazovdbf67 index &nazovdbf67 ALIAS TEMPPRVC EXCLUSIVE
		go top

Re: Very strange error when closing all databases

Posted: Fri Oct 05, 2018 8:48 am
by digitsoft
The problem may be in using indices with numeric fields, try taking the numeric fields to char and having the same length for example
index on VAR2CHAR(CLV * 100000) + VAR2CHAR(PCS * 10 + CDE) TAG PV1

Re: Very strange error when closing all databases

Posted: Mon Oct 08, 2018 7:20 am
by Eugene Lutsenko
skiman wrote:Hi,

Maybe this can help.

Code: Select all

Function CLoseAll()
***********************
LOCAL bError , aWorkareas , x, y

bError := ErrorBlock( {|e| Break(e)} )
aWorkAreas := workspacelist()
y := len(aWorkAreas)

for x = 1 to y
  BEGIN SEQUENCE
    (aWorkAreas[x])->(DbClearRelation())
    (aWorkAreas[x])->(DbCloseArea())
  ENDSEQUENCE
next
ErrorBlock(bError)
bError   := nil
Return nil
I replaced all CLOSE ALL in my system with this function!