biquadris / view.cc
view.cc
Raw
#include "view.h"
#include <memory>
#include <iostream>
#include "textdisplay.h"
#include "graphicdisplay.h"
#include "cell.h"
#include "scoreboard.h"
#include "model.h"
#include "board.h"
#include <vector>
#include "subscriptions.h"
#include <algorithm>
using namespace std;

const int PLAYERS = 2;

View::View(bool graphic, int width, int height) {
	if (graphic) displays.emplace_back(make_unique<GraphicDisplay>(width, height));
	displays.push_back(make_unique<TextDisplay>(width, height));
}

View::~View() { displays.clear(); }

vector<SubscriptionType> View::subType() {
	return vector<SubscriptionType> { SubscriptionType::ModelInfoChange,
									  SubscriptionType::ScoreChange,
									  SubscriptionType::CellModified,
									  SubscriptionType::BoardModified,
									  SubscriptionType::PlayerLose,
									  SubscriptionType::HintChange };
}

void View::notify(Subject *whoNotified, SubscriptionType t) {
	vector<SubscriptionType> subs = subType();
	if (find(subs.begin(), subs.end(), t) != subs.end()) {
		if (t == SubscriptionType::ModelInfoChange) {
			BiquadrisModel *model = dynamic_cast<BiquadrisModel *>(whoNotified);
			if (model != nullptr) updateByModel(model);
		} else if (t == SubscriptionType::ScoreChange) {
			Scoreboard *sb = dynamic_cast<Scoreboard *>(whoNotified);
			if (sb != nullptr) updateByScoreboard(sb);
		} else if (t == SubscriptionType::CellModified) {
			Cell *c = dynamic_cast<Cell *>(whoNotified);	
			if (c != nullptr) updateByCell(c);
		} else if (t == SubscriptionType::BoardModified) {
			Board *b = dynamic_cast<Board *>(whoNotified);
			if (b != nullptr) updateByBoard(b);
		} else if (t == SubscriptionType::HintChange) {
			Board *b = dynamic_cast<Board *>(whoNotified);
			if (b != nullptr) updateHint(b);
		} else if (t == SubscriptionType::PlayerLose) {
			for (auto &d : displays) {
				d->playerLoses();
			}
		}
	}
}

void View::updateByModel(BiquadrisModel *m) {
	const int nBoards = m->getPlayerCount();
	for (auto &d : displays) {
		for (int i = 0; i < nBoards; ++i) {
			const int level = m->getLevel(i);
			const int nextBlock = m->getNextBlock(i);
			d->update(i, level, nextBlock);
		}
	}
}

void View::updateByScoreboard(Scoreboard *sb) {
	const int playerCount = sb->getPlayerCount();
	for (auto &d : displays) {
		for (int p = 0; p < playerCount; ++p) {
			d->update(p, sb->getScore(p));
		}
		d->update(sb->getHighScore());
	}
}

void View::updateByBoard(Board *b) {
	const int boardId = b->getBoardId();
	const int boardWidth = b->getWidth();
	const int boardHeight = b->getHeight();
	for (auto &d : displays) {
		for (int r = 0; r < boardHeight; ++r) {
			for (int c = 0; c < boardWidth; ++c) {
				d->update(boardId, r, c, b->getType(r, c));
			}
		}
	}
}

void View::updateByCell(Cell *c) {
	const int boardId = c->getBoardId();
	const int row = c->getRow();
	const int col = c->getCol();
	const char type = c->getType();
	for (auto &d : displays) {
		d->update(boardId, row, col, type);
	}
}

void View::updateHint(Board *b) {
	for (auto &d : displays) {
		d->setHint(b->getHint());
	}
}

ostream &operator<<(ostream &out, const View &v) {
	for (auto &d : v.displays) {
		if (d->printable()) d->print(out);
	}
	return out;
}