Tests don't have to be in the same directory anymore; add sanity check; add instruction generation to lua file output
This commit is contained in:
parent
7033751d91
commit
4597a7f9ff
6 changed files with 181 additions and 27 deletions
|
@ -17,7 +17,7 @@ namespace AspectedRouting.IO.itinero1
|
|||
/// A dictionary containing the implementation of basic functions
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<string> LoadFunctions(List<string> names)
|
||||
private static IEnumerable<string> LoadFunctions(IEnumerable<string> names)
|
||||
{
|
||||
var imps = new List<string>();
|
||||
|
||||
|
@ -49,6 +49,7 @@ namespace AspectedRouting.IO.itinero1
|
|||
deps.Add("unitTestProfile");
|
||||
deps.Add("inv");
|
||||
deps.Add("double_compare");
|
||||
deps.Add("spoken_instructions");
|
||||
|
||||
var code = new List<string>();
|
||||
|
||||
|
|
|
@ -422,7 +422,6 @@ namespace AspectedRouting.IO.jsonParser
|
|||
{
|
||||
var expr = GetTopLevelExpression(e, context);
|
||||
|
||||
|
||||
var targetTypes = new List<Type>();
|
||||
foreach (var t in expr.Types)
|
||||
{
|
||||
|
|
127
AspectedRouting/IO/lua/spoken_instructions.lua
Normal file
127
AspectedRouting/IO/lua/spoken_instructions.lua
Normal file
|
@ -0,0 +1,127 @@
|
|||
-- instruction generators
|
||||
instruction_generators = {
|
||||
{
|
||||
applies_to = "", -- applies to all profiles when empty
|
||||
generators = {
|
||||
{
|
||||
name = "start",
|
||||
function_name = "get_start"
|
||||
},
|
||||
{
|
||||
name = "stop",
|
||||
function_name = "get_stop"
|
||||
},
|
||||
{
|
||||
name = "roundabout",
|
||||
function_name = "get_roundabout"
|
||||
},
|
||||
{
|
||||
name = "turn",
|
||||
function_name = "get_turn"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- gets the first instruction
|
||||
function get_start(route_position, language_reference, instruction)
|
||||
if route_position.is_first() then
|
||||
local direction = route_position.direction()
|
||||
instruction.text = itinero.format(language_reference.get("Start {0}."), language_reference.get(direction));
|
||||
instruction.shape = route_position.shape
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-- gets the last instruction
|
||||
function get_stop(route_position, language_reference, instruction)
|
||||
if route_position.is_last() then
|
||||
instruction.text = language_reference.get("Arrived at destination.");
|
||||
instruction.shape = route_position.shape
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
|
||||
-- gets a roundabout instruction
|
||||
function get_roundabout(route_position, language_reference, instruction)
|
||||
if route_position.attributes.junction == "roundabout" and
|
||||
(not route_position.is_last()) then
|
||||
local attributes = route_position.next().attributes
|
||||
if attributes.junction then
|
||||
else
|
||||
local exit = 1
|
||||
local count = 1
|
||||
local previous = route_position.previous()
|
||||
while previous and previous.attributes.junction == "roundabout" do
|
||||
local branches = previous.branches
|
||||
if branches then
|
||||
branches = branches.get_traversable()
|
||||
if branches.count > 0 then
|
||||
exit = exit + 1
|
||||
end
|
||||
end
|
||||
count = count + 1
|
||||
previous = previous.previous()
|
||||
end
|
||||
|
||||
instruction.text = itinero.format(language_reference.get("Take the {0}th exit at the next roundabout."), "" .. exit)
|
||||
if exit == 1 then
|
||||
instruction.text = itinero.format(language_reference.get("Take the first exit at the next roundabout."))
|
||||
elseif exit == 2 then
|
||||
instruction.text = itinero.format(language_reference.get("Take the second exit at the next roundabout."))
|
||||
elseif exit == 3 then
|
||||
instruction.text = itinero.format(language_reference.get("Take the third exit at the next roundabout."))
|
||||
end
|
||||
instruction.type = "roundabout"
|
||||
instruction.shape = route_position.shape
|
||||
return count
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
-- gets a turn
|
||||
function get_turn(route_position, language_reference, instruction)
|
||||
local relative_direction = route_position.relative_direction().direction
|
||||
|
||||
local turn_relevant = false
|
||||
local branches = route_position.branches
|
||||
if branches then
|
||||
branches = branches.get_traversable()
|
||||
if relative_direction == "straighton" and
|
||||
branches.count >= 2 then
|
||||
turn_relevant = true -- straight on at cross road
|
||||
end
|
||||
if relative_direction ~= "straighton" and
|
||||
branches.count > 0 then
|
||||
turn_relevant = true -- an actual normal turn
|
||||
end
|
||||
end
|
||||
|
||||
if relative_direction == "unknown" then
|
||||
turn_relevant = false -- turn could not be calculated.
|
||||
end
|
||||
|
||||
if turn_relevant then
|
||||
local next = route_position.next()
|
||||
local name = nil
|
||||
if next then
|
||||
name = next.attributes.name
|
||||
end
|
||||
if name then
|
||||
instruction.text = itinero.format(language_reference.get("Go {0} on {1}."),
|
||||
language_reference.get(relative_direction), name)
|
||||
instruction.shape = route_position.shape
|
||||
else
|
||||
instruction.text = itinero.format(language_reference.get("Go {0}."),
|
||||
language_reference.get(relative_direction))
|
||||
instruction.shape = route_position.shape
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
return 0
|
||||
end
|
|
@ -14,7 +14,7 @@ namespace AspectedRouting
|
|||
static class Program
|
||||
{
|
||||
public static IEnumerable<(AspectMetadata aspect, AspectTestSuite tests)> ParseAspects(
|
||||
this IEnumerable<string> jsonFileNames, Context context)
|
||||
this IEnumerable<string> jsonFileNames, List<string> testFileNames, Context context)
|
||||
{
|
||||
var aspects = new List<(AspectMetadata aspect, AspectTestSuite tests)>();
|
||||
foreach (var file in jsonFileNames)
|
||||
|
@ -22,22 +22,39 @@ namespace AspectedRouting
|
|||
var fi = new FileInfo(file);
|
||||
Console.WriteLine("Parsing " + file);
|
||||
var aspect = JsonParser.AspectFromJson(context, File.ReadAllText(file), fi.Name);
|
||||
if (aspect != null)
|
||||
{
|
||||
var testPath = fi.DirectoryName + "/" + aspect.Name + ".test.csv";
|
||||
AspectTestSuite tests = null;
|
||||
if (File.Exists(testPath))
|
||||
{
|
||||
tests = AspectTestSuite.FromString(aspect, File.ReadAllText(testPath));
|
||||
}
|
||||
if (aspect == null) continue;
|
||||
|
||||
aspects.Add((aspect, tests));
|
||||
|
||||
var testName = aspect.Name + ".test.csv";
|
||||
var testPath = testFileNames.FindTest(testName);
|
||||
AspectTestSuite tests = null;
|
||||
if (!string.IsNullOrEmpty(testPath) && File.Exists(testPath))
|
||||
{
|
||||
tests = AspectTestSuite.FromString(aspect, File.ReadAllText(testPath));
|
||||
}
|
||||
|
||||
aspects.Add((aspect, tests));
|
||||
}
|
||||
|
||||
return aspects;
|
||||
}
|
||||
|
||||
private static string FindTest(this IEnumerable<string> testFileNames, string testName)
|
||||
{
|
||||
var testPaths = testFileNames.Where(nm => nm.EndsWith(testName)).ToList();
|
||||
if (testPaths.Count > 1)
|
||||
{
|
||||
Console.WriteLine("[WARNING] Multiple tests found for " + testName + ", using only one arbitrarily");
|
||||
}
|
||||
|
||||
if (testPaths.Count > 0)
|
||||
{
|
||||
return testPaths.First();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static LuaPrinter GenerateLua(Context context,
|
||||
IEnumerable<(AspectMetadata aspect, AspectTestSuite tests)> aspects,
|
||||
ProfileMetaData profile, List<ProfileTestSuite> profileTests)
|
||||
|
@ -71,7 +88,7 @@ namespace AspectedRouting
|
|||
}
|
||||
|
||||
private static IEnumerable<(ProfileMetaData profile, List<ProfileTestSuite> profileTests)> ParseProfiles(
|
||||
IEnumerable<string> jsonFiles, Context context)
|
||||
IEnumerable<string> jsonFiles, IReadOnlyCollection<string> testFiles, Context context)
|
||||
{
|
||||
var result = new List<(ProfileMetaData profile, List<ProfileTestSuite> profileTests)>();
|
||||
foreach (var jsonFile in jsonFiles)
|
||||
|
@ -87,13 +104,11 @@ namespace AspectedRouting
|
|||
|
||||
profile.SanityCheckProfile(context);
|
||||
|
||||
var profileFi = new FileInfo(jsonFile);
|
||||
var profileTests = new List<ProfileTestSuite>();
|
||||
foreach (var behaviourName in profile.Behaviours.Keys)
|
||||
{
|
||||
var path = profileFi.DirectoryName + "/" + profile.Name + "." + behaviourName +
|
||||
".behaviour_test.csv";
|
||||
if (File.Exists(path))
|
||||
var path = testFiles.FindTest($"{profile.Name}.{behaviourName}.behaviour_test.csv");
|
||||
if (path != null && File.Exists(path))
|
||||
{
|
||||
var test = ProfileTestSuite.FromString(context, profile, behaviourName,
|
||||
File.ReadAllText(path));
|
||||
|
@ -122,12 +137,13 @@ namespace AspectedRouting
|
|||
var behaviour = profile.Behaviours.Keys.First();
|
||||
do
|
||||
{
|
||||
Console.Write(behaviour + " > ");
|
||||
Console.Write(profile.Name + "." + behaviour + " > ");
|
||||
var read = Console.ReadLine();
|
||||
if (read == null)
|
||||
{
|
||||
return; // End of stream has been reached
|
||||
}
|
||||
|
||||
if (read.Equals("quit"))
|
||||
{
|
||||
return;
|
||||
|
@ -143,10 +159,11 @@ namespace AspectedRouting
|
|||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Behaviour not found. Known behaviours are:\n "+string.Join("\n ", profile.Behaviours.Keys));
|
||||
Console.WriteLine("Behaviour not found. Known behaviours are:\n " +
|
||||
string.Join("\n ", profile.Behaviours.Keys));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -202,16 +219,19 @@ namespace AspectedRouting
|
|||
var files = Directory.EnumerateFiles(inputDir, "*.json", SearchOption.AllDirectories)
|
||||
.ToList();
|
||||
|
||||
var tests = Directory.EnumerateFiles(inputDir, "*test.csv", SearchOption.AllDirectories)
|
||||
.ToList();
|
||||
|
||||
var context = new Context();
|
||||
|
||||
var aspects = ParseAspects(files, context);
|
||||
var aspects = ParseAspects(files, tests, context);
|
||||
|
||||
foreach (var (aspect, _) in aspects)
|
||||
{
|
||||
context.AddFunction(aspect.Name, aspect);
|
||||
}
|
||||
|
||||
var profiles = ParseProfiles(files, context);
|
||||
var profiles = ParseProfiles(files, tests, context);
|
||||
|
||||
|
||||
// With everything parsed and typechecked, time for tests
|
||||
|
@ -238,9 +258,8 @@ namespace AspectedRouting
|
|||
File.WriteAllText(outputDir + "/" + profile.Name + ".lua", luaPrinter.ToLua());
|
||||
}
|
||||
|
||||
Repl(context,
|
||||
profiles.First(p => p.profile.Name.Equals("rollerskate")).profile);
|
||||
|
||||
Repl(context,
|
||||
profiles.First(p => p.profile.Name.Equals("bicycle")).profile);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ namespace AspectedRouting.Tests
|
|||
"oneway "+Oneway,
|
||||
"speed "+Speed,
|
||||
"priority "+Priority,
|
||||
"because "+PriorityExplanation
|
||||
"because \n "+PriorityExplanation
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,12 +77,20 @@ namespace AspectedRouting.Tests
|
|||
weight = double.Parse(testData[3]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var expected = new ProfileResult(
|
||||
testData[0],
|
||||
testData[1],
|
||||
speed,
|
||||
weight
|
||||
);
|
||||
|
||||
if (expected.Priority == 0 && expected.Access != "no")
|
||||
{
|
||||
throw new ArgumentException("A priority of zero is interpreted as 'no access' - don't use it");
|
||||
}
|
||||
|
||||
var vals = testData.GetRange(4, testData.Count - 4);
|
||||
var tags = new Dictionary<string, string>();
|
||||
for (int i = 0; i < keys.Count; i++)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue