File indexing completed on 2024-05-19 04:49:57
0001 /**************************************************************************************** 0002 * Copyright (c) 2008-2012 Soren Harward <stharward@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #define DEBUG_PREFIX "Constraint::TagMatch" 0018 0019 #include "TagMatch.h" 0020 0021 #include "core/meta/Meta.h" 0022 #include "core/meta/support/MetaConstants.h" 0023 0024 #include <math.h> 0025 0026 int 0027 ConstraintTypes::TagMatch::Comparer::rangeNum( const double strictness, const qint64 field ) 0028 { 0029 if( strictness > 0.99 ) 0030 return 0; 0031 const double s = strictness * strictness; 0032 const double w = fieldWeight( field ); 0033 return static_cast<int>( ceil( 0.460517 * w / ( 0.1 + s ) ) ); 0034 } 0035 0036 double 0037 ConstraintTypes::TagMatch::Comparer::compareNum( const double test, 0038 MetaQueryWidget::FilterCondition condition, 0039 double target, 0040 const double strictness, 0041 const qint64 field ) 0042 { 0043 const double weight = fieldWeight( field ); 0044 0045 if ( condition == MetaQueryWidget::Equals ) { 0046 // fuzzy equals -- within 1%, or within 0.001 0047 if ( ( abs( test - target ) < ( abs( test + target ) / 200.0 ) ) || ( abs( test - target ) < 0.001 ) ) { 0048 return 1.0; 0049 } else { 0050 return fuzzyProb( test, target, strictness, weight ); 0051 } 0052 0053 } else if ( condition == MetaQueryWidget::GreaterThan ) { 0054 return ( test > target ) ? 1.0 : fuzzyProb( test, target, strictness, weight ); 0055 0056 } else if ( condition == MetaQueryWidget::LessThan ) { 0057 return ( test < target ) ? 1.0 : fuzzyProb( test, target, strictness, weight ); 0058 0059 } else if ( condition == MetaQueryWidget::Within ) { 0060 target += QDateTime::currentDateTime().toTime_t(); 0061 return ( test > target ) ? 1.0 : fuzzyProb( test, target, strictness, weight ); 0062 0063 } else if ( condition == MetaQueryWidget::OlderThan ) { 0064 target += QDateTime::currentDateTime().toTime_t(); 0065 return ( test < target ) ? 1.0 : fuzzyProb( test, target, strictness, weight ); 0066 0067 } else { 0068 return 0.0; 0069 } 0070 return 0.0; 0071 } 0072 0073 double 0074 ConstraintTypes::TagMatch::Comparer::compareStr( const QString& test, 0075 MetaQueryWidget::FilterCondition condition, 0076 const QString& target ) 0077 { 0078 if ( condition == MetaQueryWidget::Matches ) { 0079 if ( test.compare( target, Qt::CaseInsensitive ) == 0 ) 0080 return 1.0; 0081 } else if ( condition == MetaQueryWidget::StartsWith ) { 0082 if ( test.startsWith( target, Qt::CaseInsensitive ) ) 0083 return 1.0; 0084 } else if ( condition == MetaQueryWidget::EndsWith ) { 0085 if ( test.endsWith( target, Qt::CaseInsensitive ) ) 0086 return 1.0; 0087 } else if ( condition == MetaQueryWidget::Contains ) { 0088 if ( test.contains( target, Qt::CaseInsensitive ) ) 0089 return 1.0; 0090 /* 0091 } else if ( comparison == CompareStrRegExp ) { 0092 QRegExp rx( target ); 0093 if ( rx.indexIn( test ) >= 0 ) 0094 return 1.0; 0095 */ 0096 } else { 0097 return 0.0; 0098 } 0099 return 0.0; 0100 } 0101 0102 double 0103 ConstraintTypes::TagMatch::Comparer::compareLabels( const Meta::TrackPtr t, 0104 MetaQueryWidget::FilterCondition condition, 0105 const QString& target ) 0106 { 0107 Meta::LabelList labelList = t->labels(); 0108 0109 double v = 0.0; 0110 foreach ( Meta::LabelPtr label, labelList ) { 0111 // this is technically more correct ... 0112 // v = qMax( compare( label->prettyName(), comparison, target ), v ); 0113 0114 // ... but as long as compareStr() returns only 0.0 or 1.0, the following is faster: 0115 v = compareStr( label->prettyName(), condition, target ); 0116 if ( v > 0.99 ) { 0117 return 1.0; 0118 } 0119 } 0120 0121 return v; 0122 } 0123 0124 double 0125 ConstraintTypes::TagMatch::Comparer::fieldWeight( qint64 field ) 0126 { 0127 if( MetaQueryWidget::isDate( field ) ) 0128 return 1209600.0; 0129 0130 switch( field ) 0131 { 0132 case Meta::valYear: return 8.0; 0133 case Meta::valTrackNr: return 5.0; 0134 case Meta::valDiscNr: return 0.75; 0135 case Meta::valBpm: return 30.0; 0136 case Meta::valLength: return 50.0; // 50 seconds 0137 case Meta::valBitrate: return 30.0; 0138 case Meta::valSamplerate: return 100.0; 0139 case Meta::valFilesize: return 100000.0; 0140 case Meta::valFormat: return 0.5; 0141 case Meta::valScore: return 20.0; 0142 case Meta::valRating: return 3.0; 0143 case Meta::valPlaycount: return 4.0; 0144 default: return 0.0; 0145 } 0146 } 0147 0148 double 0149 ConstraintTypes::TagMatch::Comparer::fuzzyProb( const double a, const double b, 0150 const double strictness, const double weight ) 0151 { 0152 const double s = strictness * strictness; 0153 return exp( -10.0 * ( 0.1 + s ) / weight * ( 1 + qAbs( a - b ) ) ); 0154 } 0155 0156