Compare commits

..

3 Commits

Author SHA1 Message Date
08d2d528c7 added test for game scanning 2026-01-05 14:49:48 +01:00
a9588b079a improved game scanning 2026-01-05 14:49:32 +01:00
d826646a5a implmented rename subcommand 2026-01-05 13:28:33 +01:00
4 changed files with 187 additions and 13 deletions

View File

@@ -9,8 +9,13 @@ type ScanCmd struct {
File string `arg:"positional"`
}
type RenameCmd struct {
File string `arg:"positional"`
}
type args struct {
Scan *ScanCmd `arg:"subcommand:scan"`
Rename *RenameCmd `arg:"subcommand:rename"`
}
func Run() {
@@ -20,5 +25,7 @@ func Run() {
switch {
case args.Scan != nil:
oplcli.Scan(args.Scan.File, oplcli.Config{})
case args.Rename != nil:
oplcli.Rename(args.Rename.File, oplcli.Config{})
}
}

View File

@@ -23,23 +23,39 @@ func scanGameFileForID(filename string) (string, error) {
return "", fmt.Errorf("failed to read file: %w", err)
}
pattern := regexp.MustCompile(`(SLUS|SLES|SLPS|SCUS|SCES|SCPS)[_-]?\d{3}[\._]\d{2}`)
match := pattern.Find(buffer[:n])
if match != nil {
gameID := string(match)
return normalizeGameID(gameID), nil
id, found := scanBufferForID(buffer[:n])
if !found {
return "", fmt.Errorf("no PS2 game ID found in file")
}
return "", fmt.Errorf("no PS2 game ID found in file")
return id, nil
}
func scanBufferForID(buffer []byte) (string, bool) {
pattern := regexp.MustCompile(`(SLUS|SLES|SLPS|SCUS|SCES|SCPS)[_\-\s]?\d{3}[\._\-\s]?\d{2}`)
match := pattern.Find(buffer)
if match != nil {
gameID := string(match)
return normalizeGameID(gameID), true
}
return "", false
}
func normalizeGameID(id string) string {
s := strings.ReplaceAll(id, "_", "-")
s = strings.ReplaceAll(s, ".", "")
s = strings.ToUpper(s)
re := regexp.MustCompile(`(?i)^([A-Z]{4})[^0-9]*([0-9]{3})[^0-9]*([0-9]{2})$`)
id = strings.TrimSpace(id)
return s
matches := re.FindStringSubmatch(id)
if len(matches) != 4 {
return ""
}
prefix := strings.ToUpper(matches[1])
number := matches[2] + matches[3]
return prefix + "-" + number
}
func renameGameFile(filePath, gameName string) (string, error) {
@@ -67,4 +83,3 @@ func renameGameFile(filePath, gameName string) (string, error) {
return newPath, nil
}

122
internal/gamefile_test.go Normal file
View File

@@ -0,0 +1,122 @@
package oplcli
import "testing"
func TestParseCases(t *testing.T) {
var testData = []struct {
name string
content []byte
expected string
wantErr bool
}{
{
name: "SLUS with underscore and dot",
content: []byte("Some binary data\x00\x00SLUS_123.45\x00\x00more data"),
expected: "SLUS-12345",
},
{
name: "SLUS with hyphen",
content: []byte("\x00\x00\x00SLUS-12345\x00\x00\x00"),
expected: "SLUS-12345",
},
{
name: "SLES format",
content: []byte("Header data\x00SLES_987.65\x00footer"),
expected: "SLES-98765",
},
{
name: "SLPS format",
content: []byte("\xFF\xFESLPS_456.78\x00"),
expected: "SLPS-45678",
},
{
name: "SCUS format",
content: []byte("SCUS-97512"),
expected: "SCUS-97512",
},
{
name: "No separator format",
content: []byte("\x00\x00SLUS12345\x00\x00"),
expected: "SLUS-12345",
},
{
name: "With spaces",
content: []byte("SLUS 123.45"),
expected: "SLUS-12345",
},
{
name: "No game ID found",
content: []byte("Just some random data without any game ID"),
expected: "",
},
{
name: "Invalid game ID format",
content: []byte("SLUS-ABC.DE"),
expected: "",
},
}
for _, tt := range testData {
t.Run(tt.name, func(t *testing.T) {
gameID, found := scanBufferForID(tt.content)
if tt.expected == "" && found {
t.Errorf("Found game id where none should be found: %s", gameID)
}
if tt.expected == "" && !found {
return
}
if tt.expected != gameID {
t.Errorf("Expected %s got %s", tt.expected, gameID)
}
})
}
}
func TestNormalize(t *testing.T) {
testData := []struct {
input string
expected string
}{
{
input: "SLUS-12345",
expected: "SLUS-12345",
},
{
input: "SLES_987.65",
expected: "SLES-98765",
},
{
input: "SLPS_456.78",
expected: "SLPS-45678",
},
{
input: "scus-97512",
expected: "SCUS-97512",
},
{
input: "SLUS12345",
expected: "SLUS-12345",
},
{
input: "SLUS123.45",
expected: "SLUS-12345",
},
{
input: "SLUs123.45",
expected: "SLUS-12345",
},
}
for _, tt := range testData {
t.Run(tt.input, func(t *testing.T) {
normalized := normalizeGameID(tt.input)
if normalized != tt.expected {
t.Errorf("Expected %s got %s", tt.expected, normalized)
}
})
}
}

View File

@@ -22,8 +22,38 @@ func Scan(file string, config Config) {
gameList, err := loadGamelist("./ps2-gameslist.txt")
if err != nil {
fmt.Printf("Failed to load game list: %v", err)
os.Exit(1)
}
gameName := gameList[gameID]
fmt.Printf("Found game name: %s\n", gameName)
}
func Rename(file string, config Config) {
fmt.Printf("Scanning file: %s\n", file)
gameID, err := scanGameFileForID(file)
if err != nil {
fmt.Printf("Failed to scan game file: %s", err)
os.Exit(1)
}
fmt.Printf("Found game ID: %s\n", gameID)
gameList, err := loadGamelist("./ps2-gameslist.txt")
if err != nil {
fmt.Printf("Failed to load game list: %v", err)
os.Exit(1)
}
gameName := gameList[gameID]
fmt.Printf("Found game name: %s\n", gameName)
newPath, err := renameGameFile(file, gameName)
if err != nil {
fmt.Printf("Failed to rename file: %v", err)
os.Exit(1)
}
fmt.Printf("Renamed %s to %s", file, newPath)
}