commit
4a1d1e0f09
12 changed files with 304 additions and 244 deletions
AspectedRouting.Test/Snippets
AspectedRouting
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AspectedRouting.IO.LuaSkeleton;
|
||||
using AspectedRouting.IO.LuaSnippets;
|
||||
|
@ -94,4 +95,26 @@ public class SnippetTests
|
|||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void ListDotWithHead_GeneratesLua()
|
||||
{
|
||||
// (dot head) (stringToTags (mapping speed $ parse))
|
||||
var eSub = Funcs.Dot.Apply(Funcs.Head,
|
||||
new Constant(new[]
|
||||
{
|
||||
Funcs.Head.Apply(Funcs.StringStringToTags.Apply(
|
||||
new Mapping(new List<string> { "_speed" }, new[] { Funcs.Parse }))),
|
||||
Funcs.Const.Apply(new Constant(Typs.Double, 42))
|
||||
})
|
||||
);
|
||||
var condition = Funcs.Dot.Apply(Funcs.Head, Funcs.StringStringToTags.Apply(
|
||||
new Mapping(new[] { "route" }, new[] { Funcs.Eq.Apply(new Constant("ferry")) })));
|
||||
var e =
|
||||
Funcs.IfDotted.Apply(condition, eSub);
|
||||
e = e.Apply(new LuaLiteral(Typs.Tags, "tags")).Finalize().Optimize(out _);
|
||||
var ctx = new Context();
|
||||
var lua = new LuaSkeleton(ctx, true);
|
||||
var code = IO.LuaSnippets.Snippets.Convert(lua, "varname", e);
|
||||
Console.WriteLine(code);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using AspectedRouting.IO.itinero1;
|
||||
|
@ -280,9 +281,9 @@ namespace AspectedRouting.IO.LuaSkeleton
|
|||
case IExpression e:
|
||||
return ToLua(e);
|
||||
case int i:
|
||||
return "" + i;
|
||||
return i.ToString(CultureInfo.InvariantCulture);
|
||||
case double d:
|
||||
return "" + d;
|
||||
return d.ToString(CultureInfo.InvariantCulture);
|
||||
case string s:
|
||||
return '"' + s.Replace("\"", "\\\"") + '"';
|
||||
case null:
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
@ -12,14 +13,14 @@ namespace AspectedRouting.IO.itinero1
|
|||
var contents = tags.Select(kv =>
|
||||
{
|
||||
var (key, value) = kv;
|
||||
var left = "[\"" + key + "\"]";
|
||||
var left = "[\"" + key .ToString(CultureInfo.InvariantCulture)+ "\"]";
|
||||
|
||||
if (Regex.IsMatch(key, "^[a-zA-Z][_a-zA-Z-9]*$"))
|
||||
{
|
||||
left = key;
|
||||
}
|
||||
|
||||
return $"{left} = \"{value}\"";
|
||||
return $"{left.ToString(CultureInfo.InvariantCulture)} = \"{value.ToString(CultureInfo.InvariantCulture)}\"";
|
||||
});
|
||||
return "{" + string.Join(", ", contents) + "}";
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using AspectedRouting.Tests;
|
||||
|
||||
|
@ -94,10 +95,10 @@ namespace AspectedRouting.IO.itinero1
|
|||
tags.Remove("#" + paramName);
|
||||
}
|
||||
|
||||
var expectedPriority = "" + expected.Priority;
|
||||
var expectedPriority = expected.Priority.ToString(CultureInfo.InvariantCulture);
|
||||
if (invertPriority)
|
||||
{
|
||||
expectedPriority = $"inv({expectedPriority})";
|
||||
expectedPriority = $"inv({expectedPriority.ToString(CultureInfo.InvariantCulture)})";
|
||||
}
|
||||
|
||||
// Generates something like:
|
||||
|
@ -106,7 +107,7 @@ namespace AspectedRouting.IO.itinero1
|
|||
$"unit_test_profile(behaviour_{testSuite.Profile.Name.AsLuaIdentifier()}_{testSuite.BehaviourName.AsLuaIdentifier()}, " +
|
||||
$"\"{testSuite.BehaviourName}\", " +
|
||||
$"{index}, " +
|
||||
$"{{access = \"{D(expected.Access)}\", speed = {expected.Speed}, oneway = \"{D(expected.Oneway)}\", priority = {expectedPriority} }}, " +
|
||||
$"{{access = \"{D(expected.Access)}\", speed = {expected.Speed.ToString(CultureInfo.InvariantCulture)}, oneway = \"{D(expected.Oneway)}\", priority = {expectedPriority} }}, " +
|
||||
tags.ToLuaTable() +
|
||||
")";
|
||||
}
|
||||
|
@ -151,8 +152,7 @@ namespace AspectedRouting.IO.itinero1
|
|||
|
||||
_skeleton.AddDep("unitTest");
|
||||
_skeleton.AddDep("debug_table");
|
||||
return
|
||||
$"unit_test({functionToApplyName.AsLuaIdentifier()}, \"{functionToApplyName}\", {index}, \"{expected}\", {parameters.ToLuaTable()}, {tags.ToLuaTable()})";
|
||||
return $"unit_test({functionToApplyName.AsLuaIdentifier()}, \"{functionToApplyName}\", {index.ToString(CultureInfo.InvariantCulture)}, \"{expected.ToString(CultureInfo.InvariantCulture)}\", {parameters.ToLuaTable()}, {tags.ToLuaTable()})";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace AspectedRouting.IO.LuaSnippets
|
|||
|
||||
var isString = cond.Types.First().Equals(Typs.String);
|
||||
result += Snippets.Convert(lua, c, cond) + "\n";
|
||||
result += $"if ( {c} or {c} == \"yes\" ) then \n";
|
||||
result += $"if ( {c} == true or {c} == \"yes\" ) then \n";
|
||||
result += " " + Snippets.Convert(lua, assignTo, ifTrue).Indent();
|
||||
|
||||
if (ifElse != null)
|
||||
|
|
|
@ -151,6 +151,8 @@ namespace AspectedRouting.IO.itinero1
|
|||
"test_all()",
|
||||
"if (not failed_tests and not failed_profile_tests) then",
|
||||
" print(\"Tests OK\")",
|
||||
"else",
|
||||
" error(\"Some tests failed\")",
|
||||
"end"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using AspectedRouting.IO.LuaSkeleton;
|
||||
using AspectedRouting.IO.LuaSnippets;
|
||||
|
@ -45,7 +46,7 @@ namespace AspectedRouting.IO.itinero2
|
|||
var exprInLua = _skeleton.ToLua(exprSpecialized);
|
||||
if (exprInLua.Contains("constRight") || exprInLua.Contains("firstArg"))
|
||||
throw new Exception("Not optimized properly:" + exprSpecialized.Repr());
|
||||
aspects.Add(weight + " * " + exprInLua);
|
||||
aspects.Add(weight.ToString(CultureInfo.InvariantCulture) + " * " + exprInLua.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
var scalingFactor = Funcs.Default.Apply(new Constant(Typs.Double, 1.0), _profile.ScalingFactor, tags)
|
||||
|
@ -90,14 +91,15 @@ If result.factor is positive, that is the cost.
|
|||
|
||||
There is no forward or backward, so this should always be the same for the same attributes
|
||||
*/
|
||||
|
||||
var parameters = _profile.Behaviours[_behaviourName];
|
||||
var tags = new LuaLiteral(Typs.Tags, "attributes");
|
||||
var hasAccess = _profile.ObstacleAccess.Apply(tags).SpecializeToSmallestType().Optimize(out _);
|
||||
var code = new List<string>
|
||||
{
|
||||
"--[[ Function called by itinero2 on every turn restriction relation", " ]]",
|
||||
"function turn_cost_factor(attributes, result)",
|
||||
|
||||
" local parameters = default_parameters()",
|
||||
_parameterPrinter.DeclareParametersFor(parameters),
|
||||
"local has_access",
|
||||
Snippets.Convert(_skeleton, "has_access", hasAccess),
|
||||
"if ( has_access == \"no\" or has_access == \"false\") then",
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AspectedRouting.IO.itinero1;
|
||||
|
@ -29,7 +28,7 @@ namespace AspectedRouting.IO.itinero2
|
|||
private readonly string _behaviourName;
|
||||
private readonly IEnumerable<BehaviourTestSuite> _behaviourTestSuite;
|
||||
private readonly Context _context;
|
||||
private readonly DateTime _lastChangeTime;
|
||||
private readonly bool _includeTests;
|
||||
private readonly LuaParameterPrinter _parameterPrinter;
|
||||
private readonly ProfileMetaData _profile;
|
||||
|
||||
|
@ -39,7 +38,7 @@ namespace AspectedRouting.IO.itinero2
|
|||
public LuaPrinter2(ProfileMetaData profile, string behaviourName,
|
||||
Context context,
|
||||
List<AspectTestSuite> aspectTests, IEnumerable<BehaviourTestSuite> behaviourTestSuite,
|
||||
DateTime lastChangeTime)
|
||||
bool includeTests = true)
|
||||
{
|
||||
_skeleton = new LuaSkeleton.LuaSkeleton(context, true);
|
||||
_profile = profile;
|
||||
|
@ -47,29 +46,61 @@ namespace AspectedRouting.IO.itinero2
|
|||
_context = context;
|
||||
_aspectTests = aspectTests;
|
||||
_behaviourTestSuite = behaviourTestSuite;
|
||||
_lastChangeTime = lastChangeTime;
|
||||
_includeTests = includeTests;
|
||||
_parameterPrinter = new LuaParameterPrinter(_profile, _skeleton);
|
||||
}
|
||||
|
||||
private string TestRunner()
|
||||
{
|
||||
return new List<string>
|
||||
{
|
||||
"if (itinero == nil) then",
|
||||
" itinero = {}",
|
||||
" itinero.log = print",
|
||||
"",
|
||||
" -- Itinero is not defined -> we are running from a lua interpreter -> the tests are intended",
|
||||
" runTests = true",
|
||||
"",
|
||||
"",
|
||||
"else",
|
||||
" print = itinero.log",
|
||||
"end",
|
||||
"",
|
||||
"test_all()",
|
||||
"if (not failed_tests and not failed_profile_tests and print ~= nil) then",
|
||||
$" print(\"Tests OK ({_profile.Name}.{_behaviourName})\")",
|
||||
"else",
|
||||
" error(\"Some tests failed\")",
|
||||
"end"
|
||||
}.Lined();
|
||||
}
|
||||
|
||||
public string ToLua()
|
||||
{
|
||||
var profileDescr = _profile.Behaviours[_behaviourName]["description"].Evaluate(_context).ToString();
|
||||
var header =
|
||||
new List<string> {
|
||||
new List<string>
|
||||
{
|
||||
$"name = \"{_profile.Name}.{_behaviourName}\"",
|
||||
$"description = \"{profileDescr} ({_profile.Description})\"",
|
||||
"",
|
||||
"-- The hierarchy of types that this vehicle is; mostly used to check access restrictions",
|
||||
$"vehicle_types = "+_skeleton.ToLua(new Constant( _profile.VehicleTyps.Select(v => new Constant(v)).ToArray()))
|
||||
"vehicle_types = " +
|
||||
_skeleton.ToLua(new Constant(_profile.VehicleTyps.Select(v => new Constant(v)).ToArray()))
|
||||
};
|
||||
|
||||
var testPrinter = new LuaTestPrinter(_skeleton,
|
||||
new List<string> { "unitTestProfile2" });
|
||||
var tests = testPrinter.GenerateFullTestSuite(
|
||||
_behaviourTestSuite.ToList(),
|
||||
new List<AspectTestSuite>(),
|
||||
true);
|
||||
var all = new List<string> {
|
||||
var tests = "";
|
||||
if (_includeTests) {
|
||||
var testPrinter = new LuaTestPrinter(_skeleton,
|
||||
new List<string> { "unitTestProfile2" });
|
||||
tests = testPrinter.GenerateFullTestSuite(
|
||||
_behaviourTestSuite.ToList(),
|
||||
new List<AspectTestSuite>(),
|
||||
true) + "\n\n" + TestRunner();
|
||||
}
|
||||
|
||||
var all = new List<string>
|
||||
{
|
||||
header.Lined(),
|
||||
"",
|
||||
GenerateMainFunction(),
|
||||
|
@ -87,25 +118,7 @@ namespace AspectedRouting.IO.itinero2
|
|||
"",
|
||||
string.Join("\n\n", _skeleton.GenerateConstants()),
|
||||
"",
|
||||
tests,
|
||||
"",
|
||||
|
||||
"if (itinero == nil) then",
|
||||
" itinero = {}",
|
||||
" itinero.log = print",
|
||||
"",
|
||||
" -- Itinero is not defined -> we are running from a lua interpreter -> the tests are intended",
|
||||
" runTests = true",
|
||||
"",
|
||||
"",
|
||||
"else",
|
||||
" print = itinero.log",
|
||||
"end",
|
||||
"",
|
||||
"test_all()",
|
||||
"if (not failed_tests and not failed_profile_tests and print ~= nil) then",
|
||||
$" print(\"Tests OK ({_profile.Name}.{_behaviourName})\")",
|
||||
"end"
|
||||
tests
|
||||
};
|
||||
|
||||
return all.Lined();
|
||||
|
|
|
@ -14,6 +14,6 @@ function if_then_else_dotted(conditionf, thnf, elsef, arg)
|
|||
if (condition) then
|
||||
return applyIfNeeded(thnf, arg)
|
||||
else
|
||||
return applyIfNeeded(elsef, arg) -- if no third parameter is given, 'els' will be nil
|
||||
return applyIfNeeded(elsef, arg) -- if no third parameter is given, 'else' will be nil
|
||||
end
|
||||
end
|
|
@ -45,6 +45,8 @@ namespace AspectedRouting.Language
|
|||
AddParams(profile.Access, "profile definition for " + profile.Name + ".access");
|
||||
AddParams(profile.Oneway, "profile definition for " + profile.Name + ".oneway");
|
||||
AddParams(profile.Speed, "profile definition for " + profile.Name + ".speed");
|
||||
AddParams(profile.ObstacleAccess, "profile definition for " + profile.Name + ".obstacleaccess");
|
||||
AddParams(profile.ObstacleCost, "profile definition for " + profile.Name + ".obstaclecost");
|
||||
|
||||
foreach (var (key, expr) in profile.Priority)
|
||||
{
|
||||
|
|
148
AspectedRouting/Printer.cs
Normal file
148
AspectedRouting/Printer.cs
Normal file
|
@ -0,0 +1,148 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using AspectedRouting.IO.itinero1;
|
||||
using AspectedRouting.IO.itinero2;
|
||||
using AspectedRouting.IO.md;
|
||||
using AspectedRouting.Language;
|
||||
using AspectedRouting.Language.Expression;
|
||||
using AspectedRouting.Tests;
|
||||
|
||||
namespace AspectedRouting
|
||||
{
|
||||
/**
|
||||
* Prints to the specified location
|
||||
*/
|
||||
public class Printer
|
||||
{
|
||||
private readonly List<(AspectMetadata aspect, AspectTestSuite tests)> _aspects;
|
||||
private readonly Context _context;
|
||||
private readonly string _outputDirectory;
|
||||
private readonly ProfileMetaData _profile;
|
||||
private readonly List<BehaviourTestSuite> _profileTests;
|
||||
private readonly bool _includeTests;
|
||||
|
||||
public Printer(string outputDirectory, ProfileMetaData profile, Context context,
|
||||
List<(AspectMetadata aspect, AspectTestSuite tests)> aspects,
|
||||
List<BehaviourTestSuite> profileTests, bool includeTests)
|
||||
{
|
||||
_outputDirectory = outputDirectory;
|
||||
_profile = profile;
|
||||
_context = context;
|
||||
_aspects = aspects;
|
||||
_profileTests = profileTests;
|
||||
_includeTests = includeTests;
|
||||
|
||||
|
||||
if (!Directory.Exists($"{outputDirectory}/profile-documentation/")) {
|
||||
Directory.CreateDirectory($"{outputDirectory}/profile-documentation/");
|
||||
}
|
||||
|
||||
if (!Directory.Exists($"{outputDirectory}/itinero1/")) {
|
||||
Directory.CreateDirectory($"{outputDirectory}/itinero1/");
|
||||
}
|
||||
|
||||
if (!Directory.Exists($"{outputDirectory}/itinero2/")) {
|
||||
Directory.CreateDirectory($"{outputDirectory}/itinero2/");
|
||||
}
|
||||
}
|
||||
|
||||
public void PrintUsedTags()
|
||||
{
|
||||
var profile = _profile;
|
||||
var context = _context;
|
||||
Console.WriteLine("\n\n\n---------- " + profile.Name +
|
||||
" : used tags and corresponding values --------------");
|
||||
foreach (var (key, values) in profile.AllExpressions(context).PossibleTags()) {
|
||||
var vs = "*";
|
||||
if (values.Any()) {
|
||||
vs = string.Join(", ", values);
|
||||
}
|
||||
|
||||
Console.WriteLine(key + ": " + vs);
|
||||
}
|
||||
|
||||
Console.WriteLine("\n\n\n------------------------");
|
||||
}
|
||||
|
||||
public void WriteProfile1()
|
||||
{
|
||||
var aspectTests = _aspects.Select(a => a.tests).ToList();
|
||||
|
||||
var luaProfile = new LuaPrinter1(_profile, _context,
|
||||
aspectTests,
|
||||
_profileTests
|
||||
).ToLua();
|
||||
|
||||
var itinero1ProfileFile = Path.Combine($"{_outputDirectory}/itinero1/" + _profile.Name + ".lua");
|
||||
File.WriteAllText(itinero1ProfileFile, luaProfile);
|
||||
Console.WriteLine($"Written {new FileInfo(itinero1ProfileFile).FullName}");
|
||||
}
|
||||
|
||||
public void WriteAllProfile2()
|
||||
{
|
||||
foreach (var (behaviourName,_) in _profile.Behaviours) {
|
||||
WriteProfile2(behaviourName);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteProfile2(string behaviourName)
|
||||
{
|
||||
var aspectTests = _aspects.Select(a => a.tests).ToList();
|
||||
|
||||
var lua2behaviour = new LuaPrinter2(
|
||||
_profile,
|
||||
behaviourName,
|
||||
_context,
|
||||
aspectTests,
|
||||
_profileTests.Where(testsSuite => testsSuite.BehaviourName == behaviourName),
|
||||
_includeTests
|
||||
).ToLua();
|
||||
|
||||
var itinero2ProfileFile = Path.Combine($"{_outputDirectory}/itinero2/{_profile.Name}.{behaviourName}.lua");
|
||||
File.WriteAllText(
|
||||
itinero2ProfileFile,
|
||||
lua2behaviour);
|
||||
Console.WriteLine($"Written {new FileInfo(itinero2ProfileFile).FullName}");
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void PrintMdInfo()
|
||||
{
|
||||
var profileMd = new MarkDownSection();
|
||||
profileMd.AddTitle(_profile.Name, 1);
|
||||
|
||||
profileMd.Add(_profile.Description);
|
||||
profileMd.AddTitle("Default parameters", 4);
|
||||
profileMd.Add("| name | value | ", "| ---- | ---- | ",
|
||||
string.Join("\n",
|
||||
_profile.DefaultParameters.Select(delegate(KeyValuePair<string, IExpression> kv)
|
||||
{
|
||||
var v = kv.Value.Evaluate(_context);
|
||||
if (!(v is string || v is int || v is double)) {
|
||||
v = "_special value_";
|
||||
}
|
||||
|
||||
return $" | {kv.Key} | {v} |";
|
||||
}))
|
||||
);
|
||||
foreach (var (behaviourName, vars) in _profile.Behaviours) {
|
||||
var behaviourMd = new ProfileToMD(_profile, behaviourName, _context);
|
||||
|
||||
File.WriteAllText(
|
||||
$"{_outputDirectory}/profile-documentation/{_profile.Name}.{behaviourName}.md",
|
||||
behaviourMd.ToString());
|
||||
profileMd.AddTitle($"[{behaviourName}](./{_profile.Name}.{behaviourName}.md)", 2);
|
||||
profileMd.Add(vars["description"].Evaluate(_context).ToString());
|
||||
profileMd.Add(behaviourMd.MainFormula());
|
||||
}
|
||||
|
||||
File.WriteAllText(
|
||||
$"{_outputDirectory}/profile-documentation/{_profile.Name}.md",
|
||||
profileMd.ToString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using AspectedRouting.IO;
|
||||
using AspectedRouting.IO.itinero1;
|
||||
using AspectedRouting.IO.itinero2;
|
||||
using AspectedRouting.IO.jsonParser;
|
||||
using AspectedRouting.IO.md;
|
||||
using AspectedRouting.Language;
|
||||
using AspectedRouting.Language.Expression;
|
||||
using AspectedRouting.Tests;
|
||||
|
@ -19,13 +18,11 @@ namespace AspectedRouting
|
|||
this IEnumerable<string> jsonFileNames, List<string> testFileNames, Context context)
|
||||
{
|
||||
var aspects = new List<(AspectMetadata aspect, AspectTestSuite tests)>();
|
||||
foreach (var file in jsonFileNames)
|
||||
{
|
||||
foreach (var file in jsonFileNames) {
|
||||
var fi = new FileInfo(file);
|
||||
|
||||
var aspect = JsonParser.AspectFromJson(context, File.ReadAllText(file), fi.Name);
|
||||
if (aspect == null)
|
||||
{
|
||||
if (aspect == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -33,8 +30,7 @@ namespace AspectedRouting
|
|||
var testName = aspect.Name + ".test.csv";
|
||||
var testPath = testFileNames.FindTest(testName);
|
||||
AspectTestSuite tests = null;
|
||||
if (!string.IsNullOrEmpty(testPath) && File.Exists(testPath))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(testPath) && File.Exists(testPath)) {
|
||||
tests = AspectTestSuite.FromString(aspect, File.ReadAllText(testPath));
|
||||
}
|
||||
|
||||
|
@ -47,13 +43,11 @@ namespace AspectedRouting
|
|||
private static string FindTest(this IEnumerable<string> testFileNames, string testName)
|
||||
{
|
||||
var testPaths = testFileNames.Where(nm => nm.EndsWith(testName)).ToList();
|
||||
if (testPaths.Count > 1)
|
||||
{
|
||||
if (testPaths.Count > 1) {
|
||||
Console.WriteLine("[WARNING] Multiple tests found for " + testName + ", using only one arbitrarily");
|
||||
}
|
||||
|
||||
if (testPaths.Count > 0)
|
||||
{
|
||||
if (testPaths.Count > 0) {
|
||||
return testPaths.First();
|
||||
}
|
||||
|
||||
|
@ -66,43 +60,35 @@ namespace AspectedRouting
|
|||
{
|
||||
var result = new List<(ProfileMetaData profile, List<BehaviourTestSuite> profileTests)>();
|
||||
foreach (var jsonFile in jsonFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
try {
|
||||
var profile =
|
||||
JsonParser.ProfileFromJson(context, File.ReadAllText(jsonFile), new FileInfo(jsonFile),
|
||||
lastChange);
|
||||
if (profile == null)
|
||||
{
|
||||
if (profile == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
profile.SanityCheckProfile(context);
|
||||
|
||||
var profileTests = new List<BehaviourTestSuite>();
|
||||
foreach (var behaviourName in profile.Behaviours.Keys)
|
||||
{
|
||||
foreach (var behaviourName in profile.Behaviours.Keys) {
|
||||
var path = testFiles.FindTest($"{profile.Name}.{behaviourName}.behaviour_test.csv");
|
||||
if (path != null && File.Exists(path))
|
||||
{
|
||||
if (path != null && File.Exists(path)) {
|
||||
var test = BehaviourTestSuite.FromString(context, profile, behaviourName,
|
||||
File.ReadAllText(path));
|
||||
profileTests.Add(test);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
Console.WriteLine($"[{profile.Name}] WARNING: no test found for behaviour {behaviourName}");
|
||||
}
|
||||
}
|
||||
|
||||
result.Add((profile, profileTests));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
catch (Exception e) {
|
||||
// PrintError(jsonFile, e);
|
||||
throw new Exception("In the file " + jsonFile, e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -111,28 +97,23 @@ namespace AspectedRouting
|
|||
{
|
||||
var profile = profiles["emergency_vehicle"];
|
||||
var behaviour = profile.Behaviours.Keys.First();
|
||||
do
|
||||
{
|
||||
do {
|
||||
Console.Write(profile.Name + "." + behaviour + " > ");
|
||||
var read = Console.ReadLine();
|
||||
if (read == null)
|
||||
{
|
||||
if (read == null) {
|
||||
return; // End of stream has been reached
|
||||
}
|
||||
|
||||
if (read == "")
|
||||
{
|
||||
if (read == "") {
|
||||
Console.WriteLine("looƆ sᴉ dɐWʇǝǝɹʇSuǝdO");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (read.Equals("quit"))
|
||||
{
|
||||
if (read.Equals("quit")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (read.Equals("help"))
|
||||
{
|
||||
if (read.Equals("help")) {
|
||||
Console.WriteLine(
|
||||
Utils.Lines(
|
||||
"select <behaviourName> to change behaviour or <vehicle.behaviourName> to change vehicle",
|
||||
|
@ -140,40 +121,31 @@ namespace AspectedRouting
|
|||
continue;
|
||||
}
|
||||
|
||||
if (read.Equals("clear"))
|
||||
{
|
||||
for (var i = 0; i < 80; i++)
|
||||
{
|
||||
Console.WriteLine();
|
||||
}
|
||||
if (read.Equals("clear")) {
|
||||
for (var i = 0; i < 80; i++) Console.WriteLine();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (read.StartsWith("select"))
|
||||
{
|
||||
if (read.StartsWith("select")) {
|
||||
var beh = read.Substring("select".Length + 1).Trim();
|
||||
|
||||
if (beh.Contains("."))
|
||||
{
|
||||
if (beh.Contains(".")) {
|
||||
var profileName = beh.Split(".")[0];
|
||||
if (!profiles.TryGetValue(profileName, out var newProfile))
|
||||
{
|
||||
if (!profiles.TryGetValue(profileName, out var newProfile)) {
|
||||
Console.Error.WriteLine("Profile " + profileName + " not found, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
||||
profile = newProfile;
|
||||
beh = beh.Substring(beh.IndexOf(".") + 1);
|
||||
beh = beh.Substring(beh.IndexOf(".", StringComparison.Ordinal) + 1);
|
||||
}
|
||||
|
||||
if (profile.Behaviours.ContainsKey(beh))
|
||||
{
|
||||
if (profile.Behaviours.ContainsKey(beh)) {
|
||||
behaviour = beh;
|
||||
Console.WriteLine("Switched to " + beh);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
Console.WriteLine("Behaviour not found. Known behaviours are:\n " +
|
||||
string.Join("\n ", profile.Behaviours.Keys));
|
||||
}
|
||||
|
@ -184,34 +156,27 @@ namespace AspectedRouting
|
|||
|
||||
var tagsRaw = read.Split(";").Select(s => s.Trim());
|
||||
var tags = new Dictionary<string, string>();
|
||||
foreach (var str in tagsRaw)
|
||||
{
|
||||
if (str == "")
|
||||
{
|
||||
foreach (var str in tagsRaw) {
|
||||
if (str == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
try {
|
||||
var strSplit = str.Split("=");
|
||||
var k = strSplit[0].Trim();
|
||||
var v = strSplit[1].Trim();
|
||||
tags[k] = v;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
catch (Exception) {
|
||||
Console.Error.WriteLine("Could not parse tag: " + str);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
var result = profile.Run(c, behaviour, tags);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
catch (Exception e) {
|
||||
Console.WriteLine(e);
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
|
@ -221,8 +186,7 @@ namespace AspectedRouting
|
|||
private static void PrintError(string file, Exception exception)
|
||||
{
|
||||
var msg = exception.Message;
|
||||
while (exception.InnerException != null)
|
||||
{
|
||||
while (exception.InnerException != null) {
|
||||
exception = exception.InnerException;
|
||||
msg += "\n " + exception.Message;
|
||||
}
|
||||
|
@ -230,113 +194,29 @@ namespace AspectedRouting
|
|||
Console.WriteLine($"Error in the file {file}:\n {msg}");
|
||||
}
|
||||
|
||||
private static void PrintUsedTags(ProfileMetaData profile, Context context)
|
||||
{
|
||||
Console.WriteLine("\n\n\n---------- " + profile.Name + " : used tags and corresponding values --------------");
|
||||
foreach (var (key, values) in profile.AllExpressions(context).PossibleTags())
|
||||
{
|
||||
var vs = "*";
|
||||
if (values.Any())
|
||||
{
|
||||
vs = string.Join(", ", values);
|
||||
}
|
||||
|
||||
Console.WriteLine(key + ": " + vs);
|
||||
}
|
||||
|
||||
Console.WriteLine("\n\n\n------------------------");
|
||||
}
|
||||
|
||||
private static int Main(string[] args)
|
||||
{
|
||||
var errMessage = MainWithError(args);
|
||||
if (errMessage == null) return 0;
|
||||
if (errMessage == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Console.WriteLine(errMessage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
private static void WriteOutputFiles(Context context,
|
||||
List<(AspectMetadata aspect, AspectTestSuite tests)> aspects, string outputDir,
|
||||
List<(ProfileMetaData profile, List<BehaviourTestSuite> profileTests)> profiles, DateTime lastChange)
|
||||
List<(ProfileMetaData profile, List<BehaviourTestSuite> profileTests)> profiles, bool includeTests)
|
||||
{
|
||||
if (!Directory.Exists($"{outputDir}/profile-documentation/"))
|
||||
{
|
||||
Directory.CreateDirectory($"{outputDir}/profile-documentation/");
|
||||
}
|
||||
|
||||
if (!Directory.Exists($"{outputDir}/itinero1/"))
|
||||
{
|
||||
Directory.CreateDirectory($"{outputDir}/itinero1/");
|
||||
}
|
||||
|
||||
if (!Directory.Exists($"{outputDir}/itinero2/"))
|
||||
{
|
||||
Directory.CreateDirectory($"{outputDir}/itinero2/");
|
||||
}
|
||||
|
||||
foreach (var (profile, profileTests) in profiles)
|
||||
{
|
||||
PrintUsedTags(profile, context);
|
||||
|
||||
var aspectTests = aspects.Select(a => a.tests).ToList();
|
||||
var luaProfile = new LuaPrinter1(profile, context,
|
||||
aspectTests,
|
||||
profileTests
|
||||
).ToLua();
|
||||
|
||||
var itinero1ProfileFile = Path.Combine($"{outputDir}/itinero1/" + profile.Name + ".lua");
|
||||
File.WriteAllText(itinero1ProfileFile, luaProfile);
|
||||
Console.WriteLine($"Written {(new FileInfo(itinero1ProfileFile)).FullName}");
|
||||
|
||||
var profileMd = new MarkDownSection();
|
||||
profileMd.AddTitle(profile.Name, 1);
|
||||
|
||||
profileMd.Add(profile.Description);
|
||||
profileMd.AddTitle("Default parameters", 4);
|
||||
profileMd.Add("| name | value | ", "| ---- | ---- | ",
|
||||
string.Join("\n",
|
||||
profile.DefaultParameters.Select(delegate (KeyValuePair<string, IExpression> kv)
|
||||
{
|
||||
var v = kv.Value.Evaluate(context);
|
||||
if (!(v is string || v is int || v is double))
|
||||
{
|
||||
v = "_special value_";
|
||||
}
|
||||
return $" | {kv.Key} | {v} |";
|
||||
}))
|
||||
);
|
||||
|
||||
foreach (var (behaviourName, vars) in profile.Behaviours)
|
||||
{
|
||||
var lua2behaviour = new LuaPrinter2(
|
||||
profile,
|
||||
behaviourName,
|
||||
context,
|
||||
aspectTests,
|
||||
profileTests.Where(testsSuite => testsSuite.BehaviourName == behaviourName),
|
||||
lastChange
|
||||
).ToLua();
|
||||
|
||||
var itinero2ProfileFile = Path.Combine($"{outputDir}/itinero2/{profile.Name}.{behaviourName}.lua");
|
||||
File.WriteAllText(
|
||||
itinero2ProfileFile,
|
||||
lua2behaviour);
|
||||
Console.WriteLine($"Written {(new FileInfo(itinero2ProfileFile)).FullName}");
|
||||
|
||||
var behaviourMd = new ProfileToMD(profile, behaviourName, context);
|
||||
|
||||
File.WriteAllText(
|
||||
$"{outputDir}/profile-documentation/{profile.Name}.{behaviourName}.md",
|
||||
behaviourMd.ToString());
|
||||
profileMd.AddTitle($"[{behaviourName}](./{profile.Name}.{behaviourName}.md)", 2);
|
||||
profileMd.Add(vars["description"].Evaluate(context).ToString());
|
||||
profileMd.Add(behaviourMd.MainFormula());
|
||||
}
|
||||
|
||||
File.WriteAllText(
|
||||
$"{outputDir}/profile-documentation/{profile.Name}.md",
|
||||
profileMd.ToString());
|
||||
foreach (var (profile, profileTests) in profiles) {
|
||||
var printer = new Printer(outputDir, profile, context, aspects, profileTests, includeTests);
|
||||
printer.PrintUsedTags();
|
||||
printer.WriteProfile1();
|
||||
printer.PrintMdInfo();
|
||||
printer.WriteAllProfile2();
|
||||
}
|
||||
|
||||
File.WriteAllText($"{outputDir}/ProfileMetadata.json",
|
||||
|
@ -349,16 +229,19 @@ namespace AspectedRouting
|
|||
|
||||
public static string MainWithError(string[] args)
|
||||
{
|
||||
if (args.Length < 2)
|
||||
{
|
||||
return "Usage: <directory where all aspects and profiles can be found> <outputdirectory>";
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false);
|
||||
if (args.Length < 2) {
|
||||
return
|
||||
"Usage: <directory where all aspects and profiles can be found> <outputdirectory> [--include-tests]\n" +
|
||||
"The flag '--include-tests' will append some self-tests in the lua files";
|
||||
}
|
||||
|
||||
var inputDir = args[0];
|
||||
var outputDir = args[1];
|
||||
var includeTests = args.Contains("--include-tests");
|
||||
var runRepl = !args.Contains("--no-repl");
|
||||
|
||||
if (!Directory.Exists(outputDir))
|
||||
{
|
||||
if (!Directory.Exists(outputDir)) {
|
||||
Directory.CreateDirectory(outputDir);
|
||||
}
|
||||
|
||||
|
@ -373,10 +256,8 @@ namespace AspectedRouting
|
|||
.ToList();
|
||||
tests.Sort();
|
||||
|
||||
foreach (var test in tests)
|
||||
{
|
||||
if (test.EndsWith(".test.csv") || test.EndsWith(".behaviour_test.csv"))
|
||||
{
|
||||
foreach (var test in tests) {
|
||||
if (test.EndsWith(".test.csv") || test.EndsWith(".behaviour_test.csv")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -388,17 +269,12 @@ namespace AspectedRouting
|
|||
|
||||
var aspects = ParseAspects(files, tests, context);
|
||||
|
||||
foreach (var (aspect, _) in aspects)
|
||||
{
|
||||
context.AddFunction(aspect.Name, aspect);
|
||||
}
|
||||
foreach (var (aspect, _) in aspects) context.AddFunction(aspect.Name, aspect);
|
||||
|
||||
var lastChange = DateTime.UnixEpoch;
|
||||
foreach (var file in files)
|
||||
{
|
||||
foreach (var file in files) {
|
||||
var time = new FileInfo(file).LastWriteTimeUtc;
|
||||
if (lastChange < time)
|
||||
{
|
||||
if (lastChange < time) {
|
||||
lastChange = time;
|
||||
}
|
||||
}
|
||||
|
@ -409,40 +285,32 @@ namespace AspectedRouting
|
|||
// With everything parsed and typechecked, time for tests
|
||||
var testsOk = true;
|
||||
foreach (var (aspect, t) in aspects)
|
||||
{
|
||||
if (t == null)
|
||||
{
|
||||
if (t == null) {
|
||||
Console.WriteLine($"[{aspect.Name}] WARNING: no tests found: please add {aspect.Name}.test.csv");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
testsOk &= t.Run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var (profile, profileTests) in profiles)
|
||||
foreach (var test in profileTests)
|
||||
{
|
||||
testsOk &= test.Run(context);
|
||||
}
|
||||
foreach (var test in profileTests)
|
||||
testsOk &= test.Run(context);
|
||||
|
||||
if (testsOk)
|
||||
{
|
||||
WriteOutputFiles(context, aspects, outputDir, profiles, lastChange);
|
||||
if (testsOk) {
|
||||
WriteOutputFiles(context, aspects, outputDir, profiles, includeTests);
|
||||
}
|
||||
|
||||
|
||||
if (!args.Contains("--no-repl"))
|
||||
{
|
||||
if (runRepl) {
|
||||
Repl(context, profiles
|
||||
.Select(p => p.profile)
|
||||
.ToDictionary(p => p.Name, p => p));
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
Console.WriteLine("Not starting REPL as --no-repl is specified");
|
||||
}
|
||||
|
||||
return !testsOk ? "Some tests failed, quitting now without generating output" : null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue