<commit_before>/*************************************************************************
 *
 *  $RCSfile: zforscan.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: er $ $Date: 2000-10-17 18:46:13 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _ZFORSCAN_HXX
#define _ZFORSCAN_HXX

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif
#ifndef _DATE_HXX //autogen
#include <tools/date.hxx>
#endif
#ifndef _LANG_HXX //autogen
#include <tools/lang.hxx>
#endif
#ifndef _COLOR_HXX //autogen
#include <vcl/color.hxx>
#endif

#include "zformat.hxx"  // just for NfKeywordTable

class International;
class SvNumberFormatter;
struct ImpSvNumberformatInfo;

#define SC_MAX_ANZ_FORMAT_STRINGS   100
#define SC_MAX_ANZ_STANDARD_FARBEN  10
#define FLAG_STANDARD_IN_FORMAT     1000
                                            // Hack: nThousand=1000
                                            // => Standard kommt im
                                            // Format vor

enum Sc_SymbolType
{
    SYMBOLTYPE_STRING = -1,                     // String in Ausgabe
    SYMBOLTYPE_DEL    = -2,                     // Sonderzeichen
    SYMBOLTYPE_BLANK  = -3,                     // Blank fuer '_'
    SYMBOLTYPE_STAR   = -4,                     // *-Buchstabe
    SYMBOLTYPE_DIGIT  = -5,                     // Ziffernplatzhalter
    SYMBOLTYPE_DECSEP = -6,                     // Komma
    SYMBOLTYPE_THSEP  = -7,                     // Tausenderpunkt
    SYMBOLTYPE_EXP    = -8,                     // Exponent E
    SYMBOLTYPE_FRAC   = -9,                     // Bruch /
    SYMBOLTYPE_EMPTY  = -10,                    // geloeschte Symbole
    SYMBOLTYPE_FRACBLANK = -11,                 // Trenner Zahl - Zaehler bei Bruch
    SYMBOLTYPE_COMMENT = -12,                   // Kommentar folgt
    SYMBOLTYPE_CURRENCY = -13,                  // Waehrungssymbol
    SYMBOLTYPE_CURRDEL  = -14,                  // Waehrungssymbol Delimiter [$]
    SYMBOLTYPE_CURREXT  = -15                   // Waehrungssymbol Extension -xxx
};

class ImpSvNumberformatScan
{
public:

    ImpSvNumberformatScan( SvNumberFormatter* pFormatter );
    ~ImpSvNumberformatScan();
    void ChangeIntl();                          // tauscht Keywords aus

    void ChangeNullDate(USHORT nDay, USHORT nMonth, USHORT nYear);
                                                // tauscht Referenzdatum aus
    void ChangeStandardPrec(short nPrec);       // tauscht Standardprecision aus

    xub_StrLen ScanFormat( String& rString, String& rComment ); // Aufruf der Scan-Analyse

    void CopyInfo(ImpSvNumberformatInfo* pInfo,
                     USHORT nAnz);              // Kopiert die FormatInfo
    USHORT GetAnzResStrings() const             { return nAnzResStrings; }

    const International& GetIntl() const        { return *pFormatter->GetInternational(); }
    const CharClass& GetChrCls() const          { return *pFormatter->GetCharClass(); }
    const LocaleDataWrapper& GetLoc() const     { return *pFormatter->GetLocaleData(); }

    const String& GetQuartalString() const  { return sKeyword[NF_KEY_QUARTER]; }
    const String& GetTrueString() const     { return sKeyword[NF_KEY_TRUE]; }
    const String& GetFalseString() const    { return sKeyword[NF_KEY_FALSE]; }
    const String& GetColorString() const    { return sKeyword[NF_KEY_COLOR]; }
    const String& GetRedString() const      { return sKeyword[NF_KEY_RED]; }
    const String& GetBooleanString() const  { return sKeyword[NF_KEY_BOOLEAN]; }
    const String& GetErrorString() const    { return sErrStr; }
    const String* GetKeyword() const        { return sKeyword; }

    Date* GetNullDate() const                   { return pNullDate; }
    const String& GetStandardName() const   { return sNameStandardFormat; }
    short GetStandardPrec() const               { return nStandardPrec; }
    const Color& GetRedColor() const            { return StandardColor[4]; }
    Color* GetColor(String& sStr);          // Setzt Hauptfarben oder
                                                // definierte Farben

    void SetConvertMode(LanguageType eTmpLge, LanguageType eNewLge)
    {
        bConvertMode = TRUE;
        eNewLnge = eNewLge;
        eTmpLnge = eTmpLge;
    }
    void SetConvertMode(BOOL bMode) { bConvertMode = bMode; }
                                                // Veraendert nur die Bool-Variable
                                                // (zum temporaeren Unterbrechen des
                                                // Convert-Modus)
    const BOOL GetConvertMode()     { return bConvertMode; }
    const LanguageType GetNewLnge() { return eNewLnge; }
                                                // Lesezugriff auf ConvertMode
                                                // und Konvertierungsland/Spr.
    const LanguageType GetTmpLnge() { return eTmpLnge; }
                                                // Lesezugriff auf
                                                // und Ausgangsland/Spr.
    SvNumberFormatter* GetNumberformatter() { return pFormatter; }
                                                // Zugriff auf Formatierer
                                                // (fuer zformat.cxx)

private:                            // ---- privater Teil
    NfKeywordTable sKeyword;                    // Schluesselworte der Syntax
    Color StandardColor[SC_MAX_ANZ_STANDARD_FARBEN];
                                                // Array der Standardfarben
    Date* pNullDate;                            // "1.1.1900"
    String sNameStandardFormat;             // "Standard"
    short nStandardPrec;                        // default Precision fuer Standardformat (2)
    SvNumberFormatter* pFormatter;              // Pointer auf die Formatliste

    String sStrArray[SC_MAX_ANZ_FORMAT_STRINGS];// Array der Symbole
    short nTypeArray[SC_MAX_ANZ_FORMAT_STRINGS];// Array der Infos
                                                // externe Infos:
    USHORT nAnzResStrings;                      // Anzahl der Ergebnissymbole
#if !(defined SOLARIS && defined X86)
    short eScannedType;                         // Typ gemaess Scan
#else
    int eScannedType;                           // wg. Optimierung
#endif
    BOOL bThousand;                             // Mit Tausenderpunkt
    USHORT nThousand;                           // Zaehlt ....-Folgen
    USHORT nCntPre;                             // Zaehlt Vorkommastellen
    USHORT nCntPost;                            // Zaehlt Nachkommastellen
    USHORT nCntExp;                             // Zaehlt Exp.Stellen, AM/PM
                                                // interne Infos:
    USHORT nAnzStrings;                         // Anzahl der Symbole
    USHORT nRepPos;                             // Position eines '*'
    USHORT nExpPos;                             // interne Position des E
    USHORT nBlankPos;                           // interne Position des Blank
    short nDecPos;                              // interne Pos. des ,
    BOOL bExp;                                  // wird bei Lesen des E gesetzt
    BOOL bFrac;                                 // wird bei Lesen des / gesetzt
    BOOL bBlank;                                // wird bei ' '(Fraction) ges.
    BOOL bDecSep;                               // Wird beim ersten , gesetzt
    String sCurString;                      // Das Waehrungssymbol in Upper
    String sErrStr;                         // String fuer Fehlerausgaben

    BOOL bConvertMode;                          // Wird im Convert-Mode gesetzt
                                                // Land/Sprache, in die der
    LanguageType eNewLnge;                      // gescannte String konvertiert
                                                // wird (fuer Excel Filter)
                                                // Land/Sprache, aus der der
    LanguageType eTmpLnge;                      // gescannte String konvertiert
                                                // wird (fuer Excel Filter)
    String sOldDecSep;                          // Dezimalsymbol der Ausgangs-
    String sOldThousandSep;                     // spr., analog Tausenderpunkt
    String sOldDateSep;                         // Datums- und Zeitsymbol
    String sOldTimeSep;
    xub_StrLen nCurrPos;                        // Position des Waehrungssymbols

#ifdef _ZFORSCAN_CXX                // ----- private Methoden -----
    void SetDependentKeywords(LanguageType eLnge);
                                                // Setzt die Sprachabh. Keyw.
    void SkipStrings(USHORT& i,xub_StrLen& nPos);// Ueberspringt StringSymbole
    USHORT PreviousKeyword(USHORT i);           // Gibt Index des vorangeh.
                                                // Schluesselworts oder 0
    USHORT NextKeyword(USHORT i);               // Gibt Index des naechsten
                                                // Schluesselworts oder 0
    sal_Unicode PreviousChar(USHORT i);             // Gibt letzten Buchstaben
                                                // vor der Position,
                                                // skipt EMPTY, STRING, STAR, BLANK
    sal_Unicode NextChar(USHORT i);                 // Gibt ersten Buchst. danach
    short PreviousType( USHORT i );             // Gibt Typ vor Position,
                                                // skipt EMPTY
    BOOL IsLastBlankBeforeFrac(USHORT i);       // True <=> es kommt kein ' '
                                                // mehr bis zum '/'
    void Reset();                               // Reset aller Variablen
                                                // vor Analysestart
    USHORT GetKeyWord(const String& sSymbol); // Vergleicht mit den Keywords
                                                // return 0 <=> nicht gefunden
    short Next_Symbol(const String& rStr,
                        xub_StrLen& nPos,
                      String& sSymbol);       // Naechstes Symbol
    xub_StrLen Symbol_Division(const String& rString);// lexikalische Voranalyse
    xub_StrLen ScanType(const String& rString); // Analyse des Formattyps
    xub_StrLen FinalScan( String& rString, String& rComment );  // Endanalyse mit Vorgabe
                                                // des Typs

    static inline BOOL StringEqualsChar( const String& rStr, sal_Unicode ch )
        { return rStr.GetChar(0) == ch && rStr.Len() == 1; }
        // Yes, for efficiency get the character first and then compare length
        // because in most places where this is used the string is one char.

#endif //_ZFORSCAN_CXX
};

#endif  // _ZFORSCAN_HXX
<commit_msg>chg: removed parameter from SetDependentKeywords<commit_after>/*************************************************************************
 *
 *  $RCSfile: zforscan.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: er $ $Date: 2000-11-03 20:46:56 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _ZFORSCAN_HXX
#define _ZFORSCAN_HXX

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif
#ifndef _DATE_HXX //autogen
#include <tools/date.hxx>
#endif
#ifndef _LANG_HXX //autogen
#include <tools/lang.hxx>
#endif
#ifndef _COLOR_HXX //autogen
#include <vcl/color.hxx>
#endif

#include "zformat.hxx"  // just for NfKeywordTable

class International;
class SvNumberFormatter;
struct ImpSvNumberformatInfo;

#define SC_MAX_ANZ_FORMAT_STRINGS   100
#define SC_MAX_ANZ_STANDARD_FARBEN  10
#define FLAG_STANDARD_IN_FORMAT     1000
                                            // Hack: nThousand=1000
                                            // => Standard kommt im
                                            // Format vor

enum Sc_SymbolType
{
    SYMBOLTYPE_STRING = -1,                     // String in Ausgabe
    SYMBOLTYPE_DEL    = -2,                     // Sonderzeichen
    SYMBOLTYPE_BLANK  = -3,                     // Blank fuer '_'
    SYMBOLTYPE_STAR   = -4,                     // *-Buchstabe
    SYMBOLTYPE_DIGIT  = -5,                     // Ziffernplatzhalter
    SYMBOLTYPE_DECSEP = -6,                     // Komma
    SYMBOLTYPE_THSEP  = -7,                     // Tausenderpunkt
    SYMBOLTYPE_EXP    = -8,                     // Exponent E
    SYMBOLTYPE_FRAC   = -9,                     // Bruch /
    SYMBOLTYPE_EMPTY  = -10,                    // geloeschte Symbole
    SYMBOLTYPE_FRACBLANK = -11,                 // Trenner Zahl - Zaehler bei Bruch
    SYMBOLTYPE_COMMENT = -12,                   // Kommentar folgt
    SYMBOLTYPE_CURRENCY = -13,                  // Waehrungssymbol
    SYMBOLTYPE_CURRDEL  = -14,                  // Waehrungssymbol Delimiter [$]
    SYMBOLTYPE_CURREXT  = -15                   // Waehrungssymbol Extension -xxx
};

class ImpSvNumberformatScan
{
public:

    ImpSvNumberformatScan( SvNumberFormatter* pFormatter );
    ~ImpSvNumberformatScan();
    void ChangeIntl();                          // tauscht Keywords aus

    void ChangeNullDate(USHORT nDay, USHORT nMonth, USHORT nYear);
                                                // tauscht Referenzdatum aus
    void ChangeStandardPrec(short nPrec);       // tauscht Standardprecision aus

    xub_StrLen ScanFormat( String& rString, String& rComment ); // Aufruf der Scan-Analyse

    void CopyInfo(ImpSvNumberformatInfo* pInfo,
                     USHORT nAnz);              // Kopiert die FormatInfo
    USHORT GetAnzResStrings() const             { return nAnzResStrings; }

    const International& GetIntl() const        { return *pFormatter->GetInternational(); }
    const CharClass& GetChrCls() const          { return *pFormatter->GetCharClass(); }
    const LocaleDataWrapper& GetLoc() const     { return *pFormatter->GetLocaleData(); }

    const String& GetQuartalString() const  { return sKeyword[NF_KEY_QUARTER]; }
    const String& GetTrueString() const     { return sKeyword[NF_KEY_TRUE]; }
    const String& GetFalseString() const    { return sKeyword[NF_KEY_FALSE]; }
    const String& GetColorString() const    { return sKeyword[NF_KEY_COLOR]; }
    const String& GetRedString() const      { return sKeyword[NF_KEY_RED]; }
    const String& GetBooleanString() const  { return sKeyword[NF_KEY_BOOLEAN]; }
    const String& GetErrorString() const    { return sErrStr; }
    const String* GetKeyword() const        { return sKeyword; }

    Date* GetNullDate() const                   { return pNullDate; }
    const String& GetStandardName() const   { return sNameStandardFormat; }
    short GetStandardPrec() const               { return nStandardPrec; }
    const Color& GetRedColor() const            { return StandardColor[4]; }
    Color* GetColor(String& sStr);          // Setzt Hauptfarben oder
                                                // definierte Farben

    void SetConvertMode(LanguageType eTmpLge, LanguageType eNewLge)
    {
        bConvertMode = TRUE;
        eNewLnge = eNewLge;
        eTmpLnge = eTmpLge;
    }
    void SetConvertMode(BOOL bMode) { bConvertMode = bMode; }
                                                // Veraendert nur die Bool-Variable
                                                // (zum temporaeren Unterbrechen des
                                                // Convert-Modus)
    const BOOL GetConvertMode()     { return bConvertMode; }
    const LanguageType GetNewLnge() { return eNewLnge; }
                                                // Lesezugriff auf ConvertMode
                                                // und Konvertierungsland/Spr.
    const LanguageType GetTmpLnge() { return eTmpLnge; }
                                                // Lesezugriff auf
                                                // und Ausgangsland/Spr.
    SvNumberFormatter* GetNumberformatter() { return pFormatter; }
                                                // Zugriff auf Formatierer
                                                // (fuer zformat.cxx)

private:                            // ---- privater Teil
    NfKeywordTable sKeyword;                    // Schluesselworte der Syntax
    Color StandardColor[SC_MAX_ANZ_STANDARD_FARBEN];
                                                // Array der Standardfarben
    Date* pNullDate;                            // "1.1.1900"
    String sNameStandardFormat;             // "Standard"
    short nStandardPrec;                        // default Precision fuer Standardformat (2)
    SvNumberFormatter* pFormatter;              // Pointer auf die Formatliste

    String sStrArray[SC_MAX_ANZ_FORMAT_STRINGS];// Array der Symbole
    short nTypeArray[SC_MAX_ANZ_FORMAT_STRINGS];// Array der Infos
                                                // externe Infos:
    USHORT nAnzResStrings;                      // Anzahl der Ergebnissymbole
#if !(defined SOLARIS && defined X86)
    short eScannedType;                         // Typ gemaess Scan
#else
    int eScannedType;                           // wg. Optimierung
#endif
    BOOL bThousand;                             // Mit Tausenderpunkt
    USHORT nThousand;                           // Zaehlt ....-Folgen
    USHORT nCntPre;                             // Zaehlt Vorkommastellen
    USHORT nCntPost;                            // Zaehlt Nachkommastellen
    USHORT nCntExp;                             // Zaehlt Exp.Stellen, AM/PM
                                                // interne Infos:
    USHORT nAnzStrings;                         // Anzahl der Symbole
    USHORT nRepPos;                             // Position eines '*'
    USHORT nExpPos;                             // interne Position des E
    USHORT nBlankPos;                           // interne Position des Blank
    short nDecPos;                              // interne Pos. des ,
    BOOL bExp;                                  // wird bei Lesen des E gesetzt
    BOOL bFrac;                                 // wird bei Lesen des / gesetzt
    BOOL bBlank;                                // wird bei ' '(Fraction) ges.
    BOOL bDecSep;                               // Wird beim ersten , gesetzt
    String sCurString;                      // Das Waehrungssymbol in Upper
    String sErrStr;                         // String fuer Fehlerausgaben

    BOOL bConvertMode;                          // Wird im Convert-Mode gesetzt
                                                // Land/Sprache, in die der
    LanguageType eNewLnge;                      // gescannte String konvertiert
                                                // wird (fuer Excel Filter)
                                                // Land/Sprache, aus der der
    LanguageType eTmpLnge;                      // gescannte String konvertiert
                                                // wird (fuer Excel Filter)
    String sOldDecSep;                          // Dezimalsymbol der Ausgangs-
    String sOldThousandSep;                     // spr., analog Tausenderpunkt
    String sOldDateSep;                         // Datums- und Zeitsymbol
    String sOldTimeSep;
    xub_StrLen nCurrPos;                        // Position des Waehrungssymbols

#ifdef _ZFORSCAN_CXX                // ----- private Methoden -----
    void SetDependentKeywords();
                                                // Setzt die Sprachabh. Keyw.
    void SkipStrings(USHORT& i,xub_StrLen& nPos);// Ueberspringt StringSymbole
    USHORT PreviousKeyword(USHORT i);           // Gibt Index des vorangeh.
                                                // Schluesselworts oder 0
    USHORT NextKeyword(USHORT i);               // Gibt Index des naechsten
                                                // Schluesselworts oder 0
    sal_Unicode PreviousChar(USHORT i);             // Gibt letzten Buchstaben
                                                // vor der Position,
                                                // skipt EMPTY, STRING, STAR, BLANK
    sal_Unicode NextChar(USHORT i);                 // Gibt ersten Buchst. danach
    short PreviousType( USHORT i );             // Gibt Typ vor Position,
                                                // skipt EMPTY
    BOOL IsLastBlankBeforeFrac(USHORT i);       // True <=> es kommt kein ' '
                                                // mehr bis zum '/'
    void Reset();                               // Reset aller Variablen
                                                // vor Analysestart
    USHORT GetKeyWord(const String& sSymbol); // Vergleicht mit den Keywords
                                                // return 0 <=> nicht gefunden
    short Next_Symbol(const String& rStr,
                        xub_StrLen& nPos,
                      String& sSymbol);       // Naechstes Symbol
    xub_StrLen Symbol_Division(const String& rString);// lexikalische Voranalyse
    xub_StrLen ScanType(const String& rString); // Analyse des Formattyps
    xub_StrLen FinalScan( String& rString, String& rComment );  // Endanalyse mit Vorgabe
                                                // des Typs

    static inline BOOL StringEqualsChar( const String& rStr, sal_Unicode ch )
        { return rStr.GetChar(0) == ch && rStr.Len() == 1; }
        // Yes, for efficiency get the character first and then compare length
        // because in most places where this is used the string is one char.

#endif //_ZFORSCAN_CXX
};

#endif  // _ZFORSCAN_HXX
<|endoftext|>


<commit_before><commit_msg>improve memory release in JNI<commit_after><|endoftext|>


<commit_before>/* -------------------------------------------------------------------------- *
 *                   OpenSim:  testCMCArm26_Millard.cpp                       *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2016 Stanford University and the Authors                *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

// INCLUDE
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Simulation/Model/AnalysisSet.h>
#include <OpenSim/Tools/CMCTool.h>
#include <OpenSim/Tools/ForwardTool.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

#include <fstream>
#include <thread>

using namespace OpenSim;
using namespace std;

void testCMCArm26() {
    cout<<"\n******************************************************************" << endl;
    cout << "*                     testCMCArm26_Millard                          *" << endl;
    cout << "******************************************************************\n" << endl;
    CMCTool cmc("arm26_Setup_CMC.xml");
    cmc.setResultsDir("Results_Arm26_Millard");
    cmc.run();

    Storage results("Results_Arm26_Millard/arm26_states.sto"), temp("std_arm26_states.sto");
    Storage *standard = new Storage();
    cmc.getModel().formStateStorage(temp, *standard);

    Array<double> rms_tols(0.015, 2*2+2*6); // activations within 1%, angles within .6 degrees
    const string& muscleType = cmc.getModel().getMuscles()[0].getConcreteClassName();
    string base = "testCMCArm26 "+ muscleType;

    rms_tols[6]  = 0.05;   // TRIlat/activation
    rms_tols[8]  = 0.05;   // TRImed/activation
    rms_tols[10] = 0.05;   // BIClong/activation
    rms_tols[12] = 0.01;   // BICshort/activation
    rms_tols[14] = 0.005;  // BRA/activation

    CHECK_STORAGE_AGAINST_STANDARD(results, *standard, rms_tols, __FILE__, __LINE__,
        base+" failed");

    cout << "\n" << base <<" passed\n" << endl;
}

int main() {

    SimTK::Array_<std::string> failures;

    Object::renameType("Thelen2003Muscle", "Millard2012EquilibriumMuscle");

    try{
        testCMCArm26();
    }catch (const std::exception& e) {
        cout << e.what() <<endl; failures.push_back("testCMCArm26_Millard");
    }

    if (!failures.empty()) {
        cout << "Done, with failure(s): " << failures << endl;
        return 1;
    }

    cout << "Done" << endl;

    return 0;
}

<commit_msg>Fix tolerances as per CI tests.<commit_after>/* -------------------------------------------------------------------------- *
 *                   OpenSim:  testCMCArm26_Millard.cpp                       *
 * -------------------------------------------------------------------------- *
 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation.  *
 * See http://opensim.stanford.edu and the NOTICE file for more information.  *
 * OpenSim is developed at Stanford University and supported by the US        *
 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA    *
 * through the Warrior Web program.                                           *
 *                                                                            *
 * Copyright (c) 2005-2016 Stanford University and the Authors                *
 *                                                                            *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
 * not use this file except in compliance with the License. You may obtain a  *
 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
 *                                                                            *
 * Unless required by applicable law or agreed to in writing, software        *
 * distributed under the License is distributed on an "AS IS" BASIS,          *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
 * See the License for the specific language governing permissions and        *
 * limitations under the License.                                             *
 * -------------------------------------------------------------------------- */

// INCLUDE
#include <OpenSim/Simulation/Model/Model.h>
#include <OpenSim/Simulation/Model/AnalysisSet.h>
#include <OpenSim/Tools/CMCTool.h>
#include <OpenSim/Tools/ForwardTool.h>
#include <OpenSim/Auxiliary/auxiliaryTestFunctions.h>

#include <fstream>
#include <thread>

using namespace OpenSim;
using namespace std;

void testCMCArm26() {
    cout<<"\n******************************************************************" << endl;
    cout << "*                     testCMCArm26_Millard                          *" << endl;
    cout << "******************************************************************\n" << endl;
    CMCTool cmc("arm26_Setup_CMC.xml");
    cmc.setResultsDir("Results_Arm26_Millard");
    cmc.run();

    Storage results("Results_Arm26_Millard/arm26_states.sto"), temp("std_arm26_states.sto");
    Storage *standard = new Storage();
    cmc.getModel().formStateStorage(temp, *standard);

    Array<double> rms_tols(0.015, 2*2+2*6); // activations within 1%, angles within .6 degrees
    const string& muscleType = cmc.getModel().getMuscles()[0].getConcreteClassName();
    string base = "testCMCArm26 "+ muscleType;

    rms_tols[6]  = 0.05;   // TRIlat/activation
    rms_tols[8]  = 0.05;   // TRImed/activation
    rms_tols[10] = 0.05;   // BIClong/activation
    rms_tols[12] = 0.02;   // BICshort/activation
    rms_tols[14] = 0.005;  // BRA/activation

    CHECK_STORAGE_AGAINST_STANDARD(results, *standard, rms_tols, __FILE__, __LINE__,
        base+" failed");

    cout << "\n" << base <<" passed\n" << endl;
}

int main() {

    SimTK::Array_<std::string> failures;

    Object::renameType("Thelen2003Muscle", "Millard2012EquilibriumMuscle");

    try{
        testCMCArm26();
    }catch (const std::exception& e) {
        cout << e.what() <<endl; failures.push_back("testCMCArm26_Millard");
    }

    if (!failures.empty()) {
        cout << "Done, with failure(s): " << failures << endl;
        return 1;
    }

    cout << "Done" << endl;

    return 0;
}

<|endoftext|>


<commit_before>#include "QxtAVFile.h"
#include "QxtAVPlayer.h"
#include "QxtAVPlayer_p.h"
#include <QxtCore/QxtHyperMacros>
#include <limits>

/**
\class QxtAVPlayer QxtAVPlayer

\ingroup media

\brief simple player using the QxtAVFile and SDL

example:
\code
QxtAudioPlayer player;
player.play("foo.wav");
\endcode
*/

//------------------------------------------------------------------------------------

static void Callback (void * userData, Uint8 *stream, int size)
	{
	short *out = (short*)stream;
	int length = size/sizeof(short);
	QxtAVPlayerPrivate * player =  (QxtAVPlayerPrivate *)userData;

	float * peek =player->peek;
	bool peeking= player->peeking;
	if(player->avfile)
		{
		short a[size];
		short *pa=a;

		QXT_DROP_SCOPE(e,player->avfile->read(a, length))
			{
			player->up_fetch_eof();
			}

		fortimes(length)
			{
			if (peeking)
				(*peek++)=(float)*pa/ (float)std::numeric_limits<short>::max();

 			(*out++) =(short)((*pa++)*0.9*player->volume_m);

			}
		}

	else
		fortimes(length)
			*out++=0;
	}

//------------------------------------------------------------------------------------

QxtAVPlayerPrivate::QxtAVPlayerPrivate()
	{
	avfile=NULL;
	samplerate=48000;
	volume_m=0.99;
	opened_m=false;
	peeking=false;
	peek=new float  [2048*10];
	connect(this,SIGNAL(eof()),this,SLOT(close()));
	}

//------------------------------------------------------------------------------------

QxtError QxtAVPlayerPrivate::play(QString file)
	{
	if (opened_m)
		{
		SDL_PauseAudio (1);
		delete avfile;
		avfile= new QxtAVFile();
		QXT_DROP_F(avfile->open(file));
		SDL_PauseAudio (0);
		}
	else
		{
		avfile= new QxtAVFile();
		QXT_DROP_F(avfile->open(file));
		QXT_DROP_F(open());
		}

	QXT_DROP_OK;
	}
//------------------------------------------------------------------------------------

QxtError QxtAVPlayerPrivate::open()
	{
	if (opened_m)	QXT_DROP(Qxt::LogicalError);
	if (!avfile)	QXT_DROP(Qxt::Bug);

	if(SDL_Init (SDL_INIT_AUDIO)<0)QXT_DROP(Qxt::SDLError);

	SDL_AudioSpec wanted_spec;
	wanted_spec.freq=avfile->samplerate();
	wanted_spec.format=AUDIO_S16SYS;
	wanted_spec.channels=2;
        wanted_spec.silence = 0;

	wanted_spec.samples=2048;
	wanted_spec.callback=Callback;
	wanted_spec.userdata=this;
	got_spec=wanted_spec;

	if(SDL_OpenAudio (&wanted_spec, NULL)<0)QXT_DROP(Qxt::SDLError);

	///unpause
	SDL_PauseAudio (0);

	opened_m=true;
	QXT_DROP_OK;
	}
//------------------------------------------------------------------------------------
QxtError QxtAVPlayerPrivate::close()
	{
	if (!opened_m)	QXT_DROP(Qxt::NotInitialised);
	SDL_PauseAudio (1);
 	SDL_CloseAudio();
	if(avfile)delete(avfile);
	avfile=NULL;
	opened_m=false;
	QXT_DROP_OK;
	}
//------------------------------------------------------------------------------------

QxtError QxtAVPlayerPrivate::setVolume(float v)
	{
	if (v>0.99)v=0.99;
	if (v<0.0)v=0.0;
	volume_m=v;
	QXT_DROP_OK;
	}

QxtError QxtAVPlayerPrivate::pause      (bool e)
	{
	if (!opened_m)	QXT_DROP(Qxt::NotInitialised);

	if (e)
	SDL_PauseAudio (1);
	else
	SDL_PauseAudio (0);
	QXT_DROP_OK;
	}

//--------------------------------interface----------------------------------------------------

QxtAVPlayer::QxtAVPlayer(QObject * parent):QObject(parent)
	{
	connect(&qxt_d(),SIGNAL(eof()),this,SIGNAL(eof()));
	}
QxtAVPlayer::~QxtAVPlayer()
	{
	qxt_d().close();
	}

QxtAVFile * QxtAVPlayer::currentFile()
	{
	return 	qxt_d().avfile;
	}

QxtError QxtAVPlayer::play      (QString url)
	{
	return 	qxt_d().play(url);
	}

QxtError QxtAVPlayer::pause      (bool e)
	{
	return 	qxt_d().pause(e);
	}
QxtError QxtAVPlayer::setVolume (float v)
	{
	return 	qxt_d().setVolume(v);
	};

/*!
points to a buffer of 2048 floats from the last flip.

this is e.g. good for having externel analysers.\n
you need to do a setPeeking(true);
*/

float * QxtAVPlayer::peek()
	{
	return qxt_d().peek;
	}

bool  QxtAVPlayer::peeking()
	{
	return qxt_d().peeking;
	}

void QxtAVPlayer::setPeeking(bool e)
	{
	qxt_d().peeking=e;
	}
<commit_msg>emits eof instead of crashing when it cannot play files now<commit_after>#include "QxtAVFile.h"
#include "QxtAVPlayer.h"
#include "QxtAVPlayer_p.h"
#include <QxtCore/QxtHyperMacros>
#include <limits>

/**
\class QxtAVPlayer QxtAVPlayer

\ingroup media

\brief simple player using the QxtAVFile and SDL

example:
\code
QxtAudioPlayer player;
player.play("foo.wav");
\endcode
*/

//------------------------------------------------------------------------------------

static void Callback (void * userData, Uint8 *stream, int size)
	{
	short *out = (short*)stream;
	int length = size/sizeof(short);
	QxtAVPlayerPrivate * player =  (QxtAVPlayerPrivate *)userData;

	float * peek =player->peek;
	bool peeking= player->peeking;
	if(player->avfile)
		{
		short a[size];
		short *pa=a;

		QXT_DROP_SCOPE(e,player->avfile->read(a, length))
			{
			player->up_fetch_eof();
			}

		fortimes(length)
			{
			if (peeking)
				(*peek++)=(float)*pa/ (float)std::numeric_limits<short>::max();

 			(*out++) =(short)((*pa++)*0.9*player->volume_m);

			}
		}

	else
		fortimes(length)
			*out++=0;
	}

//------------------------------------------------------------------------------------

QxtAVPlayerPrivate::QxtAVPlayerPrivate()
	{
	avfile=NULL;
	samplerate=48000;
	volume_m=0.99;
	opened_m=false;
	peeking=false;
	peek=new float  [2048*10];
	connect(this,SIGNAL(eof()),this,SLOT(close()));
	}

//------------------------------------------------------------------------------------

QxtError QxtAVPlayerPrivate::play(QString file)
	{
	if (opened_m)
		{
		SDL_PauseAudio (1);
		opened_m=false;
		delete avfile;
		avfile= new QxtAVFile();
		QXT_DROP_SCOPE(error,avfile->open(file))
			{
			avfile=NULL;
		 	SDL_CloseAudio();
			qWarning("error opening File");
			up_fetch_eof();
			QXT_DROP_F(error);
			}
		opened_m=true;
		SDL_PauseAudio (0);

		}
	else
		{
		avfile= new QxtAVFile();
		QXT_DROP_F(avfile->open(file));
		QXT_DROP_F(open());
		}

	QXT_DROP_OK;
	}
//------------------------------------------------------------------------------------

QxtError QxtAVPlayerPrivate::open()
	{
	if (opened_m)	QXT_DROP(Qxt::LogicalError);
	if (!avfile)	QXT_DROP(Qxt::Bug);

	if(SDL_Init (SDL_INIT_AUDIO)<0)QXT_DROP(Qxt::SDLError);

	SDL_AudioSpec wanted_spec;
	wanted_spec.freq=avfile->samplerate();
	wanted_spec.format=AUDIO_S16SYS;
	wanted_spec.channels=2;
        wanted_spec.silence = 0;

	wanted_spec.samples=2048;
	wanted_spec.callback=Callback;
	wanted_spec.userdata=this;
	got_spec=wanted_spec;

	if(SDL_OpenAudio (&wanted_spec, NULL)<0)QXT_DROP(Qxt::SDLError);

	///unpause
	SDL_PauseAudio (0);

	opened_m=true;
	QXT_DROP_OK;
	}
//------------------------------------------------------------------------------------
QxtError QxtAVPlayerPrivate::close()
	{
	if (!opened_m)	QXT_DROP(Qxt::NotInitialised);
	SDL_PauseAudio (1);
 	SDL_CloseAudio();
	if(avfile)delete(avfile);
	avfile=NULL;
	opened_m=false;
	QXT_DROP_OK;
	}
//------------------------------------------------------------------------------------

QxtError QxtAVPlayerPrivate::setVolume(float v)
	{
	if (v>0.99)v=0.99;
	if (v<0.0)v=0.0;
	volume_m=v;
	QXT_DROP_OK;
	}

QxtError QxtAVPlayerPrivate::pause      (bool e)
	{
	if (!opened_m)	QXT_DROP(Qxt::NotInitialised);

	if (e)
	SDL_PauseAudio (1);
	else
	SDL_PauseAudio (0);
	QXT_DROP_OK;
	}

//--------------------------------interface----------------------------------------------------

QxtAVPlayer::QxtAVPlayer(QObject * parent):QObject(parent)
	{
	connect(&qxt_d(),SIGNAL(eof()),this,SIGNAL(eof()));
	}
QxtAVPlayer::~QxtAVPlayer()
	{
	qxt_d().close();
	}

QxtAVFile * QxtAVPlayer::currentFile()
	{
	return 	qxt_d().avfile;
	}

QxtError QxtAVPlayer::play      (QString url)
	{
	return 	qxt_d().play(url);
	}

QxtError QxtAVPlayer::pause      (bool e)
	{
	return 	qxt_d().pause(e);
	}
QxtError QxtAVPlayer::setVolume (float v)
	{
	return 	qxt_d().setVolume(v);
	};

/*!
points to a buffer of 2048 floats from the last flip.

this is e.g. good for having externel analysers.\n
you need to do a setPeeking(true);
*/

float * QxtAVPlayer::peek()
	{
	return qxt_d().peek;
	}

bool  QxtAVPlayer::peeking()
	{
	return qxt_d().peeking;
	}

void QxtAVPlayer::setPeeking(bool e)
	{
	qxt_d().peeking=e;
	}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
using namespace std;

int coins[8] = {1, 2, 5, 10, 20, 50, 100, 200};
int main()
{
    int dp[9][201] = {0};
    //init
    for (int i = 0; i < 9; ++i)
    {
        for (int j = 0; j < 201; ++j)
        {
            dp[i][j] = 0;
        }
    }
    // base case
    for (int j = 1; j < 201; ++j)
    {
        dp[1][j] = 1;
    }

    for (int i = 2; i < 9; ++i)
    {
        for (int j = 1; j < 201; ++j)
        {
            int n = j / coins[i-1];
            int tmp = 0;
            for (int d = 0; d <= n; ++d)
            {
                tmp += dp[i-1][j - coins[i-1]*d];
            }
            dp[i][j] = tmp;
        }
    }

    cout << "the number of ways using 8 coins to make is : "
        << dp[8][200] << endl;

    cout << "1st row:" << endl;
    cout << "2rd row:" << endl;
    for (int i = 0; i < 201; ++i)
    {
        cout << dp[1][i] << "," ;
    }
    cout << endl;
    for (int i = 0; i < 201; ++i)
    {
        cout << dp[2][i] << "," ;
    }
    cout << endl;
    return 0;
}

<commit_msg>dynamic programming, last time init situation wrong, revised it, good<commit_after>#include <iostream>
#include <string>
#include <vector>
using namespace std;

int coins[8] = {1, 2, 5, 10, 20, 50, 100, 200};
/*
 * Dynamic Programming
 *
 * dp[i][j] = using the first i kinds of coins to construct sum j
 * then dp[i][j] = dp[i-1][j - k * coins[i - 1]], k = 0, 1, ... ,j / coins[i-1]
 *
 * init
 * dp[i][0] = 1, where i = 0, 1, 2, ... ,8
 */
int main()
{
    int dp[9][201] = {0};
    //init
    for (int i = 0; i < 9; ++i)
    {
        dp[i][0] = 1;
    }

    for (int i = 1; i < 9; ++i)
    {
        for (int j = 1; j < 201; ++j)
        {
            int n = j / coins[i-1];
            int tmp = 0;
            for (int d = 0; d <= n; ++d)
            {
                tmp += dp[i-1][j - coins[i-1]*d];
            }
            dp[i][j] = tmp;
        }
    }

    cout << "the number of ways using 8 coins to make is : "
        << dp[8][200] << endl;

    return 0;
}

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "ClientSession.h"
#include "PacketType.h"
#include "ClientManager.h"
#include "DatabaseJobContext.h"
#include "DatabaseJobManager.h"

bool ClientSession::OnConnect(SOCKADDR_IN* addr)
{
	memcpy(&mClientAddr, addr, sizeof(SOCKADDR_IN)) ;

	///  ͺŷ ٲٰ
	u_long arg = 1 ;
	::ioctlsocket(mSocket, FIONBIO, &arg) ;

	/// nagle ˰
	int opt = 1 ;
	::setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(int)) ;

	printf("[DEBUG] Client Connected: IP=%s, PORT=%d\n", inet_ntoa(mClientAddr.sin_addr), ntohs(mClientAddr.sin_port)) ;

	mConnected = true ;

	return PostRecv() ;
}

bool ClientSession::PostRecv()
{
	if ( !IsConnected() )
		return false ;

	DWORD recvbytes = 0 ;
	DWORD flags = 0 ;
	WSABUF buf ;
	buf.len = (ULONG)mRecvBuffer.GetFreeSpaceSize() ;
	buf.buf = (char*)mRecvBuffer.GetBuffer() ;

	memset(&mOverlappedRecv, 0, sizeof(OverlappedIO)) ;
	mOverlappedRecv.mObject = this ;

	/// 񵿱
	if ( SOCKET_ERROR == WSARecv(mSocket, &buf, 1, &recvbytes, &flags, &mOverlappedRecv, RecvCompletion) )
	{
		if ( WSAGetLastError() != WSA_IO_PENDING )
			return false ;
	}

	IncOverlappedRequest() ;

	return true ;
}

void ClientSession::Disconnect()
{
	if ( !IsConnected() )
		return ;

	LogoutResult outPacket;
	outPacket.mPlayerId = mPlayerId;
	//BroadcastWithoutSelf(&outPacket);
	printf("[DEBUG] Client Disconnected: IP=%s, PORT=%d\n", inet_ntoa(mClientAddr.sin_addr), ntohs(mClientAddr.sin_port)) ;

	::shutdown(mSocket, SD_BOTH) ;
	::closesocket(mSocket) ;

	mConnected = false ;
}

void ClientSession::OnRead(size_t len)
{
	mRecvBuffer.Commit(len) ;

	/// Ŷ Ľϰ ó
	while ( true )
	{
		/// Ŷ  ũ ŭ оͺ
		PacketHeader header ;
		if ( false == mRecvBuffer.Peek((char*)&header, sizeof(PacketHeader)) )
			return ;

		/// Ŷ ϼ Ǵ°?
		if ( mRecvBuffer.GetStoredSize() < (header.mSize - sizeof(PacketHeader)) )
			return ;

		/// Ŷ ڵ鸵
		switch ( header.mType )
		{
		case PKT_CS_LOGIN:
			{
				LoginRequest inPacket ;
				mRecvBuffer.Read((char*)&inPacket, header.mSize) ;

				int id = mPlayerId = PlayerManager::GetInstance()->GetNewPlayerId();
				PlayerManager::GetInstance()->NewPlayer(id);

				/// α DB ۾ ľ ϱ  DB ۾ ûѴ.
				LoadPlayerDataContext* newDbJob = new LoadPlayerDataContext(mSocket, id);
				GDatabaseJobManager->PushDatabaseJobRequest(newDbJob) ;

				LoginResult outPacket ;
				outPacket.mMyPlayerInfo = PlayerManager::GetInstance()->GetPlayer(id)->GetPlayerInfo();
				outPacket.mNowPlayersLength = PlayerManager::GetInstance()->GetPlayersLength();
				std::map<int,Player*> players = PlayerManager::GetInstance()->GetPlayers();
				int i=0;
				for( std::map<int,Player*>::iterator it = players.begin(); it != players.end(); ++it )
				{
					outPacket.mPlayerInfo[i] = it->second->GetPlayerInfo();
					i++;
				}
				if(!Send(&outPacket) )
					return;

				LoginBroadcastResult outPacketBroadCast;
				outPacketBroadCast.mMyPlayerInfo = PlayerManager::GetInstance()->GetPlayer(id)->GetPlayerInfo();
				if(!BroadcastWithoutSelf(&outPacketBroadCast) )
					return;
			}
			break ;

		/*case PKT_CS_CHAT:
			{
				ChatBroadcastRequest inPacket ;
				mRecvBuffer.Read((char*)&inPacket, header.mSize) ;

				ChatBroadcastResult outPacket ;
				outPacket.mPlayerId = inPacket.mPlayerId ;
				strcpy_s(outPacket.mName, mPlayerName) ;
				strcpy_s(outPacket.mChat, inPacket.mChat) ;

				/// ä ٷ  ϸ
				if ( !Broadcast(&outPacket) )
					return ;

			}
			break ;
		*/case PKT_CS_KEYSTATE:
			{
				GameKeyStatesUpdateRequest inPacket ;
				mRecvBuffer.Read((char*)&inPacket, header.mSize);

				Player* _player = PlayerManager::GetInstance()->GetPlayer(inPacket.mMyPlayerInfo.mPlayerId);
				_player->SetGameKeyStates(inPacket.mMyPlayerInfo.mGameKeyStates);
				_player->SetPosition(Point(inPacket.mMyPlayerInfo.mX, inPacket.mMyPlayerInfo.mY));

				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = _player->GetPlayerInfo();

				if( !BroadcastWithoutSelf(&outPacket) )
					return;
			}
			break ;
		default:
			{
				///   ̻ Ŷ Ŵ.
				Disconnect() ;
				return ;
			}
			break ;
		}
	}
}

bool ClientSession::Send(PacketHeader* pkt)
{
	if ( !IsConnected() )
		return false ;

	///  뷮
	if ( false == mSendBuffer.Write((char*)pkt, pkt->mSize) )
	{
		Disconnect() ;
		return false ;
	}

	///  Ͱ ִ ˻
	if ( mSendBuffer.GetContiguiousBytes() == 0 )
	{
		///  write ߴµ, Ͱ ٸ  ߸
		assert(false) ;
		Disconnect() ;
		return false ;
	}

	DWORD sendbytes = 0 ;
	DWORD flags = 0 ;

	WSABUF buf ;
	buf.len = (ULONG)mSendBuffer.GetContiguiousBytes() ;
	buf.buf = (char*)mSendBuffer.GetBufferStart() ;

	memset(&mOverlappedSend, 0, sizeof(OverlappedIO)) ;
	mOverlappedSend.mObject = this ;

	// 񵿱
	if ( SOCKET_ERROR == WSASend(mSocket, &buf, 1, &sendbytes, flags, &mOverlappedSend, SendCompletion) )
	{
		if ( WSAGetLastError() != WSA_IO_PENDING )
			return false ;
	}

	IncOverlappedRequest() ;
	return true ;
}

void ClientSession::OnWriteComplete(size_t len)
{
	///  Ϸ ʹ ۿ
	mSendBuffer.Remove(len) ;

	/// ?   쵵 ֳ? (Ŀ send queue áų, Send Completion  send  ?)
	if ( mSendBuffer.GetContiguiousBytes() > 0 )
	{
		assert(false) ;
	}

}

bool ClientSession::Broadcast(PacketHeader* pkt)
{
	if ( !Send(pkt) )
		return false ;

	if ( !IsConnected() )
		return false ;

	GClientManager->BroadcastPacket(this, pkt) ;

	return true ;
}
bool ClientSession::BroadcastWithoutSelf(PacketHeader* pkt)
{
	if ( !IsConnected() )
		return false ;

	GClientManager->BroadcastPacket(this, pkt) ;

	return true ;
}
void ClientSession::OnTick()
{
	/// Ŭ󺰷 ֱ ؾߵ  ⿡

	/// Ư ֱ DB ġ
	if ( ++mDbUpdateCount == PLAYER_DB_UPDATE_CYCLE )
	{
		mDbUpdateCount = 0 ;
		UpdatePlayerDataContext* updatePlayer = new UpdatePlayerDataContext(mSocket, mPlayerId) ;

		//strcpy_s(updatePlayer->mComment, "updated_test") ; ///< ϴ ׽Ʈ
		GDatabaseJobManager->PushDatabaseJobRequest(updatePlayer) ;
	}

}

void ClientSession::DatabaseJobDone(DatabaseJobContext* result)
{
	CRASH_ASSERT( mSocket == result->mSockKey ) ;

	const type_info& typeInfo = typeid(*result) ;

	if ( typeInfo == typeid(LoadPlayerDataContext) )
	{
		LoadPlayerDataContext* login = dynamic_cast<LoadPlayerDataContext*>(result) ;

		//LoginDone(login->mPlayerId, login->mPosX, login->mPosY, login->mPosZ, login->mPlayerName) ;

	}
	else if ( typeInfo == typeid(UpdatePlayerDataContext) )
	{
		UpdateDone() ;
	}
	else
	{
		CRASH_ASSERT(false) ;
	}

}

void ClientSession::UpdateDone()
{
	///  ֱ     .  ׽Ʈ ؼ..
	printf("DEBUG: Player[%d] Update Done\n", mPlayerId) ;
}

void ClientSession::LoginDone(int pid, double x, double y, double z, const char* name)
{
/*	LoginResult outPacket ;

	outPacket.mPlayerId = mPlayerId = pid ;
	outPacket.mPosX = mPosX = x ;
	outPacket.mPosY = mPosY = y ;
	outPacket.mPosZ = mPosZ = z ;
	strcpy_s(mPlayerName, name) ;
	strcpy_s(outPacket.mName, name) ;

	Send(&outPacket) ;
*/
	mLogon = true ;
}

///////////////////////////////////////////////////////////

void CALLBACK RecvCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
{
	ClientSession* fromClient = static_cast<OverlappedIO*>(lpOverlapped)->mObject ;

	fromClient->DecOverlappedRequest() ;

	if ( !fromClient->IsConnected() )
		return ;

	///  ߻ ش
	if ( dwError || cbTransferred == 0 )
	{
		fromClient->Disconnect() ;
		return ;
	}

	///   ó
	fromClient->OnRead(cbTransferred) ;

	/// ٽ ޱ
	if ( false == fromClient->PostRecv() )
	{
		fromClient->Disconnect() ;
		return ;
	}
}

void CALLBACK SendCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
{
	ClientSession* fromClient = static_cast<OverlappedIO*>(lpOverlapped)->mObject ;

	fromClient->DecOverlappedRequest() ;

	if ( !fromClient->IsConnected() )
		return ;

	///  ߻ ش
	if ( dwError || cbTransferred == 0 )
	{
		fromClient->Disconnect() ;
		return ;
	}

	fromClient->OnWriteComplete(cbTransferred) ;

}

<commit_msg>나간 플레이어 사라지도록 설정<commit_after>#include "stdafx.h"
#include "ClientSession.h"
#include "PacketType.h"
#include "ClientManager.h"
#include "DatabaseJobContext.h"
#include "DatabaseJobManager.h"

bool ClientSession::OnConnect(SOCKADDR_IN* addr)
{
	memcpy(&mClientAddr, addr, sizeof(SOCKADDR_IN)) ;

	///  ͺŷ ٲٰ
	u_long arg = 1 ;
	::ioctlsocket(mSocket, FIONBIO, &arg) ;

	/// nagle ˰
	int opt = 1 ;
	::setsockopt(mSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(int)) ;

	printf("[DEBUG] Client Connected: IP=%s, PORT=%d\n", inet_ntoa(mClientAddr.sin_addr), ntohs(mClientAddr.sin_port)) ;

	mConnected = true ;

	return PostRecv() ;
}

bool ClientSession::PostRecv()
{
	if ( !IsConnected() )
		return false ;

	DWORD recvbytes = 0 ;
	DWORD flags = 0 ;
	WSABUF buf ;
	buf.len = (ULONG)mRecvBuffer.GetFreeSpaceSize() ;
	buf.buf = (char*)mRecvBuffer.GetBuffer() ;

	memset(&mOverlappedRecv, 0, sizeof(OverlappedIO)) ;
	mOverlappedRecv.mObject = this ;

	/// 񵿱
	if ( SOCKET_ERROR == WSARecv(mSocket, &buf, 1, &recvbytes, &flags, &mOverlappedRecv, RecvCompletion) )
	{
		if ( WSAGetLastError() != WSA_IO_PENDING )
			return false ;
	}

	IncOverlappedRequest() ;

	return true ;
}

void ClientSession::Disconnect()
{
	if ( !IsConnected() )
		return ;

	LogoutResult outPacket;
	outPacket.mPlayerId = mPlayerId;
	PlayerManager::GetInstance()->DeletePlayer(mPlayerId);
	//BroadcastWithoutSelf(&outPacket);
	printf("[DEBUG] Client Disconnected: IP=%s, PORT=%d\n", inet_ntoa(mClientAddr.sin_addr), ntohs(mClientAddr.sin_port)) ;

	::shutdown(mSocket, SD_BOTH) ;
	::closesocket(mSocket) ;

	mConnected = false ;
}

void ClientSession::OnRead(size_t len)
{
	mRecvBuffer.Commit(len) ;

	/// Ŷ Ľϰ ó
	while ( true )
	{
		/// Ŷ  ũ ŭ оͺ
		PacketHeader header ;
		if ( false == mRecvBuffer.Peek((char*)&header, sizeof(PacketHeader)) )
			return ;

		/// Ŷ ϼ Ǵ°?
		if ( mRecvBuffer.GetStoredSize() < (header.mSize - sizeof(PacketHeader)) )
			return ;

		/// Ŷ ڵ鸵
		switch ( header.mType )
		{
		case PKT_CS_LOGIN:
			{
				LoginRequest inPacket ;
				mRecvBuffer.Read((char*)&inPacket, header.mSize) ;

				int id = mPlayerId = PlayerManager::GetInstance()->GetNewPlayerId();
				PlayerManager::GetInstance()->NewPlayer(id);

				/// α DB ۾ ľ ϱ  DB ۾ ûѴ.
				LoadPlayerDataContext* newDbJob = new LoadPlayerDataContext(mSocket, id);
				GDatabaseJobManager->PushDatabaseJobRequest(newDbJob) ;

				LoginResult outPacket ;
				outPacket.mMyPlayerInfo = PlayerManager::GetInstance()->GetPlayer(id)->GetPlayerInfo();
				outPacket.mNowPlayersLength = PlayerManager::GetInstance()->GetPlayersLength();
				std::map<int,Player*> players = PlayerManager::GetInstance()->GetPlayers();
				int i=0;
				for( std::map<int,Player*>::iterator it = players.begin(); it != players.end(); ++it )
				{
					outPacket.mPlayerInfo[i] = it->second->GetPlayerInfo();
					i++;
				}
				if(!Send(&outPacket) )
					return;

				LoginBroadcastResult outPacketBroadCast;
				outPacketBroadCast.mMyPlayerInfo = PlayerManager::GetInstance()->GetPlayer(id)->GetPlayerInfo();
				if(!BroadcastWithoutSelf(&outPacketBroadCast) )
					return;
			}
			break ;

		/*case PKT_CS_CHAT:
			{
				ChatBroadcastRequest inPacket ;
				mRecvBuffer.Read((char*)&inPacket, header.mSize) ;

				ChatBroadcastResult outPacket ;
				outPacket.mPlayerId = inPacket.mPlayerId ;
				strcpy_s(outPacket.mName, mPlayerName) ;
				strcpy_s(outPacket.mChat, inPacket.mChat) ;

				/// ä ٷ  ϸ
				if ( !Broadcast(&outPacket) )
					return ;

			}
			break ;
		*/case PKT_CS_KEYSTATE:
			{
				GameKeyStatesUpdateRequest inPacket ;
				mRecvBuffer.Read((char*)&inPacket, header.mSize);

				Player* _player = PlayerManager::GetInstance()->GetPlayer(inPacket.mMyPlayerInfo.mPlayerId);
				_player->SetGameKeyStates(inPacket.mMyPlayerInfo.mGameKeyStates);
				_player->SetPosition(Point(inPacket.mMyPlayerInfo.mX, inPacket.mMyPlayerInfo.mY));

				GameKeyStatesUpdateResult outPacket = GameKeyStatesUpdateResult();
				outPacket.mMyPlayerInfo = _player->GetPlayerInfo();

				if( !BroadcastWithoutSelf(&outPacket) )
					return;
			}
			break ;
		default:
			{
				///   ̻ Ŷ Ŵ.
				Disconnect() ;
				return ;
			}
			break ;
		}
	}
}

bool ClientSession::Send(PacketHeader* pkt)
{
	if ( !IsConnected() )
		return false ;

	///  뷮
	if ( false == mSendBuffer.Write((char*)pkt, pkt->mSize) )
	{
		Disconnect() ;
		return false ;
	}

	///  Ͱ ִ ˻
	if ( mSendBuffer.GetContiguiousBytes() == 0 )
	{
		///  write ߴµ, Ͱ ٸ  ߸
		assert(false) ;
		Disconnect() ;
		return false ;
	}

	DWORD sendbytes = 0 ;
	DWORD flags = 0 ;

	WSABUF buf ;
	buf.len = (ULONG)mSendBuffer.GetContiguiousBytes() ;
	buf.buf = (char*)mSendBuffer.GetBufferStart() ;

	memset(&mOverlappedSend, 0, sizeof(OverlappedIO)) ;
	mOverlappedSend.mObject = this ;

	// 񵿱
	if ( SOCKET_ERROR == WSASend(mSocket, &buf, 1, &sendbytes, flags, &mOverlappedSend, SendCompletion) )
	{
		if ( WSAGetLastError() != WSA_IO_PENDING )
			return false ;
	}

	IncOverlappedRequest() ;
	return true ;
}

void ClientSession::OnWriteComplete(size_t len)
{
	///  Ϸ ʹ ۿ
	mSendBuffer.Remove(len) ;

	/// ?   쵵 ֳ? (Ŀ send queue áų, Send Completion  send  ?)
	if ( mSendBuffer.GetContiguiousBytes() > 0 )
	{
		assert(false) ;
	}

}

bool ClientSession::Broadcast(PacketHeader* pkt)
{
	if ( !Send(pkt) )
		return false ;

	if ( !IsConnected() )
		return false ;

	GClientManager->BroadcastPacket(this, pkt) ;

	return true ;
}
bool ClientSession::BroadcastWithoutSelf(PacketHeader* pkt)
{
	if ( !IsConnected() )
		return false ;

	GClientManager->BroadcastPacket(this, pkt) ;

	return true ;
}
void ClientSession::OnTick()
{
	/// Ŭ󺰷 ֱ ؾߵ  ⿡

	/// Ư ֱ DB ġ
	if ( ++mDbUpdateCount == PLAYER_DB_UPDATE_CYCLE )
	{
		mDbUpdateCount = 0 ;
		UpdatePlayerDataContext* updatePlayer = new UpdatePlayerDataContext(mSocket, mPlayerId) ;

		//strcpy_s(updatePlayer->mComment, "updated_test") ; ///< ϴ ׽Ʈ
		GDatabaseJobManager->PushDatabaseJobRequest(updatePlayer) ;
	}

}

void ClientSession::DatabaseJobDone(DatabaseJobContext* result)
{
	CRASH_ASSERT( mSocket == result->mSockKey ) ;

	const type_info& typeInfo = typeid(*result) ;

	if ( typeInfo == typeid(LoadPlayerDataContext) )
	{
		LoadPlayerDataContext* login = dynamic_cast<LoadPlayerDataContext*>(result) ;

		//LoginDone(login->mPlayerId, login->mPosX, login->mPosY, login->mPosZ, login->mPlayerName) ;

	}
	else if ( typeInfo == typeid(UpdatePlayerDataContext) )
	{
		UpdateDone() ;
	}
	else
	{
		CRASH_ASSERT(false) ;
	}

}

void ClientSession::UpdateDone()
{
	///  ֱ     .  ׽Ʈ ؼ..
	printf("DEBUG: Player[%d] Update Done\n", mPlayerId) ;
}

void ClientSession::LoginDone(int pid, double x, double y, double z, const char* name)
{
/*	LoginResult outPacket ;

	outPacket.mPlayerId = mPlayerId = pid ;
	outPacket.mPosX = mPosX = x ;
	outPacket.mPosY = mPosY = y ;
	outPacket.mPosZ = mPosZ = z ;
	strcpy_s(mPlayerName, name) ;
	strcpy_s(outPacket.mName, name) ;

	Send(&outPacket) ;
*/
	mLogon = true ;
}

///////////////////////////////////////////////////////////

void CALLBACK RecvCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
{
	ClientSession* fromClient = static_cast<OverlappedIO*>(lpOverlapped)->mObject ;

	fromClient->DecOverlappedRequest() ;

	if ( !fromClient->IsConnected() )
		return ;

	///  ߻ ش
	if ( dwError || cbTransferred == 0 )
	{
		fromClient->Disconnect() ;
		return ;
	}

	///   ó
	fromClient->OnRead(cbTransferred) ;

	/// ٽ ޱ
	if ( false == fromClient->PostRecv() )
	{
		fromClient->Disconnect() ;
		return ;
	}
}

void CALLBACK SendCompletion(DWORD dwError, DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags)
{
	ClientSession* fromClient = static_cast<OverlappedIO*>(lpOverlapped)->mObject ;

	fromClient->DecOverlappedRequest() ;

	if ( !fromClient->IsConnected() )
		return ;

	///  ߻ ش
	if ( dwError || cbTransferred == 0 )
	{
		fromClient->Disconnect() ;
		return ;
	}

	fromClient->OnWriteComplete(cbTransferred) ;

}

<|endoftext|>


<commit_before>#include <utility>

#include "components/builder.hpp"
#include "drawtypes/label.hpp"
#include "modules/meta/base.hpp"

POLYBAR_NS

namespace modules {
  // module_format {{{

  string module_format::decorate(builder* builder, string output) {
    if (output.empty()) {
      builder->flush();
      return "";
    }

    if (offset != 0) {
      builder->offset(offset);
    }
    if (margin > 0) {
      builder->space(margin);
    }
    if (!bg.empty()) {
      builder->background(bg);
    }
    if (!fg.empty()) {
      builder->color(fg);
    }
    if (!ul.empty()) {
      builder->underline(ul);
    }
    if (!ol.empty()) {
      builder->overline(ol);
    }
    if (padding > 0) {
      builder->space(padding);
    }

    if (!output.empty()) {
      builder->node(prefix);
      builder->append(move(output));
      builder->node(suffix);
    }

    if (padding > 0) {
      builder->space(padding);
    }
    if (!ol.empty()) {
      builder->overline_close();
    }
    if (!ul.empty()) {
      builder->underline_close();
    }
    if (!fg.empty()) {
      builder->color_close();
    }
    if (!bg.empty()) {
      builder->background_close();
    }
    if (margin > 0) {
      builder->space(margin);
    }

    return builder->flush();
  }

  // }}}
  // module_formatter {{{

  void module_formatter::add(string name, string fallback, vector<string>&& tags, vector<string>&& whitelist) {
    const auto formatdef = [&](
        const string& param, const auto& fallback) { return m_conf.get("settings", "format-" + param, fallback); };

    auto format = make_unique<module_format>();
    format->value = m_conf.get(m_modname, name, move(fallback));
    format->fg = m_conf.get(m_modname, name + "-foreground", formatdef("foreground", format->fg));
    format->bg = m_conf.get(m_modname, name + "-background", formatdef("background", format->bg));
    format->ul = m_conf.get(m_modname, name + "-underline", formatdef("underline", format->ul));
    format->ol = m_conf.get(m_modname, name + "-overline", formatdef("overline", format->ol));
    format->ulsize = m_conf.get(m_modname, name + "-underline-size", formatdef("underline-size", format->ulsize));
    format->olsize = m_conf.get(m_modname, name + "-overline-size", formatdef("overline-size", format->olsize));
    format->spacing = m_conf.get(m_modname, name + "-spacing", formatdef("spacing", format->spacing));
    format->padding = m_conf.get(m_modname, name + "-padding", formatdef("padding", format->padding));
    format->margin = m_conf.get(m_modname, name + "-margin", formatdef("margin", format->margin));
    format->offset = m_conf.get(m_modname, name + "-offset", formatdef("offset", format->offset));
    format->tags.swap(tags);

    try {
      format->prefix = load_label(m_conf, m_modname, name + "-prefix");
    } catch (const key_error& err) {
      // prefix not defined
    }

    try {
      format->suffix = load_label(m_conf, m_modname, name + "-suffix");
    } catch (const key_error& err) {
      // suffix not defined
    }

    vector<string> tag_collection;
    tag_collection.reserve(format->tags.size() + whitelist.size());
    tag_collection.insert(tag_collection.end(), format->tags.begin(), format->tags.end());
    tag_collection.insert(tag_collection.end(), whitelist.begin(), whitelist.end());

    size_t start, end;
    string value{format->value};
    while ((start = value.find('<')) != string::npos && (end = value.find('>', start)) != string::npos) {
      if (start > 0) {
        value.erase(0, start);
        end -= start;
        start = 0;
      }
      string tag{value.substr(start, end + 1)};
      if (find(tag_collection.begin(), tag_collection.end(), tag) == tag_collection.end()) {
        throw undefined_format_tag(tag + " is not a valid format tag for \"" + name + "\"");
      }
      value.erase(0, tag.size());
    }

    m_formats.insert(make_pair(move(name), move(format)));
  }

  bool module_formatter::has(const string& tag, const string& format_name) {
    auto format = m_formats.find(format_name);
    if (format == m_formats.end()) {
      throw undefined_format(format_name);
    }
    return format->second->value.find(tag) != string::npos;
  }

  bool module_formatter::has(const string& tag) {
    for (auto&& format : m_formats) {
      if (format.second->value.find(tag) != string::npos) {
        return true;
      }
    }
    return false;
  }

  shared_ptr<module_format> module_formatter::get(const string& format_name) {
    auto format = m_formats.find(format_name);
    if (format == m_formats.end()) {
      throw undefined_format("Format \"" + format_name + "\" has not been added");
    }
    return format->second;
  }

  // }}}
}

POLYBAR_NS_END
<commit_msg>fix(modules): Separate prefix and suffix from output<commit_after>#include <utility>

#include "components/builder.hpp"
#include "drawtypes/label.hpp"
#include "modules/meta/base.hpp"

POLYBAR_NS

namespace modules {
  // module_format {{{

  string module_format::decorate(builder* builder, string output) {
    if (output.empty()) {
      builder->flush();
      return "";
    }
    builder->node(prefix);

    if (offset != 0) {
      builder->offset(offset);
    }
    if (margin > 0) {
      builder->space(margin);
    }
    if (!bg.empty()) {
      builder->background(bg);
    }
    if (!fg.empty()) {
      builder->color(fg);
    }
    if (!ul.empty()) {
      builder->underline(ul);
    }
    if (!ol.empty()) {
      builder->overline(ol);
    }
    if (padding > 0) {
      builder->space(padding);
    }

    if (!output.empty()) {
      builder->append(move(output));
    }

    if (padding > 0) {
      builder->space(padding);
    }
    if (!ol.empty()) {
      builder->overline_close();
    }
    if (!ul.empty()) {
      builder->underline_close();
    }
    if (!fg.empty()) {
      builder->color_close();
    }
    if (!bg.empty()) {
      builder->background_close();
    }
    if (margin > 0) {
      builder->space(margin);
    }
    builder->node(suffix);

    return builder->flush();
  }

  // }}}
  // module_formatter {{{

  void module_formatter::add(string name, string fallback, vector<string>&& tags, vector<string>&& whitelist) {
    const auto formatdef = [&](
        const string& param, const auto& fallback) { return m_conf.get("settings", "format-" + param, fallback); };

    auto format = make_unique<module_format>();
    format->value = m_conf.get(m_modname, name, move(fallback));
    format->fg = m_conf.get(m_modname, name + "-foreground", formatdef("foreground", format->fg));
    format->bg = m_conf.get(m_modname, name + "-background", formatdef("background", format->bg));
    format->ul = m_conf.get(m_modname, name + "-underline", formatdef("underline", format->ul));
    format->ol = m_conf.get(m_modname, name + "-overline", formatdef("overline", format->ol));
    format->ulsize = m_conf.get(m_modname, name + "-underline-size", formatdef("underline-size", format->ulsize));
    format->olsize = m_conf.get(m_modname, name + "-overline-size", formatdef("overline-size", format->olsize));
    format->spacing = m_conf.get(m_modname, name + "-spacing", formatdef("spacing", format->spacing));
    format->padding = m_conf.get(m_modname, name + "-padding", formatdef("padding", format->padding));
    format->margin = m_conf.get(m_modname, name + "-margin", formatdef("margin", format->margin));
    format->offset = m_conf.get(m_modname, name + "-offset", formatdef("offset", format->offset));
    format->tags.swap(tags);

    try {
      format->prefix = load_label(m_conf, m_modname, name + "-prefix");
    } catch (const key_error& err) {
      // prefix not defined
    }

    try {
      format->suffix = load_label(m_conf, m_modname, name + "-suffix");
    } catch (const key_error& err) {
      // suffix not defined
    }

    vector<string> tag_collection;
    tag_collection.reserve(format->tags.size() + whitelist.size());
    tag_collection.insert(tag_collection.end(), format->tags.begin(), format->tags.end());
    tag_collection.insert(tag_collection.end(), whitelist.begin(), whitelist.end());

    size_t start, end;
    string value{format->value};
    while ((start = value.find('<')) != string::npos && (end = value.find('>', start)) != string::npos) {
      if (start > 0) {
        value.erase(0, start);
        end -= start;
        start = 0;
      }
      string tag{value.substr(start, end + 1)};
      if (find(tag_collection.begin(), tag_collection.end(), tag) == tag_collection.end()) {
        throw undefined_format_tag(tag + " is not a valid format tag for \"" + name + "\"");
      }
      value.erase(0, tag.size());
    }

    m_formats.insert(make_pair(move(name), move(format)));
  }

  bool module_formatter::has(const string& tag, const string& format_name) {
    auto format = m_formats.find(format_name);
    if (format == m_formats.end()) {
      throw undefined_format(format_name);
    }
    return format->second->value.find(tag) != string::npos;
  }

  bool module_formatter::has(const string& tag) {
    for (auto&& format : m_formats) {
      if (format.second->value.find(tag) != string::npos) {
        return true;
      }
    }
    return false;
  }

  shared_ptr<module_format> module_formatter::get(const string& format_name) {
    auto format = m_formats.find(format_name);
    if (format == m_formats.end()) {
      throw undefined_format("Format \"" + format_name + "\" has not been added");
    }
    return format->second;
  }

  // }}}
}

POLYBAR_NS_END
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "util.h"

TEST(TestParseTime, Test1) {
  int t;
  EXPECT_TRUE(ParseTime("2h", &t));
  EXPECT_EQ(3600 * 2, t);
  EXPECT_TRUE(ParseTime("2hour", &t));
  EXPECT_EQ(3600 * 2, t);
  EXPECT_TRUE(ParseTime("3m", &t));
  EXPECT_EQ(60 * 3, t);
  EXPECT_TRUE(ParseTime("3min", &t));
  EXPECT_EQ(60 * 3, t);
  EXPECT_TRUE(ParseTime("40s", &t));
  EXPECT_EQ(40, t);
  EXPECT_TRUE(ParseTime("40sec", &t));
  EXPECT_EQ(40, t);
  EXPECT_TRUE(ParseTime("3d", &t));
  EXPECT_EQ(3 * 3600 * 24, t);
  EXPECT_TRUE(ParseTime("3day", &t));
  EXPECT_EQ(3 * 3600 * 24, t);

  EXPECT_FALSE(ParseTime("1f", &t));
  EXPECT_FALSE(ParseTime("40", &t));
  EXPECT_FALSE(ParseTime("-3d", &t));
}

TEST(TestParseSize, Test1) {
  int t;
  EXPECT_TRUE(ParseSize("100b", &t));
  EXPECT_EQ(100, t);
  EXPECT_TRUE(ParseSize("2k", &t));
  EXPECT_EQ(2 * 1024, t);
  EXPECT_TRUE(ParseSize("3kb", &t));
  EXPECT_EQ(3 * 1024, t);
  EXPECT_TRUE(ParseSize("3m", &t));
  EXPECT_EQ(3 * 1024 * 1024, t);
  EXPECT_TRUE(ParseSize("3mb", &t));
  EXPECT_EQ(3 * 1024 * 1024, t);
  EXPECT_TRUE(ParseSize("3G", &t));
  EXPECT_EQ(3 * 1024 * 1024 * 1024, t);

  EXPECT_FALSE(ParseSize("1f", &t));
  EXPECT_FALSE(ParseSize("40", &t));
  EXPECT_FALSE(ParseSize("-3d", &t));
}
<commit_msg>Add unit test for bytesToHuman.<commit_after>#include "gtest/gtest.h"

#include "util.h"

TEST(TestParseTime, Test1) {
  int t;
  EXPECT_TRUE(ParseTime("2h", &t));
  EXPECT_EQ(3600 * 2, t);
  EXPECT_TRUE(ParseTime("2hour", &t));
  EXPECT_EQ(3600 * 2, t);
  EXPECT_TRUE(ParseTime("3m", &t));
  EXPECT_EQ(60 * 3, t);
  EXPECT_TRUE(ParseTime("3min", &t));
  EXPECT_EQ(60 * 3, t);
  EXPECT_TRUE(ParseTime("40s", &t));
  EXPECT_EQ(40, t);
  EXPECT_TRUE(ParseTime("40sec", &t));
  EXPECT_EQ(40, t);
  EXPECT_TRUE(ParseTime("3d", &t));
  EXPECT_EQ(3 * 3600 * 24, t);
  EXPECT_TRUE(ParseTime("3day", &t));
  EXPECT_EQ(3 * 3600 * 24, t);

  EXPECT_FALSE(ParseTime("1f", &t));
  EXPECT_FALSE(ParseTime("40", &t));
  EXPECT_FALSE(ParseTime("-3d", &t));
}

TEST(TestParseSize, Test1) {
  int t;
  EXPECT_TRUE(ParseSize("100b", &t));
  EXPECT_EQ(100, t);
  EXPECT_TRUE(ParseSize("2k", &t));
  EXPECT_EQ(2 * 1024, t);
  EXPECT_TRUE(ParseSize("3kb", &t));
  EXPECT_EQ(3 * 1024, t);
  EXPECT_TRUE(ParseSize("3m", &t));
  EXPECT_EQ(3 * 1024 * 1024, t);
  EXPECT_TRUE(ParseSize("3mb", &t));
  EXPECT_EQ(3 * 1024 * 1024, t);
  EXPECT_TRUE(ParseSize("3G", &t));
  EXPECT_EQ(3 * 1024 * 1024 * 1024, t);

  EXPECT_FALSE(ParseSize("1f", &t));
  EXPECT_FALSE(ParseSize("40", &t));
  EXPECT_FALSE(ParseSize("-3d", &t));
}

TEST(TestBytesToHuman, Test1) {
  uint64_t n;
  char str[64];
  n = 42;
  bytesToHuman(str, n);
  EXPECT_STREQ("42B", str);

  memset(str, 0, sizeof(str));
  n = 42 * 1024 + 42;
  bytesToHuman(str, n);
  EXPECT_STREQ("42.04K", str);

  memset(str, 0, sizeof(str));
  n = 42LL * 1024 * 1024 + 42 * 1024 + 42;
  bytesToHuman(str, n);
  EXPECT_STREQ("42.04M", str);

  memset(str, 0, sizeof(str));
  n = 42LL * 1024 * 1024 * 1024 + 42 * 1024 * 1024 + 42 * 1024 + 42;
  bytesToHuman(str, n);
  EXPECT_STREQ("42.04G", str);

  memset(str, 0, sizeof(str));
  n = 42LL * 1024 * 1024 * 1024 * 1024 +
      42LL * 1024 * 1024 * 1024 +
      42 * 1024 * 1024 +
      42 * 1024 +
      42;
  bytesToHuman(str, n);
  EXPECT_STREQ("42.04T", str);
}
<|endoftext|>


<commit_before>#include "TrainSession.h"

#include <fstream>
#include <string>
#include <iomanip>

#include <SmurffCpp/Utils/omp_util.h>
#include <SmurffCpp/Utils/Distribution.h>
#include <SmurffCpp/Utils/MatrixUtils.h>
#include <SmurffCpp/Utils/counters.h>
#include <SmurffCpp/Utils/Error.h>
#include <SmurffCpp/Utils/StringUtils.h>
#include <SmurffCpp/Configs/Config.h>

#include <SmurffCpp/Priors/PriorFactory.h>

#include <SmurffCpp/result.h>
#include <SmurffCpp/StatusItem.h>

namespace smurff {

void TrainSession::init()
{
    THROWERROR_ASSERT_MSG(!m_is_init, "TrainSession::init called twice");

    getConfig().validate();

    if (!getConfig().getSaveName().empty())
    {
        // create state file
        m_stateFile = std::make_shared<StateFile>(getConfig().getSaveName(), true);

        //save config
        m_stateFile->saveConfig(getConfig());

        // close stateFile is we do not need it anymore
        if (!getConfig().getSaveFreq() && !getConfig().getCheckpointFreq())
            m_stateFile.reset();
    }

    // initialize pred
    if (getConfig().getTest().hasData())
    {
        m_pred = Result(getConfig().getTest());
        m_pred.setSavePred(getConfig().getSavePred());
        if (getConfig().getClassify())
            m_pred.setThreshold(getConfig().getThreshold());
    }

    // init data
    data_ptr = Data::create(getConfig().getData());

    // initialize priors
    std::shared_ptr<IPriorFactory> priorFactory = this->create_prior_factory();
    for (std::size_t i = 0; i < getConfig().getPriorTypes().size(); i++)
    {
        m_priors.push_back(priorFactory->create_prior(*this, i));
        m_priors.back()->setMode(i);
    }

    //init omp
    threads::init(getConfig().getVerbose(), getConfig().getNumThreads());

    //initialize random generator
    initRng();

    //init performance counters
    perf_data_init();

    //initialize test set
    m_pred.init();

    //initialize train matrix (centring and noise model)
    data().init();

    //initialize model (samples)
    model().init(getConfig().getNumLatent(), data().dim(), getConfig().getModelInitType(), getConfig().getSaveModel());

    //initialize priors
    for (auto &p : m_priors)
        p->init();

    // all basic init done
    m_is_init = true;

    //write info to console
    if (getConfig().getVerbose())
        info(std::cout, "");

    //restore trainSession (model, priors)
    bool resume = restore(m_iter);

    //print trainSession status to console
    if (getConfig().getVerbose())
        printStatus(std::cout, resume);
}

void TrainSession::run()
{
    init();
    while (step())
        ;
}

bool TrainSession::step()
{
    COUNTER("step");
    THROWERROR_ASSERT_MSG(m_is_init, "TrainSession::init() needs to be called before ::step()")

    // go to the next iteration
    m_iter++;

    bool isStep = m_iter < getConfig().getBurnin() + getConfig().getNSamples();

    if (isStep)
    {
        auto starti = tick();
        #pragma omp parallel
        #pragma omp master
        for (auto p : m_priors)
        {
            p->sample_latents();
            #pragma omp task
            p->update_prior();
        }

        data().update(model());
        auto endi = tick();

        //WARNING: update is an expensive operation because of sort (when calculating AUC)
        m_pred.update(m_model, m_iter < getConfig().getBurnin());

        m_secs_per_iter = endi - starti;
        m_secs_total += m_secs_per_iter;

        printStatus(std::cout);

        save();
    }

    return isStep;
}

std::ostream &TrainSession::info(std::ostream &os, std::string indent) const
{
    os << indent << name << " {\n";
    os << indent << "  Data: {" << std::endl;
    data().info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "  Model: {" << std::endl;
    model().info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "  Priors: {" << std::endl;
    for (auto &p : m_priors)
        p->info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "  Result: {" << std::endl;
    m_pred.info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "  Config: {" << std::endl;
    getConfig().info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "}\n";
    return os;
}

void TrainSession::save()
{
    //do not save if 'never save' mode is selected
    if (!getConfig().getSaveFreq() &&
        !getConfig().getCheckpointFreq())
        return;

    std::int32_t isample = m_iter - getConfig().getBurnin() + 1;
    std::int32_t niter = getConfig().getBurnin() + getConfig().getNSamples();

    //save if checkpoint threshold overdue
    if (getConfig().getCheckpointFreq() &&
       (
           (tick() - m_lastCheckpointTime) >= getConfig().getCheckpointFreq()) ||
           (m_iter == niter - 1) // also save checkpoint in last iteration
        )
    {
        std::int32_t icheckpoint = m_iter + 1;

        //save this iteration
        saveInternal(icheckpoint, true);

        //remove previous iteration if required (initial m_lastCheckpointIter is -1 which means that it does not exist)
        m_stateFile->removeOldCheckpoints();

        //upddate counters
        m_lastCheckpointTime = tick();
        m_lastCheckpointIter = m_iter;
    }

    //save model during sampling stage
    if (getConfig().getSaveFreq() && isample > 0)
    {
        //save_freq > 0: check modulo - do not save if not a save iteration
        if (getConfig().getSaveFreq() > 0 && (isample % getConfig().getSaveFreq()) != 0)
        {
            // don't save
        }
        //save_freq < 0: save last iter - do not save if (final model) mode is selected and not a final iteration
        else if (getConfig().getSaveFreq() < 0 && isample < getConfig().getNSamples())
        {
            // don't save
        }
        else
        {
            //do save this iteration
            saveInternal(isample, false);
        }
    }

    // close after final step
    if (m_iter == niter - 1) m_stateFile.reset();
}

void TrainSession::saveInternal(int iteration, bool checkpoint)
{
    bool final = iteration == getConfig().getNSamples();
    SaveState saveState = m_stateFile->createStep(iteration, checkpoint, final || checkpoint);

    if (getConfig().getVerbose())
    {
        std::cout << "-- Saving model, predictions,... into '" << m_stateFile->getPath() << "'." << std::endl;
    }
    double start = tick();

    m_model.save(saveState);
    m_pred.save(saveState);
    for (auto &p : m_priors) p->save(saveState);

    double stop = tick();
    if (getConfig().getVerbose())
    {
        std::cout << "-- Done saving model. Took " << stop - start << " seconds." << std::endl;
    }
}

bool TrainSession::restore(int &iteration)
{
    //if there is nothing to restore - start from initial iteration
    iteration = -1;

    //to keep track at what time we last checkpointed
    m_lastCheckpointTime = tick();
    m_lastCheckpointIter = -1;

    if (getConfig().getRestoreName().empty())
        return false;

    // open state file
    StateFile restoreFile(getConfig().getRestoreName());

    if (!restoreFile.hasCheckpoint())
        return false;

    SaveState saveState = restoreFile.openCheckpoint();
    if (getConfig().getVerbose())
        std::cout << "-- Restoring model, predictions,... from '" << restoreFile.getPath() << "'." << std::endl;

    m_model.restore(saveState);
    m_pred.restore(saveState);
    for (auto &p : m_priors)
        p->restore(saveState);

    //restore last iteration index
    if (saveState.isCheckpoint())
    {
        iteration = saveState.getIsample() - 1; //restore original state

        //to keep track at what time we last checkpointed
        m_lastCheckpointTime = tick();
        m_lastCheckpointIter = iteration;
    }
    else
    {
        iteration = saveState.getIsample() + getConfig().getBurnin() - 1; //restore original state

        //to keep track at what time we last checkpointed
        m_lastCheckpointTime = tick();
        m_lastCheckpointIter = iteration;
    }

    return true;
}

const Result &TrainSession::getResult() const
{
   return m_pred;
}

StatusItem TrainSession::getStatus() const
{
    THROWERROR_ASSERT(m_is_init);

    StatusItem ret;

    if (m_iter < 0)
    {
        ret.phase = "Initial";
        ret.iter = m_iter + 1;
        ret.phase_iter = 0;
    }
    else if (m_iter < getConfig().getBurnin())
    {
        ret.phase = "Burnin";
        ret.iter = m_iter + 1;
        ret.phase_iter = getConfig().getBurnin();
    }
    else
    {
        ret.phase = "Sample";
        ret.iter = m_iter - getConfig().getBurnin() + 1;
        ret.phase_iter = getConfig().getNSamples();
    }

    for (int i = 0; i < (int)model().nmodes(); ++i)
    {
        ret.model_norms.push_back(model().U(i).norm());
    }

    ret.train_rmse = data().train_rmse(model());

    ret.rmse_avg = m_pred.rmse_avg;
    ret.rmse_1sample = m_pred.rmse_1sample;

    ret.auc_avg = m_pred.auc_avg;
    ret.auc_1sample = m_pred.auc_1sample;

    ret.elapsed_iter = m_secs_per_iter;
    ret.elapsed_total = m_secs_total;

    ret.nnz_per_sec = (double)(data().nnz()) / m_secs_per_iter;
    ret.samples_per_sec = (double)(model().nsamples()) / m_secs_per_iter;

    return ret;
}

void TrainSession::printStatus(std::ostream &output, bool resume)
{
    if (!getConfig().getVerbose())
        return;

    auto status_item = getStatus();

    std::string resumeString = resume ? "Continue from " : std::string();

    if (getConfig().getVerbose() > 0)
    {
        if (m_iter < 0)
        {
            output << " ====== Initial phase ====== " << std::endl;
        }
        else if (m_iter < getConfig().getBurnin() && m_iter == 0)
        {
            output << " ====== Sampling (burning phase) ====== " << std::endl;
        }
        else if (m_iter == getConfig().getBurnin())
        {
            output << " ====== Burn-in complete, averaging samples ====== " << std::endl;
        }

        output << resumeString << status_item.asString() << std::endl;

        if (getConfig().getVerbose() > 1)
        {
            output << std::fixed << std::setprecision(4) << "  RMSE train: " << status_item.train_rmse << std::endl;
            output << "  Priors:" << std::endl;

            for (const auto &p : m_priors)
                p->status(output, "     ");

            output << "  Model:" << std::endl;
            model().status(output, "    ");
            output << "  Noise:" << std::endl;
            data().status(output, "    ");
        }

        if (getConfig().getVerbose() > 2)
        {
            output << "  Compute Performance: " << status_item.samples_per_sec << " samples/sec, " << status_item.nnz_per_sec << " nnz/sec" << std::endl;
        }
    }
}

std::string StatusItem::getCsvHeader()
{
    return "phase;iter;phase_len;rmse_avg;rmse_1samp;train_rmse;auc_avg;auc_1samp;elapsed_1samp;elapsed_total";
}

std::string StatusItem::asCsvString() const
{
    char ret[1024];
    snprintf(ret, 1024, "%s;%d;%d;%.4f;%.4f;%.4f;%.4f;:%.4f;%0.1f;%0.1f",
             phase.c_str(), iter, phase_iter, rmse_avg, rmse_1sample, train_rmse,
             auc_1sample, auc_avg, elapsed_iter, elapsed_total);

    return ret;
}

void TrainSession::initRng()
{
    //init random generator
    if (getConfig().getRandomSeedSet())
        init_bmrng(getConfig().getRandomSeed());
    else
        init_bmrng();
}

std::shared_ptr<IPriorFactory> TrainSession::create_prior_factory() const
{
    return std::make_shared<PriorFactory>();
}
} // end namespace smurff
<commit_msg>FIX: fix || and && test<commit_after>#include "TrainSession.h"

#include <fstream>
#include <string>
#include <iomanip>

#include <SmurffCpp/Utils/omp_util.h>
#include <SmurffCpp/Utils/Distribution.h>
#include <SmurffCpp/Utils/MatrixUtils.h>
#include <SmurffCpp/Utils/counters.h>
#include <SmurffCpp/Utils/Error.h>
#include <SmurffCpp/Utils/StringUtils.h>
#include <SmurffCpp/Configs/Config.h>

#include <SmurffCpp/Priors/PriorFactory.h>

#include <SmurffCpp/result.h>
#include <SmurffCpp/StatusItem.h>

namespace smurff {

void TrainSession::init()
{
    THROWERROR_ASSERT_MSG(!m_is_init, "TrainSession::init called twice");

    getConfig().validate();

    if (!getConfig().getSaveName().empty())
    {
        // create state file
        m_stateFile = std::make_shared<StateFile>(getConfig().getSaveName(), true);

        //save config
        m_stateFile->saveConfig(getConfig());

        // close stateFile is we do not need it anymore
        if (!getConfig().getSaveFreq() && !getConfig().getCheckpointFreq())
            m_stateFile.reset();
    }

    // initialize pred
    if (getConfig().getTest().hasData())
    {
        m_pred = Result(getConfig().getTest());
        m_pred.setSavePred(getConfig().getSavePred());
        if (getConfig().getClassify())
            m_pred.setThreshold(getConfig().getThreshold());
    }

    // init data
    data_ptr = Data::create(getConfig().getData());

    // initialize priors
    std::shared_ptr<IPriorFactory> priorFactory = this->create_prior_factory();
    for (std::size_t i = 0; i < getConfig().getPriorTypes().size(); i++)
    {
        m_priors.push_back(priorFactory->create_prior(*this, i));
        m_priors.back()->setMode(i);
    }

    //init omp
    threads::init(getConfig().getVerbose(), getConfig().getNumThreads());

    //initialize random generator
    initRng();

    //init performance counters
    perf_data_init();

    //initialize test set
    m_pred.init();

    //initialize train matrix (centring and noise model)
    data().init();

    //initialize model (samples)
    model().init(getConfig().getNumLatent(), data().dim(), getConfig().getModelInitType(), getConfig().getSaveModel());

    //initialize priors
    for (auto &p : m_priors)
        p->init();

    // all basic init done
    m_is_init = true;

    //write info to console
    if (getConfig().getVerbose())
        info(std::cout, "");

    //restore trainSession (model, priors)
    bool resume = restore(m_iter);

    //print trainSession status to console
    if (getConfig().getVerbose())
        printStatus(std::cout, resume);
}

void TrainSession::run()
{
    init();
    while (step())
        ;
}

bool TrainSession::step()
{
    COUNTER("step");
    THROWERROR_ASSERT_MSG(m_is_init, "TrainSession::init() needs to be called before ::step()")

    // go to the next iteration
    m_iter++;

    bool isStep = m_iter < getConfig().getBurnin() + getConfig().getNSamples();

    if (isStep)
    {
        auto starti = tick();
        #pragma omp parallel
        #pragma omp master
        for (auto p : m_priors)
        {
            p->sample_latents();
            #pragma omp task
            p->update_prior();
        }

        data().update(model());
        auto endi = tick();

        //WARNING: update is an expensive operation because of sort (when calculating AUC)
        m_pred.update(m_model, m_iter < getConfig().getBurnin());

        m_secs_per_iter = endi - starti;
        m_secs_total += m_secs_per_iter;

        printStatus(std::cout);

        save();
    }

    return isStep;
}

std::ostream &TrainSession::info(std::ostream &os, std::string indent) const
{
    os << indent << name << " {\n";
    os << indent << "  Data: {" << std::endl;
    data().info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "  Model: {" << std::endl;
    model().info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "  Priors: {" << std::endl;
    for (auto &p : m_priors)
        p->info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "  Result: {" << std::endl;
    m_pred.info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "  Config: {" << std::endl;
    getConfig().info(os, indent + "    ");
    os << indent << "  }" << std::endl;
    os << indent << "}\n";
    return os;
}

void TrainSession::save()
{
    //do not save if 'never save' mode is selected
    if (!getConfig().getSaveFreq() &&
        !getConfig().getCheckpointFreq())
        return;

    std::int32_t isample = m_iter - getConfig().getBurnin() + 1;
    std::int32_t niter = getConfig().getBurnin() + getConfig().getNSamples();

    //save if checkpoint threshold overdue
    if (
         getConfig().getCheckpointFreq() &&
         (
             ((tick() - m_lastCheckpointTime) >= getConfig().getCheckpointFreq()) ||
             (m_iter == niter - 1) // also save checkpoint in last iteration
         )
       )
    {
        std::int32_t icheckpoint = m_iter + 1;

        //save this iteration
        saveInternal(icheckpoint, true);

        //remove previous iteration if required (initial m_lastCheckpointIter is -1 which means that it does not exist)
        m_stateFile->removeOldCheckpoints();

        //upddate counters
        m_lastCheckpointTime = tick();
        m_lastCheckpointIter = m_iter;
    }

    //save model during sampling stage
    if (getConfig().getSaveFreq() && isample > 0)
    {
        //save_freq > 0: check modulo - do not save if not a save iteration
        if (getConfig().getSaveFreq() > 0 && (isample % getConfig().getSaveFreq()) != 0)
        {
            // don't save
        }
        //save_freq < 0: save last iter - do not save if (final model) mode is selected and not a final iteration
        else if (getConfig().getSaveFreq() < 0 && isample < getConfig().getNSamples())
        {
            // don't save
        }
        else
        {
            //do save this iteration
            saveInternal(isample, false);
        }
    }

    // close after final step
    if (m_iter == niter - 1) m_stateFile.reset();
}

void TrainSession::saveInternal(int iteration, bool checkpoint)
{
    bool final = iteration == getConfig().getNSamples();
    SaveState saveState = m_stateFile->createStep(iteration, checkpoint, final || checkpoint);

    if (getConfig().getVerbose())
    {
        std::cout << "-- Saving model, predictions,... into '" << m_stateFile->getPath() << "'." << std::endl;
    }
    double start = tick();

    m_model.save(saveState);
    m_pred.save(saveState);
    for (auto &p : m_priors) p->save(saveState);

    double stop = tick();
    if (getConfig().getVerbose())
    {
        std::cout << "-- Done saving model. Took " << stop - start << " seconds." << std::endl;
    }
}

bool TrainSession::restore(int &iteration)
{
    //if there is nothing to restore - start from initial iteration
    iteration = -1;

    //to keep track at what time we last checkpointed
    m_lastCheckpointTime = tick();
    m_lastCheckpointIter = -1;

    if (getConfig().getRestoreName().empty())
        return false;

    // open state file
    StateFile restoreFile(getConfig().getRestoreName());

    if (!restoreFile.hasCheckpoint())
        return false;

    SaveState saveState = restoreFile.openCheckpoint();
    if (getConfig().getVerbose())
        std::cout << "-- Restoring model, predictions,... from '" << restoreFile.getPath() << "'." << std::endl;

    m_model.restore(saveState);
    m_pred.restore(saveState);
    for (auto &p : m_priors)
        p->restore(saveState);

    //restore last iteration index
    if (saveState.isCheckpoint())
    {
        iteration = saveState.getIsample() - 1; //restore original state

        //to keep track at what time we last checkpointed
        m_lastCheckpointTime = tick();
        m_lastCheckpointIter = iteration;
    }
    else
    {
        iteration = saveState.getIsample() + getConfig().getBurnin() - 1; //restore original state

        //to keep track at what time we last checkpointed
        m_lastCheckpointTime = tick();
        m_lastCheckpointIter = iteration;
    }

    return true;
}

const Result &TrainSession::getResult() const
{
   return m_pred;
}

StatusItem TrainSession::getStatus() const
{
    THROWERROR_ASSERT(m_is_init);

    StatusItem ret;

    if (m_iter < 0)
    {
        ret.phase = "Initial";
        ret.iter = m_iter + 1;
        ret.phase_iter = 0;
    }
    else if (m_iter < getConfig().getBurnin())
    {
        ret.phase = "Burnin";
        ret.iter = m_iter + 1;
        ret.phase_iter = getConfig().getBurnin();
    }
    else
    {
        ret.phase = "Sample";
        ret.iter = m_iter - getConfig().getBurnin() + 1;
        ret.phase_iter = getConfig().getNSamples();
    }

    for (int i = 0; i < (int)model().nmodes(); ++i)
    {
        ret.model_norms.push_back(model().U(i).norm());
    }

    ret.train_rmse = data().train_rmse(model());

    ret.rmse_avg = m_pred.rmse_avg;
    ret.rmse_1sample = m_pred.rmse_1sample;

    ret.auc_avg = m_pred.auc_avg;
    ret.auc_1sample = m_pred.auc_1sample;

    ret.elapsed_iter = m_secs_per_iter;
    ret.elapsed_total = m_secs_total;

    ret.nnz_per_sec = (double)(data().nnz()) / m_secs_per_iter;
    ret.samples_per_sec = (double)(model().nsamples()) / m_secs_per_iter;

    return ret;
}

void TrainSession::printStatus(std::ostream &output, bool resume)
{
    if (!getConfig().getVerbose())
        return;

    auto status_item = getStatus();

    std::string resumeString = resume ? "Continue from " : std::string();

    if (getConfig().getVerbose() > 0)
    {
        if (m_iter < 0)
        {
            output << " ====== Initial phase ====== " << std::endl;
        }
        else if (m_iter < getConfig().getBurnin() && m_iter == 0)
        {
            output << " ====== Sampling (burning phase) ====== " << std::endl;
        }
        else if (m_iter == getConfig().getBurnin())
        {
            output << " ====== Burn-in complete, averaging samples ====== " << std::endl;
        }

        output << resumeString << status_item.asString() << std::endl;

        if (getConfig().getVerbose() > 1)
        {
            output << std::fixed << std::setprecision(4) << "  RMSE train: " << status_item.train_rmse << std::endl;
            output << "  Priors:" << std::endl;

            for (const auto &p : m_priors)
                p->status(output, "     ");

            output << "  Model:" << std::endl;
            model().status(output, "    ");
            output << "  Noise:" << std::endl;
            data().status(output, "    ");
        }

        if (getConfig().getVerbose() > 2)
        {
            output << "  Compute Performance: " << status_item.samples_per_sec << " samples/sec, " << status_item.nnz_per_sec << " nnz/sec" << std::endl;
        }
    }
}

std::string StatusItem::getCsvHeader()
{
    return "phase;iter;phase_len;rmse_avg;rmse_1samp;train_rmse;auc_avg;auc_1samp;elapsed_1samp;elapsed_total";
}

std::string StatusItem::asCsvString() const
{
    char ret[1024];
    snprintf(ret, 1024, "%s;%d;%d;%.4f;%.4f;%.4f;%.4f;:%.4f;%0.1f;%0.1f",
             phase.c_str(), iter, phase_iter, rmse_avg, rmse_1sample, train_rmse,
             auc_1sample, auc_avg, elapsed_iter, elapsed_total);

    return ret;
}

void TrainSession::initRng()
{
    //init random generator
    if (getConfig().getRandomSeedSet())
        init_bmrng(getConfig().getRandomSeed());
    else
        init_bmrng();
}

std::shared_ptr<IPriorFactory> TrainSession::create_prior_factory() const
{
    return std::make_shared<PriorFactory>();
}
} // end namespace smurff
<|endoftext|>