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); } }
/** * 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; }
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; }
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()); } }
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; } }