<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pe_struc.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 17:17:43 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef LUIDL_PE_STRUC_HXX
#define LUIDL_PE_STRUC_HXX

// USED SERVICES
    // BASE CLASSES
#include <s2_luidl/parsenv2.hxx>
#include <s2_luidl/pestate.hxx>
    // COMPONENTS
#include <s2_luidl/semnode.hxx>
#include <ary/qualiname.hxx>
    // PARAMETERS

namespace csi
{
namespace prl
{
    class TNamespace;
}
}

namespace csi
{
namespace uidl
{

class Struct;
class StructElement;
class PE_StructElement;
class PE_Type;

class PE_Struct : public UnoIDL_PE
{
  public:
                        PE_Struct();
    virtual void        EstablishContacts(
                            UnoIDL_PE *         io_pParentPE,
                            ary::Repository &   io_rRepository,
                            TokenProcessing_Result &
                                                o_rResult );
                        ~PE_Struct();
    virtual void        ProcessToken(
                            const Token &       i_rToken );

  private:
    struct S_Work
    {
                            S_Work();

        void                InitData();
        void                Prepare_PE_QualifiedName();
        void                Prepare_PE_Element();
        void                Data_Set_Name(
                                const char *        i_sName );
        void                Data_Set_TemplateParam(
                                const char *        i_sTemplateParam );

        String              sData_Name;
        String              sData_TemplateParam;
        bool                bIsPreDeclaration;
        ary::idl::Ce_id     nCurStruct;

        Dyn<PE_StructElement>
                            pPE_Element;
        ary::idl::Ce_id     nCurParsed_ElementRef;
        Dyn<PE_Type>        pPE_Type;
        ary::idl::Type_id   nCurParsed_Base;
    };

    struct S_Stati;
    class PE_StructState;
    friend struct S_Stati;
    friend class PE_StructState;

    class PE_StructState : public ParseEnvState
    {
      public:

      protected:
                            PE_StructState(
                                PE_Struct &         i_rStruct )
                                                    :   rStruct(i_rStruct) {}
        void                MoveState(
                                ParseEnvState &     i_rState ) const;
        void                SetResult(
                                E_TokenDone         i_eDone,
                                E_EnvStackAction    i_eWhat2DoWithEnvStack,
                                UnoIDL_PE *         i_pParseEnv2Push = 0 ) const
                                                    { rStruct.SetResult(i_eDone, i_eWhat2DoWithEnvStack, i_pParseEnv2Push); }

        S_Stati &           Stati() const           { return *rStruct.pStati; }
        S_Work &            Work() const            { return rStruct.aWork; }
        PE_Struct &         PE() const              { return rStruct; }

      private:
        virtual UnoIDL_PE & MyPE();
        // DATA
        PE_Struct &         rStruct;
    };

    class State_None : public PE_StructState
    {
        public:
                            State_None(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
    };
    class State_WaitForName : public PE_StructState
    {   // -> Name
      public:
                            State_WaitForName(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Identifier(
                                const TokIdentifier &
                                                    i_rToken );
    };
    class State_GotName : public PE_StructState
    {   // -> : { ; <
      public:
                            State_GotName(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };
    class State_WaitForTemplateParam : public PE_StructState
    {   // -> Template parameter identifier
      public:
                            State_WaitForTemplateParam(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Identifier(
                                const TokIdentifier &
                                                    i_rToken );
    };
    class State_WaitForTemplateEnd : public PE_StructState
    {   // -> >
      public:
                            State_WaitForTemplateEnd(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };
    class State_WaitForBase : public PE_StructState
    {   // -> Base
      public:
                            State_WaitForBase(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        On_SubPE_Left();
    };
    class State_GotBase : public PE_StructState
    {   // -> {
      public:
                            State_GotBase(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };
    class State_WaitForElement : public PE_StructState
    {   // -> Typ }
      public:
                            State_WaitForElement(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Identifier(
                                const TokIdentifier &
                                                    i_rToken );
        virtual void        Process_NameSeparator();
        virtual void        Process_BuiltInType(
                                const TokBuiltInType &
                                                    i_rToken );
        virtual void        Process_TypeModifier(
                                const TokTypeModifier &
                                                    i_rToken );
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };
    class State_WaitForFinish : public PE_StructState
    { // -> ;
      public:
                            State_WaitForFinish(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };

    struct S_Stati
    {
                            S_Stati(
                                PE_Struct &         io_rStruct );
        void                SetState(
                                ParseEnvState &     i_rNextState )
                                                    { pCurStatus = &i_rNextState; }

        State_None          aNone;
        State_WaitForName   aWaitForName;
        State_GotName       aGotName;
        State_WaitForTemplateParam
                            aWaitForTemplateParam;
        State_WaitForTemplateEnd
                            aWaitForTemplateEnd;
        State_WaitForBase   aWaitForBase;
        State_GotBase       aGotBase;
        State_WaitForElement
                            aWaitForElement;
        State_WaitForFinish aWaitForFinish;

        ParseEnvState *     pCurStatus;
    };

    virtual void        InitData();
    virtual void        TransferData();
    virtual void        ReceiveData();

    public:

    void        store_Struct();

    private:

    S_Stati &           Stati()                 { return *pStati; }
    S_Work &            Work()                  { return aWork; }

    // DATA
    S_Work              aWork;
    Dyn<S_Stati>        pStati;
};

inline void
PE_Struct::PE_StructState::MoveState(
                                ParseEnvState &     i_rState ) const
                                                    { rStruct.Stati().SetState(i_rState); }

}   // namespace uidl
}   // namespace csi

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.6.22); FILE MERGED 2008/03/28 16:02:58 rt 1.6.22.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: pe_struc.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef LUIDL_PE_STRUC_HXX
#define LUIDL_PE_STRUC_HXX

// USED SERVICES
    // BASE CLASSES
#include <s2_luidl/parsenv2.hxx>
#include <s2_luidl/pestate.hxx>
    // COMPONENTS
#include <s2_luidl/semnode.hxx>
#include <ary/qualiname.hxx>
    // PARAMETERS

namespace csi
{
namespace prl
{
    class TNamespace;
}
}

namespace csi
{
namespace uidl
{

class Struct;
class StructElement;
class PE_StructElement;
class PE_Type;

class PE_Struct : public UnoIDL_PE
{
  public:
                        PE_Struct();
    virtual void        EstablishContacts(
                            UnoIDL_PE *         io_pParentPE,
                            ary::Repository &   io_rRepository,
                            TokenProcessing_Result &
                                                o_rResult );
                        ~PE_Struct();
    virtual void        ProcessToken(
                            const Token &       i_rToken );

  private:
    struct S_Work
    {
                            S_Work();

        void                InitData();
        void                Prepare_PE_QualifiedName();
        void                Prepare_PE_Element();
        void                Data_Set_Name(
                                const char *        i_sName );
        void                Data_Set_TemplateParam(
                                const char *        i_sTemplateParam );

        String              sData_Name;
        String              sData_TemplateParam;
        bool                bIsPreDeclaration;
        ary::idl::Ce_id     nCurStruct;

        Dyn<PE_StructElement>
                            pPE_Element;
        ary::idl::Ce_id     nCurParsed_ElementRef;
        Dyn<PE_Type>        pPE_Type;
        ary::idl::Type_id   nCurParsed_Base;
    };

    struct S_Stati;
    class PE_StructState;
    friend struct S_Stati;
    friend class PE_StructState;

    class PE_StructState : public ParseEnvState
    {
      public:

      protected:
                            PE_StructState(
                                PE_Struct &         i_rStruct )
                                                    :   rStruct(i_rStruct) {}
        void                MoveState(
                                ParseEnvState &     i_rState ) const;
        void                SetResult(
                                E_TokenDone         i_eDone,
                                E_EnvStackAction    i_eWhat2DoWithEnvStack,
                                UnoIDL_PE *         i_pParseEnv2Push = 0 ) const
                                                    { rStruct.SetResult(i_eDone, i_eWhat2DoWithEnvStack, i_pParseEnv2Push); }

        S_Stati &           Stati() const           { return *rStruct.pStati; }
        S_Work &            Work() const            { return rStruct.aWork; }
        PE_Struct &         PE() const              { return rStruct; }

      private:
        virtual UnoIDL_PE & MyPE();
        // DATA
        PE_Struct &         rStruct;
    };

    class State_None : public PE_StructState
    {
        public:
                            State_None(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
    };
    class State_WaitForName : public PE_StructState
    {   // -> Name
      public:
                            State_WaitForName(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Identifier(
                                const TokIdentifier &
                                                    i_rToken );
    };
    class State_GotName : public PE_StructState
    {   // -> : { ; <
      public:
                            State_GotName(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };
    class State_WaitForTemplateParam : public PE_StructState
    {   // -> Template parameter identifier
      public:
                            State_WaitForTemplateParam(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Identifier(
                                const TokIdentifier &
                                                    i_rToken );
    };
    class State_WaitForTemplateEnd : public PE_StructState
    {   // -> >
      public:
                            State_WaitForTemplateEnd(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };
    class State_WaitForBase : public PE_StructState
    {   // -> Base
      public:
                            State_WaitForBase(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        On_SubPE_Left();
    };
    class State_GotBase : public PE_StructState
    {   // -> {
      public:
                            State_GotBase(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };
    class State_WaitForElement : public PE_StructState
    {   // -> Typ }
      public:
                            State_WaitForElement(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Identifier(
                                const TokIdentifier &
                                                    i_rToken );
        virtual void        Process_NameSeparator();
        virtual void        Process_BuiltInType(
                                const TokBuiltInType &
                                                    i_rToken );
        virtual void        Process_TypeModifier(
                                const TokTypeModifier &
                                                    i_rToken );
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };
    class State_WaitForFinish : public PE_StructState
    { // -> ;
      public:
                            State_WaitForFinish(
                                PE_Struct &         i_rStruct )
                                                    :   PE_StructState(i_rStruct) {}
        virtual void        Process_Punctuation(
                                const TokPunctuation &
                                                    i_rToken );
    };

    struct S_Stati
    {
                            S_Stati(
                                PE_Struct &         io_rStruct );
        void                SetState(
                                ParseEnvState &     i_rNextState )
                                                    { pCurStatus = &i_rNextState; }

        State_None          aNone;
        State_WaitForName   aWaitForName;
        State_GotName       aGotName;
        State_WaitForTemplateParam
                            aWaitForTemplateParam;
        State_WaitForTemplateEnd
                            aWaitForTemplateEnd;
        State_WaitForBase   aWaitForBase;
        State_GotBase       aGotBase;
        State_WaitForElement
                            aWaitForElement;
        State_WaitForFinish aWaitForFinish;

        ParseEnvState *     pCurStatus;
    };

    virtual void        InitData();
    virtual void        TransferData();
    virtual void        ReceiveData();

    public:

    void        store_Struct();

    private:

    S_Stati &           Stati()                 { return *pStati; }
    S_Work &            Work()                  { return aWork; }

    // DATA
    S_Work              aWork;
    Dyn<S_Stati>        pStati;
};

inline void
PE_Struct::PE_StructState::MoveState(
                                ParseEnvState &     i_rState ) const
                                                    { rStruct.Stati().SetState(i_rState); }

}   // namespace uidl
}   // namespace csi

#endif

<|endoftext|>


<commit_before><commit_msg>Changes in set up of CPR histograms<commit_after><|endoftext|>


<commit_before>/*Santiago Zubieta*/
#include <iostream>
#include <numeric>
#include <fstream>
#include <climits>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <deque>
#include <vector>
#include <string>
#include <cstdlib>
#include <cassert>
#include <sstream>
#include <iterator>
#include <algorithm>

using namespace std;

map<string, int> nameToIndex;
// Convert from an authors name to an index between 0 and n - 1 (# of authors)
map<int, string> indexToName;
// Convert from an index between 0 and n - 1 (# of authors) to an authors name

vector< set<int> > authors;
// A graph for keeping track of authors relationships in papers. Lets use a set
// to avoid repeated relationships since there may be more than 1 paper where
// two authors may meet so this allows us to have unique pairings.
vector<bool> visited;
// A visited list for keeping track of already visited authors in graph traver-
// sal. We will do a BFS which will allow to know the shortest distance (if any
// at all) between two authors, specifically, between any author and Paul Erdos
// to find the so called 'Erdos Distance'.
set<string> authorsSet;
// A set containing all the possible authors, to know their unique occurrences
// and give them an index for easy identification and graph traversal. Be care-
// ful that maybe the program may be queried for an author that isn't in any
// paper, therefore it doesn't have an index to search in the graph, so first
vector< vector<string> > allPapers;
// A list of the lists of authors contained in each paper, this is like
// a graph in string form, which will be converted into a graph in num-
// erical form for easy and fast traversal.
// check in this set, and if it isn't here, skip doing the graph search.

string substring(string s, int l, int r) {
// substring of a string s, from index l (inclusive) to index r (exclusive)
    string res = "";
    while(l < r) {
        res += s[l];
        l++;
    }
    return res;
}

int bfs(int start, int end) {
    queue< pair<int, int> > q;
    // The queue will contain several pairs, each one has:
    // first: the current position
    // second: the cost until current position
    q.push(make_pair(start, 0));
    // BFS will start at the original given position, with 0 cost
    while(q.size()) {
        pair<int, int> now = q.front();
        q.pop();
        int actual = now.first;
        int weight = now.second;
        if(visited[actual]) {
        // This node has been previously reach, ignore it
            continue;
        }
        if(actual == end) {
        // If this node is the target node, return the weight up to this point.
        // The BFS ensures that this weight is the minimal distance possible
        // between the start node and end node.
            return weight;
        }
        visited[actual] = true;
        set<int>::iterator it;
        for(it = authors[actual].begin(); it != authors[actual].end(); it++) {
            int next = *it;
            q.push(make_pair(next, weight + 1));
        }
    }
    return -1;
}

void resetVisited() {
// Every instance of the BFS requires the list of visited nodes to be resetted
    for(int k = 0; k < visited.size(); k++) {
        visited[k] = false;
    }
}

void initGraph() {
// Lets initialize the graph of authors with empty positions for every author
// available, and a visited list also as false, for easy graph traversal later.
// Then, from the list of papers (and the respective authors) add bidirectional
// relationships in the graph regarding co-autorships.
    for(int k = 0; k < authorsSet.size(); k++) {
        set<int> coauthors;
        authors.push_back(coauthors);
        visited.push_back(false);
    }
    for(int i = 0; i < allPapers.size(); i++) {
    // After this, the graph using only indices will be completed
        vector<string> paperAuthors = allPapers[i];
        for(int j = 0; j < paperAuthors.size() - 1; j++) {
            string name1 = paperAuthors[j];
            int index1 = nameToIndex[name1];
            for(int k = j + 1; k < paperAuthors.size(); k++) {
                string name2 = paperAuthors[k];
                int index2 = nameToIndex[name2];
                authors[index1].insert(index2);
                authors[index2].insert(index1);
            }
        }
    }
}

string readName() {
// This function reads a single name, until a second comma is found, the line
// breaks, or a ':' is found. Whitespaces are ignored.
    char c;
    string name = "";
    bool firstComma = true;
    // A name has only one comma the second one means there is at least another
    // author ahead in the list of authors of the paper
    while((c = getchar()) != EOF) {
        // Read the character
        if(c != ' ') {
        // White spaces are ignored
            if(c == ',') {
                // If a comma is found
                if(firstComma) {
                // If its the first, add it to the name and then mark that it
                // was found so the second one isn't added
                    name += ", ";
                    firstComma = false;
                }
                else {
                // If its the second, it means the name ends here
                    return name;
                }
            }
            else {
            // If its not a comma
                if(c == ':') {
                // If its a colon add it to the name, it will tell the external
                // routine that this is the last name, there won't be any more.
                    name += c;
                    return name;
                }
                else if(c == '\n'){
                // This is useful when reading just one name in a line, it will
                // end with the \n character, or line break.
                    return name;
                }
                else {
                // If it isn't a space, nor a :, nor a \n, nor a comma, add it.
                    name += c;
                }
            }
        }
    }
}

vector<string> readNames() {
// This will read a list of names in a given paper, terminating when a name co-
// mes up with a ':' at the end, marking the end of the authors and the begin-
// ning of the paper's title. Remove that ':' and store all names in a list.
    vector<string> res;
    while(true) {
        string name = readName();
        if(name[name.length() - 1] == ':') {
        // If this is the last name down the road
            name = substring(name, 0, name.length() - 1);
            // Remove the : symbol
            res.push_back(name);
            break;
        }
        res.push_back(name);
    }
    while('\n' != getchar());
    // After the names have been read, lets read characters without storing
    // them until reaching the end of the line, since all other characters are
    // part of the paper's name, in which we aren't interested at all for this.
    return res;
}

int main() {
    int s;
    // The number of scenarios
    int p, n;
    // p: the number of papers to be read
    // n: the number of authors to query for their Erdos Number
    cin >> s;
    for(int z = 0; z < s; z++) {
        authors.clear();
        visited.clear();
        allPapers.clear();
        authorsSet.clear();
        // clear all the used datastructures since these are global and need to
        // be changed for every test case of the program.
        cin >> p >> n;
        getchar();
        for(int k = 0; k < p; k++) {
            // Each read line will be a paper, first with the authors then the
            // paper's title, which will really be irrelevant for this program.
            vector<string> paperAuthors = readNames();
            for(int l = 0; l < paperAuthors.size(); l++) {
                string name = paperAuthors[l];
                authorsSet.insert(name);
            }
            allPapers.push_back(paperAuthors);
        }
        // Now that we have the list of authors in every paper, and a set that
        // contains the unique occurrences, lets iterate over the set to assign
        // each author an iterator so its easy to make a graph with them.
        set<string>::iterator it;
        int index = 0;
        for(it = authorsSet.begin(); it != authorsSet.end(); it++) {
        // Starting from 0, lets assign every unique author its own number, and
        // also keep a record of this in two maps, one that lets retrieve the
        // author's name from the number, and other that lets retrieve the num-
        // ber by using the author's name, helpful for making a graph using on-
        // ly numbers as indices and then getting the names back again
            string name = *it;
            nameToIndex[name] = index;
            indexToName[index] = name;
            index++;
        }
        initGraph();
        // Now, proceed to read a list of authors to inquire for their Erdos
        // Distance, and then do a BFS to see what is their shortest distance
        // to Paul Erdos (Erdos, P.) if any (infinity in case of none found).
        cout << "Scenario " << z + 1 << endl;
        for(int k = 0; k < n; k++) {
            resetVisited();
            string completeName = readName();
            int res;
            if(authorsSet.find(completeName) != authorsSet.end()) {
            // This is VERY important. Since the idea of making a graph invol-
            // ves giving an index to all the authors, present in the papers,
            // it may be possible that afterwards, there's a query for an au-
            // thor's Erdos Number and that author isn't in any of the availa-
            // ble paper, which would result in a nasty error since that aut-
            // hor isn't available in the map, possibly returning a bogus in-
            // dex. If the author isn't among the authors we know to be pres-
            // ent in the previously read papers, immediately print that its
            // Erdos Distance is infinity.
                int start = nameToIndex[completeName];
                int end = nameToIndex["Erdos, P."];
                res = bfs(start, end);
            }
            else {
            // The queried author isn't even in any of the given papers so the
            // immediate response is that it has infinity as its Erdos Distance
                res = -1;
            }
            if(res == -1) {
                cout << completeName << " infinity" << endl;
            }
            else {
                cout << completeName << " " << res << endl;
            }
        }
    }
}<commit_msg>Added 10044_Erdos_Numbers<commit_after>/*Santiago Zubieta*/
#include <iostream>
#include <numeric>
#include <fstream>
#include <climits>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <deque>
#include <vector>
#include <string>
#include <cstdlib>
#include <cassert>
#include <sstream>
#include <iterator>
#include <algorithm>

using namespace std;

map<string, int> nameToIndex;
// Convert from an authors name to an index between 0 and n - 1 (# of authors)
map<int, string> indexToName;
// Convert from an index between 0 and n - 1 (# of authors) to an authors name

vector< set<int> > authors;
// A graph for keeping track of authors relationships in papers. Lets use a set
// to avoid repeated relationships since there may be more than 1 paper where
// two authors may meet so this allows us to have unique pairings.
vector<bool> visited;
// A visited list for keeping track of already visited authors in graph traver-
// sal. We will do a BFS which will allow to know the shortest distance (if any
// at all) between two authors, specifically, between any author and Paul Erdos
// to find the so called 'Erdos Distance'.
set<string> authorsSet;
// A set containing all the possible authors, to know their unique occurrences
// and give them an index for easy identification and graph traversal. Be care-
// ful that maybe the program may be queried for an author that isn't in any
// paper, therefore it doesn't have an index to search in the graph, so first
// check in this set, and if it isn't here, skip doing the graph search.
vector< vector<string> > allPapers;
// A list of the lists of authors contained in each paper, this is like
// a graph in string form, which will be converted into a graph in num-
// erical form for easy and fast traversal.

string substring(string s, int l, int r) {
// substring of a string s, from index l (inclusive) to index r (exclusive)
    string res = "";
    while(l < r) {
        res += s[l];
        l++;
    }
    return res;
}

int bfs(int start, int end) {
    queue< pair<int, int> > q;
    // The queue will contain several pairs, each one has:
    // first: the current position
    // second: the cost until current position
    q.push(make_pair(start, 0));
    // BFS will start at the original given position, with 0 cost
    while(q.size()) {
        pair<int, int> now = q.front();
        q.pop();
        int actual = now.first;
        int weight = now.second;
        if(visited[actual]) {
        // This node has been previously reach, ignore it
            continue;
        }
        if(actual == end) {
        // If this node is the target node, return the weight up to this point.
        // The BFS ensures that this weight is the minimal distance possible
        // between the start node and end node.
            return weight;
        }
        visited[actual] = true;
        set<int>::iterator it;
        for(it = authors[actual].begin(); it != authors[actual].end(); it++) {
            int next = *it;
            q.push(make_pair(next, weight + 1));
        }
    }
    return -1;
}

void resetVisited() {
// Every instance of the BFS requires the list of visited nodes to be resetted
    for(int k = 0; k < visited.size(); k++) {
        visited[k] = false;
    }
}

void initGraph() {
// Lets initialize the graph of authors with empty positions for every author
// available, and a visited list also as false, for easy graph traversal later.
// Then, from the list of papers (and the respective authors) add bidirectional
// relationships in the graph regarding co-autorships.
    for(int k = 0; k < authorsSet.size(); k++) {
        set<int> coauthors;
        authors.push_back(coauthors);
        visited.push_back(false);
    }
    for(int i = 0; i < allPapers.size(); i++) {
    // After this, the graph using only indices will be completed
        vector<string> paperAuthors = allPapers[i];
        for(int j = 0; j < paperAuthors.size() - 1; j++) {
            string name1 = paperAuthors[j];
            int index1 = nameToIndex[name1];
            for(int k = j + 1; k < paperAuthors.size(); k++) {
                string name2 = paperAuthors[k];
                int index2 = nameToIndex[name2];
                authors[index1].insert(index2);
                authors[index2].insert(index1);
            }
        }
    }
}

string readName() {
// This function reads a single name, until a second comma is found, the line
// breaks, or a ':' is found. Whitespaces are ignored.
    char c;
    string name = "";
    bool firstComma = true;
    // A name has only one comma the second one means there is at least another
    // author ahead in the list of authors of the paper
    while((c = getchar()) != EOF) {
        // Read the character
        if(c != ' ') {
        // White spaces are ignored
            if(c == ',') {
                // If a comma is found
                if(firstComma) {
                // If its the first, add it to the name and then mark that it
                // was found so the second one isn't added
                    name += ", ";
                    firstComma = false;
                }
                else {
                // If its the second, it means the name ends here
                    return name;
                }
            }
            else {
            // If its not a comma
                if(c == ':') {
                // If its a colon add it to the name, it will tell the external
                // routine that this is the last name, there won't be any more.
                    name += c;
                    return name;
                }
                else if(c == '\n'){
                // This is useful when reading just one name in a line, it will
                // end with the \n character, or line break.
                    return name;
                }
                else {
                // If it isn't a space, nor a :, nor a \n, nor a comma, add it.
                    name += c;
                }
            }
        }
    }
}

vector<string> readNames() {
// This will read a list of names in a given paper, terminating when a name co-
// mes up with a ':' at the end, marking the end of the authors and the begin-
// ning of the paper's title. Remove that ':' and store all names in a list.
    vector<string> res;
    while(true) {
        string name = readName();
        if(name[name.length() - 1] == ':') {
        // If this is the last name down the road
            name = substring(name, 0, name.length() - 1);
            // Remove the : symbol
            res.push_back(name);
            break;
        }
        res.push_back(name);
    }
    while('\n' != getchar());
    // After the names have been read, lets read characters without storing
    // them until reaching the end of the line, since all other characters are
    // part of the paper's name, in which we aren't interested at all for this.
    return res;
}

int main() {
    int s;
    // The number of scenarios
    int p, n;
    // p: the number of papers to be read
    // n: the number of authors to query for their Erdos Number
    cin >> s;
    for(int z = 0; z < s; z++) {
        authors.clear();
        visited.clear();
        allPapers.clear();
        authorsSet.clear();
        // clear all the used datastructures since these are global and need to
        // be changed for every test case of the program.
        cin >> p >> n;
        getchar();
        for(int k = 0; k < p; k++) {
            // Each read line will be a paper, first with the authors then the
            // paper's title, which will really be irrelevant for this program.
            vector<string> paperAuthors = readNames();
            for(int l = 0; l < paperAuthors.size(); l++) {
                string name = paperAuthors[l];
                authorsSet.insert(name);
            }
            allPapers.push_back(paperAuthors);
        }
        // Now that we have the list of authors in every paper, and a set that
        // contains the unique occurrences, lets iterate over the set to assign
        // each author an iterator so its easy to make a graph with them.
        set<string>::iterator it;
        int index = 0;
        for(it = authorsSet.begin(); it != authorsSet.end(); it++) {
        // Starting from 0, lets assign every unique author its own number, and
        // also keep a record of this in two maps, one that lets retrieve the
        // author's name from the number, and other that lets retrieve the num-
        // ber by using the author's name, helpful for making a graph using on-
        // ly numbers as indices and then getting the names back again
            string name = *it;
            nameToIndex[name] = index;
            indexToName[index] = name;
            index++;
        }
        initGraph();
        // Now, proceed to read a list of authors to inquire for their Erdos
        // Distance, and then do a BFS to see what is their shortest distance
        // to Paul Erdos (Erdos, P.) if any (infinity in case of none found).
        cout << "Scenario " << z + 1 << endl;
        for(int k = 0; k < n; k++) {
            resetVisited();
            string completeName = readName();
            int res;
            if(authorsSet.find(completeName) != authorsSet.end()) {
            // This is VERY important. Since the idea of making a graph invol-
            // ves giving an index to all the authors, present in the papers,
            // it may be possible that afterwards, there's a query for an au-
            // thor's Erdos Number and that author isn't in any of the availa-
            // ble paper, which would result in a nasty error since that aut-
            // hor isn't available in the map, possibly returning a bogus in-
            // dex. If the author isn't among the authors we know to be pres-
            // ent in the previously read papers, immediately print that its
            // Erdos Distance is infinity.
                int start = nameToIndex[completeName];
                int end = nameToIndex["Erdos, P."];
                res = bfs(start, end);
            }
            else {
            // The queried author isn't even in any of the given papers so the
            // immediate response is that it has infinity as its Erdos Distance
                res = -1;
            }
            if(res == -1) {
                cout << completeName << " infinity" << endl;
            }
            else {
                cout << completeName << " " << res << endl;
            }
        }
    }
}<|endoftext|>


<commit_before>#include "ConnectionVisualizerSystem.h"
#include <DebugUtil.h>
#include <ToString.h>
#include "Transform.h"
#include "ParticleSystemsComponent.h"
#include "LoadMesh.h"
#include "MeshOffsetTransform.h"

ConnectionVisualizerSystem::ConnectionVisualizerSystem() :
	EntitySystem( SystemType::ConnectionVisualizerSystem)
{

}

ConnectionVisualizerSystem::~ConnectionVisualizerSystem()
{
	cleanup();
}

void ConnectionVisualizerSystem::initialize()
{

}

void ConnectionVisualizerSystem::process()
{
	while(!m_effectsToCreate.empty())
	{
		ConnectionEffectData data = m_effectsToCreate.back();
		if (data.disabled)
		{
			for (unsigned int i = 0; i < m_createdEffects.size(); i++)
			{
				if (m_createdEffects[i].parent == data.parent &&
					m_createdEffects[i].slot == data.slot)
				{
					m_createdEffects[i].disabled = true;
				}
			}
		}
		else
		{
			int toReplace = -1;
			for (unsigned int i = 0; i < m_createdEffects.size(); i++)
			{
				if (m_createdEffects[i].disabled)
				{
					toReplace = i;
					break;
				}
			}
			if (toReplace >= 0)
			{
				replaceConnectionEffectEntity(data, toReplace);
			}
			else
			{
				data.data = createConnectionEffectEntity(data);
				m_createdEffects.push_back(data);
			}
		}
		m_effectsToCreate.pop_back();
	}
	for (unsigned int i = 0; i < m_createdEffects.size(); i++)
	{
		Transform* parentTrans = static_cast<Transform*>(m_createdEffects[i].parent->getComponent(ComponentType::Transform));

		AglMatrix parentMatrix = parentTrans->getMatrix();

		AglMatrix chilMatrix = AglMatrix::createTranslationMatrix(m_createdEffects[i].offset);
		AglVector3 childForward = m_createdEffects[i].forward;
		chilMatrix *= parentMatrix;
		childForward.transformNormal(parentMatrix);

		ParticleSystemsComponent* psc = static_cast<ParticleSystemsComponent*>
							(m_createdEffects[i].data->getComponent(ComponentType::ParticleSystemsComponent));

		AglParticleSystem* ps = psc->getParticleSystemPtr(0);
		if (ps)
		{
			ps->setSpawnPoint(chilMatrix.GetTranslation()+childForward*0.55f);

			if (m_createdEffects[i].disabled)
				ps->setSpawnFrequency(0);
			else
				ps->setSpawnFrequency(3.0f);
		}
	}
}

void ConnectionVisualizerSystem::addEffect( ConnectionEffectData p_fx )
{
	m_effectsToCreate.push_back(p_fx);
}

Entity* ConnectionVisualizerSystem::createConnectionEffectEntity(ConnectionEffectData& p_data )
{
	Entity* effect = m_world->createEntity();
	effect->setName("Connection Effect");

	ParticleSystemsComponent* particleEmitter = new ParticleSystemsComponent();

	Transform* parentTrans = static_cast<Transform*>(p_data.parent->getComponent(ComponentType::Transform));

	AglMatrix parentMatrix = parentTrans->getMatrix();

	AglMatrix chilMatrix = AglMatrix::createTranslationMatrix(p_data.offset);
	chilMatrix *= parentMatrix;

	effect->addComponent( ComponentType::Transform, new Transform(chilMatrix));

	AglParticleSystem particleSystem;
	particleSystem.setSpawnPoint(chilMatrix.GetTranslation());
	particleSystem.setSpawnDirection(AglVector3(0, 1, 0));
	particleSystem.setSpawnFrequency(3.0f);
	particleSystem.setAlignmentType(AglParticleSystemHeader::SCREEN);
	particleSystem.setSpawnSpace(AglParticleSystemHeader::AglSpace_GLOBAL);
	particleSystem.setParticleSpace(AglParticleSystemHeader::AglSpace_GLOBAL);
	particleSystem.setSpawnSpeed(0.0f);
	particleSystem.setParticleSize(AglVector2(3.0f, 3.0f));
	particleSystem.setParticleAge(0.25f);
	particleSystem.setFadeOutStart(0.0f);

	ParticleSystemInstruction particleInstruction;
	particleInstruction.textureFileName = "addModule.png";
	particleInstruction.particleSystem = particleSystem;
	particleEmitter->addParticleSystemInstruction(particleInstruction);

	effect->addComponent( ComponentType::ParticleSystemsComponent, particleEmitter);
	m_world->addEntity(effect);
	return effect;
}
void ConnectionVisualizerSystem::replaceConnectionEffectEntity(ConnectionEffectData& p_data, int p_index)
{
	p_data.data = m_createdEffects[p_index].data;
	m_createdEffects[p_index] = p_data;
}
void ConnectionVisualizerSystem::disableAll()
{
	for (unsigned int i = 0; i < m_createdEffects.size(); i++)
	{
		m_createdEffects[i].disabled = true;
	}
}

void ConnectionVisualizerSystem::cleanup()
{
	m_effectsToCreate.clear();
	for (unsigned int i = 0; i < m_effectsToCreate.size(); i++)
	{
		m_world->deleteEntity(m_createdEffects[i].data);
	}
	m_createdEffects.clear();
}
<commit_msg>VS didn't save..<commit_after>#include "ConnectionVisualizerSystem.h"
#include <DebugUtil.h>
#include <ToString.h>
#include "Transform.h"
#include "ParticleSystemsComponent.h"
#include "LoadMesh.h"
#include "MeshOffsetTransform.h"

ConnectionVisualizerSystem::ConnectionVisualizerSystem() :
	EntitySystem( SystemType::ConnectionVisualizerSystem)
{

}

ConnectionVisualizerSystem::~ConnectionVisualizerSystem()
{
	cleanup();
}

void ConnectionVisualizerSystem::initialize()
{

}

void ConnectionVisualizerSystem::process()
{
	while(!m_effectsToCreate.empty())
	{
		ConnectionEffectData data = m_effectsToCreate.back();
		if (data.disabled)
		{
			for (unsigned int i = 0; i < m_createdEffects.size(); i++)
			{
				if (m_createdEffects[i].parent == data.parent &&
					m_createdEffects[i].slot == data.slot)
				{
					m_createdEffects[i].disabled = true;
				}
			}
		}
		else
		{
			int toReplace = -1;
			for (unsigned int i = 0; i < m_createdEffects.size(); i++)
			{
				if (m_createdEffects[i].disabled)
				{
					toReplace = i;
					break;
				}
			}
			if (toReplace >= 0)
			{
				replaceConnectionEffectEntity(data, toReplace);
			}
			else
			{
				data.data = createConnectionEffectEntity(data);
				m_createdEffects.push_back(data);
			}
		}
		m_effectsToCreate.pop_back();
	}
	for (unsigned int i = 0; i < m_createdEffects.size(); i++)
	{
		Transform* parentTrans = static_cast<Transform*>(m_createdEffects[i].parent->getComponent(ComponentType::Transform));

		AglMatrix parentMatrix = parentTrans->getMatrix();

		AglMatrix chilMatrix = AglMatrix::createTranslationMatrix(m_createdEffects[i].offset);
		AglVector3 childForward = m_createdEffects[i].forward;
		chilMatrix *= parentMatrix;
		childForward.transformNormal(parentMatrix);

		ParticleSystemsComponent* psc = static_cast<ParticleSystemsComponent*>
							(m_createdEffects[i].data->getComponent(ComponentType::ParticleSystemsComponent));

		AglParticleSystem* ps = psc->getParticleSystemPtr(0);
		if (ps)
		{
			ps->setSpawnPoint(chilMatrix.GetTranslation()+childForward*0.55f);

			if (m_createdEffects[i].disabled)
				ps->setSpawnFrequency(0);
			else
				ps->setSpawnFrequency(3.0f);
		}
	}
}

void ConnectionVisualizerSystem::addEffect( ConnectionEffectData p_fx )
{
	m_effectsToCreate.push_back(p_fx);
}

Entity* ConnectionVisualizerSystem::createConnectionEffectEntity(ConnectionEffectData& p_data )
{
	Entity* effect = m_world->createEntity();
	effect->setName("Connection Effect");

	ParticleSystemsComponent* particleEmitter = new ParticleSystemsComponent();

	Transform* parentTrans = static_cast<Transform*>(p_data.parent->getComponent(ComponentType::Transform));

	AglMatrix parentMatrix = parentTrans->getMatrix();

	AglMatrix chilMatrix = AglMatrix::createTranslationMatrix(p_data.offset);
	chilMatrix *= parentMatrix;

	effect->addComponent( ComponentType::Transform, new Transform(chilMatrix));

	AglParticleSystem particleSystem;
	particleSystem.setSpawnPoint(chilMatrix.GetTranslation());
	particleSystem.setSpawnDirection(AglVector3(0, 1, 0));
	particleSystem.setSpawnFrequency(3.0f);
	particleSystem.setAlignmentType(AglParticleSystemHeader::SCREEN);
	particleSystem.setSpawnSpace(AglParticleSystemHeader::AglSpace_GLOBAL);
	particleSystem.setParticleSpace(AglParticleSystemHeader::AglSpace_GLOBAL);
	particleSystem.setSpawnSpeed(0.0f);
	particleSystem.setParticleSize(AglVector2(3.0f, 3.0f));
	particleSystem.setParticleAge(0.25f);
	particleSystem.setFadeOutStart(0.0f);

	ParticleSystemInstruction particleInstruction;
	particleInstruction.textureFileName = "addModule.png";
	particleInstruction.particleSystem = particleSystem;
	particleEmitter->addParticleSystemInstruction(particleInstruction);

	effect->addComponent( ComponentType::ParticleSystemsComponent, particleEmitter);
	m_world->addEntity(effect);
	return effect;
}
void ConnectionVisualizerSystem::replaceConnectionEffectEntity(ConnectionEffectData& p_data, int p_index)
{
	p_data.data = m_createdEffects[p_index].data;
	m_createdEffects[p_index] = p_data;
}
void ConnectionVisualizerSystem::disableAll()
{
	for (unsigned int i = 0; i < m_createdEffects.size(); i++)
	{
		m_createdEffects[i].disabled = true;
	}
}

void ConnectionVisualizerSystem::cleanup()
{
	m_effectsToCreate.clear();
	for (unsigned int i = 0; i < m_createdEffects.size(); i++)
	{
		m_world->deleteEntity(m_createdEffects[i].data);
	}
	m_createdEffects.clear();
}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkMovieMaker.h"
#include "QmitkMovieMakerControls.h"
#include "QmitkTreeNodeSelector.h"
#include "QmitkStepperAdapter.h"
#include "QmitkStdMultiWidget.h"

#include "mitkOpenGLRenderer.h"
#include "mitkMovieGenerator.h"
#include "mitkGlobalInteraction.h"

#include "icon.xpm"

#include <iostream>

#include <vtkRenderer.h>
#include <vtkCamera.h>

#include <qaction.h>
#include <qfiledialog.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <qspinbox.h>
#include <qcombobox.h>

QmitkMovieMaker::QmitkMovieMaker( QObject *parent, const char *name,
  QmitkStdMultiWidget *mitkStdMultiWidget, mitk::DataTreeIteratorBase* it )

: QmitkFunctionality(parent, name, it),
  m_Controls(NULL), m_StepperAdapter(NULL), m_MultiWidget(mitkStdMultiWidget),
  m_Looping(true), m_Direction(0), m_Aspect(0)
{
  this->SetAvailability(true);
  m_Timer = new QTimer(this);
  m_Time = new QTime();

  m_FocusManagerCallback = MemberCommand::New();
  m_FocusManagerCallback->SetCallbackFunction( this, &QmitkMovieMaker::FocusChange );
  mitk::GlobalInteraction::GetInstance()->GetFocusManager()->AddObserver(
    mitk::FocusEvent(), m_FocusManagerCallback
  );
}

QmitkMovieMaker::~QmitkMovieMaker()
{
  delete m_StepperAdapter;
  delete m_Timer;
  delete m_Time;
}

mitk::BaseController* QmitkMovieMaker::GetSpatialController()
{
  mitk::BaseRenderer* focusedRenderer =
    mitk::GlobalInteraction::GetInstance()->GetFocus();

  if ( m_MultiWidget->GetRenderWindow1()->GetRenderer() == focusedRenderer )
  {
    return m_MultiWidget->GetRenderWindow1()->GetController();
  }
  else if ( m_MultiWidget->GetRenderWindow2()->GetRenderer() == focusedRenderer )
  {
    return m_MultiWidget->GetRenderWindow2()->GetController();
  }
  else if ( m_MultiWidget->GetRenderWindow3()->GetRenderer() == focusedRenderer )
  {
    return m_MultiWidget->GetRenderWindow3()->GetController();
  }
  else if ( m_MultiWidget->GetRenderWindow4()->GetRenderer() == focusedRenderer )
  {
    return m_MultiWidget->GetRenderWindow4()->GetController();
  }

  return m_MultiWidget->GetRenderWindow4()->GetController();
}

mitk::BaseController* QmitkMovieMaker::GetTemporalController()
{
  return m_MultiWidget->GetTimeNavigationController();
}

QWidget* QmitkMovieMaker::CreateMainWidget(QWidget *parent)
{
  return NULL;
}

QWidget* QmitkMovieMaker::CreateControlWidget(QWidget *parent)
{
  if (m_Controls == NULL)
  {
    m_Controls = new QmitkMovieMakerControls(parent);

    m_StepperAdapter = new QmitkStepperAdapter(
      (QObject*) m_Controls->slidAngle, this->GetSpatialController()->GetSlice(),
      "AngleStepperToMovieMakerFunctionality"
    );

    // Initialize "Selected Window" combo box
    const mitk::RenderWindow::RenderWindowSet rws =
      mitk::RenderWindow::GetInstances();

    mitk::RenderWindow::RenderWindowSet::const_iterator iter;
    for (iter = rws.begin(); iter != rws.end(); ++iter)
    {
      m_Controls->cmbSelectedWindow->insertItem((*iter)->GetName(), -1);
    }
  }
  return m_Controls;
}

void QmitkMovieMaker::CreateConnections()
{
  if ( m_Controls )
  {
    // start / pause / stop playing
    connect( (QObject*) m_Controls, SIGNAL(StartPlaying()),
      this, SLOT(StartPlaying()) );

    connect( (QObject*) m_Controls, SIGNAL(PausePlaying()),
      this, SLOT(PausePlaying()) );

    connect( (QObject*) m_Controls, SIGNAL(StopPlaying()),
      this, SLOT(StopPlaying()) );

    // radio button group: forward, backward, ping-pong
    connect( (QObject*) m_Controls, SIGNAL(SwitchDirection(int)),
      this, SLOT(SetDirection(int)) );

    // radio button group: spatial, temporal
    connect( (QObject*) m_Controls, SIGNAL(SwitchAspect(int)),
      this, SLOT(SetAspect(int)) );

    // window selection
    connect( (QObject*) m_Controls, SIGNAL(SwitchSelectedWindow(int)),
      this, SLOT(SetWindow(int)) );

    // camera rotation
    // every timer tick
    connect( (QObject*) m_Timer, SIGNAL(timeout()),
      this, SLOT(RotateCamera()) );

    // movie generation
    // when the movie button is clickethe movie button is clicked
    connect( (QObject*) m_Controls->btnMovie, SIGNAL(clicked()),
      this, SLOT(GenerateMovie()) );

    // blocking of ui elements during movie generation
    connect( (QObject*) this, SIGNAL(StartBlockControls()),
      (QObject*) m_Controls , SLOT(BlockControls()) );

    connect( (QObject*) this, SIGNAL(EndBlockControls()),
      (QObject*) m_Controls , SLOT(UnBlockControls()) );
  }
}

QAction* QmitkMovieMaker::CreateAction(QActionGroup *parent)
{
  QAction* action;
  action = new QAction( tr( "MovieMaker" ), QPixmap((const char**)icon_xpm),
    tr( "Camera Path" ), CTRL + Key_G, parent, "MovieMaker"
  );

  return action;
}

void QmitkMovieMaker::Activated()
{
  QmitkFunctionality::Activated();

  // Initialize steppers etc.
  this->FocusChange();
}

void QmitkMovieMaker::FocusChange()
{
  mitk::Stepper *stepper = this->GetAspectStepper();
  m_StepperAdapter->SetStepper( stepper );

  // Make the stepper movement non-inverted
  stepper->InverseDirectionOff();

  // Set stepping direction and aspect (spatial / temporal) for new stepper
  this->SwitchLooping( m_Looping );
  this->SwitchDirection( m_Direction );
  this->SwitchAspect( m_Aspect );

  // Set newly focused window as active in "Selected Window" combo box
  const mitk::RenderWindow::RenderWindowSet rws =
    mitk::RenderWindow::GetInstances();

  int i;
  mitk::RenderWindow::RenderWindowSet::const_iterator iter;
  for (iter = rws.begin(), i = 0; iter != rws.end(); ++iter, ++i)
  {
    mitk::BaseRenderer* focusedRenderer =
      mitk::GlobalInteraction::GetInstance()->GetFocusManager()->GetFocused();

    if ( focusedRenderer == (*iter)->GetRenderer() )
    {
      m_Controls->cmbSelectedWindow->setCurrentItem( i );
      break;
    }
  }
}

void QmitkMovieMaker::RotateCamera()
{
  // This method is called when a timer timeout occurs. It increases the
  // stepper value according to the elapsed time and camera rotation inteval.
  // Note that a screen refresh is not forced, but merely requested, and may
  // occur only after more calls to RotateCamera().

  mitk::Stepper* stepper = this->GetAspectStepper();

  m_StepperAdapter->SetStepper( stepper );

  int elapsedTime = m_Time->elapsed();
  m_Time->restart();

  static double increment = 0.0;
  increment = increment - static_cast< int >( increment );
  increment += elapsedTime * stepper->GetSteps()
    / ( m_Controls->spnDuration->value() * 1000.0 );

  int i, n = static_cast< int >( increment );
  for ( i = 0; i < n; ++i )
  {
    stepper->Next();
  }
}

void QmitkMovieMaker::StartPlaying()
{
  // Restart timer with 5 msec interval - this should be fine-grained enough
  // even for high display refresh frequencies
  m_Timer->start( 5 );

  m_Time->restart();
}

void QmitkMovieMaker::PausePlaying()
{
  m_Timer->stop();
}

void QmitkMovieMaker::StopPlaying()
{
  m_Timer->stop();
  switch ( m_Direction )
  {
  case 0:
  case 2:
    this->GetAspectStepper()->First();
    break;

  case 1:
    this->GetAspectStepper()->Last();
    break;
  }

  // Reposition slider GUI element
  m_StepperAdapter->SetStepper( this->GetAspectStepper() );
}

void QmitkMovieMaker::SetLooping( bool looping )
{
  m_Looping = looping;
  this->SwitchLooping( m_Looping );
}

void QmitkMovieMaker::SetDirection( int direction )
{
  m_Direction = direction;
  this->SwitchDirection( m_Direction );
}

void QmitkMovieMaker::SetAspect( int aspect )
{
      std::cout << "in set aspect" << aspect << std::endl;
  m_Aspect = aspect;
  this->SwitchAspect( m_Aspect );
}

void QmitkMovieMaker::SetWindow( int window )
{
  // Set newly selected window / renderer as focused
  const mitk::RenderWindow::RenderWindowSet rws =
    mitk::RenderWindow::GetInstances();

  int i;
  mitk::RenderWindow::RenderWindowSet::const_iterator iter;
  for (iter = rws.begin(), i = 0; iter != rws.end(); ++iter, ++i)
  {
    if ( i == window )
    {
      mitk::GlobalInteraction::GetInstance()->GetFocusManager()
        ->SetFocused( (*iter)->GetRenderer() );
      break;
    }
  }
}

void QmitkMovieMaker::SwitchLooping( bool looping )
{
 this->GetAspectStepper()->SetAutoRepeat( looping );
}

void QmitkMovieMaker::SwitchDirection( int direction )
{
  mitk::Stepper* stepper = this->GetAspectStepper();

  switch ( direction )
  {
  case 0:
    stepper->InverseDirectionOff();
    stepper->PingPongOff();
    break;

  case 1:
    stepper->InverseDirectionOn();
    stepper->PingPongOff();
    break;

  case 2:
    stepper->PingPongOn();
    break;
  }
}

void QmitkMovieMaker::SwitchAspect( int aspect )
{
  // Initialize stepper direction and looping
  this->SwitchDirection( m_Direction );
  this->SwitchLooping( m_Looping );
}

mitk::Stepper* QmitkMovieMaker::GetAspectStepper()
{
  if (m_Aspect == 0)
  {
    m_Stepper = NULL;
    return this->GetSpatialController()->GetSlice();
  }
  else if (m_Aspect == 1)
  {
    m_Stepper = NULL;
    return this->GetTemporalController()->GetTime();
  } else if (m_Aspect == 2) {
    if (m_Stepper.IsNull()) {
      std::cout << "creating multi stepper" << std::endl;
      m_Stepper = mitk::MultiStepper::New();
      m_Stepper->AddStepper(this->GetSpatialController()->GetSlice());
      m_Stepper->AddStepper(this->GetTemporalController()->GetTime());
    }
    return m_Stepper.GetPointer();
  }
}

void QmitkMovieMaker::GenerateMovie()
{
  emit StartBlockControls();

  // provide the movie generator with the stepper and rotate the camera each step
  mitk::MovieGenerator::Pointer movieGenerator = mitk::MovieGenerator::New();

  if ( movieGenerator.IsNotNull() )
  {
    movieGenerator->SetStepper( this->GetAspectStepper() );
    movieGenerator->SetRenderer(
      mitk::GlobalInteraction::GetInstance()->GetFocus()
    );

    QString movieFileName = QFileDialog::getSaveFileName(
      QString::null, "Movie (*.avi)", 0, "movie file dialog", "Choose a file name"
    );

    if(movieFileName.isEmpty() == false)
    {
      movieGenerator->SetFileName( movieFileName.ascii() );
      movieGenerator->WriteMovie();
    }
  }
  else
  {
    std::cerr << "Either mitk::MovieGenerator is not implemented for your";
    std::cerr << " platform or an error occurred during";
    std::cerr << " mitk::MovieGenerator::New()" << std::endl;
  }
  emit EndBlockControls();
}
<commit_msg>FIX: debug output removed<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkMovieMaker.h"
#include "QmitkMovieMakerControls.h"
#include "QmitkTreeNodeSelector.h"
#include "QmitkStepperAdapter.h"
#include "QmitkStdMultiWidget.h"

#include "mitkOpenGLRenderer.h"
#include "mitkMovieGenerator.h"
#include "mitkGlobalInteraction.h"

#include "icon.xpm"

#include <iostream>

#include <vtkRenderer.h>
#include <vtkCamera.h>

#include <qaction.h>
#include <qfiledialog.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <qspinbox.h>
#include <qcombobox.h>

QmitkMovieMaker::QmitkMovieMaker( QObject *parent, const char *name,
  QmitkStdMultiWidget *mitkStdMultiWidget, mitk::DataTreeIteratorBase* it )

: QmitkFunctionality(parent, name, it),
  m_Controls(NULL), m_StepperAdapter(NULL), m_MultiWidget(mitkStdMultiWidget),
  m_Looping(true), m_Direction(0), m_Aspect(0)
{
  this->SetAvailability(true);
  m_Timer = new QTimer(this);
  m_Time = new QTime();

  m_FocusManagerCallback = MemberCommand::New();
  m_FocusManagerCallback->SetCallbackFunction( this, &QmitkMovieMaker::FocusChange );
  mitk::GlobalInteraction::GetInstance()->GetFocusManager()->AddObserver(
    mitk::FocusEvent(), m_FocusManagerCallback
  );
}

QmitkMovieMaker::~QmitkMovieMaker()
{
  delete m_StepperAdapter;
  delete m_Timer;
  delete m_Time;
}

mitk::BaseController* QmitkMovieMaker::GetSpatialController()
{
  mitk::BaseRenderer* focusedRenderer =
    mitk::GlobalInteraction::GetInstance()->GetFocus();

  if ( m_MultiWidget->GetRenderWindow1()->GetRenderer() == focusedRenderer )
  {
    return m_MultiWidget->GetRenderWindow1()->GetController();
  }
  else if ( m_MultiWidget->GetRenderWindow2()->GetRenderer() == focusedRenderer )
  {
    return m_MultiWidget->GetRenderWindow2()->GetController();
  }
  else if ( m_MultiWidget->GetRenderWindow3()->GetRenderer() == focusedRenderer )
  {
    return m_MultiWidget->GetRenderWindow3()->GetController();
  }
  else if ( m_MultiWidget->GetRenderWindow4()->GetRenderer() == focusedRenderer )
  {
    return m_MultiWidget->GetRenderWindow4()->GetController();
  }

  return m_MultiWidget->GetRenderWindow4()->GetController();
}

mitk::BaseController* QmitkMovieMaker::GetTemporalController()
{
  return m_MultiWidget->GetTimeNavigationController();
}

QWidget* QmitkMovieMaker::CreateMainWidget(QWidget *parent)
{
  return NULL;
}

QWidget* QmitkMovieMaker::CreateControlWidget(QWidget *parent)
{
  if (m_Controls == NULL)
  {
    m_Controls = new QmitkMovieMakerControls(parent);

    m_StepperAdapter = new QmitkStepperAdapter(
      (QObject*) m_Controls->slidAngle, this->GetSpatialController()->GetSlice(),
      "AngleStepperToMovieMakerFunctionality"
    );

    // Initialize "Selected Window" combo box
    const mitk::RenderWindow::RenderWindowSet rws =
      mitk::RenderWindow::GetInstances();

    mitk::RenderWindow::RenderWindowSet::const_iterator iter;
    for (iter = rws.begin(); iter != rws.end(); ++iter)
    {
      m_Controls->cmbSelectedWindow->insertItem((*iter)->GetName(), -1);
    }
  }
  return m_Controls;
}

void QmitkMovieMaker::CreateConnections()
{
  if ( m_Controls )
  {
    // start / pause / stop playing
    connect( (QObject*) m_Controls, SIGNAL(StartPlaying()),
      this, SLOT(StartPlaying()) );

    connect( (QObject*) m_Controls, SIGNAL(PausePlaying()),
      this, SLOT(PausePlaying()) );

    connect( (QObject*) m_Controls, SIGNAL(StopPlaying()),
      this, SLOT(StopPlaying()) );

    // radio button group: forward, backward, ping-pong
    connect( (QObject*) m_Controls, SIGNAL(SwitchDirection(int)),
      this, SLOT(SetDirection(int)) );

    // radio button group: spatial, temporal
    connect( (QObject*) m_Controls, SIGNAL(SwitchAspect(int)),
      this, SLOT(SetAspect(int)) );

    // window selection
    connect( (QObject*) m_Controls, SIGNAL(SwitchSelectedWindow(int)),
      this, SLOT(SetWindow(int)) );

    // camera rotation
    // every timer tick
    connect( (QObject*) m_Timer, SIGNAL(timeout()),
      this, SLOT(RotateCamera()) );

    // movie generation
    // when the movie button is clickethe movie button is clicked
    connect( (QObject*) m_Controls->btnMovie, SIGNAL(clicked()),
      this, SLOT(GenerateMovie()) );

    // blocking of ui elements during movie generation
    connect( (QObject*) this, SIGNAL(StartBlockControls()),
      (QObject*) m_Controls , SLOT(BlockControls()) );

    connect( (QObject*) this, SIGNAL(EndBlockControls()),
      (QObject*) m_Controls , SLOT(UnBlockControls()) );
  }
}

QAction* QmitkMovieMaker::CreateAction(QActionGroup *parent)
{
  QAction* action;
  action = new QAction( tr( "MovieMaker" ), QPixmap((const char**)icon_xpm),
    tr( "Camera Path" ), CTRL + Key_G, parent, "MovieMaker"
  );

  return action;
}

void QmitkMovieMaker::Activated()
{
  QmitkFunctionality::Activated();

  // Initialize steppers etc.
  this->FocusChange();
}

void QmitkMovieMaker::FocusChange()
{
  mitk::Stepper *stepper = this->GetAspectStepper();
  m_StepperAdapter->SetStepper( stepper );

  // Make the stepper movement non-inverted
  stepper->InverseDirectionOff();

  // Set stepping direction and aspect (spatial / temporal) for new stepper
  this->SwitchLooping( m_Looping );
  this->SwitchDirection( m_Direction );
  this->SwitchAspect( m_Aspect );

  // Set newly focused window as active in "Selected Window" combo box
  const mitk::RenderWindow::RenderWindowSet rws =
    mitk::RenderWindow::GetInstances();

  int i;
  mitk::RenderWindow::RenderWindowSet::const_iterator iter;
  for (iter = rws.begin(), i = 0; iter != rws.end(); ++iter, ++i)
  {
    mitk::BaseRenderer* focusedRenderer =
      mitk::GlobalInteraction::GetInstance()->GetFocusManager()->GetFocused();

    if ( focusedRenderer == (*iter)->GetRenderer() )
    {
      m_Controls->cmbSelectedWindow->setCurrentItem( i );
      break;
    }
  }
}

void QmitkMovieMaker::RotateCamera()
{
  // This method is called when a timer timeout occurs. It increases the
  // stepper value according to the elapsed time and camera rotation inteval.
  // Note that a screen refresh is not forced, but merely requested, and may
  // occur only after more calls to RotateCamera().

  mitk::Stepper* stepper = this->GetAspectStepper();

  m_StepperAdapter->SetStepper( stepper );

  int elapsedTime = m_Time->elapsed();
  m_Time->restart();

  static double increment = 0.0;
  increment = increment - static_cast< int >( increment );
  increment += elapsedTime * stepper->GetSteps()
    / ( m_Controls->spnDuration->value() * 1000.0 );

  int i, n = static_cast< int >( increment );
  for ( i = 0; i < n; ++i )
  {
    stepper->Next();
  }
}

void QmitkMovieMaker::StartPlaying()
{
  // Restart timer with 5 msec interval - this should be fine-grained enough
  // even for high display refresh frequencies
  m_Timer->start( 5 );

  m_Time->restart();
}

void QmitkMovieMaker::PausePlaying()
{
  m_Timer->stop();
}

void QmitkMovieMaker::StopPlaying()
{
  m_Timer->stop();
  switch ( m_Direction )
  {
  case 0:
  case 2:
    this->GetAspectStepper()->First();
    break;

  case 1:
    this->GetAspectStepper()->Last();
    break;
  }

  // Reposition slider GUI element
  m_StepperAdapter->SetStepper( this->GetAspectStepper() );
}

void QmitkMovieMaker::SetLooping( bool looping )
{
  m_Looping = looping;
  this->SwitchLooping( m_Looping );
}

void QmitkMovieMaker::SetDirection( int direction )
{
  m_Direction = direction;
  this->SwitchDirection( m_Direction );
}

void QmitkMovieMaker::SetAspect( int aspect )
{
  m_Aspect = aspect;
  this->SwitchAspect( m_Aspect );
}

void QmitkMovieMaker::SetWindow( int window )
{
  // Set newly selected window / renderer as focused
  const mitk::RenderWindow::RenderWindowSet rws =
    mitk::RenderWindow::GetInstances();

  int i;
  mitk::RenderWindow::RenderWindowSet::const_iterator iter;
  for (iter = rws.begin(), i = 0; iter != rws.end(); ++iter, ++i)
  {
    if ( i == window )
    {
      mitk::GlobalInteraction::GetInstance()->GetFocusManager()
        ->SetFocused( (*iter)->GetRenderer() );
      break;
    }
  }
}

void QmitkMovieMaker::SwitchLooping( bool looping )
{
 this->GetAspectStepper()->SetAutoRepeat( looping );
}

void QmitkMovieMaker::SwitchDirection( int direction )
{
  mitk::Stepper* stepper = this->GetAspectStepper();

  switch ( direction )
  {
  case 0:
    stepper->InverseDirectionOff();
    stepper->PingPongOff();
    break;

  case 1:
    stepper->InverseDirectionOn();
    stepper->PingPongOff();
    break;

  case 2:
    stepper->PingPongOn();
    break;
  }
}

void QmitkMovieMaker::SwitchAspect( int aspect )
{
  // Initialize stepper direction and looping
  this->SwitchDirection( m_Direction );
  this->SwitchLooping( m_Looping );
}

mitk::Stepper* QmitkMovieMaker::GetAspectStepper()
{
  if (m_Aspect == 0)
  {
    m_Stepper = NULL;
    return this->GetSpatialController()->GetSlice();
  }
  else if (m_Aspect == 1)
  {
    m_Stepper = NULL;
    return this->GetTemporalController()->GetTime();
  } else if (m_Aspect == 2) {
    if (m_Stepper.IsNull()) {
      m_Stepper = mitk::MultiStepper::New();
      m_Stepper->AddStepper(this->GetSpatialController()->GetSlice());
      m_Stepper->AddStepper(this->GetTemporalController()->GetTime());
    }
    return m_Stepper.GetPointer();
  }
}

void QmitkMovieMaker::GenerateMovie()
{
  emit StartBlockControls();

  // provide the movie generator with the stepper and rotate the camera each step
  mitk::MovieGenerator::Pointer movieGenerator = mitk::MovieGenerator::New();

  if ( movieGenerator.IsNotNull() )
  {
    movieGenerator->SetStepper( this->GetAspectStepper() );
    movieGenerator->SetRenderer(
      mitk::GlobalInteraction::GetInstance()->GetFocus()
    );

    QString movieFileName = QFileDialog::getSaveFileName(
      QString::null, "Movie (*.avi)", 0, "movie file dialog", "Choose a file name"
    );

    if(movieFileName.isEmpty() == false)
    {
      movieGenerator->SetFileName( movieFileName.ascii() );
      movieGenerator->WriteMovie();
    }
  }
  else
  {
    std::cerr << "Either mitk::MovieGenerator is not implemented for your";
    std::cerr << " platform or an error occurred during";
    std::cerr << " mitk::MovieGenerator::New()" << std::endl;
  }
  emit EndBlockControls();
}
<|endoftext|>


<commit_before>#ifndef _MZ_SHARE_SELFARRAYLIST_HPP_
#define _MZ_SHARE_SELFARRAYLIST_HPP_

#include "Metazion/Share/ShareInclude.hpp"

DECL_NAMESPACE_MZ_SHARE_BEGIN

template<typename ValueType>
struct SelfArrayListNode {
    using Value_t = ValueType;

    Value_t m_value;
    int m_selfIndex = -1;
    int m_prevIndex = -1;
    int m_nextIndex = -1;
};

template<>
struct SelfArrayListNode<void> {
    int m_selfIndex = -1;
    int m_prevIndex = -1;
    int m_nextIndex = -1;
};

template<typename NodeType
, int INITSIZE
>
class SelfArrayList {
    using Node_t = NodeType;

    struct Entry {
        Node_t* m_node = nullptr;
        int m_freeNext = -1;
    };

public:
    SelfArrayList() {}

    ~SelfArrayList() {}

    SelfArrayList(const SelfArrayList& other) {
        *this = other;
    }

    SelfArrayList& operator =(const SelfArrayList& other) {
        if (&other != this) {
            for (auto index = 0; index < INITSIZE; ++index) {
                m_entries[index] = other.m_entries[index];
            }

            m_allocIndex = other.m_allocIndex;
            m_freeHead = other.m_freeHead;
            m_usedHead = other.m_usedHead;
            m_usedTail = other.m_usedTail;
            m_size = other.m_size;
        }
        return *this;
    }

    SelfArrayList(SelfArrayList&& other) {
        *this = std::move(other);
    }

    SelfArrayList& operator =(SelfArrayList&& other) {
        if (&other != this) {
            for (auto index = 0; index < INITSIZE; ++index) {
                m_entries[index] = other.m_entries[index];
            }

            m_allocIndex = other.m_allocIndex;
            m_freeHead = other.m_freeHead;
            m_usedHead = other.m_usedHead;
            m_usedTail = other.m_usedTail;
            m_size = other.m_size;
        }
        return *this;
    }

public:
    void Clear() {
        for (auto index = 0; index < INITSIZE; ++index) {
            m_entries[index] = {};
        }

        m_allocIndex = 0;
        m_freeHead = 0;
        m_usedHead = -1;
        m_usedTail = -1;
        m_size = 0;
    }

    bool IsEmpty() const {
        return -1 == m_usedHead;
    }

    int GetCapacity() const {
        return INITSIZE;
    }

    int GetSize() const {
        return m_size;
    }

    Node_t* Front() {
        if (IsInvalid(m_usedHead)) {
            return nullptr;
        }

        auto& entry = m_entries[m_usedHead];
        return entry.m_node;
    }

    const Node_t* Front() const {
        if (IsInvalid(m_usedHead)) {
            return nullptr;
        }

        auto& entry = m_entries[m_usedHead];
        return entry.m_node;
    }

    Node_t* Back() {
        if (IsInvalid(m_usedTail)) {
            return nullptr;
        }

        auto& entry = m_entries[m_usedHead];
        return entry.m_node;
    }

    const Node_t* Back() const {
        if (IsInvalid(m_usedTail)) {
            return nullptr;
        }

        auto& entry = m_entries[m_usedHead];
        return entry.m_node;
    }

    Node_t* PushFront(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(!IsContain(node));

        const auto index = NextFreeIndex();
        if (IsInvalid(index)) {
            return nullptr;
        }

        node->m_selfIndex = index;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        if (IsInvalid(m_usedHead)) {
            m_usedHead = node->m_selfIndex;
            m_usedTail = node->m_selfIndex;
        }
        else {
            Node(m_usedHead)->m_prevIndex = node->m_selfIndex;
            node->m_nextIndex = m_usedHead;
            m_usedHead = node->m_selfIndex;
        }

        m_entries[index].m_node = node;
        ++m_size;
        return node;
    }

    Node_t* PushBack(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(!IsContain(node));

        const auto index = NextFreeIndex();
        if (IsInvalid(index)) {
            return nullptr;
        }

        node->m_selfIndex = index;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        if (IsInvalid(m_usedTail)) {
            m_usedHead = node->m_selfIndex;
            m_usedTail = node->m_selfIndex;
        }
        else {
            node->m_prevIndex = m_usedTail;
            Node(m_usedTail)->m_nextIndex = node->m_selfIndex;
            m_usedTail = node->m_selfIndex;
        }

        m_entries[index].m_node = node;
        ++m_size;
        return node;
    }

    Node_t* PopFront() {
        if (IsInvalid(m_usedHead)) {
            return nullptr;
        }

        auto node = Node(m_usedHead);
        const auto index = node->m_selfIndex;

        m_usedHead = node->m_nextIndex;
        if (IsInvalid(m_usedHead)) {
            m_usedTail = -1;
        }
        else {
            Node(m_usedHead)->m_prevIndex = -1;
        }

        node->m_selfIndex = -1;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        BackFreeHead(index);

        m_entries[index].m_node = nullptr;
        --m_size;
        return node;
    }

    Node_t* PopBack() {
        if (IsInvalid(m_usedTail)) {
            return nullptr;
        }

        auto node = Node(m_usedTail);
        const auto index = node->m_selfIndex;

        m_usedTail = node->m_prevIndex;
        if (IsInvalid(m_usedTail)) {
            m_usedHead = -1;
        }
        else {
            Node(m_usedTail)->m_nextIndex = -1;
        }
        node->m_selfIndex = -1;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        BackFreeHead(index);

        m_entries[index].m_node = nullptr;
        --m_size;
        return node;
    }

    Node_t* InsertBefore(Node_t* location, Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(location));
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(IsContain(location));
        MZ_ASSERT_TRUE(!IsContain(node));

        const auto index = NextFreeIndex();
        if (IsInvalid(index)) {
            return nullptr;
        }

        node->m_selfIndex = index;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        auto prevIndex = location->m_prevIndex;
        if (IsInvalid(prevIndex)) {
            m_usedHead = node->m_selfIndex;
        }
        else {
            Node(prevIndex)->m_nextIndex = node->m_selfIndex;
        }
        location->m_prevIndex = node->m_selfIndex;
        node->m_prevIndex = prevIndex;
        node->m_nextIndex = location->m_selfIndex;

        m_entries[index].m_node = node;
        ++m_size;
        return node;
    }

    Node_t* InsertAfter(Node_t* location, Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(location));
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(IsContain(location));
        MZ_ASSERT_TRUE(!IsContain(node));

        const auto index = NextFreeIndex();
        if (IsInvalid(index)) {
            return nullptr;
        }

        node->m_selfIndex = index;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        auto nextIndex = location->m_nextIndex;
        if (IsInvalid(nextIndex)) {
            m_usedTail = node->m_selfIndex;
        }
        else {
            Node(nextIndex)->m_prevIndex = node->m_selfIndex;
        }
        location->m_nextIndex = node->m_selfIndex;
        node->m_prevIndex = location->m_selfIndex;
        node->m_nextIndex = nextIndex;

        m_entries[index].m_node = node;
        ++m_size;
        return node;
    }

    Node_t* Remove(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(IsContain(node));

        const auto index = node->m_selfIndex;
        const auto prevIndex = node->m_prevIndex;
        const auto nextIndex = node->m_nextIndex;
        if (IsInvalid(prevIndex)) {
            MZ_ASSERT_TRUE(node->m_selfIndex == m_usedHead);
            m_usedHead = nextIndex;
        }
        else {
            Node(prevIndex)->m_nextIndex = nextIndex;
        }
        if (IsInvalid(nextIndex)) {
            MZ_ASSERT_TRUE(node->m_selfIndex == m_usedTail);
            m_usedTail = prevIndex;
        }
        else {
            Node(nextIndex)->m_prevIndex = prevIndex;
        }

        node->m_selfIndex = -1;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        BackFreeHead(index);

        m_entries[index].m_node = nullptr;
        --m_size;
        return Node(nextIndex);
    }

    Node_t* Backward(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));

        return Node(node->m_prevIndex);
    }

    const Node_t* Backward(const Node_t* node) const {
        MZ_ASSERT_TRUE(!IsNull(node));

        return Node(node->m_prevIndex);
    }

    Node_t* Forward(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));

        return Node(node->m_nextIndex);
    }

    const Node_t* Forward(const Node_t* node) const {
        MZ_ASSERT_TRUE(!IsNull(node));

        return Node(node->m_nextIndex);
    }

    bool IsContain(Node_t* node) const {
        MZ_ASSERT_TRUE(!IsNull(node));

        auto cursor = Front();
        while (!IsNull(cursor)) {
            if (node == cursor) {
                return true;
            }
            cursor = Forward(cursor);
        }

        return false;
    }

private:
    int NextFreeIndex() {
        if (m_freeHead < 0) {
            return -1;
        }

        const auto index = m_freeHead;
        if (m_freeHead < m_allocIndex) {
            auto& entry = m_entries[m_freeHead];
            m_freeHead = entry.m_freeNext;
        }
        else {
            m_freeHead += 1;
            m_allocIndex = m_freeHead;
        }

        if (m_freeHead >= INITSIZE) {
            m_freeHead = -1;
        }

        return index;
    }

    int BackFreeHead(int index) {
        m_entries[index].m_freeNext = m_freeHead;
        m_freeHead = index;
        return m_freeHead;
    }

    Node_t* Node(int index) {
        if (IsInvalid(index)) {
            return nullptr;
        }

        return m_entries[index].m_node;
    }

    const Node_t* Node(int index) const {
        if (IsInvalid(index)) {
            return nullptr;
        }

        return m_entries[index].m_node;
    }

    bool IsInvalid(int index) const {
        return index < 0 || index >= INITSIZE;
    }

private:
    Entry m_entries[INITSIZE];
    int m_usedHead = -1;
    int m_usedTail = -1;
    int m_size = 0;
    int m_freeHead = 0;
    int m_allocIndex = 0;
};

DECL_NAMESPACE_MZ_SHARE_END

#endif // _MZ_SHARE_SELFARRAYLIST_HPP_
<commit_msg>Trivial modifications.<commit_after>#ifndef _MZ_SHARE_SELFARRAYLIST_HPP_
#define _MZ_SHARE_SELFARRAYLIST_HPP_

#include "Metazion/Share/ShareInclude.hpp"

DECL_NAMESPACE_MZ_SHARE_BEGIN

template<typename ValueType>
struct SelfArrayListNode {
    using Value_t = ValueType;

    Value_t m_value;
    int m_selfIndex = -1;
    int m_prevIndex = -1;
    int m_nextIndex = -1;
};

template<>
struct SelfArrayListNode<void> {
    int m_selfIndex = -1;
    int m_prevIndex = -1;
    int m_nextIndex = -1;
};

template<typename NodeType
, int INITSIZE
>
class SelfArrayList {
    using Node_t = NodeType;

    struct Entry {
        Node_t* m_node = nullptr;
        int m_freeNext = -1;
    };

public:
    SelfArrayList() {}

    ~SelfArrayList() {}

    SelfArrayList(const SelfArrayList& other) {
        *this = other;
    }

    SelfArrayList& operator =(const SelfArrayList& other) {
        if (&other != this) {
            for (auto index = 0; index < INITSIZE; ++index) {
                m_entries[index] = other.m_entries[index];
            }

            m_allocIndex = other.m_allocIndex;
            m_freeHead = other.m_freeHead;
            m_usedHead = other.m_usedHead;
            m_usedTail = other.m_usedTail;
            m_size = other.m_size;
        }
        return *this;
    }

    SelfArrayList(SelfArrayList&& other) {
        *this = std::move(other);
    }

    SelfArrayList& operator =(SelfArrayList&& other) {
        if (&other != this) {
            for (auto index = 0; index < INITSIZE; ++index) {
                m_entries[index] = other.m_entries[index];
            }

            m_allocIndex = other.m_allocIndex;
            m_freeHead = other.m_freeHead;
            m_usedHead = other.m_usedHead;
            m_usedTail = other.m_usedTail;
            m_size = other.m_size;
        }
        return *this;
    }

public:
    void Clear() {
        for (auto index = 0; index < INITSIZE; ++index) {
            m_entries[index] = {};
        }

        m_allocIndex = 0;
        m_freeHead = 0;
        m_usedHead = -1;
        m_usedTail = -1;
        m_size = 0;
    }

    bool IsEmpty() const {
        return -1 == m_usedHead;
    }

    int GetCapacity() const {
        return INITSIZE;
    }

    int GetSize() const {
        return m_size;
    }

    Node_t* Front() {
        if (IsInvalid(m_usedHead)) {
            return nullptr;
        }

        auto& entry = m_entries[m_usedHead];
        return entry.m_node;
    }

    const Node_t* Front() const {
        if (IsInvalid(m_usedHead)) {
            return nullptr;
        }

        auto& entry = m_entries[m_usedHead];
        return entry.m_node;
    }

    Node_t* Back() {
        if (IsInvalid(m_usedTail)) {
            return nullptr;
        }

        auto& entry = m_entries[m_usedHead];
        return entry.m_node;
    }

    const Node_t* Back() const {
        if (IsInvalid(m_usedTail)) {
            return nullptr;
        }

        auto& entry = m_entries[m_usedHead];
        return entry.m_node;
    }

    Node_t* PushFront(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(!IsContain(node));

        const auto index = NextFreeIndex();
        if (IsInvalid(index)) {
            return nullptr;
        }

        node->m_selfIndex = index;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        if (IsInvalid(m_usedHead)) {
            m_usedHead = node->m_selfIndex;
            m_usedTail = node->m_selfIndex;
        }
        else {
            Node(m_usedHead)->m_prevIndex = node->m_selfIndex;
            node->m_nextIndex = m_usedHead;
            m_usedHead = node->m_selfIndex;
        }

        m_entries[index].m_node = node;
        ++m_size;
        return node;
    }

    Node_t* PushBack(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(!IsContain(node));

        const auto index = NextFreeIndex();
        if (IsInvalid(index)) {
            return nullptr;
        }

        node->m_selfIndex = index;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        if (IsInvalid(m_usedTail)) {
            m_usedHead = node->m_selfIndex;
            m_usedTail = node->m_selfIndex;
        }
        else {
            node->m_prevIndex = m_usedTail;
            Node(m_usedTail)->m_nextIndex = node->m_selfIndex;
            m_usedTail = node->m_selfIndex;
        }

        m_entries[index].m_node = node;
        ++m_size;
        return node;
    }

    Node_t* PopFront() {
        if (IsInvalid(m_usedHead)) {
            return nullptr;
        }

        auto node = Node(m_usedHead);
        const auto index = node->m_selfIndex;

        m_usedHead = node->m_nextIndex;
        if (IsInvalid(m_usedHead)) {
            m_usedTail = -1;
        }
        else {
            Node(m_usedHead)->m_prevIndex = -1;
        }

        node->m_selfIndex = -1;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        BackFreeHead(index);

        m_entries[index].m_node = nullptr;
        --m_size;
        return node;
    }

    Node_t* PopBack() {
        if (IsInvalid(m_usedTail)) {
            return nullptr;
        }

        auto node = Node(m_usedTail);
        const auto index = node->m_selfIndex;

        m_usedTail = node->m_prevIndex;
        if (IsInvalid(m_usedTail)) {
            m_usedHead = -1;
        }
        else {
            Node(m_usedTail)->m_nextIndex = -1;
        }
        node->m_selfIndex = -1;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        BackFreeHead(index);

        m_entries[index].m_node = nullptr;
        --m_size;
        return node;
    }

    Node_t* InsertBefore(Node_t* location, Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(location));
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(IsContain(location));
        MZ_ASSERT_TRUE(!IsContain(node));

        const auto index = NextFreeIndex();
        if (IsInvalid(index)) {
            return nullptr;
        }

        node->m_selfIndex = index;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        auto prevIndex = location->m_prevIndex;
        if (IsInvalid(prevIndex)) {
            m_usedHead = node->m_selfIndex;
        }
        else {
            Node(prevIndex)->m_nextIndex = node->m_selfIndex;
        }
        location->m_prevIndex = node->m_selfIndex;
        node->m_prevIndex = prevIndex;
        node->m_nextIndex = location->m_selfIndex;

        m_entries[index].m_node = node;
        ++m_size;
        return node;
    }

    Node_t* InsertAfter(Node_t* location, Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(location));
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(IsContain(location));
        MZ_ASSERT_TRUE(!IsContain(node));

        const auto index = NextFreeIndex();
        if (IsInvalid(index)) {
            return nullptr;
        }

        node->m_selfIndex = index;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        auto nextIndex = location->m_nextIndex;
        if (IsInvalid(nextIndex)) {
            m_usedTail = node->m_selfIndex;
        }
        else {
            Node(nextIndex)->m_prevIndex = node->m_selfIndex;
        }
        location->m_nextIndex = node->m_selfIndex;
        node->m_prevIndex = location->m_selfIndex;
        node->m_nextIndex = nextIndex;

        m_entries[index].m_node = node;
        ++m_size;
        return node;
    }

    Node_t* Remove(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));
        MZ_ASSERT_TRUE(IsContain(node));

        const auto index = node->m_selfIndex;
        const auto prevIndex = node->m_prevIndex;
        const auto nextIndex = node->m_nextIndex;
        if (IsInvalid(prevIndex)) {
            MZ_ASSERT_TRUE(node->m_selfIndex == m_usedHead);
            m_usedHead = nextIndex;
        }
        else {
            Node(prevIndex)->m_nextIndex = nextIndex;
        }
        if (IsInvalid(nextIndex)) {
            MZ_ASSERT_TRUE(node->m_selfIndex == m_usedTail);
            m_usedTail = prevIndex;
        }
        else {
            Node(nextIndex)->m_prevIndex = prevIndex;
        }

        node->m_selfIndex = -1;
        node->m_prevIndex = -1;
        node->m_nextIndex = -1;

        BackFreeHead(index);

        m_entries[index].m_node = nullptr;
        --m_size;
        return Node(nextIndex);
    }

    Node_t* Backward(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));

        return Node(node->m_prevIndex);
    }

    const Node_t* Backward(const Node_t* node) const {
        MZ_ASSERT_TRUE(!IsNull(node));

        return Node(node->m_prevIndex);
    }

    Node_t* Forward(Node_t* node) {
        MZ_ASSERT_TRUE(!IsNull(node));

        return Node(node->m_nextIndex);
    }

    const Node_t* Forward(const Node_t* node) const {
        MZ_ASSERT_TRUE(!IsNull(node));

        return Node(node->m_nextIndex);
    }

    bool IsContain(Node_t* node) const {
        MZ_ASSERT_TRUE(!IsNull(node));

        auto cursor = Front();
        while (!IsNull(cursor)) {
            if (node == cursor) {
                return true;
            }
            cursor = Forward(cursor);
        }

        return false;
    }

private:
    int NextFreeIndex() {
        if (m_freeHead < 0) {
            return -1;
        }

        const auto index = m_freeHead;
        if (m_freeHead < m_allocIndex) {
            auto& entry = m_entries[m_freeHead];
            m_freeHead = entry.m_freeNext;
        }
        else {
            m_freeHead += 1;
            m_allocIndex = m_freeHead;
        }

        if (m_freeHead >= INITSIZE) {
            m_freeHead = -1;
        }

        return index;
    }

    int BackFreeHead(int index) {
        m_entries[index].m_freeNext = m_freeHead;
        m_freeHead = index;
        return m_freeHead;
    }

    Node_t* Node(int index) {
        if (IsInvalid(index)) {
            return nullptr;
        }

        return m_entries[index].m_node;
    }

    const Node_t* Node(int index) const {
        if (IsInvalid(index)) {
            return nullptr;
        }

        return m_entries[index].m_node;
    }

    bool IsInvalid(int index) const {
        return index < 0 || index >= INITSIZE;
    }

private:
    Entry m_entries[INITSIZE];
    int m_allocIndex = 0;
    int m_freeHead = 0;
    int m_usedHead = -1;
    int m_usedTail = -1;
    int m_size = 0;
};

DECL_NAMESPACE_MZ_SHARE_END

#endif // _MZ_SHARE_SELFARRAYLIST_HPP_
<|endoftext|>