322 lines
8.0 KiB
C++
322 lines
8.0 KiB
C++
#include "stock.hh"
|
|
#include "posexcept.hh"
|
|
|
|
using namespace std ;
|
|
using std::tr1::unordered_map ;
|
|
using std::tr1::unordered_set ;
|
|
|
|
|
|
|
|
/* *** Attribute definitions *** */
|
|
|
|
unordered_map<string, Building> Stock::buildings ;
|
|
|
|
unordered_map<Point3D, Waypoint> Stock::waypoints ;
|
|
|
|
unordered_map<string, Mobile> Stock::mobiles ;
|
|
|
|
unordered_map<string, AccessPoint> Stock::aps ;
|
|
|
|
unordered_set<ReferencePoint,
|
|
boost::hash<ReferencePoint>,
|
|
reference_point_equal_to> Stock::reference_points ;
|
|
|
|
unordered_set<CalibrationRequest> 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<string, Building>::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<string, Building>::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<Point3D, Waypoint>::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<Point3D, Waypoint>::iterator i =
|
|
waypoints.find(point) ;
|
|
|
|
Waypoint *waypoint = const_cast<Waypoint*>(&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<string, Mobile>::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<string, Mobile>::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<string, AccessPoint>::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<string, AccessPoint>::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<string, AccessPoint>::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<string, AccessPoint>::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<ReferencePoint>::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<unordered_set<ReferencePoint>::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 points'"
|
|
" list is empty!") ;
|
|
|
|
unordered_set<ReferencePoint>::const_iterator i =
|
|
reference_points.begin() ;
|
|
float distance = i->ss_square_distance(request) ;
|
|
unordered_set<ReferencePoint>::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<unordered_set<CalibrationRequest>::iterator, bool> ret =
|
|
calibration_requests.insert(request) ;
|
|
return *ret.first ;
|
|
}
|
|
|
|
|
|
const CalibrationRequest& Stock::
|
|
closest_calibration_request(const Request &request)
|
|
{
|
|
if (calibration_requests.empty())
|
|
throw element_not_found(
|
|
"Cannot search for the closest calibration request: calibration"
|
|
" requests' list is empty!") ;
|
|
|
|
unordered_set<CalibrationRequest>::const_iterator i =
|
|
calibration_requests.begin() ;
|
|
float distance = i->ss_square_distance(request) ;
|
|
unordered_set<CalibrationRequest>::const_iterator closest = i ;
|
|
|
|
for (++i ; i != calibration_requests.end() ; ++i)
|
|
{
|
|
float tmp_distance = i->ss_square_distance(request) ;
|
|
if (tmp_distance < distance)
|
|
{
|
|
distance = tmp_distance ;
|
|
closest = i ;
|
|
}
|
|
}
|
|
|
|
return *closest ;
|
|
}
|