static void Main(string[] args) { try { Console.WriteLine(Figgle.FiggleFonts.Standard.Render("Frisia Generator")); logger.Info(appName); logger.Info("Filip Liwiński (c) 2019"); Console.WriteLine(); // Setup configuration source var appSettings = "appsettings.json"; string projectPath = AppDomain.CurrentDomain.BaseDirectory; var configuration = new ConfigurationBuilder() .SetBasePath(projectPath) .AddJsonFile(appSettings) .Build(); var rewriterSection = configuration.GetSection("Rewriter"); var loopIterations = Convert.ToUInt32(rewriterSection.GetSection("LoopIterations").Value); var visitUnsatisfiablePaths = Convert.ToBoolean(rewriterSection.GetSection("VisitUnsatisfiablePaths").Value); var visitTimeoutPaths = Convert.ToBoolean(rewriterSection.GetSection("VisitTimeoutPaths").Value); var logFoundBranches = Convert.ToBoolean(rewriterSection.GetSection("LogFoundBranches").Value); var writeRewrittenCodeToFile = Convert.ToBoolean(rewriterSection.GetSection("WriteRewrittenCodeToFile").Value); var timeout = Convert.ToByte(rewriterSection.GetSection("TimeoutInSeconds").Value); logger.Info($"Loop iterations: {loopIterations}\nTimeout: {timeout}s\n"); var solver = new Z3Solver(); var generator = new ParamsGenerator(logger, solver, loopIterations, visitUnsatisfiablePaths, visitTimeoutPaths, logFoundBranches, timeout); StartAsync(logger, solver, generator, args, writeRewrittenCodeToFile, loopIterations).Wait(); } catch (Exception ex) { if (debug) { logger.Error(ex); } else { logger.Fatal(ex); } } LogManager.Flush(); Console.WriteLine("\n\nPress any key to close..."); Console.ReadKey(); }
public void While_loop_should_be_converted_to_if_statements() { foreach (var tc in TestCases) { try { // Debugging if (!string.IsNullOrEmpty(TestToDebug) && tc.Key != TestToDebug) { continue; } // Arrange var rootNode = CSharpSyntaxTree.ParseText(tc.Value).GetRoot(); var methods = rootNode.DescendantNodes().OfType <MethodDeclarationSyntax>(); foreach (var m in methods) { var conditions = new List <ExpressionSyntax>(); var solver = new Z3Solver(); var sms = new SymbolicMemoryState(m.ParameterList.Parameters); var rewriter = new FrisiaSyntaxRewriter(conditions, m.ParameterList.Parameters, sms, solver, null, LoopIterations, visitUnsatPaths: true, visitTimeoutPaths: true, logFoundBranches: false, timeout: 5); // Act var rewrittenNode = rewriter.Visit(m); //Assert var whileStatements = rootNode.DescendantNodes().OfType <WhileStatementSyntax>().ToArray(); foreach (var whileStatement in whileStatements) { var whileCondition = (BinaryExpressionSyntax)whileStatement.Condition; var rewrittenIfStatements = rewrittenNode.DescendantNodes().OfType <IfStatementSyntax>().Where(s => s.Condition.ToString() == whileCondition.ToString()).ToArray(); Assert.NotEmpty(rewrittenIfStatements); } var rewrittenWhileStatements = rewrittenNode.DescendantNodes().OfType <WhileStatementSyntax>().ToArray(); Assert.Empty(rewrittenWhileStatements); } } catch (Exception ex) { throw new TestCaseFailedException(tc.Key, ex); } } }
public void Single_child_in_block_with_parent_of_kind_block_should_be_moved_one_level_up() { // Arrange var rootNode = CSharpSyntaxTree.ParseText(@" using System; namespace Frisia.CodeReduction { class Program { public static void Method(int a) { { { { Console.WriteLine (""First content in block.""); } { Console.WriteLine (""Second content in block.""); } } } } } } ").GetRoot(); var m = rootNode.DescendantNodes().OfType <MethodDeclarationSyntax>().First(); var conditions = new List <ExpressionSyntax>(); var solver = new Z3Solver(); var sms = new SymbolicMemoryState(m.ParameterList.Parameters); var rewriter = new FrisiaSyntaxRewriter(conditions, m.ParameterList.Parameters, sms, solver, null, LoopIterations, visitUnsatPaths: true, visitTimeoutPaths: true, logFoundBranches: false, timeout: 5); // Act var rewrittenNode = rewriter.Visit(rootNode); var blockStatementsWithParentBlockAndSingleChild = rootNode.DescendantNodes().OfType <BlockSyntax>() .Where(b => b.Parent.Kind() == SK.Block && b.ChildNodes().Count() == 1); var rewrittenBlockStatementsWithParentBlockAndSingleChild = rewrittenNode.DescendantNodes().OfType <BlockSyntax>() .Where(b => b.Parent.Kind() == SK.Block && b.ChildNodes().Count() == 1); // Assert Assert.NotEmpty(blockStatementsWithParentBlockAndSingleChild); Assert.Empty(rewrittenBlockStatementsWithParentBlockAndSingleChild); }
public void Rewritten_TestCases_should_exists() { foreach (var tc in TestCases) { // Debugging if (!string.IsNullOrEmpty(TestToDebug) && tc.Key != TestToDebug) { continue; } var timer = new Stopwatch(); // Arrange var rootNode = CSharpSyntaxTree.ParseText(tc.Value).GetRoot(); var methods = rootNode.DescendantNodes().OfType <MethodDeclarationSyntax>(); foreach (var m in methods) { var conditions = new List <ExpressionSyntax>(); var solver = new Z3Solver(); var sms = new SymbolicMemoryState(m.ParameterList.Parameters); var rewriter = new FrisiaSyntaxRewriter(conditions, m.ParameterList.Parameters, sms, solver, null, LoopIterations, visitUnsatPaths: true, visitTimeoutPaths: true, logFoundBranches: false, timeout: 5); // Act timer.Start(); var rewrittenNode = (MethodDeclarationSyntax)rewriter.Visit(m); timer.Stop(); rootNode = rootNode.ReplaceNode(m, rewrittenNode); } var directory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..\\..\\..\\")) + "TestCasesRewritten\\"; var path = $"{directory}{tc.Key}"; var rewrittenNodeText = $"// This code was generated by Frisia.Rewriter.{Environment.NewLine}// Loop iterations: {LoopIterations}{Environment.NewLine}// Date: {DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss")}{Environment.NewLine}// Time: {timer.Elapsed}{Environment.NewLine}{Environment.NewLine}{rootNode.ToFullString()}"; File.WriteAllText(path, rewrittenNodeText); // Assert Assert.True(File.Exists(path)); } }
public void Each_block_statement_should_contain_single_statement() { foreach (var tc in TestCases) { try { // Debugging if (!string.IsNullOrEmpty(TestToDebug) && tc.Key != TestToDebug) { continue; } // Arrange var rootNode = CSharpSyntaxTree.ParseText(tc.Value).GetRoot(); var methods = rootNode.DescendantNodes().OfType <MethodDeclarationSyntax>(); foreach (var m in methods) { var conditions = new List <ExpressionSyntax>(); var solver = new Z3Solver(); var sms = new SymbolicMemoryState(m.ParameterList.Parameters); var rewriter = new FrisiaSyntaxRewriter(conditions, m.ParameterList.Parameters, sms, solver, null, LoopIterations, visitUnsatPaths: true, visitTimeoutPaths: true, logFoundBranches: false, timeout: 5); // Act var rewrittenNode = rewriter.Visit(m); var blocks = rewrittenNode.DescendantNodes().OfType <BlockSyntax>(); // Assert Assert.All(blocks, b => b.ChildNodes().OfType <StatementSyntax>().Where(x => x.Kind() != SK.ExpressionStatement && x.Kind() != SK.LocalDeclarationStatement).SingleOrDefault()); } } catch (Exception ex) { throw new TestCaseFailedException(tc.Key, ex); } } }
public void If_statement_should_not_contain_logical_OR_expression() { foreach (var tc in TestCases) { try { // Debugging if (!string.IsNullOrEmpty(TestToDebug) && tc.Key != TestToDebug) { continue; } // Arrange var rootNode = CSharpSyntaxTree.ParseText(tc.Value).GetRoot(); var methods = rootNode.DescendantNodes().OfType <MethodDeclarationSyntax>(); foreach (var m in methods) { var conditions = new List <ExpressionSyntax>(); var solver = new Z3Solver(); var sms = new SymbolicMemoryState(m.ParameterList.Parameters); var rewriter = new FrisiaSyntaxRewriter(conditions, m.ParameterList.Parameters, sms, solver, null, LoopIterations, visitUnsatPaths: true, visitTimeoutPaths: true, logFoundBranches: false, timeout: 5); // Act var rewrittenNode = rewriter.Visit(m); //Assert var rewrittenIfStatements = rewrittenNode.DescendantNodes().OfType <IfStatementSyntax>(); Assert.All(rewrittenIfStatements, s => Assert.True(s.Condition.Kind() != SK.LogicalOrExpression)); } } catch (Exception ex) { throw new TestCaseFailedException(tc.Key, ex); } } }
//TODO: make this more pretty public static void Main(string[] args) { var cliApp = new CommandLineApplication(); var xivPathOpt = cliApp.Option("-p |--game-path <pathToFFXIV>", "Path to the FFXIV game install (folder containing boot and game)", CommandOptionType.SingleValue); var configOpt = cliApp.Option("-c |--config-path <pathToYaml>", "Path to configuration YAML file, default to config.yaml", CommandOptionType.SingleValue); var excludedOpt = cliApp.Option("-X |--exclude <itemId>", "Item ids of items to exclude from solving", CommandOptionType.MultipleValue); var minIlvlOpt = cliApp.Option("-m |--min-itemlevel <ilvl>", "Minimum item level of items to consider. Uses max-20 if not passed.", CommandOptionType.SingleValue); var maxIlvlOpt = cliApp.Option("-M |--max-itemlevel <ilvl>", "Maximum item level of items to consider", CommandOptionType.SingleValue); var maxOvermeldTierOpt = cliApp.Option("-T |--max-overmeld-tier <tier>", "The max tier of materia allowed for overmelds", CommandOptionType.SingleValue); var noMaximizeUnweightedOpt = cliApp.Option("--no-maximize-unweighted", "Choose to disable maximizing unweighted stats (usually accuracy). Shouldn't be needed.", CommandOptionType.NoValue); var solverOpt = cliApp.Option("-s |--solver <solver>", "Solver to use (default: GLPK)", CommandOptionType.SingleValue); var debugOpt = cliApp.Option("-d |--debug", "Print the used models in the current directory as model.lp", CommandOptionType.NoValue); var jobArg = cliApp.Argument("<job>", "Enter the job abbreviation to solve for"); cliApp.HelpOption("-h |--help"); cliApp.OnExecute(() => { if (jobArg.Value == null) { Console.Error.WriteLine("You must provide a job to solve for."); return(1); } if (!xivPathOpt.HasValue()) { Console.Error.WriteLine("You must provide a path to FFXIV!"); return(1); } var realm = new ARealmReversed(xivPathOpt.Value(), Language.English); var xivColl = realm.GameData; var deserializer = new DeserializerBuilder() .WithTypeConverter(new BaseParamConverter(xivColl)) .WithTypeConverter(new ClassJobConverter(xivColl)) .WithNamingConvention(new CamelCaseNamingConvention()) .Build(); AppConfig config = null; using (var s = new FileStream(configOpt.HasValue() ? configOpt.Value() : "config.yaml", FileMode.Open)) { config = deserializer.Deserialize <AppConfig>(new StreamReader(s)); } var classJob = xivColl.GetSheet <ClassJob>().Single(x => x.Abbreviation == jobArg.Value); var jobConfig = config.JobConfigs[classJob]; var items = xivColl.GetSheet <Item>().ToList(); if (excludedOpt.HasValue()) { var excludedIds = new List <int>(); foreach (var excluded in excludedOpt.Values) { var id = int.Parse(excluded); var item = xivColl.Items[id]; if (item != null) { Console.WriteLine($"Excluding {item}."); excludedIds.Add(id); } else { Console.Error.WriteLine($"Unknown id {id}, ignoring."); } } items = items.Where(k => !excludedIds.Contains(k.Key)).ToList(); } var equip = items.OfType <Equipment>().Where(e => e.ClassJobCategory.ClassJobs.Contains(classJob)); var maxIlvl = equip.Max(x => x.ItemLevel.Key); if (maxIlvlOpt.HasValue()) { maxIlvl = int.Parse(maxIlvlOpt.Value()); } var minIlvl = maxIlvl - 20; if (minIlvlOpt.HasValue()) { minIlvl = int.Parse(minIlvlOpt.Value()); } equip = equip.Where(e => e.ItemLevel.Key >= minIlvl && e.ItemLevel.Key <= maxIlvl).ToList(); var food = items.Where(FoodItem.IsFoodItem).Select(t => new FoodItem(t)); var materia = items.OfType <MateriaItem>() .ToDictionary(i => i, i => !maxOvermeldTierOpt.HasValue() || i.Tier < int.Parse(maxOvermeldTierOpt.Value())); var relicCaps = equip.Where(e => config.RelicCaps.ContainsKey(e.ItemLevel.Key)) .ToDictionary(e => e, e => config.RelicCaps[e.ItemLevel.Key]); //TODO: improve solver handling SolverBase solver = new GLPKSolver(); if (solverOpt.HasValue()) { switch (solverOpt.Value()) { case "Gurobi": solver = new GurobiSolver(); break; case "Z3": solver = new Z3Solver(); break; } } using (var scope = new ModelScope()) { var model = new BisModel(jobConfig.Weights, jobConfig.StatRequirements, config.BaseStats, equip, food, materia, relicCaps, maximizeUnweightedValues: !noMaximizeUnweightedOpt.HasValue()); if (debugOpt.HasValue()) { using (var f = new FileStream("model.lp", FileMode.Create)) { var obj = model.Model.Objectives.First(); obj.Expression = obj.Expression.Normalize(); model.Model.Constraints.ForEach(c => c.Expression = c.Expression.Normalize()); model.Model.Write(f, FileType.LP); } } var solution = solver.Solve(model.Model); model.ApplySolution(solution); Console.WriteLine("Gear: "); model.ChosenGear.ForEach(Console.WriteLine); Console.WriteLine("Materia: "); model.ChosenMateria.ForEach(Console.WriteLine); if (model.ChosenRelicStats.Any()) { Console.WriteLine("Relic stats: "); model.ChosenRelicStats.ForEach(Console.WriteLine); } Console.WriteLine("Food: "); Console.WriteLine(model.ChosenFood); Console.WriteLine("Allocated stats: "); model.ResultAllocatableStats.ForEach(kv => Console.WriteLine(kv)); Console.WriteLine("Result stats with food:"); model.ResultTotalStats.ForEach(kv => Console.WriteLine(kv)); Console.WriteLine($"Result stat weight: {model.ResultWeight}"); } return(0); }); cliApp.Execute(args); }
public void AND_expressions_should_be_replaced_correctly() { // Arrange var rootNode = CSharpSyntaxTree.ParseText(@" using System; namespace Frisia.CodeReduction { class Program { public static void Method(int a, int b) { if (a > 0 && b > 0) { Console.WriteLine(""a > 0 && b > 0""); if (a > 1 && b > 1) { Console.WriteLine(""a > 1 && b > 1""); if (a > 2 && b > 2) { Console.WriteLine(""a > 2 && b > 2""); } else { Console.WriteLine(""!(a > 2 && b > 2)""); } } else { Console.WriteLine(""!(a > 1 && b > 1)""); if (a > 2 && b > 2) { Console.WriteLine(""a > 2 && b > 2""); } else { Console.WriteLine(""!(a > 2 && b > 2)""); } } } else { Console.WriteLine(""!(a > 0 && b > 0)""); if (a < 1 && b < 1) { Console.WriteLine(""a < 1 && b < 1""); if (a < 2 && b < 2) { Console.WriteLine(""a < 2 && b < 2""); } else { Console.WriteLine(""!(a < 2 && b < 2)""); } } else { Console.WriteLine(""!(a < 1 && b < 1)""); if (a < 2 && b < 2) { Console.WriteLine(""a < 2 && b < 2""); } else { Console.WriteLine(""!(a < 2 && b < 2)""); } } } } } } ").GetRoot(); var methods = rootNode.DescendantNodes().OfType <MethodDeclarationSyntax>(); foreach (var m in methods) { var conditions = new List <ExpressionSyntax>(); var solver = new Z3Solver(); var sms = new SymbolicMemoryState(m.ParameterList.Parameters); var rewriter = new FrisiaSyntaxRewriter(conditions, m.ParameterList.Parameters, sms, solver, null, LoopIterations, visitUnsatPaths: true, visitTimeoutPaths: true, logFoundBranches: false, timeout: 5); // Act var rewrittenNode = rewriter.Visit(rootNode); //var ifStatements = rootNode.DescendantNodes().OfType<IfStatementSyntax>().ToArray(); var rewrittenIfStatements = rewrittenNode.DescendantNodes().OfType <IfStatementSyntax>().ToArray(); // Assert Assert.Equal(26, rewrittenIfStatements.Length); } }