diff --git a/GOLAppLib/lib/x64/Debug/GOLAppLib.lib b/GOLAppLib/lib/x64/Debug/GOLAppLib.lib deleted file mode 100644 index c89ee75..0000000 Binary files a/GOLAppLib/lib/x64/Debug/GOLAppLib.lib and /dev/null differ diff --git a/GOLAppLib/lib/x64/Debug/GOLAppLib.pdb b/GOLAppLib/lib/x64/Debug/GOLAppLib.pdb deleted file mode 100644 index 529e667..0000000 Binary files a/GOLAppLib/lib/x64/Debug/GOLAppLib.pdb and /dev/null differ diff --git a/GOLAppLib/lib/x64/Debug/GOLEngine.idb b/GOLAppLib/lib/x64/Debug/GOLEngine.idb deleted file mode 100644 index 0cbe801..0000000 Binary files a/GOLAppLib/lib/x64/Debug/GOLEngine.idb and /dev/null differ diff --git a/GOLAppLib/lib/x64/Debug/GOLEngine.lib b/GOLAppLib/lib/x64/Debug/GOLEngine.lib deleted file mode 100644 index e955159..0000000 Binary files a/GOLAppLib/lib/x64/Debug/GOLEngine.lib and /dev/null differ diff --git a/GOLAppLib/lib/x64/Debug/GOLEngine.pdb b/GOLAppLib/lib/x64/Debug/GOLEngine.pdb deleted file mode 100644 index 451e5ce..0000000 Binary files a/GOLAppLib/lib/x64/Debug/GOLEngine.pdb and /dev/null differ diff --git a/GOLAppLib/lib/x64/Release/GOLAppLib.lib b/GOLAppLib/lib/x64/Release/GOLAppLib.lib deleted file mode 100644 index 28d0ee9..0000000 Binary files a/GOLAppLib/lib/x64/Release/GOLAppLib.lib and /dev/null differ diff --git a/GOLAppLib/lib/x64/Release/GOLEngine.lib b/GOLAppLib/lib/x64/Release/GOLEngine.lib deleted file mode 100644 index 398c452..0000000 Binary files a/GOLAppLib/lib/x64/Release/GOLEngine.lib and /dev/null differ diff --git a/GOLAppLib/lib/x64/Release/GOLEngine.pdb b/GOLAppLib/lib/x64/Release/GOLEngine.pdb deleted file mode 100644 index c875605..0000000 Binary files a/GOLAppLib/lib/x64/Release/GOLEngine.pdb and /dev/null differ diff --git a/GPA675Lab1GOL/GOLTeamH.cpp b/GPA675Lab1GOL/GOLTeamH.cpp index 0c5f456..34f4e52 100644 --- a/GPA675Lab1GOL/GOLTeamH.cpp +++ b/GPA675Lab1GOL/GOLTeamH.cpp @@ -1,41 +1,112 @@ #include "GOLTeamH.h" + + + + +//! \brief Accesseur retournant la largeur de la grille de simualtion. + //! + //! \return La largeur de la grille. + //! size_t GOLTeamH::width() const { return mData.width(); } + + +//! \brief Accesseur retournant la hauteur de la grille de simualtion. + //! + //! \return La hauteur de la grille. + //! size_t GOLTeamH::height() const { return mData.height(); } +//! \brief Accesseur retournant le nombre total de cellules de la grille + //! de simualtion. + //! + //! \return Le nombre total de cellules de la grille. size_t GOLTeamH::size() const { return mData.size(); } +//! \brief Accesseur retournant l'état d'une cellule. + //! + //! \details Cette fonction ne valide pas les entrées pour une raison de + //! performance. + //! L'origine est le coin supérieur gauche de la grille. + //! + //! \param x La coordonnée en x de la cellule. + //! \param y La coordonnée en y de la cellule. + //! \return L'état de la cellule. GOL::State GOLTeamH::state(int x, int y) const { return mData.value(x, y); } +//! \brief Accesseur retournant la chaîne de caractères correspondant à + //! la règle courante. + //! + //! \details La chaîne de caractères est de la forme "B###/S###". + //! + //! \return La chaîne de caractères correspondant à la règle courante selon + //! le format `B###.../S###...`. + std::string GOLTeamH::rule() const { return mRule.value_or(std::move(std::string())); } +//! \brief Accesseur retournant la stratégie courante de gestion des bords. + //! + //! \return La stratégie courante de gestion des bords. GOL::BorderManagement GOLTeamH::borderManagement() const { return mBorderManagement.value_or(GOL::BorderManagement::immutableAsIs); } +//! \brief Accesseur retournant la couleur d'un état. + //! + //! \details Cette fonction retourne la couleur associée à l'état passé + //! en argument. + //! + //! \param state L'état dont on veut connaître la couleur. + //! \return La couleur associée à l'état. GOL::Color GOLTeamH::color(State state) const { return state == GOL::State::alive ? mAliveColor : mDeadColor; } -// TODO +//! \brief Accesseurs retournant des informations générales sur la + //! simulation en cours. + //! + //! \details Retourne plusieurs informations sur la simulation. Chaque + //! valeur est optionnelle et peut être indéterminée. + //! + //! Voir la documentation liée à la structure Statistics pour plus de détails. + //! + //! Toutefois, les tendances sont définies ainsi : + //! - La tendance indique la variation entre le nombre de cellules mortes + //! et vivantes en valeur absolue et relative. + //! - Une tendance est à la hausse s'il y a plus de cellules naissantes + //! que mourantes. + //! - Un premier caractères indique si la tendance est à la hausse (+) ou + //! à la baisse (-). + //! - La tendance doit se faire sur un certain nombre d'itérations. Ce + //! nombre est défini par l'implémentation mais doit être supérieur à 10 + //! itérations. L'objectif est d'avoir une lecture relativement stable de + //! la tendance afin qu'elle soit agréable à lire dans l'interface usager. + //! - Optionnellement, vous pouvez ajouter un second caractère indiquant + //! la stabilité de la tendance. Voici la légende : + //! - '-' : stable + //! - '~' : légèrement instable + //! - 'w' : instable + //! - 'W' : très instable + //! + //! \return Une structure contenant les informations sur la simulation. GOL::Statistics GOLTeamH::statistics() const { return std::move(GOL::Statistics{ @@ -54,22 +125,96 @@ GOL::Statistics GOLTeamH::statistics() const }); } -// TODO +//! \brief Accesseurs retournant les informations sur la réalisation + //! de l'implémentation. + //! + //! \details Retourne plusieurs informations sur la réalisation de + //! l'implémentation. Chaque valeur est optionnelle et peut être + //! indéterminée. + //! + //! En quelque sorte, c'est l'approche utilisée pour produire un mini + //! rapport utilitaire. + //! + //! Voir la documentation liée à la structure ImplementationInformation + //! pour plus de détails. + //! + //! Pour les réponses 'answers', l'objectif est d'utiliser clairement le + //! vocabulaire technique approprié tout en étant très concis et très précis. + //! + //! \return Une structure contenant les informations sur la réalisation + //! GOL::ImplementationInformation GOLTeamH::information() const { return std::move(ImplementationInformation{ .title{"Laboratoire 1"}, - .authors{{"Timothée Leclaire-Fournier"}, {"Martin Euzenat"} } + .authors{{"Timothée Leclaire-Fournier"}, {"Martin Euzenat martin.euzenat.1@ens.etsmtl.ca"}}, + .answers{}, + .optionnalComments{} // Réponses aux questions... }); } + +//! \brief Mutateur modifiant la taille de la grille de simulation. +//! +//! \details Cette fonction réinitialise la taille et le contenu de la +//! grille. La taille est spécifié peut être 0 x 0. Le contenu de la +//! grille est entièrement mis à l'état passé en argument. +//! +//! Cette fonction s'assure que si l'une des dimensions est 0, alors les +//! deux sont mises à 0. +//! +//! L'ancient motif de la grille est perdu. L'itération courante est remise +//! à 0. +//! +//! \param width La nouvelle largeur de la grille. +//! \param height La nouvelle hauteur de la grille. +//! \param defaultState L'état d'initialisation des cellules. +//! void GOLTeamH::resize(size_t width, size_t height, State defaultState) { mData.resize(width, height, defaultState); } -// La performance n'est pas tant recherchée puisque cette fonction est appelée très rarement +//! \brief Mutateur modifiant la règle de la simulation. + //! + //! \details Cette fonction s'assure que la chaîne de caractères est valide + //! et assigne la nouvelle règle pour que les prochaines évolutions + //! l'utilisent. + //! + //! Si la règle est valide, on assigne la novuelle règle, l'ancienne règle + //! est perdue et l'itération courante est remise à 0. Si la règle est + //! invalide, on ne fait rien. + //! + //! La simulation doit être en mesure de supporté les règles valides. + //! + //! Les règles sont définies par une chaîne de caractère suivant ce format: + //! `B###.../S###...`, par exemple : `B3/S23`. + //! - La lettre `B` (minuscule ou majuscule) débute la section 'B'orn + //! concernant les états morts qui naissent + //! - Suit une série de _n_ caractères pouvant contenir une instance de + //! chacun de ces caractères : '0', '1', '2', '3', '4', '5', '6', '7', '8'. + //! La valeur de _n_ peut varier de 0 à 9. Cette séquence indique toutes + //! les combinaisons du nombre de cellules voisines vivantes qui font + //! naître une cellule morte. + //! - Le caractère barre oblique `/` (_slash_) qui indique la transition + //! vers la section suivante. + //! - La lettre `S` (minuscule ou majuscule) débute la section 'S'urvive + //! concernant les états vivants qui survivent (qui restent vivantes). + //! - Suit une série de _n_ caractères pouvant contenir une instance de + //! chacun de ces caractères : '0', '1', '2', '3', '4', '5', '6', '7', '8'. + //! La valeur de _n_ peut varier de 0 à 9. Cette séquence indique toutes + //! les combinaisons du nombre de cellules voisines vivantes qui font + //! naître une cellule morte. + //! + //! Par exemple : `B02/S1357` indique que : + //! - si une cellule est morte : + //! - elle naît se elle possède 0 ou 2 voisins vivants + //! - si la cellule est vivante : + //! - elle survie si elle possède 1, 3, 5 ou 7 voisins vivants + //! + //! La règle de Conway `B3/S23` est celle par défaut. + bool GOLTeamH::setRule(std::string const& rule) { mRule = rule; @@ -117,150 +262,221 @@ bool GOLTeamH::setRule(std::string const& rule) return false; } -void GOLTeamH::setBorderManagement(GOL::BorderManagement borderManagement) +//! \brief Mutateur modifiant la stratégie de gestion de bord. + //! + //! \details Cette fonction assigne la nouvelle stratégie pour que les + //! prochaines évolutions l'utilisent. + //! + //! L'ancienne stratégie est perdue. L'itération courante est remise à 0. + //! + //! Vous devez être en mesure de gérer les effets de bord selon 5 + //! stratégies différentes : + //! - BorderManagement::immutableAsIs : immuable tel quel. Les cellules + //! du contour ne sont jamais modifiées. + //! - BorderManagement::foreverDead : mort pour toujours. Les cellules + //! du contour ne sont jamais modifiées, elles sont toujours mortes. + //! - BorderManagement::foreverAlive : vivant pour toujours. Les cellules + //! du contour ne sont jamais modifiées, elles sont toujours vivantes. + //! - BorderManagement::warping : téléportation. Les cellules du contour + //! sont évaluées. On utilise les cellules du côté opposé de la grille + //! pour les cellules extérieures. + //! - BorderManagement::mirror : miroir. Les cellules du contour sont + //! évaluées. On utilise les cellules du côté opposé de la cellule pour + //! les cellules extérieures. + //! + //! Pour les 2 exemples suivants, la cellule analysée `-*-` possède 3 + //! voisins situés à l'extérieur de la grille 'x', 'y' et 'z'. Ces cellules + //! sont substituées par les voisins opposés 'X', 'Y' et 'Z'. + //! + //! BorderManagement::warping utilise les voisins opposés par rapport à la + //! **grille**. +void GOLTeamH::setBorderManagement(BorderManagement borderManagement) { - mBorderManagement = borderManagement; - mIteration = 0; - - switch (borderManagement) { - case GOL::BorderManagement::foreverDead: - mData.fillBorder(GridTeamH::CellType::dead); - break; - case GOL::BorderManagement::foreverAlive: - mData.fillBorder(GridTeamH::CellType::alive); - break; - case GOL::BorderManagement::warping: - mData.fillBorderWarped(); - break; - case GOL::BorderManagement::mirror: - mData.fillBorderWarped(); - break; - } + mBorderManagement = borderManagement; } + +//! \brief Mutateur modifiant l'état d'une cellule de la grille. + //! + //! \details Cette fonction ne valide pas les entrées pour une raison de + //! performance. L'origine est le coin supérieur gauche de la grille. + //! + //! \param x La coordonnée en x de la cellule. + //! \param y La coordonnée en y de la cellule. + //! \param state Le nouvel état de la cellule. void GOLTeamH::setState(int x, int y, State state) { mData.setAt(x, y, state); mIteration = 0; } +//! \brief Mutateur remplissant de façon uniforme toutes les cellules de + //! la grille. + //! + //! \details Cette fonction remplit toutes les cellules de la grille avec + //! l'état passé en argument. + //! + //! L'itération courante est remise à 0. + //! + //! \param state L'état d'initialisation des cellules. void GOLTeamH::fill(State state) { - if (mBorderManagement == GOL::BorderManagement::immutableAsIs) - mData.fill(state, true); - else - mData.fill(state, false); - + mData.fill(state); mIteration = 0; } +//! \brief Mutateur remplissant de façon alternée toutes les cellules de + //! la grille. + //! + //! \details Cette fonction remplit toutes les cellules de la grille avec + //! un motif en damier. La première cellule, en haut à gauche, est de + //! l'état passée en argument. + //! + //! L'itération courante est remise à 0. + //! + //! \param firstCell L'état de la première cellule. void GOLTeamH::fillAlternately(State firstCell) { - if (mBorderManagement == GOL::BorderManagement::immutableAsIs) - mData.fillAternately(firstCell, true); - else - mData.fillAternately(firstCell, false); - + mData.fillAternately(firstCell); mIteration = 0; } +//! \brief Mutateur remplissant de façon aléatoire toutes les cellules de + //! la grille. + //! + //! \details Cette fonction remplit toutes les cellules de la grille avec + //! un motif aléatoire. Le pourcentage de probabilité d'une cellule d'être + //! vivante est passé en argument. + //! + //! L'itération courante est remise à 0. + //! + //! \param percentAlive Le pourcentage de probabilité d'une cellule d'être + //! vivante. La valeur doit être comprise entre 0.0 et 1.0 inclusivement. void GOLTeamH::randomize(double percentAlive) { - if (mBorderManagement == GOL::BorderManagement::immutableAsIs) - mData.randomize(percentAlive, true); - else - mData.randomize(percentAlive, false); - + mData.randomize(percentAlive); mIteration = 0; } -// TODO +//! \brief Mutateur remplissant la grille par le patron passé en argument. + //! + //! \details Cette fonction remplit la grille avec le patron donné. Le + //! patron est centré sur la coordonnées (centerX, centerY). + //! + //! Le patron respecte un format précis. Se référer à l'énoncé pour voir + //! tous les détails. + //! + //! Si le patron n'est pas valide, la grille n'est pas modifiée et on + //! retourne false. Sinon, on retourne vrai. + //! + //! L'itération courante est remise à 0. + //! + //! \param pattern Le patron à appliquer. + //! \param centerX La coordonnée en x de la grille où se trouve centré le patron. + //! \param centerY La coordonnée en y de la grille où se trouve centré le patron. + //! \return true si le patron est valide, false sinon. + //! bool GOLTeamH::setFromPattern(std::string const& pattern, int centerX, int centerY) { mIteration = 0; return false; } -// TODO +//! \brief Mutateur remplissant la grille par le patron passé en argument. + //! + //! \details Cette fonction est une surcharge utilitaire de la fonction + //! setFromPattern(std::string const & pattern, int centerX, int centerY). + //! Cette version utilise le centre de la grille comme centre du patron. + //! + //! L'itération courante est remise à 0. + //! + //! \param pattern Le patron à appliquer. + //! \return true si le patron est valide, false sinon. bool GOLTeamH::setFromPattern(std::string const& pattern) { mIteration = 0; return false; } +//! \brief Mutateur modifiant la couleur d'un état. + //! + //! \details Cette fonction modifie la couleur d'un état. + //! + //! Formellement, cette fonction ne modifie rien en soit mais plutôt + //! permet de stocker quelle couleur utiliser pour représenter un état + //! lors de l'affichage de la grille sur une image. + //! + //! \param state L'état dont on veut modifier la couleur. + //! \param color La nouvelle couleur de l'état. void GOLTeamH::setSolidColor(State state, Color const& color) { - if (state == State::dead) - mDeadColor = color; - else - mAliveColor = color; + } +<<<<<<< HEAD +//! \details Cette fonction constitue la partie centrale de la simulation. + //! Elle est responsable de faire évoluer la grille d'une itération. + //! + //! Cette fonction doit appliquer la logique de l'automate cellulaire en + //! tenant compte pour chaque cellule : + //! - de la grille + //! - de l'état de chacune des cellules voisines + //! - de la règle de la simulation + //! - de la stratégie de gestion de bord + //! + //! Après l'appel de cette fonction, la grille est mise à jour avec le + //! nouvel état de chaque cellule suivant l'état précédent. Les statistiques + //! doivent tenir compte de cette évolution. +======= +// TODO: performance +>>>>>>> 42a4f5dfba2d2df6f34eecb5fb19fea8a70afc9c void GOLTeamH::processOneStep() { - auto& grid{ mData.data() }; - auto& intGrid{ mData.intData() }; - - if (mBorderManagement == GOL::BorderManagement::foreverDead) { - size_t aliveCount{}; - size_t offset{ width() + 2 }; - auto* ptr{ &grid[0]}; - - for (size_t i{}; i < mData.realSize() - offset - 1; ++i) { - - if (mData.isInBorder(i)) { - ptr++; - continue; - } - - aliveCount = 0; - - // Top - ptr -= offset + 1; - if (*ptr == GOL::State::alive) - aliveCount++; - ptr++; - if (*ptr == GOL::State::alive) - aliveCount++; - ptr++; - if (*ptr == GOL::State::alive) - aliveCount++; - - // Milieu - ptr += offset - 2; - if (*ptr == GOL::State::alive) - aliveCount++; - ptr += 2; - if (*ptr == GOL::State::alive) - aliveCount++; - - - // Dessous - ptr += offset - 2; - if (*ptr == GOL::State::alive) - aliveCount++; - ptr++; - if (*ptr == GOL::State::alive) - aliveCount++; - ptr++; - if (*ptr == GOL::State::alive) - aliveCount++; - - if (grid[i] == GOL::State::alive) - intGrid[i] = (mParsedRuleSurvive.test(aliveCount)) ? GOL::State::alive : GOL::State::dead; - else - intGrid[i] = (mParsedRuleRevive.test(aliveCount)) ? GOL::State::alive : GOL::State::dead; - - // On retourne à une place plus loin qu'à l'origine. - ptr -= offset; - } - ptr = nullptr; - - mData.switchToIntermediate(); - mIteration.value()++; + // On commence à itérer sur les côtés. En règlant ces cas particuliers, on + // peut éviter des branches dans la boucle principale. Le branch predictor + // aime cela. + for (size_t i{}; i < mData.width(); ++i) { + } } +<<<<<<< HEAD + +//! \brief Fonction dessinant l'état de la simulation sur une image passée + //! en paramètre. + //! + //! \details Cette fonction dessine l'état courant de chaque cellule sur + //! l'image donnée. Chaque pixel de l'image correspond à une cellule de + //! la grille de simulation. + //! + //! La couleur de chaque pixel est déterminée par la couleur associée à + //! l'état de la cellule. + //! + //! L'organisation en mémoire est ce qu'on appel 'Packed Pixel' suivant + //! l'ordre ARGB. Ainsi, toutes les données d'un pixel est contiguë en + //! mémoire. Les 4 canaux de couleurs sont stockés dans un entier non + //! signé de 32 bits. Chaque canal est codé sur 8 bits. Le canal alpha est + //! le plus significatif et le canal bleu est le moins significatif. + //! + //! La variable buffer pointe vers un tableau de pixels de taille + //! buffer_size. La taille de l'image est donc buffer_size / sizeof(uint32_t). + //! + //!
+ //! [ 32 bits ] + //! [8 bits][8 bits][8 bits][8 bits] + //! [alpha ][red ][green ][blue ] + //! [alpha ][rouge ][vert ][bleu ] + //!+ //! + //! Vous pouvez considérer que l'image a été créée avec le format de + //! Qt QImage::Format_ARGB32. + //! + //! Il est attendu que vous fassiez une validation minimum des intrants. + //! + //! \param buffer Le tableau de pixels de l'image. + //! \param buffer_size La taille du tableau de pixels. +======= +>>>>>>> 42a4f5dfba2d2df6f34eecb5fb19fea8a70afc9c void GOLTeamH::updateImage(uint32_t* buffer, size_t buffer_size) const { if (buffer == nullptr) @@ -268,30 +484,29 @@ void GOLTeamH::updateImage(uint32_t* buffer, size_t buffer_size) const auto s_ptr = buffer; auto e_ptr = &buffer[buffer_size]; - auto& grid = mData.data(); - // On itère sur chaque éléments du tableau et on associe la couleur. - for (size_t index{ width() + 2 }; - index < (width() + 2) * (height() + 1); - index++) { - - if (mData.isInBorder(index)) - continue; - - auto var = static_cast