Feedback is valuable!

(Back to Tracker’s Overview page)

In order to improve our service and provide new functionalities, we will need your help! In the end, you are the end-user and you are the one and only that can drive us in our journey to connect the music scenes around the world.

By visiting our Tracker app, you can do that easily! You could either drop a word or two to our email (tzertzeloscrew@gmail.com) or visit our Facebook, Tumblr, WordPress pages or just leave a quick message to us!

Media

By clicking in the Feedback icon, the feedback form is shown. In the form, you can add your feedback and its topic if any. In case you have a question & you potentially wait for a reply, you could attach your email within the form.

FeedbackForm

When ready, just “Shoot!”!

Thanks

Check also:

Advertisements

Discover artists related to your favorite artists with the Tracker app

(Back to Tracker’s Overview page)

The Tracker app allows you to easily find relevant artists to your favorite ones. This is achieved by combining the power of the artist filter with the tag filter.

First, select your favorite artist from the available artists provided by the artist filter.

Combo1

In this example, we used the artist filter’s text field in order to find Sleep.

Combo2

After selecting Sleep from the artist filter, the app will update its view and show us only Sleep’s future events.

Combo3

We then hover and click on Sleep’s event header in order to allow the artist information window to appear, showing all collected information regarding Sleep.  

Combo4

The artist information window reveals the band’s related external pages and the tags that are associated to the selected artist. Sleep’s artist information window shows that Sleep are related to “San Jose”,“sludge”,“metal”,“stoner” and so on. From Sleep’s tags, let’s click on the “sludge” tag. The app will show other bands except Sleep that are related to sludge and contain that particular tag in their information window. 

Combo5

After clicking on the sludge tag, the app shows additionally also Bongzilla and Moss, due to the fact that also hold the selected tag. By selecting more tags from the artist information window, you can discover new artists related to tags/keywords associated with your favorite artist easily!  

Check also

Information sharing about events, artists and their work with the Tracker app

(Back to Tracker’s Overview page)

The Tracker app allows you to browse events of all recommended artists and obtain easily collected information about each artist and their work. Pages such as a Facebook or a Bandcamp page are the de facto way for artists to post their work or publish an announcement. Through the Tracker app, you can easily visit your favorite band’s Facebook/Bandcamp pages with just a click.

InformationSharing3

Collected future events are shown, grouped by each featured artist.

InformationSharing1

By hovering & clicking on any artist event header, the artist information window is triggered, appearing next to the interactive artist header. In that example. we just hovered upon the artist header associated with Sumac. 

InformationSharing2

The artist information window shows artist information such as the artist’s related tags/keywords and its associated pages. By clicking on any of the available pages, you can visit easily any related page associated to your favorite artist. With that way, you are just two clicks away from checking out the most recent work/posts of your favorite artist!

Check also:

Find events of your favorite artist with the Tracker app

(Back to Tracker’s Overview page)

The Tracker app allows you to easily find and view only the events of your favorite artists, filtering out all other artists.  Filtering is achieved by selecting the artists of your choice from the artist filter.

ArtistSearchLocationInThePageMini

The artist filter shows all the artists which are hosted in an event in the future. You can just select or type any available artist name from the filter and the app’s view will only show the events of your favorite artists. So easy!

ArtistFilter

In this example, we selected “Extreme Noise Terror”, “Deafheaven”, “Heretoir” and Napalm Death” in order to find their respective future gigs in case there were any. The app indeed was able to find events matching our selected artists from the artist filter. The matched artists/events are shown in the app’s main view.

ArtistSearchFilter

By clicking the “Reset” button, all selected artist filters become available again.

Check also:

Find future events in your city with the Tracker app

(Back to Tracker’s Overview page)

The Tracker app allows you to view events that are taking place in a specific city and then filter out events  in cities other than the selected one. For each country, only the cities that contain events are shown in a list.

City1

From each city list, you can select a city of your choice and then the app will only show the events that are taking place in the city of your choice. In that example, we just clicked at “Tilburg”.

City2

In case you want to see all the events and undo the city filter, you can select the “ALL” option from the city list.

In the future & depending on the feedback we receive, we will adjust the amount of tracked countries! So please go ahead and provide your preference for additional countries to be tracked!

Check also:

Easily browse recommended events in your country with the Tracker app

(Back to Tracker’s Overview page)

The Tracker app currently supports four countries: Greece, Netherlands, Sweden and Great Britain.

Country0

Initially all events from each country are shown.

In order to see events in a specific country, we just need to select one of the available countries, let’s say Netherlands. Let’s click on “NL”.

Country1

Now we are able to browse all future events that will take place in the Netherlands! We could then use the date cursor in order to browse events in the future.

Let’s click on the date cursor’s right arrow in order to view the events for the next month.

Country1

After clicking on the date cursor’s right arrow, the Tracker is showing all events that will take place in the Netherlands during May.

Country2

We then could go back on April again by clicking the date cursor’s left arrow or view next month’s events and so on. Months that do not contain any events are not showing during month traversal through the date cursor.

Check also:

A Generic C++ 11 Column-based Data Table – A full template member method specialization & inheritance use case

c++-pacman

It’s been a while since i wrote about a programming related post, right?


Well today, I am going to show you how to use templates in specializations in order to support different implementations of a member function (by data type) & hide the underlying specialization data type from the owner of the templated resources by using (unique) pointers to the resources base class.

Hmm, all this sound a bit vague, right? Well, consider the following use case!

1. Problem
Make a Data Table class that accepts & stores an arbitrary number of vectors of integers/doubles/wide character strings and is able to access each vector independently at any given moment.Each vector could be viewed as a Data Column, where each data cell in the column has the same data type as the rest cells of the given column. The Data Table class has the additional property that the last column is somewhat special and accepts an old school C style struct (the Object struct) that stores either a column of strings, integers or doubles into our table.

#include <string>
typedef struct Object{
	enum ObjectType{
	    INT,
	    DOUBLE,
	    STRING,
	    ALL
	};
	ObjectType t;
    std::wstring str;
    int i;
    double d;
} Object;


A representation of a Data Table instance could be like the following:

+-----+-------------------------------------------------------+---------+------------+---------------+-----------------+---------------+
| id  | name                                                  | city_id | country_id | creation_date | longitude       | latitude      |
+-----+-------------------------------------------------------+---------+------------+---------------+-----------------+---------------+
|   1 | download festival                                     |     345 |        826 |    1486116627 |  -1.37659071746 | 52.8253416376 |
|   2 | roadburn festival                                     |     249 |        528 |    1486116627 |         5.09283 |      51.55774 |
|  89 | crossing border festival                              |    1222 |        528 |    1486125508 |       4.3161918 |    52.0806249 |
| 174 | sweden rock festival                                  |    1281 |        752 |    1486125656 |              -1 |            -1 |
| 203 | leeds festival                                        |     283 |        826 |    1486125855 |  -1.38795856125 | 53.8692024936 |
| 204 | reading festival                                      |     187 |        840 |    1486125855 | -0.991504837082 | 51.4644779002 |
| 212 | i'll be your mirror - all tomorrow's parties festival |     181 |        826 |    1486585624 | -0.131165437732 | 51.5936679342 |
| 236 | bloodstock open air festival, catton hall             |    1286 |        826 |    1486585635 |  -1.69612337663 | 52.7419809397 |
| 284 | bråvalla festivalen - site office                     |    1297 |        752 |    1486672011 |        16.12269 |      58.60874 |
+-----+-------------------------------------------------------+---------+------------+---------------+-----------------+---------------+


Hmmm, the Data Table & its Data Columns seem like a MYSQL table isn’t it ? 🙂 The first column (id) along country_id, city_id & creation_date is of integer type, the name Data Column is of type wide string and the longitude & latitude have double as their data type.

2. Implementation
We will start with the Table class. As mentioned in the Problem definition section, our Table should store initially any number of Columns of one specific data type plus one additional special Column, the Value Column. These requirements are implemented by keeping a vector of unique pointers to Columns (Table::m_Columns class member variable) & a unique pointer to store the Value Column (Table::m_Value class member variable) respectively. Why am i using unique pointers? Well, the Table class is the owner of the Columns & i want all Column resources to be freed after the Table’s lifetime expires (Table::~Table() is called) at some point.

//Table.h
#include "DataColumnFactory.h"
#include <assert.h>

class Table{
    using ColumnRsrc = std::unique_ptr<Column>;

    std::vector<ColumnRsrc> m_Columns;
    ColumnRsrc m_Value;
    std::wstring m_Name;

    public:
    Table(const std::wstring& name):m_Name(name){}
    ~Table(){}

    template <typename T>
    void add(std::vector<T> t) {
        auto column = DataColumnFactory::getColumn<T>();
        column.get()->add(t);
        m_Columns.push_back(std::move(column) );
    }

    void addValue(Object* o){
        if(!o) return;
        if(!m_Value.get() ){
            m_Value = DataColumnFactory::getColumnByType(o);
        }            
        assert(m_Value.get());
        m_Value.get()->add(o);
    }

    void dump(){
        dumpTableGeneralInfo();

        int i = 0;
    	for(auto &column : m_Columns){
            std::wcout << "Column #" << ++i << std::endl;
    	    column.get()->dump();
    	}

        if(m_Value.get()){
            std::wcout << "Column #" << ++i << std::endl;
            m_Value.get()->dump();
        }
    }

private:
    void dumpTableGeneralInfo(){
        //...implementation skipped
    }
};


The Table class provides two methods for inserting data, the first add() method allows the user to insert Column data which will be stored in the m_Columns member method & the second add() method that accepts as argument an Object type, allowing us to insert data to the Table’s special Value Column. Both methods are using the DataColumnFactory class in order to allocate a new DataColumn instance. The first add() method’s implementation gets a template argument T that is passed to the DataColumnFactory, indicating the type of data that the newly allocated DataColumn will store. The second overload accepts as argument an Object* that is then passed to the DataColumnFactory. The DataCloneFactory knows the Object instance’s internal representation, thus it allocates & returns to our Table instance a DataColumn with type that is dependent to the Object instance’s storage type (INTEGER, STRING or DOUBLE).

//DataCloneFactory.h
#include "Column.h"

class DataColumnFactory{
public:
    template<typename T>
    static std::unique_ptr<DataColumn<T>> getColumn(){
         std::unique_ptr<DataColumn<T>> column(new DataColumn<T>);
         return std::move(column);
    }

    static std::unique_ptr<Column> getColumnByType(Object* o){
        if(!o) return nullptr;
        switch(o->t){
            case Object::ObjectType::INT:{
                return std::move ( DataColumnFactory::getColumn<int>() );
            }
            case Object::ObjectType::DOUBLE:{
                return std::move ( DataColumnFactory::getColumn<double>() );
            }
            case Object::ObjectType::STRING:{
                return std::move ( DataColumnFactory::getColumn<std::wstring>() );
            }
            default: break;
        }
        return nullptr;
    }
};


The DataCloneFactory returns a (moved) DataColumn unique pointer to the Table; as we said, the Table instance is the owner of the columns. The factory contains two static methods that are responsible for allocating the DataColumns. The first templated method DataColumnFactory::getColumn() accepts as template argument T, that is the argument passed through Table::add(std::vector), representing the new Data Column’s data type. getColumn() allocates & returns a unique pointer to the newly allocated DataColumn to the Table instance. The second static method, DataColumnFactory::getColumnByType(Object*) allocates & returns a unique pointer to a new DataColumn, depending on the Object* argument’s type value. This static method returns a unique pointer to a Column instance, the base class of all DataColumns. In both cases, after calling a factory method, the Table instance stores the newly created DataColumn/Column objects to m_Columns & m_Value respectively.

3. Polymorphism
Keep in mind that m_Columns & m_Value are actually of Column (base class)data type, not of type DataColumn (derived class from Column), allowing us to use the columns polymorphically, hiding away from the Table instance their underlying data types. Is it a std::wstring, a double, an integer Column, who knows? Let’s call a member function on them & see how they behave!

//Column.h
#include 
#include 
#include 
#include "Object.h"

class Column{
public:
    virtual ~Column(){}
    virtual void add(Object *) = 0;
    virtual void dump() = 0;
    virtual int size() = 0;
};

template <class T>
class DataColumn : public Column{
    std::vector<T> values;
    public:
    	DataColumn():values({}){}
    	virtual ~DataColumn(){}
    	virtual void add(Object*) override;

    	void add(std::vector<T> v){
	    for(int i = 0;i<v.size();i++){
                values.push_back(v[i]);
	    }
    	}

    	virtual void dump() override{
            for(auto &k : values){
    	        std::wcout << "* " << k << std::endl;
    	    }
            std::wcout << std::endl;
    	}

        virtual int size() override {return values.size();}
};

template<>
void DataColumn<int>::add(Object* o){
    values.push_back(o->i);
}

template<>
void DataColumn<std::wstring>::add(Object* o){
    values.push_back(o->str);	
}

template<>
void DataColumn<double>::add(Object* o){
	 values.push_back(o->d);
}


The Column interface provides 3 methods: add(Object*), dump() & size(). All derived classes need to provide implementations about how to add an Object* to a column, how to print the contents of a Column instance and how to return the amount of Column items (of the same data type) that are contained in the Column. The Column class is an interface & it does not store any state for the Column itself, it just represents what a generic Column should look like & what/which minimum operations should be permitted in order to allow a derived class to become Column instance.

4. Template method class specialization
The DataColumn class that extends the Column interface is a template class that takes as template argument T the data type of the elements that will store. The class contains a vector as private member, that is where the Column elements will be stored. Except the three virtual methods that were inherited from the Column interface, the DataColumn class provides also the method add(std::vector), allowing us to store the Column elements to our vector. This method is used  for storing simple Columns by the Table class. In order to store data retrieved from an Object*, three methods with template specialization are offered. Each method knows which member of the Object* to access in order to get its value from the struct & store it in its vector, depending on the Data Column’s template specialization. Thus, the DataColumn<double>::add(Object*) knows that the d struct member contains the double value and that one needs to be accessed in order to retrieve & store the value to its std::vector values. DataColumn<std::wstring>::add(Object*) in the same way knows that the str member needs to be accessed in order to retrieve & store the wstring value to its std::vector values. Finally, the same also applies for DataColumn<int>::add(Object*) which accesses the member i. By providing full template specialization implementations for each supported data type, we allow the compiler to know at compile time which function to call, allowing us to instead of writing different full implementations of the derived classes DataColumn<std::wstring>, DataColumn<double>, DataColumn<int> to just provide different method implementation depending on template specialization type of the DataColumn, keeping things generic & compact as much as possible.

5. Client Code
After having explained the whole story, let’s see how we could use our Table class in order to store some data.

//templated_inheritance.cpp
#include "Table.h"

int main(){
    //Table with wstring Value Column
    Table stringColumn(L"WStringValueColumn");
    stringColumn.add<int>({1,2,3,4});
    stringColumn.add<double>({1.1,2.2,3.1,4.1});
    stringColumn.add<std::wstring>({L"Tzertzelos Blog", L"serving",L"the underground",L"since 2013!!"});

    Object o;
    o.t = Object::ObjectType::STRING;
    o.str = L"Cult of Luna";
    stringColumn.addValue(&o);
    stringColumn.dump();

    //Table with double Value Column
    Table numericColumn(L"DoubleValueColumn");
    numericColumn.add<int>({5,6,7,8});
    numericColumn.add<double>({1.12,2.22,3.12,4.12});
    numericColumn.add<std::wstring>({L"Tzertzelos", L"B",L"LO",L"G"});

    Object o2;
    o2.t = Object::ObjectType::DOUBLE;
    o2.d = 1.3334;
    numericColumn.addValue(&o2);

    o2.d = 1.3335;
    numericColumn.addValue(&o2);
    numericColumn.dump();


    Table nullTable(L"Null");
    nullTable.dump();
    return 0;
}


This client code instantiates 3 tables, the first table’s special Value Column has wstring data type, the second instance’s Value Column has double data type & the last table is an empty table.

6. Compile & Run
Download the code from here on your Linux box, then just type “make all” in order to compile the code. Then, the out executable will be built. Run it by typing “./out“.


The output will be:

gclkaze@gclkaze-VirtualBox:~/Desktop/Projects/C++/TemplatedInheritance$ ./out
Table WStringValueColumn => 4 X 4
Cells =>13
Column #1
* 1
* 2
* 3
* 4

Column #2
* 1.1
* 2.2
* 3.1
* 4.1

Column #3
* Tzertzelos Blog
* serving
* the underground
* since 2013!!

Column #4
* Cult of Luna

Table DoubleValueColumn => 4 X 4
Cells =>14
Column #1
* 5
* 6
* 7
* 8

Column #2
* 1.12
* 2.22
* 3.12
* 4.12

Column #3
* Tzertzelos
* B
* LO
* G

Column #4
* 1.3334
* 1.3335

Table Null => 0 X Cells =>0

7. Things learned
With the previous exercise, we got an idea about how to:

  • use class templates
  • use member method template specialization
  • use unique pointers
  • use the Factory Design Pattern
  • combine polymorphism with templates.

Enjoy & drop a comment/question/suggestion for improvement if any!
Cheers,
Kazeone

6. References

I. Generic Data Table source in GitHub

II. Template specialization

III. Factory Design Pattern

IV. std::unique_ptr

V. RAII

VI. C++ STL