mirror of
https://github.com/MaSzyna-EU07/StarterNG.git
synced 2026-11-14 04:05:50 +01:00
fix: find a scenery's image and timetables whatever the case of their names
The //$i image and a trainset's timetable are looked up through CaseInsensitivePaths, so on Linux they show when the scenery names them in other letter case than the disk has. A timetable written with backslashes is found there too, and with it the train number of a Hasler tape.
This commit is contained in:
@@ -182,6 +182,20 @@ public class TimetableLocatorTests
|
||||
Assert.NotNull(new TimetableLocator(files).Resolve(scenery, "r1.txt"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"rozklady\tgs3657")]
|
||||
[InlineData("ROZKLADY/TGS3657.TXT")]
|
||||
public void A_timetable_named_in_other_case_or_with_backslashes_is_found_as_on_disk(string name)
|
||||
{
|
||||
var files = new InMemoryFileSystem(caseSensitive: true)
|
||||
.WithFile(TestInstallation.At("scenery", "Braniewo.scn"), "//$n Braniewo")
|
||||
.WithFile(TestInstallation.At("scenery", "Rozklady", "TGS3657.txt"), "rozkład");
|
||||
var scenery = Assert.Single(new TestInstallation(files).Sceneries.LoadAll());
|
||||
|
||||
Assert.Equal(TestInstallation.At("scenery", "Rozklady", "TGS3657.txt"),
|
||||
new TimetableLocator(files).Resolve(scenery, name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void The_formats_none_and_a_missing_file_both_resolve_to_nothing()
|
||||
{
|
||||
|
||||
@@ -89,6 +89,23 @@ public class SceneryRepositoryTests
|
||||
Assert.Equal(Path.Combine("game", "scenery", "images", "kato.jpg"), image);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("calkowo_v2_kopalniaA.jpg", "game/scenery/images/calkowo_v2_kopalniaA.jpg")]
|
||||
[InlineData(@"Images\Calkowo_V2_KopalniaA.JPG", "game/scenery/images/calkowo_v2_kopalniaA.jpg")]
|
||||
[InlineData("CALKOWO_V2.JPG", "game/scenery/Calkowo_v2.jpg")]
|
||||
public void The_preview_image_is_found_whatever_the_case_it_is_named_in(string named, string onDisk)
|
||||
{
|
||||
var files = new InMemoryFileSystem(caseSensitive: true)
|
||||
.WithFile("game/scenery/calkowo.scn", "//$i " + named)
|
||||
.WithFile("game/scenery/images/calkowo_v2_kopalniaA.jpg", "binary")
|
||||
.WithFile("game/scenery/Calkowo_v2.jpg", "binary");
|
||||
var scenery = Assert.Single(Build(files, out _).LoadAll());
|
||||
|
||||
string? image = new SceneryImageLocator(files).Resolve(scenery);
|
||||
|
||||
Assert.Equal(Path.GetFullPath(onDisk), Path.GetFullPath(image!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void A_scenery_without_an_image_directive_resolves_to_nothing()
|
||||
{
|
||||
|
||||
@@ -130,6 +130,17 @@ public class TapeLaunchTests
|
||||
Assert.Null(new StarterNG.Infrastructure.Sceneries.TimetableLocator(new InMemoryFileSystem())
|
||||
.TrainNumber(new StarterNG.Domain.Sceneries.Scenery(TestInstallation.At("scenery", "td.scn"), ""), name));
|
||||
|
||||
[Fact]
|
||||
public void The_train_number_comes_from_a_timetable_named_in_other_case_with_backslashes()
|
||||
{
|
||||
var files = new InMemoryFileSystem(caseSensitive: true)
|
||||
.WithFile(TestInstallation.At("scenery", "Baltyk", "EIE1531.txt"), "[ Rodzaj i numer pociagu | EIE1531 ]\r\n");
|
||||
|
||||
Assert.Equal("EIE1531", new StarterNG.Infrastructure.Sceneries.TimetableLocator(files)
|
||||
.TrainNumber(new StarterNG.Domain.Sceneries.Scenery(TestInstallation.At("scenery", "td.scn"), ""),
|
||||
@"baltyk\eie1531"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void A_timetable_that_is_not_there_gives_no_train_number() =>
|
||||
Assert.Null(new StarterNG.Infrastructure.Sceneries.TimetableLocator(new InMemoryFileSystem())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using StarterNG.Application.Abstractions;
|
||||
using StarterNG.Domain.Sceneries;
|
||||
|
||||
@@ -8,11 +9,13 @@ namespace StarterNG.Infrastructure.Sceneries;
|
||||
public sealed class SceneryImageLocator
|
||||
{
|
||||
private readonly IFileSystem _files;
|
||||
private readonly CaseInsensitivePaths _names;
|
||||
private readonly Dictionary<string, string?> _cache = new();
|
||||
|
||||
public SceneryImageLocator(IFileSystem files)
|
||||
{
|
||||
_files = files;
|
||||
_names = new CaseInsensitivePaths(files);
|
||||
}
|
||||
|
||||
public string? Resolve(Scenery scenery)
|
||||
@@ -34,22 +37,23 @@ public sealed class SceneryImageLocator
|
||||
return null;
|
||||
|
||||
string name = scenery.ImageName.Replace('\\', '/').Trim();
|
||||
if (Path.IsPathFullyQualified(name))
|
||||
return _names.Find("", name);
|
||||
if (_files.FileExists(name))
|
||||
return name;
|
||||
|
||||
string sceneryDir = Path.GetDirectoryName(scenery.Path) ?? ".";
|
||||
string root = Path.GetDirectoryName(sceneryDir) ?? ".";
|
||||
|
||||
string[] candidates =
|
||||
(string Folder, string Name)[] candidates =
|
||||
{
|
||||
name,
|
||||
Path.Combine(root, name),
|
||||
Path.Combine(sceneryDir, name),
|
||||
Path.Combine(sceneryDir, "images", name),
|
||||
Path.Combine(root, "scenery", "images", name)
|
||||
(root, name),
|
||||
(sceneryDir, name),
|
||||
(sceneryDir, "images/" + name),
|
||||
(root, "scenery/images/" + name)
|
||||
};
|
||||
|
||||
foreach (string candidate in candidates)
|
||||
if (_files.FileExists(candidate))
|
||||
return candidate;
|
||||
|
||||
return null;
|
||||
return candidates.Select(candidate => _names.Find(candidate.Folder, candidate.Name))
|
||||
.FirstOrDefault(found => found is not null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@ public sealed class TimetableLocator
|
||||
RegexOptions.Multiline | RegexOptions.IgnoreCase);
|
||||
|
||||
private readonly IFileSystem _files;
|
||||
private readonly CaseInsensitivePaths _names;
|
||||
|
||||
public TimetableLocator(IFileSystem files)
|
||||
{
|
||||
_files = files;
|
||||
_names = new CaseInsensitivePaths(files);
|
||||
}
|
||||
|
||||
public string? Resolve(Scenery scenery, string? name)
|
||||
@@ -30,17 +32,19 @@ public sealed class TimetableLocator
|
||||
|
||||
string sceneryDir = Path.GetDirectoryName(scenery.Path) ?? ".";
|
||||
string root = Path.GetDirectoryName(sceneryDir) ?? ".";
|
||||
name = name.Replace('\\', '/');
|
||||
|
||||
string[] candidates =
|
||||
(string Folder, string Name)[] candidates =
|
||||
{
|
||||
Path.Combine(root, "timetables", name + ".txt"),
|
||||
Path.Combine(sceneryDir, name + ".txt"),
|
||||
Path.Combine(root, "scenario", name + ".txt"),
|
||||
Path.Combine(root, "timetables", name),
|
||||
Path.Combine(sceneryDir, name)
|
||||
(root, "timetables/" + name + ".txt"),
|
||||
(sceneryDir, name + ".txt"),
|
||||
(root, "scenario/" + name + ".txt"),
|
||||
(root, "timetables/" + name),
|
||||
(sceneryDir, name)
|
||||
};
|
||||
|
||||
return candidates.FirstOrDefault(_files.FileExists);
|
||||
return candidates.Select(candidate => _names.Find(candidate.Folder, candidate.Name))
|
||||
.FirstOrDefault(found => found is not null);
|
||||
}
|
||||
|
||||
/// <summary>The number the timetable gives its train; null with no timetable or no such heading in it.</summary>
|
||||
|
||||
Reference in New Issue
Block a user