1 /****************************************************************************************
2  * Copyright (c) 2008-2012 Soren Harward <stharward@gmail.com>                          *
3  *                                                                                      *
4  * This program is free software; you can redistribute it and/or modify it under        *
5  * the terms of the GNU General Public License as published by the Free Software        *
6  * Foundation; either version 2 of the License, or (at your option) any later           *
7  * version.                                                                             *
8  *                                                                                      *
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
11  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
12  *                                                                                      *
13  * You should have received a copy of the GNU General Public License along with         *
14  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
15  ****************************************************************************************/
16 
17 #ifndef APG_GENERIC_MATCHING_CONSTRAINT
18 #define APG_GENERIC_MATCHING_CONSTRAINT
19 
20 #include "playlistgenerator/Constraint.h"
21 
22 #include "core/meta/forward_declarations.h"
23 
24 #include <QBitArray>
25 
26 /* The basic ConstraintGroup logic works properly only if all the
27  * constraints in the group are independent.  Constraints that work by
28  * matching track attributes to fixed values need additional logic, because
29  * it is possible (and even likely) that the user will create a group in
30  * which two or more constraints match against the same attribute, and are
31  * thus interdependent.
32  *
33  * For example, let's say that the user creates a "match any" group, and
34  * adds two constraints: one for "genre: Rock" and the other for "genre:
35  * Rap".  These two constraints are interdependent.  Without this
36  * workaround, the solver algorithm will fill up the playlist with either
37  * Rock tracks or Rap tracks, but not a mixture of both, because it is
38  * trying to maximize the individual satisfactions and not the joint
39  * satisfaction.  For "match all" groups, the solver adds tracks that
40  * improve only the least-satisfied constraint, instead of adding tracks
41  * that improve all constraints.
42  *
43  * Interdependent constraints should have their results combined (using the
44  * appropriate boolean operator) and the satisfaction value should be the
45  * value of the combined results.  From a programming standpoint, it would
46  * make sense just to prohibit the user from adding interdependent
47  * constraints to a group.  But that approach would add a restriction to
48  * constraint trees which is difficult for the user to understand, and an
49  * even bigger departure from other audio player programs than the
50  * constraint tree already is.  It might not even be any easier to program
51  * than this logic workaround.  Thus the decision to make the code the way
52  * it is.
53  *
54  * Thus far, the only Constraint that actually needs this workaround is
55  * TagMatch.  More (like SimilarityMatch) might come later.  -- sth */
56 
57 namespace ConstraintTypes {
58 	class MatchingConstraint : public Constraint {
59         public:
60             virtual const QBitArray whatTracksMatch(const Meta::TrackList&) = 0;
61             virtual int constraintMatchType() const = 0;
62 
63         protected:
64             MatchingConstraint(ConstraintNode*);
65     };
66 }
67 #endif // MATCHINGCONSTRAINT_H
68