add compile & test worker
This commit is contained in:
120
src/LiquidCode.Tester.Worker/Services/PackageParserService.cs
Normal file
120
src/LiquidCode.Tester.Worker/Services/PackageParserService.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System.IO.Compression;
|
||||
using LiquidCode.Tester.Common.Models;
|
||||
|
||||
namespace LiquidCode.Tester.Worker.Services;
|
||||
|
||||
public class PackageParserService : IPackageParserService
|
||||
{
|
||||
private readonly ILogger<PackageParserService> _logger;
|
||||
|
||||
public PackageParserService(ILogger<PackageParserService> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<ProblemPackage> ParsePackageAsync(Stream packageStream)
|
||||
{
|
||||
var workingDirectory = Path.Combine(Path.GetTempPath(), $"problem_{Guid.NewGuid()}");
|
||||
Directory.CreateDirectory(workingDirectory);
|
||||
|
||||
_logger.LogInformation("Extracting package to {WorkingDirectory}", workingDirectory);
|
||||
|
||||
try
|
||||
{
|
||||
// Extract ZIP archive
|
||||
using var archive = new ZipArchive(packageStream, ZipArchiveMode.Read);
|
||||
archive.ExtractToDirectory(workingDirectory);
|
||||
|
||||
var package = new ProblemPackage
|
||||
{
|
||||
WorkingDirectory = workingDirectory
|
||||
};
|
||||
|
||||
// Find tests directory
|
||||
var testsDir = Path.Combine(workingDirectory, "tests");
|
||||
if (!Directory.Exists(testsDir))
|
||||
{
|
||||
_logger.LogWarning("Tests directory not found, searching for test files in root");
|
||||
testsDir = workingDirectory;
|
||||
}
|
||||
|
||||
// Parse test cases
|
||||
var inputFiles = Directory.GetFiles(testsDir, "*", SearchOption.AllDirectories)
|
||||
.Where(f => Path.GetFileName(f).EndsWith(".in") || Path.GetFileName(f).Contains("input"))
|
||||
.OrderBy(f => f)
|
||||
.ToList();
|
||||
|
||||
for (int i = 0; i < inputFiles.Count; i++)
|
||||
{
|
||||
var inputFile = inputFiles[i];
|
||||
var outputFile = FindCorrespondingOutputFile(inputFile);
|
||||
|
||||
if (outputFile == null)
|
||||
{
|
||||
_logger.LogWarning("No output file found for input {InputFile}", inputFile);
|
||||
continue;
|
||||
}
|
||||
|
||||
package.TestCases.Add(new TestCase
|
||||
{
|
||||
Number = i + 1,
|
||||
InputFilePath = inputFile,
|
||||
OutputFilePath = outputFile,
|
||||
TimeLimit = package.DefaultTimeLimit,
|
||||
MemoryLimit = package.DefaultMemoryLimit
|
||||
});
|
||||
}
|
||||
|
||||
// Look for checker
|
||||
var checkerCandidates = new[] { "check.cpp", "checker.cpp", "check", "checker" };
|
||||
foreach (var candidate in checkerCandidates)
|
||||
{
|
||||
var checkerPath = Path.Combine(workingDirectory, candidate);
|
||||
if (File.Exists(checkerPath))
|
||||
{
|
||||
package.CheckerPath = checkerPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("Parsed package with {TestCount} tests", package.TestCases.Count);
|
||||
return package;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to parse package");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private string? FindCorrespondingOutputFile(string inputFile)
|
||||
{
|
||||
var directory = Path.GetDirectoryName(inputFile)!;
|
||||
var fileName = Path.GetFileNameWithoutExtension(inputFile);
|
||||
var extension = Path.GetExtension(inputFile);
|
||||
|
||||
// Try various output file naming patterns
|
||||
var patterns = new[]
|
||||
{
|
||||
fileName.Replace("input", "output") + ".out",
|
||||
fileName.Replace("input", "output") + ".a",
|
||||
fileName.Replace("input", "answer") + ".out",
|
||||
fileName.Replace("input", "answer") + ".a",
|
||||
fileName + ".out",
|
||||
fileName + ".a",
|
||||
fileName.Replace(".in", ".out"),
|
||||
fileName.Replace(".in", ".a")
|
||||
};
|
||||
|
||||
foreach (var pattern in patterns)
|
||||
{
|
||||
var candidate = Path.Combine(directory, pattern);
|
||||
if (File.Exists(candidate))
|
||||
{
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user