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