#if !defined(HISTORYSTATS_GUARD_CONTACT_H) #define HISTORYSTATS_GUARD_CONTACT_H #include "_globals.h" #include "_consts.h" #include #include #include #include #include "inout.h" #include "settings.h" #include "message.h" #include "statistic.h" /* * Contact */ class Contact : private pattern::NotCopyable { private: ext::string m_Nick; ext::string m_Protocol; ext::string m_Group; InOut m_Bytes; InOut m_Messages; InOut m_Chats; bool m_bChatDurValid; DWORD m_ChatDurMin; DWORD m_ChatDurMax; DWORD m_ChatDurSum; bool m_bFirstLastTimeValid; DWORD m_FirstTime; DWORD m_LastTime; InOut m_Files; InOut m_Urls; int m_NumContacts; int m_NumSubcontacts; std::vector m_Slots; Statistic* m_pStatistic; private: void updateTime(DWORD msgTime); void updateChatDur(DWORD timeDelta); double getAvg(int nTotal) const; public: explicit Contact(Statistic* pStatistic, int nSlots, const ext::string& nick, const ext::string& protocol, const ext::string& group, int nContacts, int nSubcontacts); // basic contact info const ext::string& getNick() const { return m_Nick; } const ext::string& getProtocol() const { return m_Protocol; } const ext::string& getGroup() const { return m_Group; } // characters/messages/bytes (absolute) int getOutBytes() const { return m_Bytes.out; } int getInBytes() const { return m_Bytes.in; } int getTotalBytes() const { return m_Bytes.total(); } int getOutMessages() const { return m_Messages.out; } int getInMessages() const { return m_Messages.in; } int getTotalMessages() const { return m_Messages.total(); } int getOutChats() const { return m_Chats.out; } int getInChats() const { return m_Chats.in; } int getTotalChats() const { return m_Chats.total(); } // characters/messages/bytes (average) double getOutBytesAvg() const { return getAvg(m_Bytes.out); } double getInBytesAvg() const { return getAvg(m_Bytes.in); } double getTotalBytesAvg() const { return getAvg(m_Bytes.total()); } double getOutMessagesAvg() const { return getAvg(m_Messages.out); } double getInMessagesAvg() const { return getAvg(m_Messages.in); } double getTotalMessagesAvg() const { return getAvg(m_Messages.total()); } double getOutChatsAvg() const { return getAvg(m_Chats.out); } double getInChatsAvg() const { return getAvg(m_Chats.in); } double getTotalChatsAvg() const { return getAvg(m_Chats.total()); } // chat duration bool isChatDurValid() const { return m_bChatDurValid; } DWORD getChatDurMin() const { return m_ChatDurMin; } DWORD getChatDurAvg() const { return getTotalChats() ? m_ChatDurSum / getTotalChats() : 0; } DWORD getChatDurMax() const { return m_ChatDurMax; } int getChatDurMinForSort() const { return m_bChatDurValid ? getChatDurMin() : -1; } int getChatDurAvgForSort() const { return m_bChatDurValid ? getChatDurAvg() : -1; } int getChatDurMaxForSort() const { return m_bChatDurValid ? getChatDurMax() : -1; } DWORD getChatDurSum() const { return m_ChatDurSum; } // first/last time bool isFirstLastTimeValid() const { return m_bFirstLastTimeValid; } DWORD getFirstTime() const { return m_FirstTime; } DWORD getLastTime() const { return m_LastTime; } // files and URLs int getOutUrls() const { return m_Urls.out; } int getInUrls() const { return m_Urls.in; } int getTotalUrls() const { return m_Urls.total(); } int getOutFiles() const { return m_Files.out; } int getInFiles() const { return m_Files.in; } int getTotalFiles() const { return m_Files.total(); } // (sub)contact counts int getNumContacts() const { return m_NumContacts; } int getNumSubcontacts() const { return m_NumSubcontacts; } // stuff for reading history void beginMessages() { } void endMessages() { } void addMessage(Message& msg); void addChat(bool bOutgoing, DWORD localTimestampStarted, DWORD duration); void addEvent(WORD eventType, bool bOutgoing); void merge(const Contact& other); // slot stuff int countSlot() const { return m_Slots.size(); } const void* getSlot(int index) const { return m_Slots[index]; } void* getSlot(int index) { return m_Slots[index]; } void setSlot(int index, void* pData) { m_Slots[index] = pData; } }; /* * ContactCompareBase */ class ContactCompareBase { protected: bool m_bAsc; public: virtual bool cmp(const Contact& first, const Contact& second) { return m_bAsc; } void setDir(bool bAsc) { m_bAsc = bAsc; } explicit ContactCompareBase() : m_bAsc(true) { } }; /* * ContactCompare */ template class ContactCompare : public ContactCompareBase { private: T_ (Contact::*m_getData)() const; ContactCompareBase* m_pNextCmp; public: virtual bool cmp(const Contact& first, const Contact& second) { T_ firstVal = (first.*m_getData)(); T_ secondVal = (second.*m_getData)(); if (firstVal == secondVal) { return m_pNextCmp->cmp(first, second); } else { return (m_bAsc ? (firstVal < secondVal) : (firstVal > secondVal)); } } public: explicit ContactCompare(ContactCompareBase* pNextCmp, T_ (Contact::*getData)() const) : m_pNextCmp(pNextCmp) { m_getData = getData; } }; /* * ContactCompareStr */ class ContactCompareStr : public ContactCompareBase { private: const ext::string& (Contact::*m_getData)() const; ContactCompareBase* m_pNextCmp; public: virtual bool cmp(const Contact& first, const Contact& second) { const ext::string& firstVal = (first.*m_getData)(); const ext::string& secondVal = (second.*m_getData)(); // int cmpRes = ext::strfunc::icmp(firstVal.c_str(), secondVal.c_str()); int cmpRes = ext::strfunc::icoll(firstVal.c_str(), secondVal.c_str()); if (cmpRes == 0) { return m_pNextCmp->cmp(first, second); } else { return (m_bAsc ? (cmpRes < 0) : (cmpRes > 0)); } } public: explicit ContactCompareStr(ContactCompareBase* pNextCmp, const ext::string& (Contact::*getData)() const) : m_pNextCmp(pNextCmp) { m_getData = getData; } }; /* * ContactCompareOp */ class ContactCompareOp { private: ContactCompareBase* m_pCmp; public: bool operator ()(const Contact* first, const Contact* second) { return m_pCmp->cmp(*first, *second); } explicit ContactCompareOp(ContactCompareBase* pCmp) : m_pCmp(pCmp) { } }; #endif // HISTORYSTATS_GUARD_CONTACT_H