#include "stock.hh" #include "posexcept.hh" using namespace std ; using std::tr1::unordered_map ; using std::tr1::unordered_set ; /* *** Attribute definitions *** */ unordered_map Stock::buildings ; unordered_map Stock::waypoints ; unordered_map Stock::mobiles ; unordered_map Stock::aps ; unordered_set Stock::reference_points ; unordered_set Stock::calibration_requests ; void Stock::clear() { buildings.clear() ; // Waypoints are normally deleted in Building::~Building(), so we must // not clear waypoints before buildings, but we clear it *after*, just // in case. waypoints.clear() ; mobiles.clear() ; aps.clear() ; reference_points.clear() ; calibration_requests.clear() ; } /* *** Building operations *** */ /** * The name of the Building is initialised. */ const Building& Stock::find_create_building(const string &name) { unordered_map::const_iterator i = buildings.find(name) ; if (i != buildings.end()) return i->second ; Building &building = buildings[name] ; building.set_name(name) ; return building ; } /** * @param name The name of the Building to search for. * It must be a valid name, as no check is performed. * @return A const reference to the Building. * @throw element_not_found is thrown if the Building corresponding * to \em name does not exist. */ const Building& Stock::get_building(const string &name) { unordered_map::const_iterator i = buildings.find(name) ; if (i != buildings.end()) return i->second ; throw element_not_found("No Building with name « " + name + " »!") ; } /* *** Waypoint operations *** */ const Waypoint& Stock:: find_create_waypoint(const Point3D &point) { unordered_map::const_iterator i = waypoints.find(point) ; if (i != waypoints.end()) return i->second ; Waypoint &waypoint = waypoints[point] ; waypoint.set_coordinates(point) ; return waypoint ; } void Stock::waypoint_remove_building(const Waypoint &point, const Building *building) { unordered_map::iterator i = waypoints.find(point) ; Waypoint *waypoint = const_cast(&i->second) ; waypoint->remove_building(building) ; // If the Waypoint is not linked to any Building any more, we // delete it if (waypoint->get_1st_building() == NULL) waypoints.erase(i) ; } /* *** Mobile operations *** */ /** * @param mac The MAC address of the Mobile to search for. * It must be a valid MAC address, as no check is performed. * @return A const reference to the Mobile. * @throw element_not_found is thrown if the Mobile corresponding * to \em mac does not exist. */ const Mobile& Stock::get_mobile(const string &mac) { unordered_map::const_iterator i = mobiles.find(mac) ; if (i != mobiles.end()) return i->second ; throw element_not_found("No Mobile with MAC address « " + mac + " »!") ; } /** * If created, the MAC address of the Mobile is initialised. */ const Mobile& Stock::find_create_mobile(const string &mac) { unordered_map::const_iterator i = mobiles.find(mac) ; if (i != mobiles.end()) return i->second ; Mobile &mobile = mobiles[mac] ; mobile.set_mac_addr(mac) ; return mobile ; } /* *** AccessPoint operations *** */ /** * @param mac The MAC address of the AccessPoint to search for. * It must be a valid MAC address, as no check is performed. * @return A const reference to the AccessPoint. * @throw element_not_found is thrown if the AccessPoint corresponding * to \em mac does not exist. */ const AccessPoint& Stock::get_ap(const string &mac) { unordered_map::const_iterator i = aps.find(mac) ; if (i != aps.end()) return i->second ; throw element_not_found("No AccessPoint with MAC address « " + mac + " »!") ; } /** * The MAC address of the AccessPoint is initialised. */ const AccessPoint& Stock::find_create_ap(const string &mac) { unordered_map::const_iterator i = aps.find(mac) ; if (i != aps.end()) return i->second ; AccessPoint &ap = aps[mac] ; ap.set_mac_addr(mac) ; return ap ; } /** * If the AccessPoint already exists, it is replaced by the \em source. */ const AccessPoint& Stock::find_create_ap(const AccessPoint &source) { const string &mac = source.get_mac_addr() ; unordered_map::const_iterator i = aps.find(mac) ; if (i != aps.end()) return i->second ; aps[mac] = source ; return aps[mac] ; } void Stock::update_all_friis_indexes() { for (unordered_map::iterator ap = aps.begin() ; ap != aps.end() ; ++ap) { string ap_mac = ap->second.get_mac_addr() ; double friis_idx_sum = 0 ; int nb_friis_idx = 0 ; // Compute main general term, independant from scans double ap_freq = ap->second.get_frequency() ; double const_term = ap->second.get_antenna_gain() - 20 * log10(4 * M_PI) + 20 * log10(PosUtil::LIGHT_SPEED / ap_freq) + ap->second.get_trx_power() ; /* * Compute indexes for each ReferencePoint. The Friis index for an * AP is the average of all indexes in all ReferencePoint. */ for (unordered_set::const_iterator rp = reference_points.begin() ; rp != reference_points.end() ; ++rp) { int nb_idx = 0 ; float ap_friis_idx_sum = rp->friis_indexes_for_ap(ap->second, const_term, nb_idx) ; if (nb_idx != 0) { friis_idx_sum += ap_friis_idx_sum ; nb_friis_idx += nb_idx ; } } if (nb_friis_idx > 0) ap->second.set_friis_index(friis_idx_sum / nb_friis_idx) ; } } /* *** ReferencePoint operations *** */ const ReferencePoint& Stock:: find_create_reference_point(const ReferencePoint &point) { // unordered_set::insert() do all the job: see the documentation at // http://boost.org/doc/libs/1_42_0/doc/html/boost/unordered_set.html pair::iterator, bool> ret = reference_points.insert(point) ; return *ret.first ; } const ReferencePoint& Stock:: closest_reference_point(const Request &request) { if (reference_points.empty()) throw element_not_found("Cannot search for the closest reference \ point: reference point list is empty!") ; unordered_set::const_iterator i = reference_points.begin() ; float distance = i->ss_square_distance(request) ; unordered_set::const_iterator closest = i ; for (++i ; i != reference_points.end() ; ++i) { float tmp_distance = i->ss_square_distance(request) ; if (tmp_distance < distance) { distance = tmp_distance ; closest = i ; } } return *closest ; } /* *** CalibrationRequest operations *** */ const CalibrationRequest& Stock:: find_create_calibration_request(const CalibrationRequest &request) { pair::iterator, bool> ret = calibration_requests.insert(request) ; return *ret.first ; }