Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,6 @@ FodyWeavers.xsd

# Built Visual Studio Code Extensions
*.vsix

# Advent of Code session cookie - DO NOT COMMIT
.aoc-session
100 changes: 4 additions & 96 deletions AoC/AoC.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand All @@ -12,101 +12,9 @@
</ItemGroup>

<ItemGroup>
<None Update="Input\_2022\01.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\06.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\05.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\04.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\03.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\02.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\07.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\08.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\09.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\10.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\11.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\12.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\13.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\14.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\15.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\16.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\17.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\18.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\19.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\20.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\21.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\22.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\23.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\24.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2022\25.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2024\01.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2024\07.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2024\06.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2024\05.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2024\04.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2024\03.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Input\_2024\02.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<!-- Copy all input files to output directory -->
<None Update="Input\**\*.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

Expand Down
5 changes: 5 additions & 0 deletions AoC/Input/_2025/01.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
100
200
300
400
500
184 changes: 169 additions & 15 deletions AoC/Interface/AoCDay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,190 @@
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using AoC.Services;

namespace AoC.Interface
{
public abstract class AoCDay
{
protected List<TestCase> TestCases { get; } = new List<TestCase>();

public string[] GetInput()
{
var res = File.ReadAllLines($"Input/{GetType().Namespace[^5..]}/{GetType().Name.Replace("Day", "")}.txt");
if (res.Length == 0)
var year = int.Parse(GetType().Namespace![^4..]);
var day = int.Parse(GetType().Name.Replace("Day", ""));

// Use paths relative to the executable location
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
var inputPath = Path.Combine(baseDir, "Input", $"_{year}", $"{day:D2}.txt");
var sourceInputPath = Path.Combine(baseDir, "..", "..", "..", "Input", $"_{year}", $"{day:D2}.txt");

// Check if input file exists and has content
if (File.Exists(inputPath) && new FileInfo(inputPath).Length > 0)
{
return File.ReadAllLines(inputPath);
}

// Try automated fetch if session cookie is configured
if (AoCConfig.HasSessionCookie())
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("No input found!");
Console.ForegroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Use clipboard to set input? (y/n)");
Console.WriteLine($"Input file not found. Attempting to fetch from adventofcode.com...");
Console.ForegroundColor = ConsoleColor.White;
if (Console.ReadKey() is ConsoleKeyInfo key && key.Key == ConsoleKey.Y)

var client = new AoCClient();
var input = client.FetchInputAsync(year, day).GetAwaiter().GetResult();

if (!string.IsNullOrEmpty(input))
{
var input = GetText();
File.WriteAllLines($"Input/{GetType().Namespace[^5..]}/{GetType().Name.Replace("Day", "")}.txt", input.Split(Environment.NewLine));
File.WriteAllLines($"../../../Input/{GetType().Namespace[^5..]}/{GetType().Name.Replace("Day", "")}.txt", input.Split(Environment.NewLine));
Console.SetCursorPosition(0, Console.CursorTop);
// Ensure directory exists
Directory.CreateDirectory(Path.GetDirectoryName(inputPath)!);
Directory.CreateDirectory(Path.GetDirectoryName(sourceInputPath)!);

// Save to both locations
var lines = input.Split('\n');
File.WriteAllLines(inputPath, lines);
File.WriteAllLines(sourceInputPath, lines);

Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Input saved to file: " + $"Input/{GetType().Namespace[^5..]}/{GetType().Name.Replace("Day", "")}.txt");
Console.WriteLine($"✓ Input saved to: {inputPath}");
Console.ForegroundColor = ConsoleColor.White;
res = input.Split(Environment.NewLine);

return lines;
}
}

return res;
// Fallback to clipboard method
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("No input found!");
Console.ForegroundColor = ConsoleColor.White;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("Use clipboard to set input? (y/n)");
Console.ForegroundColor = ConsoleColor.White;
if (Console.ReadKey() is ConsoleKeyInfo key && key.Key == ConsoleKey.Y)
{
var input = GetText();
Directory.CreateDirectory(Path.GetDirectoryName(inputPath)!);
Directory.CreateDirectory(Path.GetDirectoryName(sourceInputPath)!);
File.WriteAllLines(inputPath, input.Split(Environment.NewLine));
File.WriteAllLines(sourceInputPath, input.Split(Environment.NewLine));
Console.SetCursorPosition(0, Console.CursorTop);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Input saved to file: {inputPath}");
Console.ForegroundColor = ConsoleColor.White;
return input.Split(Environment.NewLine);
}

return Array.Empty<string>();
}

public abstract void RunPart1();
public abstract void RunPart2();

// Optional: Override these for automated testing
public virtual string? SolvePart1(string[] input) => null;
public virtual string? SolvePart2(string[] input) => null;

protected void AddTestCase(string input, string? expectedPart1 = null, string? expectedPart2 = null)
{
TestCases.Add(new TestCase
{
Input = input.Split('\n'),
ExpectedPart1 = expectedPart1,
ExpectedPart2 = expectedPart2
});
}

public bool RunTests(int part)
{
if (TestCases.Count == 0)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("No test cases defined.");
Console.ForegroundColor = ConsoleColor.White;
return true;
}

Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"\n▶ Running {TestCases.Count} test case(s) for Part {part}...");
Console.ForegroundColor = ConsoleColor.White;

bool allPassed = true;
for (int i = 0; i < TestCases.Count; i++)
{
var testCase = TestCases[i];
var expected = part == 1 ? testCase.ExpectedPart1 : testCase.ExpectedPart2;

if (expected == null)
continue;

var result = part == 1 ? SolvePart1(testCase.Input) : SolvePart2(testCase.Input);

if (result == expected)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($" ✓ Test {i + 1} passed: {result}");
Console.ForegroundColor = ConsoleColor.White;
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($" ✗ Test {i + 1} failed:");
Console.WriteLine($" Expected: {expected}");
Console.WriteLine($" Got: {result}");
Console.ForegroundColor = ConsoleColor.White;
allPassed = false;
}
}

return allPassed;
}

public async Task<bool> SubmitAnswer(int part, string answer)
{
if (!AoCConfig.HasSessionCookie())
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Cannot submit: Session cookie not configured.");
Console.ForegroundColor = ConsoleColor.White;
return false;
}

var year = int.Parse(GetType().Namespace![^4..]);
var day = int.Parse(GetType().Name.Replace("Day", ""));

var client = new AoCClient();
var result = await client.SubmitAnswerAsync(year, day, part, answer);

if (result.Success)
{
if (result.IsCorrect)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"\n{result.Message}");
Console.ForegroundColor = ConsoleColor.White;
return true;
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"\n{result.Message}");
Console.ForegroundColor = ConsoleColor.White;
return false;
}
}
else
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"\n{result.Message}");
if (result.WaitTimeSeconds.HasValue)
{
Console.WriteLine($"Please wait {result.WaitTimeSeconds} seconds before trying again.");
}
Console.ForegroundColor = ConsoleColor.White;
return false;
}
}

private static string GetText()
{
var powershell = new Process
Expand All @@ -61,4 +208,11 @@ private static string GetText()
return text.TrimEnd();
}
}

public class TestCase
{
public string[] Input { get; set; } = Array.Empty<string>();
public string? ExpectedPart1 { get; set; }
public string? ExpectedPart2 { get; set; }
}
}
Loading