@@ -65,29 +65,64 @@ public record SlskdFolderData(
6565 [ property: JsonPropertyName ( "fileCount" ) ] int FileCount ,
6666 [ property: JsonPropertyName ( "files" ) ] List < SlskdFileData > Files )
6767 {
68- public int CalculatePriority ( )
68+ public int CalculatePriority ( int expectedTrackCount = 0 )
6969 {
70+ // Early exit: completely locked folders
7071 if ( LockedFileCount >= FileCount && FileCount > 0 )
7172 return 0 ;
7273
74+ // Early exit: more than 50% locked = useless source
75+ double availabilityRatio = FileCount > 0 ? ( FileCount - LockedFileCount ) / ( double ) FileCount : 1.0 ;
76+ if ( availabilityRatio <= 0.5 )
77+ return 0 ;
78+
7379 int score = 0 ;
74- if ( FileCount > 0 )
80+
81+ // Get actual track count
82+ int actualTrackCount = 0 ;
83+ if ( expectedTrackCount > 0 )
7584 {
76- double availabilityRatio = ( FileCount - LockedFileCount ) / ( double ) FileCount ;
77- score += ( int ) ( Math . Pow ( availabilityRatio , 0.6 ) * 4000 ) ;
85+ actualTrackCount = Files . Count ( f =>
86+ AudioFormatHelper . GetAudioCodecFromExtension (
87+ f . Extension ?? System . IO . Path . GetExtension ( f . Filename ) ?? "" ) != AudioFormat . Unknown ) ;
7888 }
7989
90+ // Early exit: Missing 50%+ of expected tracks
91+ if ( expectedTrackCount > 0 && actualTrackCount > 0 && actualTrackCount <= expectedTrackCount * 0.5 )
92+ return 0 ;
93+
94+ // ===== TRACK COUNT MATCHING (0 to +2500) =====
95+ if ( expectedTrackCount > 0 && actualTrackCount > 0 )
96+ {
97+ int trackDiff = actualTrackCount - expectedTrackCount ;
98+
99+ if ( trackDiff < 0 ) // -1: ~500 pts, -2: ~60 pts, -3+: near 0
100+ score += ( int ) ( 2500 * Math . Exp ( - Math . Pow ( Math . Abs ( trackDiff ) , 2 ) * 5 ) ) ;
101+ else if ( trackDiff == 0 ) // PERFECT MATCH
102+ score += 2500 ;
103+ else // EXTRA TRACKS: Less critical, just penalized: +1: ~1600 pts, +2: ~600 pts, +3: ~100 pts, +15: near 0
104+ score += ( int ) ( 2500 * Math . Exp ( - Math . Pow ( trackDiff , 2 ) * 1.5 ) ) ;
105+ }
106+
107+ // ===== AVAILABILITY RATIO (0 to +2000) =====
108+ score += ( int ) ( Math . Pow ( availabilityRatio , 2.0 ) * 2000 ) ;
109+
110+ // ===== UPLOAD SPEED (0 to +1800) =====
80111 if ( UploadSpeed > 0 )
81112 {
82113 double speedMbps = UploadSpeed / ( 1024.0 * 1024.0 / 8.0 ) ;
83- score += ( int ) ( Math . Log10 ( Math . Max ( 0.1 , speedMbps ) + 1 ) * 1200 ) ;
114+ score += Math . Min ( 1800 , ( int ) ( Math . Log10 ( Math . Max ( 0.1 , speedMbps ) + 1 ) * 1100 ) ) ;
84115 }
85- double queuePenalty = Math . Pow ( 0.9 , Math . Min ( QueueLength , 30 ) ) ;
86- score += ( int ) ( queuePenalty * 2000 ) ;
87- if ( HasFreeUploadSlot )
88- score += 1000 ;
89- if ( FileCount >= 15 )
90- score += 200 ;
116+
117+ // ===== QUEUE LENGTH (50 to +1500) =====
118+ double queueFactor = Math . Pow ( 0.94 , Math . Min ( QueueLength , 40 ) ) ;
119+ score += ( int ) ( queueFactor * 1500 ) ;
120+
121+ // ===== FREE UPLOAD SLOT (0 or +800) =====
122+ score += HasFreeUploadSlot ? 800 : 0 ;
123+
124+ // ===== COLLECTION SIZE (0 to +300) =====
125+ score += Math . Min ( 300 , ( int ) ( Math . Log10 ( Math . Max ( 1 , FileCount ) + 1 ) * 150 ) ) ;
91126
92127 return Math . Clamp ( score , 0 , 10000 ) ;
93128 }
@@ -100,7 +135,7 @@ public record SlskdSearchData(
100135 [ property: JsonPropertyName ( "expandDirectory" ) ] bool ExpandDirectory ,
101136 [ property: JsonPropertyName ( "mimimumFiles" ) ] int MinimumFiles )
102137 {
103- private readonly static JsonSerializerOptions _jsonOptions = new ( ) { PropertyNameCaseInsensitive = true } ;
138+ private static readonly JsonSerializerOptions _jsonOptions = new ( ) { PropertyNameCaseInsensitive = true } ;
104139 public static SlskdSearchData FromJson ( string jsonString ) => JsonSerializer . Deserialize < SlskdSearchData > ( jsonString , _jsonOptions ) ! ;
105140 }
106141
0 commit comments