generate images within pdf following naming format, stationID_date_...

This commit is contained in:
misya 2025-04-24 15:41:53 +08:00
parent 138d88918f
commit e220868d72
3 changed files with 112 additions and 35 deletions

View File

@ -27,7 +27,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
public IActionResult TarBallForm() public IActionResult TarBallForm()
{ {
var marineTarballs = _context.MarineTarballs var marineTarballs = _context.MarineTarballs
.Where(t => t.StationID != "1") .Where(t => t.StationID != "1")//remove unusable data (to be modified later to delete)
.Select(t => new .Select(t => new
{ {
t.Id, t.Id,
@ -86,20 +86,71 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
if (tarballData == null) if (tarballData == null)
return NotFound("Record not found"); return NotFound("Record not found");
// 2. Get photos from station folder // 2. Get photos from station folder (with date matching)
var sampleDateString = tarballData.DateSample.ToString("yyyyMMdd");
var stationFolder = Path.Combine(PhotoBasePath, tarballData.StationID); var stationFolder = Path.Combine(PhotoBasePath, tarballData.StationID);
var stationImages = new List<string>(); var stationImages = new List<string>();
if (Directory.Exists(stationFolder)) if (Directory.Exists(stationFolder))
{ {
stationImages = Directory.GetFiles(stationFolder) var allImages = Directory.GetFiles(stationFolder)
.Where(f => f.EndsWith(".jpg") || f.EndsWith(".png")) .Where(f => {
.OrderBy(f => f) // Alphabetical order var fileName = Path.GetFileNameWithoutExtension(f);
.Take(4) // Only need 4 photos max var parts = fileName.Split('_');
return parts.Length >= 3 &&
parts[0] == tarballData.StationID &&
parts[1] == sampleDateString &&
(f.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
f.EndsWith(".png", StringComparison.OrdinalIgnoreCase)) &&
IsImageValid(f);
})
.ToList();
// Define image priority order
var imageTypesInOrder = new List<string>
{
"LEFTSIDECOASTALVIEW",
"RIGHTSIDECOASTALVIEW",
"DRAWINGVERTICALLINES",
"DRAWINGHORIZONTALLINES",
"OPTIONAL01",
"OPTIONAL02",
"OPTIONAL03",
"OPTIONAL04"
};
// Sort logic (same as before)
bool hasValidFormat = allImages.Any(f =>
imageTypesInOrder.Any(t => Path.GetFileNameWithoutExtension(f).ToUpper().Contains(t)));
if (hasValidFormat)
{
stationImages = allImages
.OrderBy(f => {
var fileName = Path.GetFileNameWithoutExtension(f).ToUpper();
var typeIndex = imageTypesInOrder.FindIndex(t => fileName.Contains(t));
return typeIndex >= 0 ? typeIndex : int.MaxValue;
})
.ThenBy(f => f)
.Take(8)
.ToList(); .ToList();
} }
else
{
stationImages = allImages
.OrderBy(f => f)
.Take(8)
.ToList();
Console.WriteLine($"WARNING: No images matched keywords. Sorted alphabetically.");
}
}
Console.WriteLine($"Found {stationImages.Count} images for {tarballData.StationID}"); // Validate minimum images
if (stationImages.Count < 4)
{
return StatusCode(400, $"Minimum 4 images required for {tarballData.DateSample:yyyy/MM/dd}. Found: {stationImages.Count}");
}
// 3. Generate PDF // 3. Generate PDF
var pdf = new TarBallPDF( var pdf = new TarBallPDF(
@ -119,7 +170,11 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
stationImages.Count > 0 ? stationImages[0] : null, stationImages.Count > 0 ? stationImages[0] : null,
stationImages.Count > 1 ? stationImages[1] : null, stationImages.Count > 1 ? stationImages[1] : null,
stationImages.Count > 2 ? stationImages[2] : null, stationImages.Count > 2 ? stationImages[2] : null,
stationImages.Count > 3 ? stationImages[3] : null stationImages.Count > 3 ? stationImages[3] : null,
stationImages.Count > 4 ? stationImages[4] : null,
stationImages.Count > 5 ? stationImages[5] : null,
stationImages.Count > 6 ? stationImages[6] : null,
stationImages.Count > 7 ? stationImages[7] : null
).GeneratePdf(); ).GeneratePdf();
// 4. Return file // 4. Return file
@ -141,7 +196,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
if (!Directory.Exists(folderPath)) if (!Directory.Exists(folderPath))
{ {
Console.WriteLine($"Folder not found: {folderPath}"); Console.WriteLine($"Folder not found: {folderPath}");
return new List<string>(); // Return empty list return []; // Return empty list
} }
// Get ALL .jpg/.png files (no date sorting) // Get ALL .jpg/.png files (no date sorting)
@ -153,10 +208,24 @@ namespace PSTW_CentralSystem.Areas.MMS.Controllers
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Error fetching photos: {ex.Message}"); Console.WriteLine($"Error fetching photos: {ex.Message}");
return new List<string>(); // Return empty list on error return []; // Return empty list on error
}
}
private bool IsImageValid(string imagePath)
{
try
{
using (var image = System.Drawing.Image.FromFile(imagePath))
return true;
}
catch
{
Console.WriteLine($"Invalid image skipped: {imagePath}");
return false;
}
} }
} }
}
} }

View File

@ -9,7 +9,9 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
public class TarBallPDF(string stationID, string stateName, string locationName, public class TarBallPDF(string stationID, string stateName, string locationName,
string longitude, string latitude, DateTime dateSample, TimeSpan timeSample, string longitude, string latitude, DateTime dateSample, TimeSpan timeSample,
string classifyID, bool tarBallYes, bool tarBallNo, bool isSand, bool isNonSandy, string classifyID, bool tarBallYes, bool tarBallNo, bool isSand, bool isNonSandy,
bool isCoquina, string photoPath1, string photoPath2, string photoPath3, string photoPath4) bool isCoquina, string photoPath1, string photoPath2, string photoPath3, string photoPath4,
string photoPath5, string photoPath6, string photoPath7, string photoPath8
)
: IDocument : IDocument
{ {
private readonly string _stationId = stationID; private readonly string _stationId = stationID;
@ -29,6 +31,10 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
private readonly string? _photoPath2 = photoPath2; private readonly string? _photoPath2 = photoPath2;
private readonly string? _photoPath3 = photoPath3; private readonly string? _photoPath3 = photoPath3;
private readonly string? _photoPath4 = photoPath4; private readonly string? _photoPath4 = photoPath4;
private readonly string? _photoPath5 = photoPath5;
private readonly string? _photoPath6 = photoPath6;
private readonly string? _photoPath7 = photoPath7;
private readonly string? _photoPath8 = photoPath8;
//INSERT LOADIMAGE() HERE //INSERT LOADIMAGE() HERE
private Image? LoadImage(string? imagePath) private Image? LoadImage(string? imagePath)
@ -180,7 +186,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
.Text(text => .Text(text =>
{ {
text.Span("Tar Ball: ").Style(TextStyle.Default.FontSize(10)); text.Span("Tar Ball: ").Style(TextStyle.Default.FontSize(10));
text.Span(_classifyID == "NO" ? "☐ YES ☑ NO" : "☑ YES ☐ NO").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "NO" ? " ☐ YES ☑ NO" : " ☑ YES ☐ NO").Style(TextStyle.Default.FontSize(10));
}); });
// 2. Classification (always shown) // 2. Classification (always shown)
@ -194,7 +200,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
.Text(text => .Text(text =>
{ {
text.Span(_classifyID == "SD" ? "☑ Sand " : "☐ Sand ").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "SD" ? "☑ Sand " : "☐ Sand ").Style(TextStyle.Default.FontSize(10));
text.Span(_classifyID == "NS" ? "☑ Non-sandy " : "☐ Non-sandy ").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "NS" ? " ☑ Non-sandy " : " ☐ Non-sandy ").Style(TextStyle.Default.FontSize(10));
text.Span(_classifyID == "CO" ? "☑ Coquina" : "☐ Coquina").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "CO" ? "☑ Coquina" : "☐ Coquina").Style(TextStyle.Default.FontSize(10));
}); });
@ -267,7 +273,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
// Additional Photos Section // Additional Photos Section
column.Item().Table(table => column.Item().Table(table =>
{ {
column.Spacing(0); column.Spacing(3);
table.ColumnsDefinition(columns => table.ColumnsDefinition(columns =>
{ {
@ -275,14 +281,22 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
columns.RelativeColumn(1); columns.RelativeColumn(1);
}); });
table.Cell().Element(CellStyle).Height(150); table.Cell().Element(CellStyle).Height(150)
table.Cell().Element(CellStyle).Height(150); .Image(LoadImage(_photoPath5) ?? null) // Just pass null if no image
.FitArea();
table.Cell().Element(CellStyle).Height(150)
.Image(LoadImage(_photoPath6) ?? null) // Just pass null if no image
.FitArea();
table.Cell().Element(CellStyle).Text("Figure 5:").FontSize(12).AlignLeft(); table.Cell().Element(CellStyle).Text("Figure 5:").FontSize(12).AlignLeft();
table.Cell().Element(CellStyle).Text("Figure 6:").FontSize(12).AlignLeft(); table.Cell().Element(CellStyle).Text("Figure 6:").FontSize(12).AlignLeft();
table.Cell().Element(CellStyle).Height(150); table.Cell().Element(CellStyle).Height(150)
table.Cell().Element(CellStyle).Height(150); .Image(LoadImage(_photoPath7) ?? null) // Just pass null if no image
.FitArea();
table.Cell().Element(CellStyle).Height(150)
.Image(LoadImage(_photoPath8) ?? null) // Just pass null if no image
.FitArea();
table.Cell().Element(CellStyle).Text("Figure 7:").FontSize(12).AlignLeft(); table.Cell().Element(CellStyle).Text("Figure 7:").FontSize(12).AlignLeft();
table.Cell().Element(CellStyle).Text("Figure 8:").FontSize(12).AlignLeft(); table.Cell().Element(CellStyle).Text("Figure 8:").FontSize(12).AlignLeft();
@ -302,6 +316,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
{ {
table.ColumnsDefinition(columns => table.ColumnsDefinition(columns =>
{ {
//the overall layout of the authorization section
columns.RelativeColumn(2); columns.RelativeColumn(2);
columns.RelativeColumn(1); columns.RelativeColumn(1);
columns.RelativeColumn(2); columns.RelativeColumn(2);
@ -320,8 +335,8 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
table.Cell().RowSpan(2).Element(CellStyle).Text("CHECKED BY :").Bold().FontSize(12); table.Cell().RowSpan(2).Element(CellStyle).Text("CHECKED BY :").Bold().FontSize(12);
table.Cell().Element(CellStyle).Text("Signature").FontSize(12); table.Cell().Element(CellStyle).Text("Signature").FontSize(12);
table.Cell().Element(CellStyle).Text(""); table.Cell().ColumnSpan(2).Element(CellStyle).Text("");
table.Cell().Element(CellStyle).Text("Date").FontSize(12); //table.Cell().Element(CellStyle).Text("Date").FontSize(12);
table.Cell().Element(CellStyle).Text(""); table.Cell().Element(CellStyle).Text("");
table.Cell().Element(CellStyle).Text("Designation").FontSize(12); table.Cell().Element(CellStyle).Text("Designation").FontSize(12);
@ -329,8 +344,8 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
table.Cell().RowSpan(2).Element(CellStyle).Text("VERIFIED BY :").Bold().FontSize(12); table.Cell().RowSpan(2).Element(CellStyle).Text("VERIFIED BY :").Bold().FontSize(12);
table.Cell().Element(CellStyle).Text("Signature").FontSize(12); table.Cell().Element(CellStyle).Text("Signature").FontSize(12);
table.Cell().Element(CellStyle).Text(""); table.Cell().ColumnSpan(2).Element(CellStyle).Text("");
table.Cell().Element(CellStyle).Text("Date").FontSize(12); //table.Cell().Element(CellStyle).Text("Date").FontSize(12);
table.Cell().Element(CellStyle).Text(""); table.Cell().Element(CellStyle).Text("");
table.Cell().Element(CellStyle).Text("Designation").FontSize(12); table.Cell().Element(CellStyle).Text("Designation").FontSize(12);
@ -341,10 +356,6 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
// Footer Section // Footer Section
page.Footer().AlignCenter().Text(text => page.Footer().AlignCenter().Text(text =>
{ {
text.Span("Page ");
text.CurrentPageNumber();
text.Span(" of ");
text.TotalPages();
}); });
static IContainer CellStyle(IContainer container) => container.Border(0.5f).Padding(5); static IContainer CellStyle(IContainer container) => container.Border(0.5f).Padding(5);

View File

@ -22,6 +22,10 @@ namespace PSTW_CentralSystem.Models
public required string PhotoPath2 { get; set; } // Right Side Coastal View public required string PhotoPath2 { get; set; } // Right Side Coastal View
public required string PhotoPath3 { get; set; } // Vertical Lines public required string PhotoPath3 { get; set; } // Vertical Lines
public required string PhotoPath4 { get; set; } // Horizontal Lines public required string PhotoPath4 { get; set; } // Horizontal Lines
public required string PhotoPath5 { get; set; } // optional
public required string PhotoPath6 { get; set; } // optional
public required string PhotoPath7 { get; set; } // optional
public required string PhotoPath8 { get; set; } // optional
[ForeignKey("StationID")] [ForeignKey("StationID")]
public required MarineStation MarineStation { get; set; } public required MarineStation MarineStation { get; set; }
@ -48,12 +52,5 @@ namespace PSTW_CentralSystem.Models
public required string StateID { get; set; } // Maps to 'stateID' public required string StateID { get; set; } // Maps to 'stateID'
public required string StateName { get; set; } // Maps to 'stateName' public required string StateName { get; set; } // Maps to 'stateName'
} }
public class MarineClassify
{
public int Id { get; set; } // Maps to 'id'
public required string ClassifyID{ get; set; } // Maps to classification ID
public required string ClassifyName { get; set; } // Maps to classification name
}
} }