#include #include /////////////////////////////////////////////////////////// // DowJones /////////////////////////////////////////////////////////// class TDowJones : public TFile_cache { struct TExchangeData : public TObject { real _num; real _den; int _dec; int _dec_prices; public: const TExchangeData& operator=(const TExchangeData& d) { _num = d._num; _den = d._den; _dec = d._dec; _dec_prices = d._dec_prices; return d; } TExchangeData() : _num(1.0), _den(1.0), _dec(0), _dec_prices(0) { } }; TString16 _base_val, _firm_val; protected: virtual TObject* rec2obj(const TRectype& rec) const; virtual void flush(); void test_cache(); const TExchangeData& get(const char* key); public: const TString& get_base_val(); const TString& get_firm_val(); const char* expand_value(const char* val); real exchange(const real& num, const char* fromval, const real& fromchg, const char* toval, const real& tochg, bool price = FALSE); int get_dec(const char* val, bool prices = FALSE); TDowJones() : TFile_cache("%VAL") { } virtual ~TDowJones() { } } DowJones; TObject* TDowJones::rec2obj(const TRectype& rec) const { TExchangeData* data = new TExchangeData; data->_den = rec.get_real("I11"); if (data->_den > ZERO) { data->_num = rec.get_real("R11"); if (data->_num < 1.0) data->_num = 1.0; } else { data->_num = rec.get_real("I10"); if (data->_num < 1.0) data->_num = 1.0; data->_den = rec.get_real("R10"); data->_num = 1.0; } const bool invalid = rec.get("CODTAB").empty(); data->_dec = invalid ? 0 : rec.get_int("I0"); data->_dec_prices = invalid ? data->_dec : rec.get_int("I1"); if (data->_dec_prices < data->_dec) data->_dec_prices = data->_dec; if (data->_den <= ZERO) { NFCHECK("Codice valuta assente"); data->_den = 1.0; data->_num = 1.0; } return data; } void TDowJones::flush() { _base_val.cut(0); _firm_val.cut(0); } void TDowJones::test_cache() { if (_cache.items() == 0) { fill(); FOR_EACH_ASSOC_OBJECT(_cache, hash, key, obj) { const TExchangeData* data = (const TExchangeData*)obj; if (data->_num == 1.0 && data->_den == 1.0) { _base_val = key; break; } } if (_base_val.empty()) { _base_val = "LIT"; _cache.add(_base_val, new TExchangeData); } TConfig cfg(CONFIG_DITTA, "cg"); _firm_val = cfg.get("CodVal", NULL, -1, _base_val); } } const char* TDowJones::expand_value(const char* val) { if (val) { if (*val == '_') { if (stricmp(val, "_FIRM") == 0) val = get_firm_val(); else if (stricmp(val, "_BASE") == 0) val = ""; } } else val = ""; if (*val == '\0') val = get_base_val(); return val; } const TDowJones::TExchangeData& TDowJones::get(const char* val) { test_cache(); return (const TExchangeData&)query(expand_value(val)); } const TString& TDowJones::get_base_val() { test_cache(); return _base_val; } const TString& TDowJones::get_firm_val() { test_cache(); return _firm_val; } real TDowJones::exchange(const real& num, // Importo da convertire const char* fromval, // Dalla valuta const real& fromchg, // Dal cambio const char* toval, // Alla valuta const real& tochg, // Al cambio bool price) // e' un prezzo ? { real n = num; if (n != ZERO) { real fromden = fromchg; real fromnum = 1.0; real toden = tochg; real tonum = 1.0; if (fromden <= ZERO) { const TExchangeData& datafrom = get(fromval); fromden = datafrom._den; fromnum = datafrom._num; } const TExchangeData& datato = get(toval); if (toden <= ZERO) { toden = datato._den; tonum = datato._num; } n *= fromden * tonum; n /= fromnum * toden; n.round(price ? datato._dec_prices : datato._dec); } return n; } int TDowJones::get_dec(const char* val, bool price) { const TExchangeData& data = get(val); return price ? data._dec_prices : data._dec; } /////////////////////////////////////////////////////////// // TCurrency /////////////////////////////////////////////////////////// const TString& TCurrency::get_base_val() { return DowJones.get_base_val(); } const TString& TCurrency::get_firm_val() { return DowJones.get_firm_val(); } int TCurrency::get_base_dec(bool price) { return DowJones.get_dec(NULL, price); } int TCurrency::get_firm_dec(bool price) { return DowJones.get_dec("_FIRM", price); } void TCurrency::force_value(const char* newval, const real& newchange) { newval = DowJones.expand_value(newval); if (newval && *newval) { strncpy(_val, newval, 4); _val[3] = '\0'; _exchange = newchange; } else { *_val = '\0'; _exchange = ZERO; } } void TCurrency::change_value(const char* val, const real& newchange) { val = DowJones.expand_value(val); if (!_num.is_zero() && stricmp(_val, val) != 0) { _num = DowJones.exchange(_num, _val, _exchange, val, newchange, is_price()); } force_value(val, newchange); } int TCurrency::decimals() const { return DowJones.get_dec(_val, is_price()); } int TCurrency::compare(const TSortable& s) const { const TCurrency& cur = (const TCurrency&)s; if (same_value_as(cur)) { return _num == cur._num ? 0 : (_num > cur._num ? +1 : -1); } TCurrency curr(cur); curr.change_value(_val); return _num == curr._num ? 0 : (_num > curr._num ? +1 : -1); } void TCurrency::copy(const TCurrency& cur) { _num = cur._num; force_value(cur._val, cur._exchange); } const char* TCurrency::string(bool dotted) const { if (dotted) { TString16 picture; picture.format(".%d", decimals()); return _num.string(picture); } return _num.string(0, decimals()); } TCurrency& TCurrency::operator+=(const TCurrency& cur) { CHECK(is_price() == cur.is_price(), "Somma di pere e mele!"); if (same_value_as(cur)) { _num += cur._num; } else { real n = DowJones.exchange(cur._num, cur._val, cur._exchange, _val, _exchange, is_price()); _num += n; } return *this; } TCurrency TCurrency::operator+(const TCurrency& num) const { TCurrency cur(*this); cur += num; return cur; } TCurrency& TCurrency::operator-=(const TCurrency& cur) { CHECK(is_price() == cur.is_price(), "Sottrazione di pere e mele!"); if (same_value_as(cur)) _num -= cur._num; else { real n = DowJones.exchange(cur._num, cur._val, cur._exchange, _val, _exchange, is_price()); _num -= n; } return *this; } TCurrency& TCurrency::operator*=(const real& num) { _num *= num; // Arrotondo forzando price a FALSE _num.round(DowJones.get_dec(_val, _price = FALSE)); return *this; } TCurrency TCurrency::operator*(const real& num) const { TCurrency cur(*this); cur *= num; return cur; } bool TCurrency::is_base_value() const { return *_val == '\0' || get_base_val() == _val; } bool TCurrency::same_value_as(const TCurrency& cur) const { const int cmp = stricmp(_val, cur._val); if (cmp == 0) return TRUE; if (*_val == '\0' || *cur._val == '\0') return is_base_value() == cur.is_base_value(); return FALSE; } TCurrency::TCurrency(const real& num, const char* val, const real& exchg, bool price) : _num(num), _price(price) { force_value(val, exchg); }