/********************************************************************** * * FreeDoko a Doppelkopf-Game * * Copyright (C) 2001-2007 by Diether Knof and Borg Enders * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program 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 General Public License for more details. * You can find this license in the file 'gpl.txt'. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * Contact: * Diether Knof dknof@gmx.de * Borg Enders borg@borgsoft.de * **********************************************************************/ #include "card_counter.h" /** ** standard constructor ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.9 **/ CardCounter::CardCounter() : map(), cards_no_(0), cards_(), no_(Card::MAX_INT + 1, 0) { } /** ** copy constructor ** ** @param card_counter object to copy from ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.9 **/ CardCounter::CardCounter(CardCounter const& card_counter) : map(card_counter), cards_no_(card_counter.cards_no_), cards_(card_counter.cards_), no_(card_counter.no_) { } /** ** copy operator ** ** @param card_counter object to copy from ** ** @return object ** ** @author Diether Knof ** ** @version 0.6.9 **/ CardCounter& CardCounter::operator=(CardCounter const& card_counter) { static_cast& >(*this) = card_counter; this->cards_no_ = card_counter.cards_no_; this->cards_ = card_counter.cards_; this->no_ = card_counter.no_; return *this; } // CardCounter& CardCounter::operator=(CardCounter card_counter) /** ** destructor ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.9 **/ CardCounter::~CardCounter() { } /** ** clears all data ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.9 **/ void CardCounter::clear() { this->cards_.clear(); this->cards_no_ = 0; this->map::clear(); this->no_ = vector(Card::MAX_INT + 1, 0); return ; } // void CardCounter::clear() /** ** writes the data ('card = number') in 'ostr' ** ** @param ostr output stream to write the data to ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.9 **/ void CardCounter::write(ostream& ostr) const { ostr << "cardno = " << this->cards_no() << '\n'; for (CardCounter::const_iterator x = this->begin(); x != this->end(); ++x) { if (x->second) ostr << setw(14) << x->first << " = " << x->second << endl; } return ; } // void CardCounter::write(ostream& ostr) const /** ** -> result ** ** @param - ** ** @return the total number of cards ** ** @author Diether Knof ** ** @version 0.6.9 **/ unsigned CardCounter::cards_no() const { #ifdef DEBUG DEBUG_ASSERTION((this->cards_no_ == this->cards_.size()), "CardCounter::cards_no():\n" " 'this->cards_no_ = " << this->cards_no_ << " != " << this->cards_.size() << " = this->cards_.size()"); unsigned n = 0; for (CardCounter::const_iterator x = this->begin(); x != this->end(); ++x) n += x->second; DEBUG_ASSERTION((this->cards_no_ == n), "CardCounter::cards_no():\n" " 'this->cards_no_ = " << this->cards_no_ << " != " << n << " = Sum"); #endif return this->cards_no_; } // unsigned CardCounter::cards_no() const /** ** -> result ** ** @param card card to return the number of ** ** @return the number for 'card' ** ** @author Diether Knof ** ** @version 0.6.9 **/ unsigned CardCounter::operator[](Card const& card) const { return this->no_[card.to_int()]; #ifdef OUTDATED // 0.7.4 DK // because of performace (~15% better whit 'this->no_') CardCounter::const_iterator const x = this->find(card); if (x == this->end()) return 0; return x->second; #endif } // unsigned CardCounter::operator[](Card card) const /** ** set the counter of 'card' to exactly 'n' ** ** @param card card to set the number of ** @param n new number for 'card' ** ** @return whether something has changed ** ** @author Diether Knof ** ** @version 0.6.9 **/ bool CardCounter::set(Card const& card, unsigned const n) { unsigned const m = (*this)[card]; if (n > m) return this->min_set(card, n); else if (m < n) return this->max_set(card, n); return false; } // bool CardCounter::set(Card const& card, unsigned const n) /** ** set the counter of 'card' to minmal 'n' ** ** @param card card to set the number of ** @param n minimal number for 'card' ** ** @return whether something has changed ** ** @author Diether Knof ** ** @version 0.6.9 **/ bool CardCounter::min_set(Card const& card, unsigned const n) { if (n == 0) return false; unsigned const t = (*this)[card]; if (t >= n) return false; // add the card to the vector this->cards_.insert(this->cards_.end(), (n - t), card); // set the number this->map::operator[](card) = n; this->no_[card.to_int()] = n; // adjust the total cards number this->cards_no_ += (n - t); return true; } // bool CardCounter::min_set(Card const& card, unsigned const n) /** ** set the counter of 'card' to maximal 'n' ** ** @param card card to set the number of ** @param n maximal number for 'card' ** ** @return whether something has changed ** ** @author Diether Knof ** ** @version 0.6.9 **/ bool CardCounter::max_set(Card const& card, unsigned const n) { unsigned const t = (*this)[card]; if (t <= n) return false; { // remove the cards from the list list::iterator i = std::find(this->cards_.begin(), this->cards_.end(), card); for (unsigned a = 0; a < t - n; ++a) { i = this->cards_.erase(i); i = std::find(i, this->cards_.end(), card); } // for (a < t - n) } // remove the cards from the list // set the number if (n == 0) { this->map::erase(card); } else { // if !(n == 0) this->map::operator[](card) = n; } // if !(n == 0) this->no_[card.to_int()] = n; // adjust the total cards number this->cards_no_ -= t - n; return true; } // bool CardCounter::max_set(Card const& card, unsigned const n) /** ** erases the counter of 'card' ** ** @param card card to erase ** ** @return whether something has changed ** ** @author Diether Knof ** ** @version 0.6.9 **/ bool CardCounter::erase(Card const& card) { return this->max_set(card, 0); } // bool CardCounter::erase(Card const& card) /** ** increments the counter of 'card' ** ** @param card card to increment ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.9 **/ void CardCounter::inc(Card const& card) { this->map::operator[](card) += 1; this->cards_.push_back(card); this->cards_no_ += 1; this->no_[card.to_int()] += 1; return ; } // void CardCounter::inc(Card const& card) /** ** decrements the counter of 'card' ** ** @param card card to decrements ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.9 **/ void CardCounter::dec(Card const& card) { map::iterator x = this->find(card); DEBUG_ASSERTION((x != this->end()) && x->second, "CardCounter::dec(" << card << "):\n" " the counter is '0'"); x->second -= 1; if (x->second == 0) this->map::erase(x); this->no_[card.to_int()] -= 1; this->cards_.erase(std::find(this->cards_.begin(), this->cards_.end(), card)); this->cards_no_ -= 1; return ; } // void CardCounter::dec(Card const& card) /** ** writes the card counter in 'ostr' ** ** @param ostr output stream to write into ** @param card_counter object to write ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.6.9 **/ ostream& operator<<(ostream& ostr, CardCounter const& card_counter) { card_counter.write(ostr); return ostr; } // ostream& operator<<(ostream& ostr, CardCounter const& card_counter) /** ** -> result ** ** @param card_counter_a first object ** @param card_counter_b second object ** ** @return whether the two objects are equal ** ** @author Diether Knof ** ** @version 0.6.9 **/ bool operator==(CardCounter const& card_counter_a, CardCounter const& card_counter_b) { return (static_cast const&>(card_counter_a) == static_cast const&>(card_counter_b)); } // bool operator==(CardCounter card_counter_a, CardCounter card_counter_b) /** ** -> result ** ** @param card_counter_a first object ** @param card_counter_b second object ** ** @return whether the two objects differ ** ** @author Diether Knof ** ** @version 0.6.9 **/ bool operator!=(CardCounter const& card_counter_a, CardCounter const& card_counter_b) { return (static_cast const&>(card_counter_a) != static_cast const&>(card_counter_b)); } // bool operator!=(CardCounter card_counter_a, CardCounter card_counter_b)