summaryrefslogtreecommitdiff
path: root/plugins/Quotes/QuotesProviderGoogleFinance.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Quotes/QuotesProviderGoogleFinance.cpp')
-rw-r--r--plugins/Quotes/QuotesProviderGoogleFinance.cpp366
1 files changed, 366 insertions, 0 deletions
diff --git a/plugins/Quotes/QuotesProviderGoogleFinance.cpp b/plugins/Quotes/QuotesProviderGoogleFinance.cpp
new file mode 100644
index 0000000000..25b49f4120
--- /dev/null
+++ b/plugins/Quotes/QuotesProviderGoogleFinance.cpp
@@ -0,0 +1,366 @@
+#include "StdAfx.h"
+#include "QuotesProviderGoogleFinance.h"
+#include "QuotesProviderVisitor.h"
+#include "EconomicRateInfo.h"
+#include "DBUtils.h"
+#include "resource.h"
+#include "ModuleInfo.h"
+// #include "QuotesProviders.h"
+// #include "CommonOptionDlg.h"
+// #include "WinCtrlHelper.h"
+#include "IHTMLParser.h"
+#include "IHTMLEngine.h"
+#include "HTTPSession.h"
+#include "Log.h"
+#include "Locale.h"
+
+CQuotesProviderGoogleFinance::CQuotesProviderGoogleFinance()
+{
+}
+
+CQuotesProviderGoogleFinance::~CQuotesProviderGoogleFinance()
+{
+}
+
+namespace
+{
+ tstring build_url(HANDLE hContact,const tstring& rsURL)
+ {
+ tostringstream o;
+ o << rsURL << _T("?q=") << Quotes_DBGetStringT(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_ID);
+ return o.str();
+ }
+
+ struct CGoogleInfo
+ {
+ enum
+ {
+ giRate = 0x0001,
+ giOpen = 0x0002,
+ giPercentChangeAfterHours = 0x0004,
+ giPercentChangeToYesterdayClose = 0x0008
+ };
+ CGoogleInfo()
+ : m_dRate(0.0),m_dOpenValue(0.0),m_dPercentChangeAfterHours(0.0),m_dPercentChangeToYersterdayClose(0.0),m_nFlags(0){}
+// tstring m_sCmpID;
+ tstring m_sCmpName;
+ double m_dRate;
+ double m_dOpenValue;
+ double m_dPercentChangeAfterHours;
+ double m_dPercentChangeToYersterdayClose;
+
+// tstring m_sRateID;
+// tstring m_sDiffID;
+ byte m_nFlags;
+ };
+
+ tstring make_rate_id_value(const tstring& rsCmpID,int nFlags)
+ {
+ tostringstream o;
+ o << _T("ref_") << rsCmpID;
+ switch(nFlags)
+ {
+ default:
+ assert(!"Unknown type of value");
+ case CGoogleInfo::giRate:
+ o << _T("_l");
+ break;
+ case CGoogleInfo::giPercentChangeAfterHours:
+ o << _T("_ecp");
+ break;
+ case CGoogleInfo::giPercentChangeToYesterdayClose:
+ o << _T("_cp");
+ break;
+ }
+
+ return o.str();
+ }
+
+ tstring get_var_value(const tstring& rsHTML,LPCTSTR pszVarName,size_t cVarNameLength)
+ {
+ tstring sResult;
+ tstring::size_type n = rsHTML.find(pszVarName);
+ if(tstring::npos != n)
+ {
+ size_t cLengthHTML = rsHTML.size();
+ for(size_t i = n + cVarNameLength;i < cLengthHTML;++i)
+ {
+ TCHAR c = rsHTML[i];
+ if(_T(';') == c)
+ {
+ break;
+ }
+ else
+ {
+ sResult.push_back(c);
+ }
+ }
+ }
+
+ return sResult;
+ }
+
+ tstring get_company_id(const tstring& rsHTML)
+ {
+ static LPCTSTR pszVarName = _T("setCompanyId(");
+ static size_t cVarNameLength = _tcslen(pszVarName);
+
+ tstring sResult;
+ tstring::size_type n = rsHTML.find(pszVarName);
+ if(tstring::npos != n)
+ {
+ size_t cLengthHTML = rsHTML.size();
+ for(size_t i = n + cVarNameLength;i < cLengthHTML;++i)
+ {
+ TCHAR c = rsHTML[i];
+ if(_T(')') == c)
+ {
+ break;
+ }
+ else
+ {
+ sResult.push_back(c);
+ }
+ }
+ }
+ return sResult;
+// return get_var_value(rsHTML,pszVarName,cVarNameLength);
+ }
+
+ tstring get_company_name(const tstring& rsHTML)
+ {
+ static LPCTSTR pszVarName = _T("var _companyName = ");
+ static size_t cVarNameLength = _tcslen(pszVarName);
+
+ tstring s = get_var_value(rsHTML,pszVarName,cVarNameLength);
+ if(s.size() > 0 && _T('\'') == s[0])
+ {
+ s.erase(s.begin());
+ }
+
+ if(s.size() > 0 && _T('\'') == s[s.size()-1])
+ {
+ s.erase(s.rbegin().base()-1);
+ }
+
+ return s;
+ }
+
+ bool get_double_value(const tstring& rsText,double& rdValue)
+ {
+ tistringstream input(rsText);
+ input.imbue(std::locale("English_United States.1252"));
+ input >> rdValue;
+
+ if((true == input.bad()) || (true == input.fail()))
+ {
+ tistringstream inputSys(rsText);
+ input.imbue(GetSystemLocale());
+ input >> rdValue;
+ return (false == inputSys.bad()) && (false == inputSys.fail());
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ bool get_rate(const IHTMLNode::THTMLNodePtr& pRate,CGoogleInfo& rInfo)
+ {
+ tstring sRate = pRate->GetText();
+
+ if(true == get_double_value(sRate,rInfo.m_dRate))
+ {
+ rInfo.m_nFlags |= CGoogleInfo::giRate;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool get_inline_data(const IHTMLNode::THTMLNodePtr& pNode,CGoogleInfo& rInfo)
+ {
+ size_t cChild = pNode->GetChildCount();
+ for(size_t i = 0;i < cChild;++i)
+ {
+ IHTMLNode::THTMLNodePtr pChild = pNode->GetChildPtr(i);
+ size_t c = pChild->GetChildCount();
+ assert(2 == c);
+ if(c >= 2)
+ {
+ IHTMLNode::THTMLNodePtr pName = pChild->GetChildPtr(0);
+
+ tstring sName = pName->GetText();
+ if(0 == quotes_stricmp(sName.c_str(),_T("Open")))
+ {
+ IHTMLNode::THTMLNodePtr pValue = pChild->GetChildPtr(1);
+ tstring sValue = pValue->GetText();
+ if(true == get_double_value(sValue,rInfo.m_dOpenValue))
+ {
+ rInfo.m_nFlags |= CGoogleInfo::giOpen;
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ bool get_dif_value(const IHTMLNode::THTMLNodePtr& pNode,CGoogleInfo& rInfo,int nItem)
+ {
+ tstring sDiff = pNode->GetText();
+ // this value is in brackets and it has percentage sign.
+ // Remove these symbols.
+ for(tstring::iterator i = sDiff.begin();i != sDiff.end();)
+ {
+ TCHAR s = *i;
+ if(_T('(') == s || _T(')') == s || _T('%') == s)
+ {
+ i = sDiff.erase(i);
+ }
+ else
+ {
+ ++i;
+ }
+ }
+
+ double* pValue = NULL;
+ switch(nItem)
+ {
+ case CGoogleInfo::giPercentChangeAfterHours:
+ pValue = &rInfo.m_dPercentChangeAfterHours;
+ break;
+ case CGoogleInfo::giPercentChangeToYesterdayClose:
+ pValue = &rInfo.m_dPercentChangeToYersterdayClose;
+ break;
+ }
+
+ assert(pValue);
+
+ if((pValue) && (true == get_double_value(sDiff,*pValue)))
+ {
+ rInfo.m_nFlags |= nItem;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+
+ bool parse_responce(const tstring& rsHTML,CGoogleInfo& rInfo)
+ {
+ IHTMLEngine::THTMLParserPtr pHTMLParser = CModuleInfo::GetHTMLEngine()->GetParserPtr();
+ IHTMLNode::THTMLNodePtr pRoot = pHTMLParser->ParseString(rsHTML);
+ if(pRoot)
+ {
+ tstring sCmpID = get_company_id(rsHTML);
+ if(false == sCmpID.empty())
+ {
+ tstring sRateID = make_rate_id_value(sCmpID,CGoogleInfo::giRate);
+ IHTMLNode::THTMLNodePtr pRate = pRoot->GetElementByID(sRateID);
+ if(pRate && get_rate(pRate,rInfo))
+ {
+ rInfo.m_sCmpName = get_company_name(rsHTML);
+
+ IHTMLNode::THTMLNodePtr pInline = pRoot->GetElementByID(_T("snap-data"));
+ if(pInline)
+ {
+ get_inline_data(pInline,rInfo);
+ }
+
+ tstring sDiffID = make_rate_id_value(sCmpID,CGoogleInfo::giPercentChangeAfterHours);
+ IHTMLNode::THTMLNodePtr pDiff = pRoot->GetElementByID(sDiffID);
+ if(pDiff)
+ {
+ get_dif_value(pDiff,rInfo,CGoogleInfo::giPercentChangeAfterHours);
+ }
+
+ sDiffID = make_rate_id_value(sCmpID,CGoogleInfo::giPercentChangeToYesterdayClose);
+ pDiff = pRoot->GetElementByID(sDiffID);
+ if(pDiff)
+ {
+ get_dif_value(pDiff,rInfo,CGoogleInfo::giPercentChangeToYesterdayClose);
+ }
+
+ return true;
+ }
+
+ //return (true == parse_html_node(pRoot,rInfo));
+ }
+ }
+
+ return false;
+ }
+}
+
+void CQuotesProviderGoogleFinance::RefreshQuotes(TContracts& anContacts)
+{
+ CHTTPSession http;
+ tstring sURL = GetURL();
+ bool bUseExtendedStatus = CModuleInfo::GetInstance().GetExtendedStatusFlag();
+
+ for(TContracts::const_iterator i = anContacts.begin();i != anContacts.end() && IsOnline();++i)
+ {
+ HANDLE hContact = *i;
+
+ if(bUseExtendedStatus)
+ {
+ SetContactStatus(hContact,ID_STATUS_OCCUPIED);
+ }
+
+ tstring sFullURL = build_url(hContact,sURL);
+// LogIt(Info,sFullURL);
+ if((true == http.OpenURL(sFullURL)) && (true == IsOnline()))
+ {
+ tstring sHTML;
+ if((true == http.ReadResponce(sHTML)) && (true == IsOnline()))
+ {
+// LogIt(Info,sHTML);
+
+ CGoogleInfo Info;
+ parse_responce(sHTML,Info);
+ if(true == IsOnline())
+ {
+ if(Info.m_nFlags&CGoogleInfo::giRate)
+ {
+ if(Info.m_nFlags&CGoogleInfo::giOpen)
+ {
+ Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_OPEN_VALUE,Info.m_dOpenValue);
+ }
+ if(Info.m_nFlags&CGoogleInfo::giPercentChangeAfterHours)
+ {
+ Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_DIFF,Info.m_dPercentChangeAfterHours);
+ }
+ if(Info.m_nFlags&CGoogleInfo::giPercentChangeToYesterdayClose)
+ {
+ Quotes_DBWriteDouble(hContact,QUOTES_MODULE_NAME,DB_STR_GOOGLE_FINANCE_PERCENT_CHANGE_TO_YERSTERDAY_CLOSE,Info.m_dPercentChangeToYersterdayClose);
+ }
+ if(false == Info.m_sCmpName.empty())
+ {
+ DBWriteContactSettingTString(hContact,QUOTES_MODULE_NAME,DB_STR_QUOTE_DESCRIPTION,Info.m_sCmpName.c_str());
+ }
+
+ WriteContactRate(hContact,Info.m_dRate);
+ continue;
+ }
+ }
+ }
+ }
+
+ SetContactStatus(hContact,ID_STATUS_NA);
+ }
+
+}
+
+
+void CQuotesProviderGoogleFinance::Accept(CQuotesProviderVisitor& visitor)const
+{
+ CQuotesProviderFinance::Accept(visitor);
+ visitor.Visit(*this);
+}
+