Beispiel #1
0
void BFCPFloorControlServer::ProcessFloorRequest(BFCPMsgFloorRequest *req, BFCPUser* user)
{
	// Check that floorId value(s) in the request exist.
	int num_floors = req->CountFloorIds();
	for (int i=0; i < num_floors; i++) {
		int floorId = req->GetFloorId(i);
		if (! HasFloor(floorId)) {
			::Error("BFCPFloorControlServer::ProcessFloorRequest() | requesting non existing floor '%d'\n", floorId);
			ReplyError(req, BFCPAttrErrorCode::InvalidFloorId, L"requested floor does not exist");
			return;
		}
	}

	// Check that the beneficiaryId (if present) is a valid user.
	if (req->HasBeneficiaryId()) {
		if (! HasUser(req->GetBeneficiaryId())) {
			::Error("BFCPFloorControlServer::ProcessFloorRequest() | beneficiary '%d' does not exist\n", req->GetBeneficiaryId());
			ReplyError(req, BFCPAttrErrorCode::UserDoesNotExist, L"beneficiary does not exist");
			return;
		}
	}

	// Set an unique floorRequestId.
	int floorRequestId = this->floorRequestCounter++;

	// Create a BFCPFloorRequest.
	BFCPFloorRequest* floorRequest = new BFCPFloorRequest(floorRequestId, req->GetUserId(), this->conferenceId);
	if (req->HasBeneficiaryId())
		floorRequest->SetBeneficiaryId(req->GetBeneficiaryId());
	for (int i=0; i < req->CountFloorIds(); i++)
		floorRequest->AddFloorId(req->GetFloorId(i));

	// Add to the floorRequests map.
	this->floorRequests[floorRequestId] = floorRequest;
	::Log("BFCPFloorControlServer::ProcessFloorRequest() | FloorRequest '%d' added to conference '%d'\n", floorRequestId, this->conferenceId);

	// Build a "Pending" FloorRequestStatus response.
	BFCPMsgFloorRequestStatus *floorRequestStatus = floorRequest->CreateFloorRequestStatus(req->GetTransactionId());

	// Send it.
	SendMessage(floorRequestStatus);

	// Delete it.
	delete floorRequestStatus;

	// If the FloorRequest comes from the chair automatically grant it.
	if (user->IsChair()) {
		::Log("BFCPFloorControlServer::ProcessFloorRequest() | the FloorRequest sender is a chair, request authorized\n");
		GrantFloorRequest(floorRequestId);
	}
	// Otherwise notify the chair.
	else {
		::Log("BFCPFloorControlServer::ProcessFloorRequest() | the FloorRequest sender is not a chair, let's ask the chair\n");
		::Debug("BFCPFloorControlServer::ProcessFloorRequest() | calling listener->onFloorRequest(%d)\n", floorRequestId);
		this->listener->onFloorRequest(floorRequestId, floorRequest->GetUserId(), floorRequest->GetBeneficiaryId(), floorRequest->GetFloorIds());
		::Debug("BFCPFloorControlServer::ProcessFloorRequest() | listener->onFloorRequest(%d) returns\n", floorRequestId);
	}
}
Beispiel #2
0
/**
 * Checks if the middle of each floor is reachable from the elevator.
 * @param lowestFloorOfElevator pointer of the lowest floor which has an interface to the elevator
 * @param highestFloorOfElevator pointer of the highest floor which has an interface to the elevator
 * @return pointer of the floor which is unreachable, otherwise returns null pointer
 */
Floor* Elevator::CanReachFloor(Floor *lowestFloorOfElevator, Floor *highestFloorOfElevator) {

	bool currentFloorIsHighestFloor = true;


	// pointer to the current floor, which will be checked
	Floor *currentFloor = lowestFloorOfElevator;

	// determines the half of the height of the current floor
	double halfHeightOfCurrentFloor = currentFloor->GetHeight() / 2.0;

	// height counter is used to check if an elevator can reach a floor
	double heightCounter = halfHeightOfCurrentFloor;

	// take the next floor above
	currentFloor = currentFloor->GetAbove();

	while (currentFloorIsHighestFloor) {

		// determines the half of the height of the current floor
		halfHeightOfCurrentFloor = currentFloor->GetHeight() / 2.0;

		if (!HasFloor(currentFloor)) {

			heightCounter += currentFloor->GetHeight();


		} else {

			heightCounter += halfHeightOfCurrentFloor;

			double value = fmod(heightCounter, speed_);
			heightCounter += halfHeightOfCurrentFloor;

			// checks the determined value if it is unequal zero
			if (value != 0) {
				return currentFloor;
			}
		}


		// checks if the current floor is the highest floor
		if (currentFloor == highestFloorOfElevator) {
			currentFloorIsHighestFloor = false;
		} else {
			currentFloor = currentFloor->GetAbove();
		}
	}

	return nullptr;
}
Beispiel #3
0
int BFCPFloorControlServer::GetGrantedFloorRequestId(int floorId)
{
	if (this->ending) { return 0; }

	if (! HasFloor(floorId)) {
		::Error("BFCPFloorControlServer::GetGrantedFloorRequestId() | floor '%d' does not exist\n", floorId);
		return 0;
	}

	// Get all the ongoing FloorRequest including the given floor.
	std::vector<BFCPFloorRequest*> floorRequests = GetFloorRequestsForFloor(floorId);

	// Choose the first one that is Granted (can only be one).
	int num_floor_requests = floorRequests.size();
	for (int i=0; i<num_floor_requests; i++) {
		if (floorRequests[i]->IsGranted()) {
			return floorRequests[i]->GetFloorRequestId();
		}
	}

	return 0;
}
Beispiel #4
0
void Elevator::Validate() {

	Entity::Validate();

	if (speed_ <= 0) {
		std::ostringstream oss("Speed of ", std::ostringstream::ate);
		oss << GetName() << " must be positive.";
		throw TestfileException(oss.str());
	}

	if (load_ < 10) {
		std::ostringstream oss("Maximum load of ", std::ostringstream::ate);
		oss << GetName() << " must be greater or equal to 10.";
		throw TestfileException(oss.str());
	}

	if (!current_) {
		std::ostringstream oss("Starting floor of ", std::ostringstream::ate);
		oss << GetName() << " is null.";
		throw TestfileException(oss.str());
	}

	if (current_->GetType() != "Floor") {
		std::ostringstream oss("Starting floor of ", std::ostringstream::ate);
		oss << GetName() << " does not reference a floor object.";
		throw TestfileException(oss.str());
	}

	if (count_ < 2) {
		std::ostringstream oss("", std::ostringstream::ate);
		oss << GetName() << " must have at least 2 interfaces.";
		throw TestfileException(oss.str());
	}

	std::set<Interface*> unique;

	Floor *lowest = nullptr;
	Floor *highest = nullptr;

	for (int i = 0; i < count_; ++i) {

		Interface *interf = interfs_[i];

		if (!interf) {
			std::ostringstream oss("An interface of ", std::ostringstream::ate);
			oss << GetName() << " is null.";
			throw TestfileException(oss.str());
		}

		if (unique.count(interf)) {
			std::ostringstream oss("Interfaces used by ", std::ostringstream::ate);
			oss << GetName() << " are not unique.";
			throw TestfileException(oss.str());
		}
		unique.insert(interf);

		if (interf->GetType() != "Interface") {
			std::ostringstream oss("Interface ", std::ostringstream::ate);
			oss << interf->GetId() << " of ";
			oss << GetName() << " is not an interface object.";
			throw TestfileException(oss.str());
		}

		if (interf->GetLoadableCount() != 1) {
			std::ostringstream oss("", std::ostringstream::ate);
			oss << interf->GetName() << " of ";
			oss << GetName() << " must reference exactly one object.";
			throw TestfileException(oss.str());
		}

		Loadable *loadable = interf->GetLoadable(0);

		if (!loadable) {
			std::ostringstream oss("Referenced object of ", std::ostringstream::ate);
			oss << interf->GetName() << " of ";
			oss << GetName() << " is null.";
			throw TestfileException(oss.str());
		}

		if (loadable->GetType() != "Floor") {
			std::ostringstream oss("Referenced object of ", std::ostringstream::ate);
			oss << interf->GetName() << " of ";
			oss << GetName() << " must be an floor object.";
			throw TestfileException(oss.str());
		}

		Floor *floor = static_cast<Floor*>(loadable);

		if (!floor->HasElevator(this)) {
			std::ostringstream oss("Floor ", std::ostringstream::ate);
			oss << floor->GetId() << " referenced by ";
			oss << interf->GetName() << " of ";
			oss << GetName() << " does not point back to the elevator.";
			throw TestfileException(oss.str());
		}

		if (!lowest)
			lowest = floor;
		else if (lowest->IsBelow(floor)) {
			lowest = floor;
		}

		if (!highest)
			highest = floor;
		else if (highest->IsAbove(floor)) {
			highest = floor;
		}
	}

	if (highest->IsAbove(current_) || lowest->IsBelow(current_)) {
		std::ostringstream oss("Starting floor of ", std::ostringstream::ate);
		oss << GetName() << " is not between Floor " << lowest->GetId() << " and Floor " << highest->GetId() << ".";
		throw TestfileException(oss.str());
	}

	// validate if the elevator can start in the starting floor
	if (!HasFloor(this->current_)) {
		std::ostringstream oss("Elevator ", std::ostringstream::ate);
		oss << GetId() << " can not start in Floor " << current_->GetId() << " because the Floor has no interface to this Elevator.";
		throw TestfileException(oss.str());
	}

	Floor* floorTmp = CanReachFloor(lowest, highest);
	if (floorTmp) {
		std::ostringstream oss("Elevator ", std::ostringstream::ate);
		oss << GetId() << " can not reach center of Floor " << floorTmp->GetId() << ".";
		throw TestfileException(oss.str());
	}
}
Beispiel #5
0
void BFCPFloorControlServer::ProcessFloorQuery(BFCPMsgFloorQuery *req, BFCPUser* user)
{
	// Check that floorId value(s) in the request exist.
	int num_floors = req->CountFloorIds();
	for (int i=0; i < num_floors; i++) {
		int floorId = req->GetFloorId(i);
		if (! HasFloor(floorId)) {
			::Error("BFCPFloorControlServer::ProcessFloorQuery() | requesting non existing floor '%d'\n", floorId);
			ReplyError(req, BFCPAttrErrorCode::InvalidFloorId, L"requested floor does not exist");
			return;
		}
	}

	// Reset the list of floors this user is subscribed to.
	user->ResetQueriedFloorIds();

	// And insert the Floors included in the new FloorQuery.
	for (int i=0; i<num_floors; i++)
		user->AddQueriedFloorId(req->GetFloorId(i));

	::Debug("BFCPFloorControlServer::ProcessFloorQuery() | user '%d' information updated:\n", user->GetUserId());
	user->Dump();

	int num_queried_floors = user->CountQueriedFloorIds();

	// If the user has no queried floors then reply an empty FloorStatus and exit.
	if (num_queried_floors == 0) {
		::Debug("BFCPFloorControlServer::ProcessFloorQuery() | no queried floors, replying empty FloorStatus\n");
		BFCPMsgFloorStatus* floorStatus = new BFCPMsgFloorStatus(req->GetTransactionId(), this->GetConferenceId(), req->GetUserId());
		SendMessage(floorStatus);
		delete floorStatus;
		return;
	}

	// Otherwise, get the queried floors from the user (no duplicated floorIds there) and
	// generate a FloorStatus response for one of them and FloorStatus notifications for
	// the others.
	for (int i=0; i<num_queried_floors; i++) {
		BFCPMsgFloorStatus* floorStatus;
		int floorId = user->GetQueriedFloorId(i);

		// First FloorStatus will be a response to the FloorQuery.
		if (i == 0)
			floorStatus = new BFCPMsgFloorStatus(req->GetTransactionId(), this->GetConferenceId(), req->GetUserId());
		// Other FloorStatus are notifications.
		else
			floorStatus = new BFCPMsgFloorStatus(0, this->GetConferenceId(), req->GetUserId());

		// Set the floorId.
		floorStatus->SetFloorId(floorId);

		// Get all the ongoing FloorRequest that include this floor.
		std::vector<BFCPFloorRequest*> floorRequests = GetFloorRequestsForFloor(floorId);

		::Debug("BFCPFloorControlServer::ProcessFloorQuery() | found %d ongoing FloorRequests related to floor '%d'\n", floorRequests.size(), floorId);

		// Generate a FloorRequestInformation attribute from each FloorRequest and append
		// it to the FloorStatus message.
		for (int j=0; j<floorRequests.size(); j++) {
			BFCPAttrFloorRequestInformation* floorRequestInformation = floorRequests[j]->CreateFloorRequestInformation();
			floorStatus->AddFloorRequestInformation(floorRequestInformation);
		}

		// Send the response o notification to the user who sent the FloorQuery.
		SendMessage(floorStatus);

		delete floorStatus;
	}
}