Skip to content

Commit 44c77dd

Browse files
committed
Improve Fuzzy matching #131
Update to 2.1.4
1 parent edfba08 commit 44c77dd

File tree

4 files changed

+124
-29
lines changed

4 files changed

+124
-29
lines changed

b2sbackglassserver/b2sbackglassserver/Classes/B2SData.vb

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Imports System
22
Imports System.Drawing
3+
Imports System.Text.RegularExpressions
34

45
Public Class B2SData
56

@@ -655,11 +656,122 @@ Public Class B2SData
655656
Public Shared Function ShortFileName(ByVal longFileName As String) As String
656657
' Cut filename after the first parenthesis
657658
' Return short file name
658-
If longFileName Like "*)*" Then
659-
Return longFileName.Substring(0, longFileName.IndexOf(")") - 1)
659+
If longFileName Like "* *" Then
660+
Return longFileName.Substring(0, longFileName.IndexOf(" ") - 1)
660661
End If
661662
Return longFileName
662663

663664
End Function
664665

665-
End Class
666+
Public Class FuzzyFileName
667+
668+
' Optimized function to calculate the Levenshtein distance between two strings
669+
Public Shared Function LevenshteinDistance(ByVal s As String, ByVal t As String) As Integer
670+
Dim n As Integer = s.Length
671+
Dim m As Integer = t.Length
672+
673+
' If one of the strings is empty, return the length of the other string
674+
If n = 0 Then Return m
675+
If m = 0 Then Return n
676+
677+
' Ensure n <= m to use less space
678+
If n > m Then
679+
Dim temp As String = s
680+
s = t
681+
t = temp
682+
n = s.Length
683+
m = t.Length
684+
End If
685+
686+
' Create two work vectors of integer distances
687+
Dim previousRow(n) As Integer
688+
Dim currentRow(n) As Integer
689+
690+
' Initialize the previous row
691+
For i As Integer = 0 To n
692+
previousRow(i) = i
693+
Next
694+
695+
' Compute the distance
696+
For j As Integer = 1 To m
697+
currentRow(0) = j
698+
For i As Integer = 1 To n
699+
Dim cost As Integer = If(s(i - 1) = t(j - 1), 0, 1)
700+
currentRow(i) = Math.Min(Math.Min(currentRow(i - 1) + 1, previousRow(i) + 1), previousRow(i - 1) + cost)
701+
Next
702+
' Swap the current and previous rows
703+
Dim tempRow() As Integer = previousRow
704+
previousRow = currentRow
705+
currentRow = tempRow
706+
Next
707+
708+
Return previousRow(n)
709+
End Function
710+
711+
' Function to calculate the percentage match between two strings
712+
Public Shared Function PercentageMatch(ByVal s As String, ByVal t As String) As Double
713+
Dim maxLength As Integer = Math.Max(s.Length, t.Length)
714+
If maxLength = 0 Then
715+
Return 100.0
716+
End If
717+
718+
Dim distance As Integer = LevenshteinDistance(s, t)
719+
Return (1.0 - CDbl(distance) / maxLength) * 100.0
720+
End Function
721+
722+
' Function to normalize a string
723+
Public Shared Function NormalizeString(ByVal input As String) As String
724+
' Convert to lowercase, remove special characters, and trim whitespace
725+
Dim normalized As String = input.ToLower()
726+
normalized = Regex.Replace(normalized, "[^\w\s]", "")
727+
normalized = normalized.Trim()
728+
Return normalized
729+
End Function
730+
731+
' Function to tokenize a string
732+
Public Shared Function TokenizeString(ByVal input As String) As List(Of String)
733+
' Split the string into words
734+
Dim tokens As List(Of String) = New List(Of String)(input.Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries))
735+
Return tokens
736+
End Function
737+
738+
' Function to calculate the Jaccard similarity between two sets of tokens
739+
Public Shared Function JaccardSimilarity(ByVal tokens1 As List(Of String), ByVal tokens2 As List(Of String)) As Double
740+
Dim intersection As Integer = tokens1.Intersect(tokens2).Count()
741+
Dim union As Integer = tokens1.Union(tokens2).Count()
742+
Return CDbl(intersection) / union
743+
End Function
744+
745+
' Function to find the best match among candidates
746+
Public Shared Function FindBestMatch(ByVal target As String, ByVal candidates As List(Of String)) As String
747+
Dim bestMatch As String = String.Empty
748+
Dim highestMatchScore As Double = 0.0
749+
750+
' Normalize and tokenize the target string
751+
Dim normalizedTarget As String = NormalizeString(target)
752+
Dim targetTokens As List(Of String) = TokenizeString(normalizedTarget)
753+
754+
For Each candidate As String In candidates
755+
' Normalize and tokenize the candidate string
756+
Dim normalizedCandidate As String = NormalizeString(candidate)
757+
Dim candidateTokens As List(Of String) = TokenizeString(normalizedCandidate)
758+
759+
' Calculate the Jaccard similarity
760+
Dim jaccardScore As Double = JaccardSimilarity(targetTokens, candidateTokens)
761+
762+
' Calculate the Levenshtein distance percentage match
763+
Dim levenshteinScore As Double = PercentageMatch(normalizedTarget, normalizedCandidate)
764+
765+
' Combine the scores (you can adjust the weights as needed)
766+
Dim combinedScore As Double = (jaccardScore + levenshteinScore) / 2
767+
768+
If combinedScore > highestMatchScore Then
769+
highestMatchScore = combinedScore
770+
bestMatch = candidate
771+
End If
772+
Next
773+
774+
Return bestMatch
775+
End Function
776+
End Class
777+
End Class

b2sbackglassserver/b2sbackglassserver/Classes/B2SVersionInfo.vb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Public Class B2SVersionInfo
44
Public Const B2S_VERSION_MAJOR = "2"
55
Public Const B2S_VERSION_MINOR = "1"
6-
Public Const B2S_VERSION_REVISION = "3"
6+
Public Const B2S_VERSION_REVISION = "4"
77
Public Const B2S_VERSION_BUILD = "999"
88
Public Const B2S_VERSION_HASH = "nonset"
99
' 2.5.0

b2sbackglassserver/b2sbackglassserver/Forms/formBackglass.vb

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,6 @@ Public Class formBackglass
19071907
#Region "load B2S data and more B2S stuff"
19081908

19091909
Private Sub LoadB2SData()
1910-
19111910
Dim filename As String = B2SData.TableFileName & ".directb2s"
19121911
Dim shortFilename As String = B2SData.ShortFileName(filename) & ".directb2s"
19131912
Dim hyperpinFilename As String = String.Empty
@@ -1932,27 +1931,15 @@ Public Class formBackglass
19321931
If Not IO.File.Exists(hyperpinFilename) AndAlso Not IO.File.Exists(shorthyperpinFilename) Then
19331932
If filename.Length >= 8 Then
19341933
' look for short name
1935-
B2SSettings.MatchingFileNames = IO.Directory.GetFiles(IO.Directory.GetCurrentDirectory(), shortFilename.Replace(".directb2s", "*.directb2s"))
1934+
B2SSettings.MatchingFileNames = IO.Directory.GetFiles(IO.Directory.GetCurrentDirectory(), "*.directb2s")
1935+
Dim candidateFilenames As New List(Of String)(B2SSettings.MatchingFileNames)
1936+
Dim bestMatch As String = B2SData.FuzzyFileName.FindBestMatch(filename, candidateFilenames)
19361937

1937-
If B2SSettings.MatchingFileNames IsNot Nothing Then
1938-
For i As Integer = 0 To B2SSettings.MatchingFileNames.Length - 1
1939-
Dim fileinfo As IO.FileInfo = New IO.FileInfo(B2SSettings.MatchingFileNames(i))
1940-
B2SSettings.MatchingFileNames(i) = fileinfo.Name
1941-
Next
1942-
B2SScreen.debugLog.WriteLogEntry("FuzzyMatching Matching FileNames:" & String.Join(", ", B2SSettings.MatchingFileNames))
1938+
If Not String.IsNullOrEmpty(bestMatch) Then
1939+
shortFilename = bestMatch
19431940
End If
1944-
shortFilename = String.Empty
1945-
For Each matchedFileName As String In B2SSettings.MatchingFileNames
1946-
If String.IsNullOrEmpty(shortFilename) Then
1947-
shortFilename = matchedFileName
1948-
End If
1949-
If Not String.IsNullOrEmpty(B2SSettings.MatchingFileName) AndAlso File.Equals(B2SSettings.MatchingFileName, StringComparison.CurrentCultureIgnoreCase) Then
1950-
shortFilename = matchedFileName
1951-
Exit For
1952-
End If
1953-
Next
1954-
B2SScreen.debugLog.WriteLogEntry("FuzzyMatching Selected FileName:" & shortFilename)
19551941

1942+
B2SScreen.debugLog.WriteLogEntry("FuzzyMatching Selected FileName:" & shortFilename)
19561943
End If
19571944
End If
19581945
B2SScreen.debugLog.WriteLogEntry("FuzzyMatching END")

b2sbackglassserver/b2sbackglassserver/Server.vb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
Imports System
2-
Imports System.Text
1+
Imports System.Text
32
Imports System.Runtime.InteropServices
43
Imports Microsoft.Win32
5-
Imports System.Linq.Expressions
64
Imports System.Drawing
7-
Imports System.Reflection
8-
Imports System.Runtime.InteropServices.WindowsRuntime
95

106
<ProgId("B2S.Server"), ComClass(Server.ClassID, Server.InterfaceID, Server.EventsID)>
117
Public Class Server
@@ -2152,7 +2148,7 @@ Public Class Server
21522148
If picbox.Left <> xpos OrElse picbox.Top <> ypos Then
21532149
picbox.Left = xpos
21542150
picbox.Top = ypos
2155-
picbox.RectangleF = New RectangleF(CInt(picbox.Left / rescaleBackglass.Width), CInt(picbox.Top / rescaleBackglass.Height), picbox.RectangleF.Width, picbox.RectangleF.Height)
2151+
picbox.RectangleF = New RectangleF(CInt(picbox.Left / rescaleBackglass.Width), CInt(picbox.Top / rescaleBackglass.Height), picbox.RectangleF.Width, picbox.RectangleF.Height)
21562152
If picbox.Parent IsNot Nothing Then picbox.Parent.Invalidate()
21572153
End If
21582154
End If

0 commit comments

Comments
 (0)