Skip to content

Add "Fuzzy" search #523

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
46098ef
Basic functionality within ludo
Feb 15, 2024
5ce1b2d
cleaned up the pbp file check
Feb 15, 2024
aa7043c
cleaned up trailing whitespace
Feb 15, 2024
5c56421
Added m3u support and improved multi disc playlist support.
Feb 15, 2024
42b97cf
Starting on fuzzy search
Feb 17, 2024
26ed695
I've broken something, but I'm not sure what.
Feb 17, 2024
877fc20
update to g1.18 to slices support.
Feb 18, 2024
cb4772c
fixed CRC fallthrough to name
Feb 18, 2024
6f86332
fixed no match debugging
Feb 18, 2024
c43df73
I seem to have broken my lookup for multidisc entries
Feb 18, 2024
3dd61b1
basic fuzzy search is working fully. Next up is searching without par…
Feb 18, 2024
55c9427
configurable starting path added.
Feb 18, 2024
723ec5e
Merge branch 'set_default_path' into fuzzy_search
Feb 18, 2024
3aed43e
almost there. need to update FindByROMName to take file extension int…
Feb 18, 2024
8298d8c
I'm spiraling a bit. Matches are better but I'm failing to limit to t…
Feb 18, 2024
1a0ee1e
enforcing extension match
Feb 18, 2024
41da337
Merge branch 'extension_matching' into fuzzy_search
Feb 18, 2024
30a2840
I broke n64 somehow, but everything else is working.
Feb 18, 2024
6463e75
fixed n64 support by adding .z64 to the scanner matches.
Feb 18, 2024
b1c0159
Merge branch 'master' into fuzzy_search
bagelbyheart Feb 26, 2024
4837758
satisfy staticcheck
Feb 26, 2024
9cb0c2f
Merge branch 'master' into fuzzy_search
bagelbyheart Mar 5, 2024
fa831ff
hopefully this fixes the build errors in x86 linux.
Mar 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 82 additions & 3 deletions dat/dat.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ package dat

import (
"encoding/xml"
"fmt"
"strings"
//"slices"
"sort"
//"github.com/kr/pretty"
"log"
//"path/filepath"
"strconv"
"sync"
"path/filepath"
//"github.com/libretro/ludo/utils"
)

// DB is a database that contains many Dats, mapped to their system name
Expand Down Expand Up @@ -63,9 +71,15 @@ func Parse(dat []byte) Dat {
}

// FindByCRC loops over the Dats in the DB and concurrently matches CRC checksums.
func (db *DB) FindByCRC(romPath string, romName string, crc uint32, games chan (Game)) {
func (db *DB) FindByCRC(romPath string, romName string, crc uint32, games chan (Game)) (bool) {
var wg sync.WaitGroup
wg.Add(len(*db))
// this structure and subsequent object are remade ever run.
type SafeBool struct {
mu sync.Mutex
found bool
}
game_found := SafeBool{found: false}
Copy link
Contributor

@igorcafe igorcafe Mar 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't analyze it deeply, but do you really need a mutex or a atomic.Bool fits your needs?

// For every Dat in the DB
for system, dat := range *db {
go func(dat Dat, crc uint32, system string) {
Expand All @@ -79,17 +93,41 @@ func (db *DB) FindByCRC(romPath string, romName string, crc uint32, games chan (
game.Path = romPath
game.System = system
games <- game
game_found.mu.Lock()
fmt.Printf("CRC match: %s -> %s\n", romName, game.Name)
game_found.found = true
game_found.mu.Unlock()
}
}
wg.Done()
}(dat, crc, system)
}
// Synchronize all the goroutines
wg.Wait()
// then check if the game was found or not. If it wasn't pass it to
// FindByROMName. For some reason this isn't consistently working.
//fmt.Printf("%s: %v\n", romName, game_found.found)
return game_found.found
// if !game_found.found {
// db.FindByROMName(romPath, filepath.Base(romPath), crc, games)
// }
}

// FindByROMName loops over the Dats in the DB and concurrently matches ROM names.
func (db *DB) FindByROMName(romPath string, romName string, crc uint32, games chan (Game)) {
// I'm going to update this to do fuzzy matching. To me that means:
// - try to build a list with a mutex,
// - if there is an exact name match use that
// - otherwise at the end look through the potential matches with a few
// adjustments for country codes (hoping for exact match)
// - finally try to find a match without country code
// - before failing
func (db *DB) FindByROMName(romPath string, romName string, crc uint32, games chan (Game)) (bool) {
type SafeLookup struct {
mu sync.Mutex
options []Game
found bool
}
game_found := SafeLookup{found: false}
var wg sync.WaitGroup
wg.Add(len(*db))
// For every Dat in the DB
Expand All @@ -103,16 +141,57 @@ func (db *DB) FindByROMName(romPath string, romName string, crc uint32, games ch
// If the checksums match
for _, ROM := range game.ROMs {
if romName == ROM.Name {
fmt.Printf("Exact match: %s -> %s\n", romName, ROM.Name)
game.Path = romPath
game.System = system
games <- game
game_found.mu.Lock()
game_found.found = true
game_found.mu.Unlock()
} else {
var gameName = strings.Split(romName, ".")[0]
var gameExt = strings.Split(romName, ".")[1]
Copy link
Contributor

@igorcafe igorcafe Mar 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the file may contain multiple dots or even no dots.
I guess you could use filepath.Ext.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call!

if (strings.Contains(ROM.Name, gameName)) &&
(strings.Contains(ROM.Name, gameExt)) {
var option_has bool
for _, option := range game_found.options {
//fmt.Println(romName, option.Name)
if option.Name == game.Name {
option_has = true
}
}
if !(option_has) {
game_found.mu.Lock()
//fmt.Println(romName, game.Name)
game.Path = romPath
game.System = system
game_found.options = append(game_found.options, game)
game_found.mu.Unlock()
}
}
}
// element is the element from someSlice for where we are
}
}
wg.Done()
}(dat, crc, system)
}
// Synchronize all the goroutines
wg.Wait()
if !game_found.found {
if len(game_found.options) > 0 {
game_found.found = true
sort.SliceStable(game_found.options, func(i, j int) bool {
return len(game_found.options[i].Name) < len(game_found.options[j].Name)
})
for _, option := range game_found.options {
fmt.Printf("Fuzzy match: %s -> %s for %s\n", filepath.Base(romPath), option.Name, option.System)
games <- option
break
}
}
//if game_found.found == false {
// fmt.Printf("No match: %s\n", romName)
//}
}
return game_found.found
}
29 changes: 17 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,38 @@ module github.com/libretro/ludo

require (
github.com/adrg/xdg v0.4.0
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/cavaliercoder/grab v2.0.0+incompatible
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/disintegration/imaging v1.6.2
github.com/fatih/structs v1.1.0
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240118000515-a250818d05e3
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/kr/pretty v0.2.1
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mholt/archiver/v3 v3.5.1
github.com/pelletier/go-toml v1.9.5
github.com/tanema/gween v0.0.0-20221212145351-621cc8a459d1
github.com/youpy/go-wav v0.3.2
golang.org/x/image v0.15.0
golang.org/x/mobile v0.0.0-20240112133503-c713f31d574b
)

require (
github.com/andybalholm/brotli v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/klauspost/compress v1.17.6 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mholt/archiver/v3 v3.5.1
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/pelletier/go-toml v1.9.5
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/tanema/gween v0.0.0-20221212145351-621cc8a459d1
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/youpy/go-wav v0.3.2
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/youpy/go-riff v0.1.0 // indirect
github.com/zaf/g711 v1.4.0 // indirect
golang.org/x/image v0.15.0
golang.org/x/mobile v0.0.0-20240112133503-c713f31d574b
golang.org/x/sys v0.17.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.0 // indirect
)

go 1.13
go 1.18
Loading