How to read track & field results from a website? - c++

I want to read track and field results from http://athletisme-quebec.ca/calendrier-et-resultats.php for members of my track & field team (I'm in charge of compiling statistics on the members).
I've written a program that adds/removes athletes and their results, and saves all the data in .txt files that can be retrieved every time we run the program. It then manipulates the data to get certain statistics I want.
I have the following classes that I need to fill with data from the websites (I omitted the methods here, since they're irrelevant to the question):
Base class Performance
class Performance {
private:
string athlete_;
string location_;
int date_;
protected:
string event_;
};
Derived class TrackPerformance
class TrackPerformance: public Performance {
private:
PerformanceTime performanceTime_;
};
Derived class FieldPerformance
class FieldPerformance: public Performance {
private:
double performanceResult_;
};
PerformanceTime class (uses double for math calculations, and string for display purposes & for entering times like 4:12.23 easily [it gets automatically converted to double, and vice-versa])
class PerformanceTime {
private:
string performanceTimeStr_;
double performanceTimeDbl_;
};
Athlete class that holds the performances of each athlete
class Athlete {
private:
string name_;
string gender_;
map < string, vector <Performance*> > performances_; // the key is the event name
};
So, what would be the best way to do it? I tried finding an API to no avail.
They all follow a similar format, so I could open each event one by one and parse it using ifstream, but I want to know if there's a better way.
Example results: http://athletisme-quebec.ca/medias/resultsindoorchpt2016.htm

Related

Private Vector in Header file: How to Get and Set values

I'm trying to declare a vector containing user objects in the header file, but I'm unsure of how to use the setter and getter functions to push values objects back to the vector or call them again.
class userbase
{
public:
userbase();
virtual ~userbase();
//FUNCTION DECLARATIONS
void record_User(user);
void setUserVector(vector<user> const &newUser) {
//userbase_V = newUser;
userbase_V.push_back(newUser);
}
vector<user> const &getUservector() const {
return userbase_V;
}
protected:
private:
vector <user> userbase_V;
};
Getters/setters are quite often misunderstood. The aim of using such functions is encapsulation which means restricting access to your data or exposing certain functions.
The reason why we don't make private members public in the first place is because there are some operations that we don't want users of our class to perform.
Consider the following class:
class userbase
{
public:
vector<user> users;
};
Let's say the goal of the userbase class is to manage a loyal, unwavering list of followers of an application. And since users is a public member, we can do whatever we want with it:
class company
{
public:
void massacre()
{
m_userbase.users.clear(); // Aaaaahhh!!!
}
private:
userbase m_userbase;
};
What? Where did all our loyal, unwavering followers go? We can't just remove our users!
The company class has access to all of std::vector's functionality on m_userbase.users. But really, from userbase's point of view, we don't want the outside to access particular functions (in this case, clear() or erase()). We want to restrict what operations can be performed (modifiers) and what attributes can retrieved (accessors). That is, we want to encapsulate the users vector.
Making userbase a private member is the first step:
class userbase
{
private:
vector<user> users;
};
Now let's add some naive "encapsulation" to see if it solves our problem. (This is where a lot of misunderstanding stems from.)
Here's our new class:
class userbase
{
public:
void setUsers(vector<user> const& newUsers) {
users = newUsers;
}
vector<user> const& getUsers() const {
return users;
}
private:
vector<user> users;
}
Can the company still clear the users vector directly? Yes.
class company
{
public:
void massacre()
{
auto users = m_userbase.getUsers();
users.clear();
m_userbase.setUsers(users); // Aaaaahhh!!!
// or simply create a new vector with no data
m_userbase.setUsers(std::vector<user>{}); // Aaaaahhh!!!
}
private:
userbase m_userbase;
};
So simply providing getters/setters doesn't solve the issue.
The common approach is to instead approach it the other way around. Instead of asking "What don't I want the outside to do?", ask "What do I want to allow the outside to do?". This way, you can figure what sort of functionality to expose. This is part of designing a good API.
Maybe our API wants to be able to: add a user, get a user's name, and count the number of users. Then we would design a class like this:
class userbase
{
public:
/// modifiers:
// Add a user to the userbase.
void addUser(User const& user);
/// accessors:
// Returns the user's name given its index.
string getUserName(size_t index) const;
// Returns the number of users belonging to this userbase.
size_t numberOfUsers() const;
private:
vector<user> m_users;
};
The takeaway is: it's up to you to decide what "the outside" can or can't do with its members. You'll need to spend more time thinking and less time writing code, but this is normal.
Further reading:
Why use getter and setters? (A good read even though it's tagged with Java.)

Prevent breaking encapsulation

I have this class:
class Phone {
private:
string producer, color;
int weight, dimension;
public:
Phone(string &producer, string &color, int &weight, int &dimension):
producer(producer), color(color), weight(weight), dimension(dimension) {};
Phone():
producer(""), color(""), weight(0), dimension(0) {};
virtual ~Phone() {};
string getProducer(void) const;
string getColor(void) const;
int getWeight(void) const;
int getDimension(void) const;
virtual void displayInfo(void) const;
};
The problem is here caused by the fact that I expose the internal implementation of the object via getters.
But how can I prevent this?
Because usually in my code, I need to know some private data from my object (for comparision is one example), and that's why I use getters.
So then I rewrite the class to something like this:
class Phone {
private:
string producer, color;
int weight, dimension;
public:
Phone(string &producer, string &color, int &weight, int &dimension):
producer(producer), color(color), weight(weight), dimension(dimension) {};
Phone():
producer(""), color(""), weight(0), dimension(0) {};
virtual ~Phone() {};
bool isTheProducer(string& producer) const { return this->producer == producer };
bool hasWeight(int& weight) const { return this->weight == weight };
bool hasDimension(int& dimension) const { return this->dimension == dimension };
virtual void displayInfo(void) const;
};
Is this a better design (by the fact that I don't get the actual private value)?
As you might have seen from the other answers and comments, the answer is: It depends.
In fact, it depends mainly on the usecases where your class is used. Let's stick first to the example given in the question, the comparison of objects. Since it is not clearly visible from the question if we want to compare two phone objects or just a specific data member I will discuss both situations here.
Comparing a data member to out-of-class data
Let's take this usecase where we search for all phones with a weight bigger than x(just pseudocode):
for (Phone& p in phoneList) {
if (p.getWeight() > x) {
cout << "Found";
}
}
Then the first class example is perfectly fine, since this is not an intrinsic feature of the phone, and thus the phone class is not responsible for handling it. In addition, the result does not expose more than absolutely required for the task.
Comparing two phone objects
In this case both code examples are equally good (or in this case equally bad). In both cases the user has to know a lot of details about how phones are represented to compare all necessary members. If in a later revision a new member is added to the class, every code segment that compares two phones has to be adapted. To overcome this, one can add a function to the class that does exactly the comparison.
class Phone {
private:
string producer, color;
int weight, dimension;
public:
bool IsEqualTo(const Phone& other)
{
return (producer == other.producer && color == other.color &&....);
}
Non comparitive usecase
But let's go to a more advanced example. Let's assume the following task: A user enters the pin to a phone and if it is the correct one, the phone should unlock. Let's assume a very naive approach:
class Phone
{
private:
int pin;
bool unlocked;
public:
int getPin() { return pin; }
void unlock() { unlocked = true; }
};
and the corresponding call
if (phone.getPin() == enteredPin)
phone.unlock();
In this case we have a totally different situation. Here we need to consider the "tell, don't ask" rule, which basically says that it is a bad design to query the state of an object first, make a decision and then tell the object what to do. Instead we should only tell the object what we want, and let it do the work for us. In this usecase this is obvious, since unlocking the phone only when the pin is correct is a responsibility of the phone, not of the user that uses the phone class. But in more complex scenarious many programmers will do exactly what I described here.
Back to the problem: A good solution here would be for example
class Phone
{
private:
int pin;
bool unlocked;
public:
void CheckPin(int enteredPin) {
if (pin == enteredPin)
unlocked = true;
}
};
with the code
phone.CheckPin(enteredPin);
Hope this helps, and thanks to #KonradRudolph for pointing to the "tell, don't ask rule". Feel free to help me to improve the answer per commenting on it :)
The first one, even with getter, is encapsulated. Consider the color() method, which returns a string. Even if you change the implementation of Phone such that you store the color as an enum rather than a string, your method can still return a string if you do some sort of conversion first. The important part is that you can change the implementation of color() and the underlying storage without users of the class needing to change.
Compare to a class that stores color as a publicly accessible string. If you later change the data member to an enum, you need to modify every location that uses the color. This is less of a property of encapsulation and more a property of separating interface from implementation.
Encapsulation allows controlling of attributes exclusively via methods within the class. Both examples are encapsulated.

Handling derived class creation using mappers in C++

I'm reading through Martin Fowler's PoEAA right now on object-relational structural patterns. As a project to do while learning them, I thought I'd build a mini eCommerce system in C++. I'm having trouble figuring out how to return the objects from the mapper.
I have a Product base class, which has derived classes Hat and Shirt. Products have a type member to identify which derived class they are. I also have a ProductMapper class, with derived classes HatMapper and ShirtMapper, all of which implement a bunch of finder methods which let me try and retrieve certain hats and shirts.
class Product
{
unsigned long long int id;
std::string name;
unsigned int type;
};
// Derived classes don't necessarily have the same members.
class Hat : public Product
{
unsigned char fitted;
unsigned char color;
unsigned char style;
};
class Shirt : public Product
{
unsigned char size;
};
In the logic part of my application where I'd instantiate these mappers and retrieve products is where I'm having trouble. I can instantiate a HatMapper and pull back Hat objects without any problem, same with a ShirtMapper and Shirt objects. The patterns work great in these cases (in particular I'm using class table inheritance, i.e. one product table with product data, one table for hats with hat-specific data, and one table for shirts with shirt-specific data).
My problem is, what do I do if I want to retrieve all products, both hats and shirts? I can instantiate a ProductMapper and fetch all of the product data, but that seems like the wrong approach since I'd have to loop through all the Products I retrieve and build up Hats and Shirts based on their type in my logic portion of the program. Additionally, I'd have to modify any code that handles the situation this way when I add new product types. Seems bad.
The Fowler book has examples of the mappers with the base mapper using the derived mappers which seems completely wrong to me (have to modify the base mapper every time I add a new product, not great). Here's a quick example of how it's done there:
class ProductMapper
{
unsigned long long int productId;
unsigned long long int productType;
HatMapper * hm;
ShirtMapper * sm;
Product * FindById(unsigned long long int id)
{
// Query database for data.
if (this->productType == PRODUCT_TYPE_HAT)
{
return hm->FindById(id); // Hat object.
}
else if (this->productType == PRODUCT_TYPE_SHIRT)
{
return sm->FindById(id); // Shirt object.
}
return NULL;
}
};
Here's how I'd use this in the logic part of my program. Examples of this aren't provided in the book:
ProductMapper * pm = new ProductMapper();
Product * p = pm->FindById(1); // It's a Product, but a Hat or Shirt?
// Have to check type since a Product was returned.
switch (p->type)
{
case PRODUCT_TYPE_HAT:
{
Hat * h = (Hat) p;
break;
}
// Etc. Modify this every time a new product type is added or removed.
}
This will introduce circular dependencies. Additionally, assuming I somehow eliminate the circular dependencies, the result of the HatMapper and ShirtMapper classes are Hat objects and Shirt objects. Thus when I return from the ProductMapper, I'll be downcasting, so I'd have to again manipulate the result in my logic, which again introduces the issue of modifying code when I introduce new product types.
I'm at a loss for what to do. In a perfect world, I'd like to have a Product class and a ProductMapper class, both of which I can extend quickly, introducing new product types without having to modify existing code (at least too much).
I would like to be able to use these patterns from PoEAA, they do seem nice and useful, but I'm not sure if it's just something I can't do in C++ or I'm missing something that's preventing me from doing it. Alternative patterns and approaches are also really welcomed.
It feels like the Type Object pattern could help in this case, I know the link is about game programming but it is sufficient to apply the pattern to other domains.
The problem right now is that if you want to add products you have to add several classes, which can become hard to maintain as you noticed.
Edit: Maybe you could use something like that (code is C++11 to simplify the example):
class ProductProperty
{
typedef std::map<std::string, unsigned char> PropertyMap;
PropertyMap properties;
public:
ProductProperty(std::initializer_list<PropertyMap::value_type> il):
properties(il)
{}
// Use of at() is intended to only deal with the defined properties
const PropertyMap::value_type::second_type&
get(const PropertyMap::value_type::first_type& prop) const
{
return properties.at(prop);
}
PropertyMap::value_type::second_type&
get(const PropertyMap::value_type::first_type& prop)
{
return properties.at(prop);
}
};
// Some helpers to illustrate
std::shared_ptr<ProductProperty> makeHatProperty()
{
return std::make_shared<ProductProperty>(
ProductProperty{
{"fitted", ***whatever**},
{"color", ***whatever**},
{"style", ***whatever**}
});
}
std::shared_ptr<ProductProperty> makeShirtProperty()
{
return std::make_shared<ProductProperty>(
ProductProperty{{"size", ***whatever**}}
);
}
class Product
{
unsigned long long int id;
std::string name;
unsigned int type;
std::shared_ptr<ProductProperty> properties;
public:
Product(std::shared_ptr<ProductProperty> props):
properties(props)
{}
// Whatever function you need to get/set/check properties
};

Interaction between objects

If I have a class Music like this
class Music{
private:
string song[20];
string album[20];
string artistName[20];
string genre[20];
static int i;
int j;
int duration[20];
public:
Music(string musicName,string artist,string genre,string albumname,int duration);
void addMusic(string musicName,string artist,string genre,string albumname,int duration);
bool browseMusic(string musicName);
void getParticularSongDetail(string musicName);
void totalNumberOfSongs();
};
and a person class like this
class Person{
public:
Person(string,string,string);
string getFirstName();
string getMiddleName();
string getLastName();
int getId();
private:
//some variables
}
how can I add 20 songs to Music class that belongs to a particular person?
The answer really depends on how you wish to design your program.
The following are some possible solutions for you:
The Person could have an array of Music objects.
The Music class could have a keep track of the Peron's id it belongs to.
The Music classes may be something you won't want to repeat between users, so you might make a 3rd class which helps make the associations. (e.g. Multiple people might own the same Tool album CD/mp3, so another class could help you make the associations, or you might have an array in your Music class to keep track of multiple Persons... Normally a "list" would be a better datatype than an array, however from your code examples I stuck to arrays to keep the response simple).

c++ composition (has-a) issue

One important and essential rule I have learnt as a C++ programmer is the preference of Composition over Inheritance (http://en.wikipedia.org/wiki/Composition_over_inheritance).
I totally agree with this rule which mostly makes things much more simple than It would be if we used Inheritance.
I have a problem which should be solved using Composition but I'm really struggling to do so.
Suppose you have a Vendor Machine, and you have two types of products:
Discrete product - like a snack.
Fluid product - like a drink.
These two types of products will need to be represented in a class called VendorCell which contains the cell content.
These two products share some identical attributes(dm) as Price, Quantity and so on...BUT also contain some different attributes.
Therefore using Composition here might lead for the following result:
class VendorCell {
private : // default access modifier
int price;
int quantity;
// int firstProductAttributeOnly
// char secondProductAttributeOnly
};
As you can see the commented lines show that for a single VendorCell depending on the product it containing, only one of these two commented lines will be significant and useable (the other one is only relevant for the other type - fluid for example).
Therefore I might have a VendorCell with a snack inside and its secondProductAttributeOnly is not needed.
Is composition (for the VendorCell) is the right solution? is It seems proper to you guys that someone will determine the VendorCell type via a constructor and one DM (the DM dedicated for the other type) will not be used at all (mark it as -1 for example) ?>
Thanks you all!
Your general rule of favoring composition over inheritance is right. The problem here is that you want a container of polymorphic objects, not a giant aggregate class that can hold all possible products. However, because of the slicing problem, you can't hold polymorphic objects directly, but you need to hold them by (preferably smart) pointer. You can hold them directly by (smart) pointer such as
class AbstractProduct { /* price, quauntity interface */ };
class AbstractSnack: public AbstractProduct { /* extended interface */ };
class AbstractDrink: public AbstractProduct { /* extended interface */ };
typedef std::unique_ptr<AbstractProduct> VendorCell;
typedef std::vector< VendorCell > VendorMachine;
You simply define your snacks/drinks by deriving from AbstractSnack/AbstractDrink
class SnickersBar: public AbstractSnack { /* your implementation */ };
class CocaColaBottle: public AbstractDrink { /* your implementation */ };
and then you can insert or extract products like this:
// fill the machine
VendorMachine my_machine;
my_machine.emplace_back(new SnickersBar());
my_machine.emplace_back(new CocaColaBottle());
my_snack = my_machine[0]; // get a Snickers bar
my_drink = my_machine[1]; // get a Coca Cola bottle;
There are also other solutions such as Boost.Any that uses a wrapper class that internally holds a pointer to a polymorphic object. You could also refactor this code by replacing the typedef with a separate class VendorMachine that holds a std::vector< VendorCell >, so that you can get a nicer interface (with money exchange functionality e.g.)
You inherit in order to be re-used.
You compose in order to re-use.
If you have different attributes then you probably want to inherit, otherwise compose.
Some variation:
class ProductVariety {
public:
virtual void display(Screen& screen) = 0;
};
An implementation:
class Liquid : public ProductVariety {
public:
virtual void display(Screen& screen) {
//...
}
}
Composing variation:
class Product
{
int price;
int quantity;
unique_ptr<ProductVariety> variety;
}