#include "Bag.h" #include "../Pieces/Piece.h" #include "PiecesList.h" #include #include #include static const double SMALLEST_CONSIDERED_PROPORTION = 0.01; // the smallest a proportion can get before it is considered equal to 0 Bag::Bag(const std::shared_ptr& piecesList) : piecesList(piecesList) { this->highestSize = this->piecesList->getHighestLoadedSize(); this->selectedPieces = this->piecesList->getSelectedPieces(); this->distributionMode = this->piecesList->getDistributionMode(); this->propotionsPerSize = this->piecesList->getProportionsPerSize(); this->currentBags.clear(); this->nextBags.clear(); this->sizesBag.clear(); this->sizesProgression.clear(); if (this->distributionMode == DEFAULT) { this->currentBags.push_back(this->selectedPieces); this->nextBags.push_back({}); } else { for (int i = 0; i <= this->highestSize; i++) { this->currentBags.push_back(PieceBag()); this->nextBags.push_back(PieceBag()); this->sizesProgression.push_back(0); } for (const auto& piece : this->selectedPieces) { int pieceSize = this->piecesList->lookAtPiece(piece).getPositions().size(); this->currentBags.at(pieceSize).push_back(piece); } } this->prepareNext(); } void Bag::jumpToNextBag() { for (int i = 0; i < this->currentBags.size(); i++) { if (this->currentBags.at(i).size() < this->nextBags.at(i).size()) { std::swap(this->currentBags.at(i), this->nextBags.at(i)); } for (const auto& piece : this->nextBags.at(i)) { this->currentBags.at(i).push_back(piece); } this->nextBags.at(i).clear(); } this->prepareNext(); } Piece Bag::lookNext() { return this->piecesList->getPiece(this->next); } Piece Bag::getNext() { std::pair nextIndex = this->next; this->prepareNext(); return this->piecesList->getPiece(nextIndex); } void Bag::prepareNext() { if (this->distributionMode == DEFAULT) { this->getNextPieceFromBag(0); } else { if (this->sizesBag.empty()) { for (int i = 0; i <= this->highestSize; i++) { if (this->propotionsPerSize.at(i) >= SMALLEST_CONSIDERED_PROPORTION && !(this->currentBags.at(i).empty() && this->nextBags.at(i).empty())) { while (this->sizesProgression.at(i) < 1) { this->sizesBag.push_back(i); this->sizesProgression.at(i) += this->propotionsPerSize.at(i); } this->sizesProgression.at(i) -= 1; } } } int nextSizeIndex = std::rand() % this->sizesBag.size(); int nextSize = this->sizesBag.at(nextSizeIndex); this->sizesBag.erase(this->sizesBag.begin() + nextSizeIndex); this->getNextPieceFromBag(nextSize); } } void Bag::getNextPieceFromBag(int bagIndex) { if (this->currentBags.at(bagIndex).empty()) { std::swap(this->currentBags.at(bagIndex), this->nextBags.at(bagIndex)); } int indexIndex = std::rand() % this->currentBags.at(bagIndex).size(); this->next = this->currentBags.at(bagIndex).at(indexIndex); this->nextBags.at(bagIndex).push_back(this->next); this->currentBags.at(bagIndex).erase(this->currentBags.at(bagIndex).begin() + indexIndex); }