Added Files
This commit is contained in:
14
.claude/settings.local.json
Normal file
14
.claude/settings.local.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Skill(roslyn-bridge)",
|
||||
"Bash(powershell -File:*)",
|
||||
"Bash(curl:*)",
|
||||
"Bash(dotnet:*)",
|
||||
"Bash(rm:*)",
|
||||
"Bash(powershell:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
}
|
||||
}
|
||||
32
.gitignore
vendored
Normal file
32
.gitignore
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
#Ignore thumbnails created by Windows
|
||||
Thumbs.db
|
||||
#Ignore files built by Visual Studio
|
||||
*.obj
|
||||
*.exe
|
||||
*.pdb
|
||||
*.user
|
||||
*.aps
|
||||
*.pch
|
||||
*.vspscc
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ncb
|
||||
*.suo
|
||||
*.tlb
|
||||
*.tlh
|
||||
*.bak
|
||||
*.cache
|
||||
*.ilk
|
||||
*.log
|
||||
[Bb]in
|
||||
[Dd]ebug*/
|
||||
*.lib
|
||||
*.sbr
|
||||
obj/
|
||||
[Rr]elease*/
|
||||
_ReSharper*/
|
||||
[Tt]est[Rr]esult*
|
||||
.vs/
|
||||
#Nuget packages folder
|
||||
packages/
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "PepLib"]
|
||||
path = PepLib
|
||||
url = https://git.thecozycat.net/aj/PepLib.git
|
||||
280
DEPLOY.md
Normal file
280
DEPLOY.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# PepApi Deployment Guide
|
||||
|
||||
## Quick Deployment (Windows Service)
|
||||
|
||||
### Prerequisites
|
||||
- .NET 8 Runtime or SDK installed
|
||||
- Administrator privileges
|
||||
- Network access to PepDB SQL Server
|
||||
- Access to nest files directory
|
||||
|
||||
### Deploy as Windows Service
|
||||
|
||||
```powershell
|
||||
# Run as Administrator
|
||||
powershell -ExecutionPolicy Bypass -File Deploy-PepApi.ps1 -OpenFirewall
|
||||
```
|
||||
|
||||
This will:
|
||||
- Build and publish PepApi.Core in Release mode
|
||||
- Install to `C:\Services\PepApi`
|
||||
- Create Windows Service named "PepApi"
|
||||
- Configure service to run on port 8085
|
||||
- Open Windows Firewall for port 8085
|
||||
- Start the service automatically
|
||||
|
||||
### Custom Deployment
|
||||
|
||||
```powershell
|
||||
# Custom service name and location
|
||||
powershell -ExecutionPolicy Bypass -File Deploy-PepApi.ps1 `
|
||||
-ServiceName "MyPepApi" `
|
||||
-InstallDir "D:\Services\PepApi" `
|
||||
-Urls "http://*:9000" `
|
||||
-OpenFirewall
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
After deployment, **you must update** `C:\Services\PepApi\appsettings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"PepDB": "data source=YOUR_SERVER\\INSTANCE;initial catalog=PEP;integrated security=True;..."
|
||||
},
|
||||
"PepSettings": {
|
||||
"NestDirectory": "\\\\YOUR_SERVER\\PEP Nest",
|
||||
"MaterialsFile": "C:\\Pep\\PEP2012\\CONFIG\\material.lfn"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then restart the service:
|
||||
```powershell
|
||||
Restart-Service -Name PepApi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Alternative: Self-Hosted (No Service)
|
||||
|
||||
### Build and Run
|
||||
|
||||
```bash
|
||||
cd PepApi.Core
|
||||
dotnet publish -c Release -o ./publish
|
||||
cd publish
|
||||
.\PepApi.Core.exe
|
||||
```
|
||||
|
||||
### Run with Custom Settings
|
||||
|
||||
```bash
|
||||
.\PepApi.Core.exe --urls "http://*:8085"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Alternative: IIS Deployment
|
||||
|
||||
### 1. Install Prerequisites
|
||||
- Install ASP.NET Core Hosting Bundle from Microsoft
|
||||
- Create IIS Application Pool (No Managed Code)
|
||||
|
||||
### 2. Publish Application
|
||||
|
||||
```bash
|
||||
dotnet publish PepApi.Core/PepApi.Core.csproj -c Release -o C:\inetpub\PepApi
|
||||
```
|
||||
|
||||
### 3. Configure IIS
|
||||
- Create new website in IIS Manager
|
||||
- Point to `C:\inetpub\PepApi`
|
||||
- Use Application Pool with "No Managed Code"
|
||||
- Set binding to port 8085
|
||||
|
||||
### 4. Update Configuration
|
||||
- Edit `C:\inetpub\PepApi\appsettings.json`
|
||||
- Restart IIS site
|
||||
|
||||
---
|
||||
|
||||
## Verify Deployment
|
||||
|
||||
### Check Service Status
|
||||
```powershell
|
||||
Get-Service -Name PepApi
|
||||
```
|
||||
|
||||
### Test API
|
||||
```powershell
|
||||
# Health check
|
||||
Invoke-WebRequest http://localhost:8085/swagger
|
||||
|
||||
# Test nests endpoint
|
||||
Invoke-WebRequest http://localhost:8085/nests/2024
|
||||
```
|
||||
|
||||
### View Logs
|
||||
```powershell
|
||||
# Service logs in Event Viewer
|
||||
Get-EventLog -LogName Application -Source PepApi -Newest 20
|
||||
|
||||
# Or check console output if running self-hosted
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Service Management
|
||||
|
||||
### Start Service
|
||||
```powershell
|
||||
Start-Service -Name PepApi
|
||||
```
|
||||
|
||||
### Stop Service
|
||||
```powershell
|
||||
Stop-Service -Name PepApi
|
||||
```
|
||||
|
||||
### Restart Service
|
||||
```powershell
|
||||
Restart-Service -Name PepApi
|
||||
```
|
||||
|
||||
### Uninstall Service
|
||||
```powershell
|
||||
Stop-Service -Name PepApi
|
||||
sc.exe delete PepApi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Firewall Configuration
|
||||
|
||||
If you didn't use `-OpenFirewall` during deployment:
|
||||
|
||||
```powershell
|
||||
# Open port 8085
|
||||
New-NetFirewallRule -DisplayName "PepApi HTTP 8085" `
|
||||
-Direction Inbound `
|
||||
-Protocol TCP `
|
||||
-LocalPort 8085 `
|
||||
-Action Allow
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service Won't Start
|
||||
|
||||
1. Check Event Viewer for errors:
|
||||
```powershell
|
||||
Get-EventLog -LogName Application -Source PepApi -Newest 10
|
||||
```
|
||||
|
||||
2. Verify configuration:
|
||||
- Database connection string is correct
|
||||
- Network paths are accessible
|
||||
- Files exist at specified paths
|
||||
|
||||
3. Test manually:
|
||||
```bash
|
||||
cd C:\Services\PepApi
|
||||
.\PepApi.Core.exe
|
||||
```
|
||||
|
||||
### Database Connection Errors
|
||||
|
||||
- Verify SQL Server is accessible
|
||||
- Check Windows Authentication permissions
|
||||
- Test connection string with SSMS
|
||||
- Ensure `TrustServerCertificate=True` in connection string
|
||||
|
||||
### File Access Errors
|
||||
|
||||
- Verify service account has read access to:
|
||||
- Nest directory (`\\REMCOSRV0\PEP Nest`)
|
||||
- Materials file (`C:\Pep\PEP2012\CONFIG\material.lfn`)
|
||||
- Configure service to run as appropriate account
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
```powershell
|
||||
# Find what's using port 8085
|
||||
netstat -ano | findstr :8085
|
||||
|
||||
# Kill the process
|
||||
Stop-Process -Id [PID] -Force
|
||||
|
||||
# Or deploy on different port
|
||||
Deploy-PepApi.ps1 -Urls "http://*:9000"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Update/Redeploy
|
||||
|
||||
To update the service with new code:
|
||||
|
||||
```powershell
|
||||
# Simply run the deploy script again
|
||||
powershell -ExecutionPolicy Bypass -File Deploy-PepApi.ps1 -OpenFirewall
|
||||
```
|
||||
|
||||
The script will:
|
||||
- Stop the existing service
|
||||
- Deploy the new version
|
||||
- Restart the service
|
||||
|
||||
**Note:** Your `appsettings.json` changes will be preserved.
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
Once deployed, the API will be available at:
|
||||
|
||||
- **Swagger UI:** `http://localhost:8085/swagger`
|
||||
- **OpenAPI Spec:** `http://localhost:8085/swagger/v1/swagger.json`
|
||||
|
||||
### Endpoints
|
||||
- `GET /nests/{year}` - Get nests for year
|
||||
- `GET /nests/{nestName}?year=YYYY` - Get nest (year optional, finds most recent)
|
||||
- `GET /nests/{nestName}/download?year=YYYY` - Download nest file
|
||||
- `GET /nests/{nestName}/plates?year=YYYY` - Get plates
|
||||
- `GET /materials` - Get all materials
|
||||
- `GET /materials/{id}` - Get specific material
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
⚠️ **Before production deployment:**
|
||||
|
||||
1. Enable HTTPS (not configured by default)
|
||||
2. Add authentication/authorization
|
||||
3. Review CORS policy (currently allows all origins)
|
||||
4. Update DotNetZip package (has security vulnerability)
|
||||
5. Run service with least-privilege account
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- Consider adding response caching
|
||||
- Enable response compression in production
|
||||
- Monitor database query performance
|
||||
- Add connection pooling configuration if needed
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
For issues:
|
||||
1. Check Event Viewer logs
|
||||
2. Review `appsettings.json` configuration
|
||||
3. Test database and file access manually
|
||||
4. Review MIGRATION_SUMMARY.md for detailed changes
|
||||
188
Deploy-PepApi.ps1
Normal file
188
Deploy-PepApi.ps1
Normal file
@@ -0,0 +1,188 @@
|
||||
<#
|
||||
Deploy PepApi as a Windows Service
|
||||
|
||||
Examples:
|
||||
# Run from repository root:
|
||||
powershell -ExecutionPolicy Bypass -File Deploy-PepApi.ps1 -ServiceName PepApi -InstallDir C:\Services\PepApi -Urls "http://*:8085" -OpenFirewall
|
||||
|
||||
# Custom installation:
|
||||
powershell -ExecutionPolicy Bypass -File Deploy-PepApi.ps1 -ServiceName PepApiService -InstallDir D:\MyServices\PepApi -Urls "http://*:8085" -OpenFirewall
|
||||
|
||||
Requires: dotnet SDK/runtime installed and administrative privileges.
|
||||
#>
|
||||
|
||||
Param(
|
||||
[string]$ServiceName = "PepApi",
|
||||
[string]$PublishConfiguration = "Release",
|
||||
[string]$InstallDir = "C:\Services\PepApi",
|
||||
[string]$Urls = "http://*:8085",
|
||||
[switch]$OpenFirewall,
|
||||
[int]$PublishTimeoutSeconds = 180,
|
||||
[int]$ServiceStopTimeoutSeconds = 30,
|
||||
[int]$ServiceStartTimeoutSeconds = 30
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# Detect repository root
|
||||
$ScriptDir = Split-Path -Parent $PSCommandPath
|
||||
$RepoRoot = if ((Split-Path -Leaf $ScriptDir) -eq 'scripts') {
|
||||
Split-Path -Parent $ScriptDir
|
||||
} else {
|
||||
$ScriptDir
|
||||
}
|
||||
|
||||
Write-Host "Repository root: $RepoRoot"
|
||||
$ProjectPath = Join-Path $RepoRoot 'PepApi.Core\PepApi.Core.csproj'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $ProjectPath)) {
|
||||
throw "Project not found at: $ProjectPath"
|
||||
}
|
||||
|
||||
function Ensure-Dir($path) {
|
||||
if (-not (Test-Path -LiteralPath $path)) {
|
||||
New-Item -ItemType Directory -Path $path | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
function Stop-And-DeleteService($name) {
|
||||
$svc = Get-Service -Name $name -ErrorAction SilentlyContinue
|
||||
if ($null -ne $svc) {
|
||||
if ($svc.Status -ne 'Stopped') {
|
||||
Write-Host "Stopping service '$name'..."
|
||||
Stop-Service -Name $name -Force -ErrorAction SilentlyContinue
|
||||
try { $svc.WaitForStatus('Stopped',[TimeSpan]::FromSeconds($ServiceStopTimeoutSeconds)) | Out-Null } catch {}
|
||||
# If still running, kill by PID
|
||||
$q = & sc.exe queryex $name 2>$null
|
||||
$pidLine = $q | Where-Object { $_ -match 'PID' }
|
||||
if ($pidLine -and ($pidLine -match '(\d+)$')) {
|
||||
$procId = [int]$Matches[1]
|
||||
if ($procId -gt 0) {
|
||||
try { Write-Host "Killing service process PID=$procId ..."; Stop-Process -Id $procId -Force } catch {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Host "Deleting service '$name'..."
|
||||
sc.exe delete $name | Out-Null
|
||||
Start-Sleep -Seconds 1
|
||||
}
|
||||
}
|
||||
|
||||
function Publish-App() {
|
||||
Write-Host "Publishing PepApi.Core to $InstallDir ..."
|
||||
Ensure-Dir $InstallDir
|
||||
|
||||
# Run dotnet publish directly - output will be visible
|
||||
& dotnet publish $ProjectPath -c $PublishConfiguration -o $InstallDir
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dotnet publish failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
|
||||
# Copy appsettings.json if it doesn't exist in install dir (preserve existing config)
|
||||
$sourceSettings = Join-Path (Split-Path -Parent $ProjectPath) 'appsettings.json'
|
||||
$targetSettings = Join-Path $InstallDir 'appsettings.json'
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "============================================"
|
||||
Write-Host "IMPORTANT: Configuration File" -ForegroundColor Yellow
|
||||
Write-Host "============================================"
|
||||
Write-Host "Please review and update the configuration file at:" -ForegroundColor Yellow
|
||||
Write-Host " $targetSettings" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Update the following settings:" -ForegroundColor Yellow
|
||||
Write-Host " - ConnectionStrings:PepDB (SQL Server connection)" -ForegroundColor White
|
||||
Write-Host " - PepSettings:NestDirectory (network path to nests)" -ForegroundColor White
|
||||
Write-Host " - PepSettings:MaterialsFile (path to material.lfn)" -ForegroundColor White
|
||||
Write-Host "============================================"
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
function Stop-ExeLocks($path) {
|
||||
$procs = Get-Process -ErrorAction SilentlyContinue | Where-Object {
|
||||
$_.Path -and ($_.Path -ieq $path)
|
||||
}
|
||||
foreach ($p in $procs) {
|
||||
try { Write-Host "Killing process $($p.Id) $($p.ProcessName) ..."; Stop-Process -Id $p.Id -Force } catch {}
|
||||
}
|
||||
# Wait until unlocked
|
||||
for ($i=0; $i -lt 50; $i++) {
|
||||
$still = Get-Process -ErrorAction SilentlyContinue | Where-Object { $_.Path -and ($_.Path -ieq $path) }
|
||||
if (-not $still) { break }
|
||||
Start-Sleep -Milliseconds 200
|
||||
}
|
||||
}
|
||||
|
||||
function Create-Service($name, $bin, $urls) {
|
||||
$binPath = '"' + $bin + '" --urls ' + $urls
|
||||
Write-Host "Creating service '$name' with binPath: $binPath"
|
||||
# Note: space after '=' is required for sc.exe syntax
|
||||
sc.exe create $name binPath= "$binPath" start= auto DisplayName= "$name" | Out-Null
|
||||
# Set recovery to restart on failure
|
||||
sc.exe failure $name reset= 86400 actions= restart/60000/restart/60000/restart/60000 | Out-Null
|
||||
}
|
||||
|
||||
function Start-ServiceSafe($name) {
|
||||
Write-Host "Starting service '$name'..."
|
||||
Start-Service -Name $name
|
||||
(Get-Service -Name $name).WaitForStatus('Running',[TimeSpan]::FromSeconds($ServiceStartTimeoutSeconds)) | Out-Null
|
||||
sc.exe query $name | Write-Host
|
||||
}
|
||||
|
||||
if (-not (Get-Command dotnet -ErrorAction SilentlyContinue)) {
|
||||
throw "dotnet SDK/Runtime not found in PATH. Please install .NET 8+ or add it to PATH."
|
||||
}
|
||||
|
||||
Write-Host "================================================"
|
||||
Write-Host "PepApi Deployment Script" -ForegroundColor Green
|
||||
Write-Host "================================================"
|
||||
Write-Host "Service Name: $ServiceName"
|
||||
Write-Host "Install Dir: $InstallDir"
|
||||
Write-Host "URLs: $Urls"
|
||||
Write-Host "Configuration: $PublishConfiguration"
|
||||
Write-Host "Open Firewall: $OpenFirewall"
|
||||
Write-Host "================================================"
|
||||
Write-Host ""
|
||||
|
||||
Stop-And-DeleteService -name $ServiceName
|
||||
Stop-ExeLocks -path (Join-Path $InstallDir 'PepApi.Core.exe')
|
||||
try { Remove-Item -LiteralPath (Join-Path $InstallDir 'PepApi.Core.exe') -Force -ErrorAction SilentlyContinue } catch {}
|
||||
Publish-App
|
||||
|
||||
$exe = Join-Path $InstallDir 'PepApi.Core.exe'
|
||||
if (-not (Test-Path -LiteralPath $exe)) {
|
||||
throw "Expected published executable not found: $exe"
|
||||
}
|
||||
|
||||
Create-Service -name $ServiceName -bin $exe -urls $Urls
|
||||
|
||||
if ($OpenFirewall) {
|
||||
$port = ($Urls -split ':')[-1]
|
||||
if ($port -match '^(\d+)$') {
|
||||
$ruleName = "$ServiceName HTTP $port"
|
||||
$existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
|
||||
if ($null -eq $existingRule) {
|
||||
Write-Host "Creating firewall rule for TCP port $port ..."
|
||||
New-NetFirewallRule -DisplayName $ruleName -Direction Inbound -Protocol TCP -LocalPort $port -Action Allow | Out-Null
|
||||
} else {
|
||||
Write-Host "Firewall rule '$ruleName' already exists, skipping creation."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Start-ServiceSafe -name $ServiceName
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "================================================"
|
||||
Write-Host "Deployment Complete!" -ForegroundColor Green
|
||||
Write-Host "================================================"
|
||||
Write-Host "Service '$ServiceName' is running."
|
||||
Write-Host "API available at: $Urls"
|
||||
Write-Host "Swagger UI at: $($Urls -replace '\*', 'localhost')/swagger"
|
||||
Write-Host ""
|
||||
Write-Host "Next Steps:" -ForegroundColor Yellow
|
||||
Write-Host " 1. Verify configuration in: $InstallDir\appsettings.json"
|
||||
Write-Host " 2. Test API endpoint: $($Urls -replace '\*', 'localhost')/swagger"
|
||||
Write-Host " 3. Check service status: Get-Service -Name $ServiceName"
|
||||
Write-Host "================================================"
|
||||
7
PepApi.Core/Configuration/PepSettings.cs
Normal file
7
PepApi.Core/Configuration/PepSettings.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace PepApi.Core.Configuration;
|
||||
|
||||
public class PepSettings
|
||||
{
|
||||
public string NestDirectory { get; set; } = string.Empty;
|
||||
public string MaterialsFile { get; set; } = string.Empty;
|
||||
}
|
||||
41
PepApi.Core/Controllers/MaterialsController.cs
Normal file
41
PepApi.Core/Controllers/MaterialsController.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using PepApi.Core.Configuration;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepApi.Core.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("materials")]
|
||||
public class MaterialsController : ControllerBase
|
||||
{
|
||||
private readonly string _materialsFile;
|
||||
|
||||
public MaterialsController(IOptions<PepSettings> settings)
|
||||
{
|
||||
_materialsFile = settings.Value.MaterialsFile;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<List<MaterialData>>> GetMaterials()
|
||||
{
|
||||
var reader = new MaterialDataReader();
|
||||
await Task.Run(() => reader.Read(_materialsFile));
|
||||
|
||||
return Ok(reader.Materials);
|
||||
}
|
||||
|
||||
[HttpGet("{materialNo:int}")]
|
||||
public async Task<ActionResult<List<MaterialData>>> GetMaterial(int materialNo)
|
||||
{
|
||||
var reader = new MaterialDataReader();
|
||||
await Task.Run(() => reader.Read(_materialsFile));
|
||||
|
||||
var materials = reader.Materials.Where(m => m.Number == materialNo).ToList();
|
||||
|
||||
if (!materials.Any())
|
||||
return NotFound(new { message = $"Material {materialNo} not found" });
|
||||
|
||||
return Ok(materials);
|
||||
}
|
||||
}
|
||||
231
PepApi.Core/Controllers/NestsController.cs
Normal file
231
PepApi.Core/Controllers/NestsController.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PepApi.Core.Configuration;
|
||||
using PepApi.Core.Models;
|
||||
using PepLib;
|
||||
using PepLib.Data;
|
||||
using Plate = PepApi.Core.Models.Plate;
|
||||
|
||||
namespace PepApi.Core.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("nests")]
|
||||
public class NestsController : ControllerBase
|
||||
{
|
||||
private readonly PepDB _db;
|
||||
private readonly string _nestDirectory;
|
||||
|
||||
public NestsController(PepDB db, IOptions<PepSettings> settings)
|
||||
{
|
||||
_db = db;
|
||||
_nestDirectory = settings.Value.NestDirectory;
|
||||
}
|
||||
|
||||
[HttpGet("{year:int:regex(^\\d{{4}}$)}")]
|
||||
public async Task<ActionResult<List<NestSummary>>> GetNests(int year, [FromQuery] NestFilterData? filter)
|
||||
{
|
||||
if (year == 0)
|
||||
year = DateTime.Now.Year;
|
||||
|
||||
var dir = Path.Combine(_nestDirectory, year.ToString());
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
return Ok(new List<NestSummary>());
|
||||
}
|
||||
|
||||
var nestHeaders = await _db.NestHeaders
|
||||
.Where(n => n.DateProgrammed != null && n.DateProgrammed.Value.Year == year)
|
||||
.ToListAsync();
|
||||
|
||||
var nestSummaries = nestHeaders.Select(ConvertFrom).ToList();
|
||||
|
||||
if (filter != null)
|
||||
{
|
||||
return Ok(filter.Apply(nestSummaries.AsQueryable()).ToList());
|
||||
}
|
||||
|
||||
return Ok(nestSummaries);
|
||||
}
|
||||
|
||||
private static NestSummary ConvertFrom(NestHeader nestHeader)
|
||||
{
|
||||
return new NestSummary
|
||||
{
|
||||
Comments = nestHeader.Comments,
|
||||
Customer = nestHeader.CustomerName,
|
||||
DateCreated = nestHeader.DateProgrammed!.Value,
|
||||
DateLastModified = nestHeader.ModifiedDate!.Value,
|
||||
HasErrors = !nestHeader.Errors.IsNullOrWhiteSpace(),
|
||||
MaterialGrade = nestHeader.MatGrade,
|
||||
MaterialNumber = int.Parse(nestHeader.Material ?? "0"),
|
||||
Name = nestHeader.NestName,
|
||||
Notes = nestHeader.Remarks,
|
||||
ProgrammedBy = nestHeader.Programmer,
|
||||
Revision = nestHeader.UserDefined1,
|
||||
Status = PepHelper.GetStatus(nestHeader.Status),
|
||||
Application = PepHelper.GetApplication(nestHeader.Application)
|
||||
};
|
||||
}
|
||||
|
||||
// Get nest by name - finds most recent if year not specified
|
||||
[HttpGet("{nestName}")]
|
||||
public async Task<ActionResult<NestDetails>> GetNestInfo(string nestName, [FromQuery] int? year = null)
|
||||
{
|
||||
var nestFile = year.HasValue
|
||||
? GetNestPath(nestName, year.Value)
|
||||
: await FindMostRecentNestAsync(nestName);
|
||||
|
||||
if (nestFile == null || !System.IO.File.Exists(nestFile))
|
||||
return NotFound(new { message = "Nest not found" });
|
||||
|
||||
var details = await GetNestDetailsAsync(nestFile);
|
||||
return Ok(details);
|
||||
}
|
||||
|
||||
// Get nest by year and name (backward compatibility)
|
||||
[HttpGet("{year:int:regex(^\\d{{4}}$)}/{nestName}")]
|
||||
public async Task<ActionResult<NestDetails>> GetNestInfoByYear(int year, string nestName)
|
||||
{
|
||||
var nestFile = GetNestPath(nestName, year);
|
||||
|
||||
if (!System.IO.File.Exists(nestFile))
|
||||
return NotFound(new { message = "Nest not found" });
|
||||
|
||||
var details = await GetNestDetailsAsync(nestFile);
|
||||
return Ok(details);
|
||||
}
|
||||
|
||||
// Download nest file - finds most recent if year not specified
|
||||
[HttpGet("{nestName}/download")]
|
||||
public async Task<IActionResult> DownloadFile(string nestName, [FromQuery] int? year = null)
|
||||
{
|
||||
var filePath = year.HasValue
|
||||
? GetNestPath(nestName, year.Value)
|
||||
: await FindMostRecentNestAsync(nestName);
|
||||
|
||||
if (filePath == null || !System.IO.File.Exists(filePath))
|
||||
return NotFound(new { message = "Nest not found" });
|
||||
|
||||
var bytes = System.IO.File.ReadAllBytes(filePath);
|
||||
var fileName = Path.GetFileName(filePath);
|
||||
var mimeType = "application/octet-stream";
|
||||
|
||||
return File(bytes, mimeType, fileName);
|
||||
}
|
||||
|
||||
// Download nest file by year (backward compatibility)
|
||||
[HttpGet("{year:int:regex(^\\d{{4}}$)}/{nestName}/download")]
|
||||
public IActionResult DownloadFileByYear(int year, string nestName)
|
||||
{
|
||||
var filePath = GetNestPath(nestName, year);
|
||||
|
||||
if (!System.IO.File.Exists(filePath))
|
||||
return NotFound(new { message = "Nest not found" });
|
||||
|
||||
var bytes = System.IO.File.ReadAllBytes(filePath);
|
||||
var fileName = Path.GetFileName(filePath);
|
||||
var mimeType = "application/octet-stream";
|
||||
|
||||
return File(bytes, mimeType, fileName);
|
||||
}
|
||||
|
||||
// Get plates - finds most recent if year not specified
|
||||
[HttpGet("{nestName}/plates")]
|
||||
public async Task<ActionResult<List<Plate>>> GetPlates(string nestName, [FromQuery] int? year = null)
|
||||
{
|
||||
var nestFile = year.HasValue
|
||||
? GetNestPath(nestName, year.Value)
|
||||
: await FindMostRecentNestAsync(nestName);
|
||||
|
||||
if (nestFile == null || !System.IO.File.Exists(nestFile))
|
||||
return NotFound(new { message = "Nest not found" });
|
||||
|
||||
var nest = Nest.Load(nestFile);
|
||||
var plates = PepHelper.GetPlates(nest);
|
||||
var combined = PepHelper.CombineLikePlates(plates);
|
||||
|
||||
return Ok(combined);
|
||||
}
|
||||
|
||||
// Get plates by year (backward compatibility)
|
||||
[HttpGet("{year:int:regex(^\\d{{4}}$)}/{nestName}/plates")]
|
||||
public ActionResult<List<Plate>> GetPlatesByYear(int year, string nestName)
|
||||
{
|
||||
var nestFile = GetNestPath(nestName, year);
|
||||
|
||||
if (!System.IO.File.Exists(nestFile))
|
||||
return NotFound(new { message = "Nest not found" });
|
||||
|
||||
var nest = Nest.Load(nestFile);
|
||||
var plates = PepHelper.GetPlates(nest);
|
||||
var combined = PepHelper.CombineLikePlates(plates);
|
||||
|
||||
return Ok(combined);
|
||||
}
|
||||
|
||||
private async Task<string?> FindMostRecentNestAsync(string nestName)
|
||||
{
|
||||
// Query database for most recent nest by name
|
||||
var mostRecent = await _db.NestHeaders
|
||||
.Where(n => n.NestName.ToUpper() == nestName.ToUpper() && n.DateProgrammed != null)
|
||||
.OrderByDescending(n => n.DateProgrammed)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (mostRecent == null)
|
||||
return null;
|
||||
|
||||
var year = mostRecent.DateProgrammed!.Value.Year;
|
||||
return GetNestPath(nestName, year);
|
||||
}
|
||||
|
||||
private string GetNestPath(string nestName, int year)
|
||||
{
|
||||
var fileName = nestName + ".zip";
|
||||
var filePath = Path.Combine(_nestDirectory, year.ToString(), fileName);
|
||||
|
||||
if (System.IO.File.Exists(filePath))
|
||||
return filePath;
|
||||
|
||||
fileName = nestName + ".pep";
|
||||
filePath = Path.Combine(_nestDirectory, year.ToString(), fileName);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
private async Task<NestDetails> GetNestDetailsAsync(string nestFilePath)
|
||||
{
|
||||
var nest = Nest.Load(nestFilePath);
|
||||
var dir = Path.GetDirectoryName(nestFilePath) + "\\";
|
||||
var name = Path.GetFileNameWithoutExtension(nestFilePath).ToUpper();
|
||||
|
||||
var info = await _db.NestHeaders
|
||||
.FirstOrDefaultAsync(n => n.NestName.ToUpper() == name && dir == n.Path);
|
||||
|
||||
if (info == null)
|
||||
throw new Exception("Nest header not found in database");
|
||||
|
||||
var details = new NestDetails
|
||||
{
|
||||
Name = info.NestName,
|
||||
DateCreated = info.DateProgrammed!.Value,
|
||||
Status = PepHelper.GetStatus(info.Status),
|
||||
DateLastModified = info.ModifiedDate!.Value,
|
||||
Material = PepHelper.GetMaterial(nest),
|
||||
Plates = PepHelper.GetPlates(nest),
|
||||
Parts = PepHelper.GetParts(nest),
|
||||
NumberOfTestSquares = PepHelper.GetTestSquareCount(nest),
|
||||
AreTestSquaresOutOfSequence = !PepHelper.AreTestSquaresInCorrectOrder(nest),
|
||||
Customer = info.CustomerName,
|
||||
Comments = info.Comments,
|
||||
HasErrors = !info.Errors.IsNullOrWhiteSpace(),
|
||||
Notes = info.Remarks,
|
||||
ProgrammedBy = info.Programmer,
|
||||
Revision = info.UserDefined1,
|
||||
Application = PepHelper.GetApplication(info.Application)
|
||||
};
|
||||
|
||||
return details;
|
||||
}
|
||||
}
|
||||
67
PepApi.Core/Extensions.cs
Normal file
67
PepApi.Core/Extensions.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using PepApi.Core.Models;
|
||||
using PepLib;
|
||||
|
||||
namespace PepApi.Core
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static bool IsNullOrWhiteSpace(this string s)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(s);
|
||||
}
|
||||
|
||||
public static bool IsNullOrEmpty(this string s)
|
||||
{
|
||||
return string.IsNullOrEmpty(s);
|
||||
}
|
||||
|
||||
public static bool IsNaN(this double d)
|
||||
{
|
||||
return double.IsNaN(d);
|
||||
}
|
||||
|
||||
public static bool IsInfinity(this double d)
|
||||
{
|
||||
return double.IsInfinity(d);
|
||||
}
|
||||
|
||||
public static bool IsNegativeInfinity(this double d)
|
||||
{
|
||||
return double.IsNegativeInfinity(d);
|
||||
}
|
||||
|
||||
public static bool IsPositiveInfinity(this double d)
|
||||
{
|
||||
return double.IsPositiveInfinity(d);
|
||||
}
|
||||
|
||||
public static bool IsEven(this int i)
|
||||
{
|
||||
return i % 2 == 0;
|
||||
}
|
||||
|
||||
public static bool IsOdd(this int i)
|
||||
{
|
||||
return i % 2 != 0;
|
||||
}
|
||||
|
||||
public static NestSummary ConvertToNestSummary(this NestInfo nest)
|
||||
{
|
||||
return new NestSummary
|
||||
{
|
||||
Name = nest.Name,
|
||||
DateCreated = nest.DateCreated,
|
||||
DateLastModified = nest.DateLastModified,
|
||||
Status = nest.Status.ToString(),
|
||||
Comments = nest.Comments,
|
||||
Customer = nest.Customer,
|
||||
ProgrammedBy = nest.ProgrammedBy,
|
||||
MaterialNumber = nest.MaterialNumber,
|
||||
MaterialGrade = nest.MaterialGrade,
|
||||
Notes = nest.Notes,
|
||||
HasErrors = !nest.Errors.IsNullOrWhiteSpace(),
|
||||
Revision = nest.UserDefined1
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
13
PepApi.Core/Models/Material.cs
Normal file
13
PepApi.Core/Models/Material.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class Material
|
||||
{
|
||||
public int Number { get; set; }
|
||||
|
||||
public string Grade { get; set; }
|
||||
|
||||
public double Thickness { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
||||
46
PepApi.Core/Models/NestDetails.cs
Normal file
46
PepApi.Core/Models/NestDetails.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class NestDetails
|
||||
{
|
||||
public NestDetails()
|
||||
{
|
||||
Parts = new List<Part>();
|
||||
Plates = new List<Plate>();
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public DateTime DateCreated { get; set; }
|
||||
|
||||
public DateTime DateLastModified { get; set; }
|
||||
|
||||
public string Status { get; set; }
|
||||
|
||||
public string Comments { get; set; }
|
||||
|
||||
public string Customer { get; set; }
|
||||
|
||||
public string ProgrammedBy { get; set; }
|
||||
|
||||
public Material Material { get; set; }
|
||||
|
||||
public string Notes { get; set; }
|
||||
|
||||
public bool HasErrors { get; set; }
|
||||
|
||||
public string Revision { get; set; }
|
||||
|
||||
public string Application { get; set; }
|
||||
|
||||
public int NumberOfTestSquares { get; set; }
|
||||
|
||||
public bool AreTestSquaresOutOfSequence { get; set; }
|
||||
|
||||
public List<Part> Parts { get; set; }
|
||||
|
||||
public List<Plate> Plates { get; set; }
|
||||
}
|
||||
}
|
||||
100
PepApi.Core/Models/NestFilterData.cs
Normal file
100
PepApi.Core/Models/NestFilterData.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PepLib;
|
||||
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class NestFilterData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Customer { get; set; }
|
||||
|
||||
public string Comments {get;set;}
|
||||
|
||||
public DateTime? StartDate { get; set; }
|
||||
|
||||
public DateTime? EndDate { get; set; }
|
||||
|
||||
public int? MaterialNumber { get; set; }
|
||||
|
||||
public string MaterialGrade { get; set; }
|
||||
|
||||
public string ProgrammedBy { get; set; }
|
||||
|
||||
public string Notes { get; set; }
|
||||
|
||||
public string Status { get; set; }
|
||||
|
||||
public string Application { get; set; }
|
||||
|
||||
public IQueryable<NestSummary> Apply(IQueryable<NestSummary> nests)
|
||||
{
|
||||
if (this.Name != null)
|
||||
{
|
||||
var x = this.Name.ToUpper();
|
||||
nests = nests.Where(n => n.Name.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.Customer != null)
|
||||
{
|
||||
var x = this.Customer.ToUpper();
|
||||
nests = nests.Where(n => n.Customer.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.Comments != null)
|
||||
{
|
||||
var x = this.Comments.ToUpper();
|
||||
nests = nests.Where(n => n.Comments.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.MaterialNumber != null)
|
||||
{
|
||||
nests = nests.Where(n => n.MaterialNumber == this.MaterialNumber);
|
||||
}
|
||||
|
||||
if (this.MaterialGrade != null)
|
||||
{
|
||||
var x = this.MaterialGrade.ToUpper();
|
||||
nests = nests.Where(n => n.MaterialGrade.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.ProgrammedBy != null)
|
||||
{
|
||||
var x = this.ProgrammedBy.ToUpper();
|
||||
nests = nests.Where(n => n.ProgrammedBy.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.Notes != null)
|
||||
{
|
||||
var x = this.Notes.ToUpper();
|
||||
nests = nests.Where(n => n.Notes.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.StartDate != null)
|
||||
{
|
||||
nests = nests.Where(n => n.DateCreated >= this.StartDate);
|
||||
}
|
||||
|
||||
if (this.EndDate != null)
|
||||
{
|
||||
nests = nests.Where(n => n.DateCreated <= this.EndDate);
|
||||
}
|
||||
|
||||
if (this.Status != null)
|
||||
{
|
||||
var x = this.Status.ToUpper();
|
||||
nests = nests.Where(n => n.Status.ToUpper() == x);
|
||||
}
|
||||
|
||||
if (this.Application != null)
|
||||
{
|
||||
var x = this.Application.ToUpper();
|
||||
nests = nests.Where(n => n.Application.ToUpper() == x);
|
||||
}
|
||||
|
||||
return nests;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
PepApi.Core/Models/NestSummary.cs
Normal file
35
PepApi.Core/Models/NestSummary.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using PepLib;
|
||||
using System;
|
||||
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class NestSummary
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public DateTime DateCreated { get; set; }
|
||||
|
||||
public DateTime DateLastModified { get; set; }
|
||||
|
||||
public string Status { get; set; }
|
||||
|
||||
public string Comments { get; set; }
|
||||
|
||||
public string Customer { get; set; }
|
||||
|
||||
public string ProgrammedBy { get; set; }
|
||||
|
||||
public int MaterialNumber { get; set; }
|
||||
|
||||
public string MaterialGrade { get; set; }
|
||||
|
||||
public string Notes { get; set; }
|
||||
|
||||
public bool HasErrors { get; set; }
|
||||
|
||||
public string Revision { get; set; }
|
||||
|
||||
public string Application { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
10
PepApi.Core/Models/Part.cs
Normal file
10
PepApi.Core/Models/Part.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class Part
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int QtyNested { get; set; }
|
||||
public int QtyRequired { get; set; }
|
||||
public int[] NestedOn { get; set; }
|
||||
}
|
||||
}
|
||||
20
PepApi.Core/Models/Plate.cs
Normal file
20
PepApi.Core/Models/Plate.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class Plate
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public double Thickness { get; set; }
|
||||
|
||||
public Material Material { get; set; }
|
||||
|
||||
public Size Size { get; set; }
|
||||
|
||||
public int Qty { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Material.Thickness}, {Material.Grade} {Material.Description}, {Size.ToString()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
14
PepApi.Core/Models/Size.cs
Normal file
14
PepApi.Core/Models/Size.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class Size
|
||||
{
|
||||
public double Width { get; set; }
|
||||
|
||||
public double Length { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Width} x {Length}";
|
||||
}
|
||||
}
|
||||
}
|
||||
18
PepApi.Core/PepApi.Core.csproj
Normal file
18
PepApi.Core/PepApi.Core.csproj
Normal file
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.20" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PepLib.Core\PepLib.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
6
PepApi.Core/PepApi.Core.http
Normal file
6
PepApi.Core/PepApi.Core.http
Normal file
@@ -0,0 +1,6 @@
|
||||
@PepApi.Core_HostAddress = http://localhost:5151
|
||||
|
||||
GET {{PepApi.Core_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
234
PepApi.Core/PepHelper.cs
Normal file
234
PepApi.Core/PepHelper.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using PepLib;
|
||||
using Material = PepApi.Core.Models.Material;
|
||||
using Part = PepApi.Core.Models.Part;
|
||||
using Plate = PepApi.Core.Models.Plate;
|
||||
using Size = PepApi.Core.Models.Size;
|
||||
|
||||
namespace PepApi.Core
|
||||
{
|
||||
internal static class PepHelper
|
||||
{
|
||||
public static bool IsTestSquare(PepLib.Part part)
|
||||
{
|
||||
if (part == null || part.DrawingName == null)
|
||||
return false;
|
||||
|
||||
var drawingName = part.DrawingName.ToUpper();
|
||||
|
||||
if (drawingName.Contains("TEST SQUARE"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int GetTestSquareCount(Nest nest)
|
||||
{
|
||||
var count = 0;
|
||||
|
||||
foreach (var plate in nest.Plates)
|
||||
{
|
||||
foreach (var part in plate.Parts)
|
||||
{
|
||||
if (IsTestSquare(part))
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static bool AreTestSquaresInCorrectOrder(PepLib.Plate plate)
|
||||
{
|
||||
var partsStarted = false;
|
||||
|
||||
foreach (var part in plate.Parts)
|
||||
{
|
||||
var isTestSquare = IsTestSquare(part);
|
||||
|
||||
if (isTestSquare)
|
||||
{
|
||||
if (partsStarted)
|
||||
{
|
||||
// test square found after a part
|
||||
// test squares must be cut first
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (part.IsDisplayOnly)
|
||||
continue;
|
||||
|
||||
partsStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool AreTestSquaresInCorrectOrder(PepLib.Nest nest)
|
||||
{
|
||||
foreach (var plate in nest.Plates)
|
||||
{
|
||||
if (!AreTestSquaresInCorrectOrder(plate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string GetStatus(int statusNum)
|
||||
{
|
||||
switch (statusNum)
|
||||
{
|
||||
case -1: return "Deleted";
|
||||
case 0: return "To be cut";
|
||||
case 1: return "Quote";
|
||||
case 2: return "Has been cut";
|
||||
case 3: return "Hold";
|
||||
case 4: return "Quote, accepted, to be cut";
|
||||
case 5: return "Quote, accepted, has been cut";
|
||||
case 6: return "Quote, accepted, hold";
|
||||
case 7: return "Quote, accepted, moved to wip";
|
||||
case 8: return "Quote, rejected";
|
||||
case 9: return "Quote, timed out";
|
||||
default: return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetApplication(int applicationID)
|
||||
{
|
||||
switch (applicationID)
|
||||
{
|
||||
case 1: return "Laser";
|
||||
case 2: return "Plasma";
|
||||
default: return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateQtyNested(Part part, Nest nest)
|
||||
{
|
||||
part.QtyNested = 0;
|
||||
|
||||
var nestedOn = new List<int>();
|
||||
var partName = part.Name.ToUpper();
|
||||
|
||||
for (int i = 0; i < nest.Plates.Count; i++)
|
||||
{
|
||||
var plate = nest.Plates[i];
|
||||
var qtyNested = 0;
|
||||
|
||||
qtyNested = plate.Parts.Count(p => p.DrawingName?.ToUpper() == partName);
|
||||
|
||||
// plate.Duplicates is actually the quantity, so 1 Duplicate = 1 plate
|
||||
qtyNested *= plate.Duplicates;
|
||||
|
||||
if (qtyNested > 0)
|
||||
{
|
||||
part.QtyNested += qtyNested;
|
||||
nestedOn.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
part.NestedOn = nestedOn.ToArray();
|
||||
}
|
||||
|
||||
public static List<Part> GetParts(Nest nest)
|
||||
{
|
||||
var parts = new List<Part>();
|
||||
|
||||
for (int i = 0; i < nest.Drawings.Count; i++)
|
||||
{
|
||||
var drawing = nest.Drawings[i];
|
||||
|
||||
if (drawing.Name.IsNullOrWhiteSpace())
|
||||
continue;
|
||||
|
||||
var dwg = nest.Drawings.FirstOrDefault(d => d.Name == drawing.Name);
|
||||
|
||||
var part = new Part
|
||||
{
|
||||
Name = drawing.Name,
|
||||
QtyRequired = dwg.QtyRequired
|
||||
};
|
||||
|
||||
UpdateQtyNested(part, nest);
|
||||
|
||||
parts.Add(part);
|
||||
}
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
public static List<Plate> GetPlates(Nest nest)
|
||||
{
|
||||
var plates = new List<Plate>();
|
||||
|
||||
for (int i = 0; i < nest.Plates.Count; i++)
|
||||
{
|
||||
var plate = nest.Plates[i];
|
||||
|
||||
var p = new Plate
|
||||
{
|
||||
Name = plate.Name,
|
||||
Material = GetMaterial(plate),
|
||||
Qty = plate.Duplicates,
|
||||
Thickness = plate.Thickness,
|
||||
Size = new Size
|
||||
{
|
||||
Width = plate.Size.Height,
|
||||
Length = plate.Size.Width
|
||||
}
|
||||
};
|
||||
|
||||
plates.Add(p);
|
||||
}
|
||||
|
||||
return plates;
|
||||
}
|
||||
|
||||
public static List<Plate> CombineLikePlates(IEnumerable<Plate> plates)
|
||||
{
|
||||
var combinedPlatesList = new List<Plate>();
|
||||
var uniquePlates = plates.GroupBy(p => p.ToString());
|
||||
|
||||
foreach (var item in uniquePlates)
|
||||
{
|
||||
var plate = item.First();
|
||||
plate.Name = null;
|
||||
plate.Qty = item.Sum((Plate p) => p.Qty);
|
||||
|
||||
combinedPlatesList.Add(plate);
|
||||
}
|
||||
|
||||
return combinedPlatesList
|
||||
.OrderBy(p => p.Material.Number)
|
||||
.ThenBy(p => p.Material.Grade)
|
||||
.ThenBy(p => p.Size.Width)
|
||||
.ThenBy(p => p.Size.Length)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static Material GetMaterial(PepLib.Plate plate)
|
||||
{
|
||||
return new Material
|
||||
{
|
||||
Number = plate.Material.Id,
|
||||
Grade = plate.Material.Grade,
|
||||
Thickness = plate.Thickness,
|
||||
Description = plate.Description
|
||||
};
|
||||
}
|
||||
|
||||
public static Material GetMaterial(PepLib.Nest nest)
|
||||
{
|
||||
return GetMaterial(nest.Plates.First());
|
||||
}
|
||||
}
|
||||
}
|
||||
61
PepApi.Core/Program.cs
Normal file
61
PepApi.Core/Program.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PepApi.Core.Configuration;
|
||||
using PepLib.Data;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container
|
||||
builder.Services.AddControllers()
|
||||
.AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.PropertyNamingPolicy = null; // Keep PascalCase for backward compatibility
|
||||
});
|
||||
|
||||
// Configure PepSettings from appsettings.json
|
||||
builder.Services.Configure<PepSettings>(
|
||||
builder.Configuration.GetSection("PepSettings"));
|
||||
|
||||
// Configure Entity Framework Core with SQL Server (read-only with connection pooling)
|
||||
builder.Services.AddDbContextPool<PepDB>(options =>
|
||||
{
|
||||
options.UseSqlServer(builder.Configuration.GetConnectionString("PepDB"));
|
||||
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); // Read-only optimization
|
||||
});
|
||||
|
||||
// Add Swagger/OpenAPI
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
|
||||
{
|
||||
Title = "PepApi",
|
||||
Version = "v1",
|
||||
Description = "PEP Nesting API - Modern ASP.NET Core version"
|
||||
});
|
||||
});
|
||||
|
||||
// Add CORS if needed
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddDefaultPolicy(policy =>
|
||||
{
|
||||
policy.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseCors();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
41
PepApi.Core/Properties/launchSettings.json
Normal file
41
PepApi.Core/Properties/launchSettings.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:53377",
|
||||
"sslPort": 44393
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5151",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:7066;http://localhost:5151",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
PepApi.Core/appsettings.Development.json
Normal file
8
PepApi.Core/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
23
PepApi.Core/appsettings.json
Normal file
23
PepApi.Core/appsettings.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"PepDB": "data source=REMCOSRV0\\RWS64;initial catalog=PEP;integrated security=True;MultipleActiveResultSets=True;TrustServerCertificate=True"
|
||||
},
|
||||
"PepSettings": {
|
||||
"NestDirectory": "\\\\REMCOSRV0\\PEP Nest",
|
||||
"MaterialsFile": "C:\\Pep\\PEP2012\\CONFIG\\material.lfn"
|
||||
},
|
||||
"Kestrel": {
|
||||
"Endpoints": {
|
||||
"Http": {
|
||||
"Url": "http://*:8085"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
PepApi.sln
Normal file
51
PepApi.sln
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36518.9 d17.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepApi.Core", "PepApi.Core\PepApi.Core.csproj", "{6761DEB6-14DD-4930-B1BB-BEC16A278E73}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PepLib.Core", "PepLib.Core\PepLib.Core.csproj", "{3E03F837-2CD5-4681-BED9-7179DF766DF6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6761DEB6-14DD-4930-B1BB-BEC16A278E73}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3E03F837-2CD5-4681-BED9-7179DF766DF6}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {39F3E901-33B2-4CAB-8BEB-5FDDB48998F9}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
17
PepLib.Core/AngleConverter.cs
Normal file
17
PepLib.Core/AngleConverter.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public static class AngleConverter
|
||||
{
|
||||
public static double ToDegrees(double radians)
|
||||
{
|
||||
return 180.0 / Math.PI * radians;
|
||||
}
|
||||
|
||||
public static double ToRadians(double degrees)
|
||||
{
|
||||
return Math.PI / 180.0 * degrees;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
PepLib.Core/ApplicationType.cs
Normal file
15
PepLib.Core/ApplicationType.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public enum ApplicationType
|
||||
{
|
||||
None = 0x0,
|
||||
Laser = 0x1,
|
||||
Flame = 0x2,
|
||||
Punch = 0x3,
|
||||
PlasmaPunch = 0x4,
|
||||
Waterjet = 0x6,
|
||||
LaserPunch = 0x7,
|
||||
FlamePlasma = 0x9
|
||||
}
|
||||
}
|
||||
154
PepLib.Core/Box.cs
Normal file
154
PepLib.Core/Box.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Box
|
||||
{
|
||||
public Box()
|
||||
: this(0, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public Box(double x, double y, double w, double h)
|
||||
{
|
||||
Location = new Vector(x, y);
|
||||
Size = new PepLib.Size(0, 0);
|
||||
Width = w;
|
||||
Height = h;
|
||||
}
|
||||
|
||||
public Vector Location;
|
||||
|
||||
public Vector Center
|
||||
{
|
||||
get { return new Vector(X + Width * 0.5, Y + Height * 0.5); }
|
||||
}
|
||||
|
||||
public Size Size;
|
||||
|
||||
public double X
|
||||
{
|
||||
get { return Location.X; }
|
||||
set { Location.X = value; }
|
||||
}
|
||||
|
||||
public double Y
|
||||
{
|
||||
get { return Location.Y; }
|
||||
set { Location.Y = value; }
|
||||
}
|
||||
|
||||
public double Width
|
||||
{
|
||||
get { return Size.Width; }
|
||||
set { Size.Width = value; }
|
||||
}
|
||||
|
||||
public double Height
|
||||
{
|
||||
get { return Size.Height; }
|
||||
set { Size.Height = value; }
|
||||
}
|
||||
|
||||
public void MoveTo(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public void MoveTo(Vector pt)
|
||||
{
|
||||
X = pt.X;
|
||||
Y = pt.Y;
|
||||
}
|
||||
|
||||
public void Offset(double x, double y)
|
||||
{
|
||||
X += x;
|
||||
Y += y;
|
||||
}
|
||||
|
||||
public void Offset(Vector voffset)
|
||||
{
|
||||
Location += voffset;
|
||||
}
|
||||
|
||||
public double Left
|
||||
{
|
||||
get { return X; }
|
||||
}
|
||||
|
||||
public double Right
|
||||
{
|
||||
get { return X + Width; }
|
||||
}
|
||||
|
||||
public double Top
|
||||
{
|
||||
get { return Y + Height; }
|
||||
}
|
||||
|
||||
public double Bottom
|
||||
{
|
||||
get { return Y; }
|
||||
}
|
||||
|
||||
public double Area()
|
||||
{
|
||||
return Width * Height;
|
||||
}
|
||||
|
||||
public double Perimeter()
|
||||
{
|
||||
return Width * 2 + Height * 2;
|
||||
}
|
||||
|
||||
public bool IsIntersecting(Box box)
|
||||
{
|
||||
if (Left >= box.Right)
|
||||
return false;
|
||||
|
||||
if (Right >= box.Left)
|
||||
return false;
|
||||
|
||||
if (Top <= box.Bottom)
|
||||
return false;
|
||||
|
||||
if (Bottom <= box.Top)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Contains(Box box)
|
||||
{
|
||||
if (box.Left < Left)
|
||||
return false;
|
||||
|
||||
if (box.Right > Right)
|
||||
return false;
|
||||
|
||||
if (box.Bottom < Bottom)
|
||||
return false;
|
||||
|
||||
if (box.Top > Top)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Contains(Vector pt)
|
||||
{
|
||||
return pt.X >= Left && pt.X <= Right
|
||||
&& pt.Y >= Bottom && pt.Y <= Top;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[Box: X={0}, Y={1}, Width={2}, Height={3}]", X, Y, Width, Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
74
PepLib.Core/Codes/CircularMove.cs
Normal file
74
PepLib.Core/Codes/CircularMove.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class CircularMove : Motion
|
||||
{
|
||||
public CircularMove()
|
||||
{
|
||||
}
|
||||
|
||||
public CircularMove(Vector endPoint, Vector centerPoint, RotationType rotation = RotationType.CCW)
|
||||
{
|
||||
EndPoint = endPoint;
|
||||
CenterPoint = centerPoint;
|
||||
Rotation = rotation;
|
||||
}
|
||||
|
||||
public CircularMove(double x, double y, double i, double j, RotationType rotation = RotationType.CCW)
|
||||
{
|
||||
EndPoint = new Vector(x, y);
|
||||
CenterPoint = new Vector(i, j);
|
||||
Rotation = rotation;
|
||||
}
|
||||
|
||||
public RotationType Rotation { get; set; }
|
||||
|
||||
public EntityType Type { get; set; }
|
||||
|
||||
public Vector CenterPoint { get; set; }
|
||||
|
||||
public override void Rotate(double angle)
|
||||
{
|
||||
base.Rotate(angle);
|
||||
CenterPoint = CenterPoint.Rotate(angle);
|
||||
}
|
||||
|
||||
public override void Rotate(double angle, Vector origin)
|
||||
{
|
||||
base.Rotate(angle, origin);
|
||||
CenterPoint = CenterPoint.Rotate(angle, origin);
|
||||
}
|
||||
|
||||
public override void Offset(double x, double y)
|
||||
{
|
||||
base.Offset(x, y);
|
||||
CenterPoint = new Vector(CenterPoint.X + x, CenterPoint.Y + y);
|
||||
}
|
||||
|
||||
public override void Offset(Vector voffset)
|
||||
{
|
||||
base.Offset(voffset);
|
||||
CenterPoint += voffset;
|
||||
}
|
||||
|
||||
public override CodeType CodeType()
|
||||
{
|
||||
return Codes.CodeType.CircularMove;
|
||||
}
|
||||
|
||||
public override ICode Clone()
|
||||
{
|
||||
return new CircularMove(EndPoint, CenterPoint, Rotation)
|
||||
{
|
||||
Type = Type
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Rotation == RotationType.CW ?
|
||||
string.Format("G02 X{0} Y{1} I{2} J{3}", EndPoint.X, EndPoint.Y, CenterPoint.X, CenterPoint.Y) :
|
||||
string.Format("G03 X{0} Y{1} I{2} J{3}", EndPoint.X, EndPoint.Y, CenterPoint.X, CenterPoint.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
14
PepLib.Core/Codes/CodeType.cs
Normal file
14
PepLib.Core/Codes/CodeType.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public enum CodeType
|
||||
{
|
||||
CircularMove,
|
||||
Comment,
|
||||
LinearMove,
|
||||
RapidMove,
|
||||
SetFeedrate,
|
||||
SetKerf,
|
||||
SubProgramCall
|
||||
}
|
||||
}
|
||||
32
PepLib.Core/Codes/Comment.cs
Normal file
32
PepLib.Core/Codes/Comment.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class Comment : ICode
|
||||
{
|
||||
public Comment()
|
||||
{
|
||||
}
|
||||
|
||||
public Comment(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public CodeType CodeType()
|
||||
{
|
||||
return Codes.CodeType.Comment;
|
||||
}
|
||||
|
||||
public ICode Clone()
|
||||
{
|
||||
return new Comment(Value);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ':' + Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
PepLib.Core/Codes/EntityType.cs
Normal file
13
PepLib.Core/Codes/EntityType.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public enum EntityType
|
||||
{
|
||||
Display,
|
||||
Scribe,
|
||||
Cut,
|
||||
InternalLeadin,
|
||||
InternalLeadout,
|
||||
ExternalLeadin,
|
||||
ExternalLeadout
|
||||
}
|
||||
}
|
||||
8
PepLib.Core/Codes/ICode.cs
Normal file
8
PepLib.Core/Codes/ICode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public interface ICode
|
||||
{
|
||||
CodeType CodeType();
|
||||
ICode Clone();
|
||||
}
|
||||
}
|
||||
42
PepLib.Core/Codes/LinearMove.cs
Normal file
42
PepLib.Core/Codes/LinearMove.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class LinearMove : Motion
|
||||
{
|
||||
public LinearMove()
|
||||
: this(new Vector())
|
||||
{
|
||||
}
|
||||
|
||||
public LinearMove(double x, double y)
|
||||
: this(new Vector(x, y))
|
||||
{
|
||||
}
|
||||
|
||||
public LinearMove(Vector endPoint)
|
||||
{
|
||||
EndPoint = endPoint;
|
||||
Type = EntityType.Cut;
|
||||
}
|
||||
|
||||
public EntityType Type { get; set; }
|
||||
|
||||
public override CodeType CodeType()
|
||||
{
|
||||
return Codes.CodeType.LinearMove;
|
||||
}
|
||||
|
||||
public override ICode Clone()
|
||||
{
|
||||
return new LinearMove(EndPoint)
|
||||
{
|
||||
Type = Type
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("G01 X{0} Y{1}", EndPoint.X, EndPoint.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
PepLib.Core/Codes/Motion.cs
Normal file
32
PepLib.Core/Codes/Motion.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public abstract class Motion : IMovable, ICode
|
||||
{
|
||||
public Vector EndPoint { get; set; }
|
||||
|
||||
public virtual void Rotate(double angle)
|
||||
{
|
||||
EndPoint = EndPoint.Rotate(angle);
|
||||
}
|
||||
|
||||
public virtual void Rotate(double angle, Vector origin)
|
||||
{
|
||||
EndPoint = EndPoint.Rotate(angle, origin);
|
||||
}
|
||||
|
||||
public virtual void Offset(double x, double y)
|
||||
{
|
||||
EndPoint = new Vector(EndPoint.X + x, EndPoint.Y + y);
|
||||
}
|
||||
|
||||
public virtual void Offset(Vector voffset)
|
||||
{
|
||||
EndPoint += voffset;
|
||||
}
|
||||
|
||||
public abstract CodeType CodeType();
|
||||
|
||||
public abstract ICode Clone();
|
||||
}
|
||||
}
|
||||
34
PepLib.Core/Codes/RapidMove.cs
Normal file
34
PepLib.Core/Codes/RapidMove.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class RapidMove : Motion
|
||||
{
|
||||
public RapidMove()
|
||||
{
|
||||
}
|
||||
|
||||
public RapidMove(Vector endPoint)
|
||||
{
|
||||
EndPoint = endPoint;
|
||||
}
|
||||
|
||||
public RapidMove(double x, double y)
|
||||
{
|
||||
EndPoint = new Vector(x, y);
|
||||
}
|
||||
|
||||
public override CodeType CodeType()
|
||||
{
|
||||
return Codes.CodeType.RapidMove;
|
||||
}
|
||||
|
||||
public override ICode Clone()
|
||||
{
|
||||
return new RapidMove(EndPoint);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("G00 X{0} Y{1}", EndPoint.X, EndPoint.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
PepLib.Core/Codes/SetFeedrate.cs
Normal file
32
PepLib.Core/Codes/SetFeedrate.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class SetFeedrate : ICode
|
||||
{
|
||||
public SetFeedrate()
|
||||
{
|
||||
}
|
||||
|
||||
public SetFeedrate(double value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public double Value { get; set; }
|
||||
|
||||
public CodeType CodeType()
|
||||
{
|
||||
return Codes.CodeType.SetFeedrate;
|
||||
}
|
||||
|
||||
public ICode Clone()
|
||||
{
|
||||
return new SetFeedrate(Value);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("F{0}", Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
34
PepLib.Core/Codes/SetKerf.cs
Normal file
34
PepLib.Core/Codes/SetKerf.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class SetKerf : ICode
|
||||
{
|
||||
public SetKerf(KerfType kerf = KerfType.Left)
|
||||
{
|
||||
Kerf = kerf;
|
||||
}
|
||||
|
||||
public KerfType Kerf { get; set; }
|
||||
|
||||
public CodeType CodeType()
|
||||
{
|
||||
return Codes.CodeType.SetKerf;
|
||||
}
|
||||
|
||||
public ICode Clone()
|
||||
{
|
||||
return new SetKerf(Kerf);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Kerf == KerfType.None)
|
||||
return "G40";
|
||||
|
||||
if (Kerf == KerfType.Left)
|
||||
return "G41";
|
||||
|
||||
return "G42";
|
||||
}
|
||||
}
|
||||
}
|
||||
85
PepLib.Core/Codes/SubProgramCall.cs
Normal file
85
PepLib.Core/Codes/SubProgramCall.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class SubProgramCall : ICode
|
||||
{
|
||||
private double rotation;
|
||||
private Loop loop;
|
||||
|
||||
public SubProgramCall()
|
||||
{
|
||||
}
|
||||
|
||||
public SubProgramCall(int loopId, int repeatCount, double rotation)
|
||||
{
|
||||
LoopId = loopId;
|
||||
RepeatCount = repeatCount;
|
||||
Rotation = rotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The id associated with the current set loop.
|
||||
/// </summary>
|
||||
public int LoopId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of times the loop is cut.
|
||||
/// </summary>
|
||||
public int RepeatCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the loop associated with the loop id.
|
||||
/// </summary>
|
||||
public Loop Loop
|
||||
{
|
||||
get { return loop; }
|
||||
set
|
||||
{
|
||||
loop = (Loop)value.Clone();
|
||||
UpdateLoopRotation();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current rotation of the loop in degrees.
|
||||
/// </summary>
|
||||
public double Rotation
|
||||
{
|
||||
get { return rotation; }
|
||||
set
|
||||
{
|
||||
rotation = value;
|
||||
UpdateLoopRotation();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLoopRotation()
|
||||
{
|
||||
if (loop != null)
|
||||
{
|
||||
var diffAngle = AngleConverter.ToRadians(rotation) - loop.Rotation;
|
||||
|
||||
if (!diffAngle.IsEqualTo(0.0))
|
||||
loop.Rotate(diffAngle);
|
||||
}
|
||||
}
|
||||
|
||||
public CodeType CodeType()
|
||||
{
|
||||
return Codes.CodeType.SubProgramCall;
|
||||
}
|
||||
|
||||
public ICode Clone()
|
||||
{
|
||||
return new SubProgramCall(LoopId, RepeatCount, Rotation)
|
||||
{
|
||||
Loop = Loop
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("G92 L{0} R{1} P{2}", LoopId, RepeatCount, Rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
216
PepLib.Core/Data/Drawing.cs
Normal file
216
PepLib.Core/Data/Drawing.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
namespace PepLib.Data
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
|
||||
[Table("Drawing")]
|
||||
public partial class Drawing
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(20)]
|
||||
public string CustID { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(32)]
|
||||
public string Revision { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Path { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string File { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string InUseBy { get; set; }
|
||||
|
||||
public DateTime? InUseDate { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Status { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string StatusModifiedBy { get; set; }
|
||||
|
||||
public DateTime? StatusModifiedDate { get; set; }
|
||||
|
||||
public DateTime? CreationDate { get; set; }
|
||||
|
||||
public DateTime? LastEditDate { get; set; }
|
||||
|
||||
public DateTime? LastRefDate { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Customer { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Comment { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Notes { get; set; }
|
||||
|
||||
public byte Grain { get; set; }
|
||||
|
||||
public double GrainAngle { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Material { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string MatGrade { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Programmer { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string CreatedBy { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Type { get; set; }
|
||||
|
||||
public byte CommonCut { get; set; }
|
||||
|
||||
public byte CombineCut { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Errors { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Hardness { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Specification { get; set; }
|
||||
|
||||
public byte NestInCutOuts { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined1 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined2 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined3 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined4 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined5 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined6 { get; set; }
|
||||
|
||||
public short Machine { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Application { get; set; }
|
||||
|
||||
public int PartCount { get; set; }
|
||||
|
||||
public int Color { get; set; }
|
||||
|
||||
public short CombineMethod { get; set; }
|
||||
|
||||
public byte SeqCutouts { get; set; }
|
||||
|
||||
public byte AllowMirror { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string SourceFile { get; set; }
|
||||
|
||||
public DateTime? SourceDate { get; set; }
|
||||
|
||||
public int SourceSize { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string CadScaled { get; set; }
|
||||
|
||||
public int CadDimVerified { get; set; }
|
||||
|
||||
public int CadDimCount { get; set; }
|
||||
|
||||
public double Width { get; set; }
|
||||
|
||||
public double Length { get; set; }
|
||||
|
||||
public double RectArea { get; set; }
|
||||
|
||||
public double ExtArea { get; set; }
|
||||
|
||||
public double TrueArea { get; set; }
|
||||
|
||||
public double ExtUtil { get; set; }
|
||||
|
||||
public double TrueUtil { get; set; }
|
||||
|
||||
public double SmallestAreaAng { get; set; }
|
||||
|
||||
public double SmallestAreaLen { get; set; }
|
||||
|
||||
public double SmallestAreaWid { get; set; }
|
||||
|
||||
public double SmallestYAng { get; set; }
|
||||
|
||||
public double SmallestYLen { get; set; }
|
||||
|
||||
public double SmallestYWid { get; set; }
|
||||
|
||||
public double CutLength { get; set; }
|
||||
|
||||
public double ScribeLength { get; set; }
|
||||
|
||||
public int Checked { get; set; }
|
||||
|
||||
public byte PepBendStatus { get; set; }
|
||||
|
||||
public int HasBevel { get; set; }
|
||||
|
||||
public int HasLeadIn { get; set; }
|
||||
|
||||
public int HasTab { get; set; }
|
||||
|
||||
public DateTime? ModifiedDate { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string ModifiedBy { get; set; }
|
||||
}
|
||||
}
|
||||
84
PepLib.Core/Data/NestDetail.cs
Normal file
84
PepLib.Core/Data/NestDetail.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
namespace PepLib.Data
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
|
||||
[Table("NestDetail")]
|
||||
public partial class NestDetail
|
||||
{
|
||||
[Key]
|
||||
public int AutoInc { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(200)]
|
||||
public string NestName { get; set; }
|
||||
|
||||
public int CopyID { get; set; }
|
||||
|
||||
[StringLength(200)]
|
||||
public string Drawing { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(20)]
|
||||
public string CustID { get; set; }
|
||||
|
||||
public int? DwgLoopNo { get; set; }
|
||||
|
||||
[StringLength(40)]
|
||||
public string DwgRevision { get; set; }
|
||||
|
||||
[StringLength(40)]
|
||||
public string CustomerNo { get; set; }
|
||||
|
||||
[StringLength(64)]
|
||||
public string CustomerName { get; set; }
|
||||
|
||||
public int? QtyReq { get; set; }
|
||||
|
||||
public int? QtyNstd { get; set; }
|
||||
|
||||
public int? QtyRem { get; set; }
|
||||
|
||||
public double? CutDist { get; set; }
|
||||
|
||||
public double? ScribeDist { get; set; }
|
||||
|
||||
public int? CutTime { get; set; }
|
||||
|
||||
public int? PierceCount { get; set; }
|
||||
|
||||
public int? IntersectionCount { get; set; }
|
||||
|
||||
public double? Area1 { get; set; }
|
||||
|
||||
public double? Area2 { get; set; }
|
||||
|
||||
public double? CostPerPart { get; set; }
|
||||
|
||||
public double? Net1Weight { get; set; }
|
||||
|
||||
public double? Net2Weight { get; set; }
|
||||
|
||||
public double? Net2WithRemWeight { get; set; }
|
||||
|
||||
public double? Net3Weight { get; set; }
|
||||
|
||||
public double? Net4Weight { get; set; }
|
||||
|
||||
public double? GrossWeight { get; set; }
|
||||
|
||||
public double? PercentOfMaterial { get; set; }
|
||||
|
||||
public double? PercentOfTime { get; set; }
|
||||
|
||||
public double? RotationConstraint { get; set; }
|
||||
|
||||
public DateTime? ModifiedDate { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string ModifiedBy { get; set; }
|
||||
}
|
||||
}
|
||||
79
PepLib.Core/Data/NestDrawing.cs
Normal file
79
PepLib.Core/Data/NestDrawing.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
namespace PepLib.Data
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
|
||||
[Table("NestDrawing")]
|
||||
public partial class NestDrawing
|
||||
{
|
||||
[Key]
|
||||
public int AutoInc { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string NestName { get; set; }
|
||||
|
||||
public int CopyID { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Drawing { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(20)]
|
||||
public string CustID { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(32)]
|
||||
public string DwgRevision { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string DwgDesc { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string ImageFile { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined1 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined2 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined3 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined4 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined5 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined6 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Description { get; set; }
|
||||
|
||||
public decimal SizeX { get; set; }
|
||||
|
||||
public decimal SizeY { get; set; }
|
||||
|
||||
public DateTime? ModifiedDate { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string ModifiedBy { get; set; }
|
||||
}
|
||||
}
|
||||
287
PepLib.Core/Data/NestHeader.cs
Normal file
287
PepLib.Core/Data/NestHeader.cs
Normal file
@@ -0,0 +1,287 @@
|
||||
namespace PepLib.Data
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
|
||||
[Table("NestHeader")]
|
||||
public partial class NestHeader
|
||||
{
|
||||
[Key]
|
||||
public int AutoInc { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string NestName { get; set; }
|
||||
|
||||
public int CopyID { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(20)]
|
||||
public string CustID { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string CustomerName { get; set; }
|
||||
|
||||
public DateTime? DateProgrammed { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Material { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(128)]
|
||||
public string MatDescription { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string MatGrade { get; set; }
|
||||
|
||||
public double MatThick { get; set; }
|
||||
|
||||
public double MatCost { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Programmer { get; set; }
|
||||
|
||||
public int Machine { get; set; }
|
||||
|
||||
public int Application { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Post { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Comments { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Remarks { get; set; }
|
||||
|
||||
public int ProgramCount { get; set; }
|
||||
|
||||
public int Duplicates { get; set; }
|
||||
|
||||
public double MachineCostPerHour { get; set; }
|
||||
|
||||
public double MachineHoursNeeded { get; set; }
|
||||
|
||||
public double MatDensity { get; set; }
|
||||
|
||||
public double HandlingCostPerPlate { get; set; }
|
||||
|
||||
public double HandlingCostPerPart { get; set; }
|
||||
|
||||
public int PlateCount { get; set; }
|
||||
|
||||
public int PartCount { get; set; }
|
||||
|
||||
public double CostOfConsumablesPerPierce { get; set; }
|
||||
|
||||
public double ConsumablesPerPierceNeeded { get; set; }
|
||||
|
||||
public bool CPTApplied { get; set; }
|
||||
|
||||
public double CuttingPierceTime { get; set; }
|
||||
|
||||
public double ScribePierceTime { get; set; }
|
||||
|
||||
public double IntersectDelayTime { get; set; }
|
||||
|
||||
public double HeadUpDownTimeBetweenCutouts { get; set; }
|
||||
|
||||
public double HeadUpDownTimeBetweenParts { get; set; }
|
||||
|
||||
public double RapidFeedRate { get; set; }
|
||||
|
||||
public double PercentOfFeedRateForArcs { get; set; }
|
||||
|
||||
public double PercentOfFeedRateForSmallHoles { get; set; }
|
||||
|
||||
public double PercentOfFeedRateForMediumHoles { get; set; }
|
||||
|
||||
public double PercentOfFeedRateForSmallCutouts { get; set; }
|
||||
|
||||
public double AssistGasPressure { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(3)]
|
||||
public string TypeOfGas { get; set; }
|
||||
|
||||
public double NozzleSize { get; set; }
|
||||
|
||||
public double CostOfGasPerCF { get; set; }
|
||||
|
||||
public double CFOfGasNeeded { get; set; }
|
||||
|
||||
public double TotalCutDist { get; set; }
|
||||
|
||||
public double TotalRapidDist { get; set; }
|
||||
|
||||
public double EdgePierceCount { get; set; }
|
||||
|
||||
public double BubblePierceCount { get; set; }
|
||||
|
||||
public double RadiusCornerCount { get; set; }
|
||||
|
||||
public bool IncludeRemnantCost { get; set; }
|
||||
|
||||
public double ClampRepositionTime { get; set; }
|
||||
|
||||
public double PlateLoadTime { get; set; }
|
||||
|
||||
public double PlateUnloadTime { get; set; }
|
||||
|
||||
public double TimePerPart { get; set; }
|
||||
|
||||
public int rStatus { get; set; }
|
||||
|
||||
public DateTime? rDateStamp { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined1 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined2 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined3 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined4 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined5 { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string UserDefined6 { get; set; }
|
||||
|
||||
public double ActualCutTime { get; set; }
|
||||
|
||||
public double ActualStartTime { get; set; }
|
||||
|
||||
public double ActualEndTime { get; set; }
|
||||
|
||||
public double CuttingFeedRate { get; set; }
|
||||
|
||||
public DateTime? ModifiedDate { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string ModifiedBy { get; set; }
|
||||
|
||||
public int Status { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Path { get; set; }
|
||||
|
||||
public DateTime? DueDate { get; set; }
|
||||
|
||||
public int NestGenTime { get; set; }
|
||||
|
||||
public int NestEditTime { get; set; }
|
||||
|
||||
public int NestEditCount { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string NestGenMethod { get; set; }
|
||||
|
||||
public double ScribingFeedRate { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string FeedRateScenarios { get; set; }
|
||||
|
||||
public double PercentOfFeedRateForInsideBevel { get; set; }
|
||||
|
||||
public double PercentOfFeedRateForOutsideBevel { get; set; }
|
||||
|
||||
public double SetupTime { get; set; }
|
||||
|
||||
public double BubbleEdgePierceTime { get; set; }
|
||||
|
||||
public double BevelTorchTiltTime { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(3)]
|
||||
public string OutputJobCosting { get; set; }
|
||||
|
||||
public double CadDrawingCharge { get; set; }
|
||||
|
||||
public double MaterialMarkup { get; set; }
|
||||
|
||||
public double OverheadMarkup { get; set; }
|
||||
|
||||
public double CostOfFreightPerPound { get; set; }
|
||||
|
||||
public double DrillCostPerHole { get; set; }
|
||||
|
||||
public double DrillCostPerUniquePart { get; set; }
|
||||
|
||||
public double DrillCostHardConsumable { get; set; }
|
||||
|
||||
public double DrillPiercesPerHardConsumable { get; set; }
|
||||
|
||||
public double DrillTimeChangeHardConsumable { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(3)]
|
||||
public string ReportNestedDrawingsOnly { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(3)]
|
||||
public string DisplayTimingInfo { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(3)]
|
||||
public string OutputPostTechTable { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string WeightTypeForDisplay { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string WeightTypeForCosting { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Errors { get; set; }
|
||||
|
||||
public int DefToolLib { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string DefPlateSize { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string DefKerfDirection { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string InUse { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string ApplicationName { get; set; }
|
||||
|
||||
public DateTime? RequestedSchedDate { get; set; }
|
||||
|
||||
public double AutoGrainDim { get; set; }
|
||||
}
|
||||
}
|
||||
163
PepLib.Core/Data/PepDB.cs
Normal file
163
PepLib.Core/Data/PepDB.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace PepLib.Data;
|
||||
|
||||
public partial class PepDB : DbContext
|
||||
{
|
||||
public PepDB(DbContextOptions<PepDB> options)
|
||||
: base(options)
|
||||
{
|
||||
// Configure as read-only - no change tracking for better performance
|
||||
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||
ChangeTracker.AutoDetectChangesEnabled = false;
|
||||
}
|
||||
|
||||
public virtual DbSet<Drawing> Drawings { get; set; }
|
||||
public virtual DbSet<NestDetail> NestDetails { get; set; }
|
||||
public virtual DbSet<NestDrawing> NestDrawings { get; set; }
|
||||
public virtual DbSet<NestHeader> NestHeaders { get; set; }
|
||||
public virtual DbSet<PlateDetail> PlateDetails { get; set; }
|
||||
public virtual DbSet<PlateHeader> PlateHeaders { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Drawing>(entity =>
|
||||
{
|
||||
entity.Property(e => e.Name).IsUnicode(false);
|
||||
entity.Property(e => e.CustID).IsUnicode(false);
|
||||
entity.Property(e => e.Revision).IsUnicode(false);
|
||||
entity.Property(e => e.Path).IsUnicode(false);
|
||||
entity.Property(e => e.File).IsUnicode(false);
|
||||
entity.Property(e => e.InUseBy).IsUnicode(false);
|
||||
entity.Property(e => e.Status).IsUnicode(false);
|
||||
entity.Property(e => e.StatusModifiedBy).IsUnicode(false);
|
||||
entity.Property(e => e.Description).IsUnicode(false);
|
||||
entity.Property(e => e.Customer).IsUnicode(false);
|
||||
entity.Property(e => e.Comment).IsUnicode(false);
|
||||
entity.Property(e => e.Notes).IsUnicode(false);
|
||||
entity.Property(e => e.Material).IsUnicode(false);
|
||||
entity.Property(e => e.MatGrade).IsUnicode(false);
|
||||
entity.Property(e => e.Programmer).IsUnicode(false);
|
||||
entity.Property(e => e.CreatedBy).IsUnicode(false);
|
||||
entity.Property(e => e.Type).IsUnicode(false);
|
||||
entity.Property(e => e.Errors).IsUnicode(false);
|
||||
entity.Property(e => e.Hardness).IsUnicode(false);
|
||||
entity.Property(e => e.Specification).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined1).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined2).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined3).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined4).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined5).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined6).IsUnicode(false);
|
||||
entity.Property(e => e.Application).IsUnicode(false);
|
||||
entity.Property(e => e.SourceFile).IsUnicode(false);
|
||||
entity.Property(e => e.CadScaled).IsUnicode(false);
|
||||
entity.Property(e => e.ModifiedBy).IsUnicode(false);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<NestDetail>(entity =>
|
||||
{
|
||||
entity.Property(e => e.NestName).IsUnicode(false);
|
||||
entity.Property(e => e.Drawing).IsUnicode(false);
|
||||
entity.Property(e => e.CustID).IsUnicode(false);
|
||||
entity.Property(e => e.DwgRevision).IsUnicode(false);
|
||||
entity.Property(e => e.CustomerNo).IsUnicode(false);
|
||||
entity.Property(e => e.CustomerName).IsUnicode(false);
|
||||
entity.Property(e => e.ModifiedBy).IsUnicode(false);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<NestDrawing>(entity =>
|
||||
{
|
||||
entity.Property(e => e.NestName).IsUnicode(false);
|
||||
entity.Property(e => e.Drawing).IsUnicode(false);
|
||||
entity.Property(e => e.CustID).IsUnicode(false);
|
||||
entity.Property(e => e.DwgRevision).IsUnicode(false);
|
||||
entity.Property(e => e.DwgDesc).IsUnicode(false);
|
||||
entity.Property(e => e.ImageFile).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined1).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined2).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined3).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined4).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined5).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined6).IsUnicode(false);
|
||||
entity.Property(e => e.Description).IsUnicode(false);
|
||||
entity.Property(e => e.SizeX).HasPrecision(15, 4);
|
||||
entity.Property(e => e.SizeY).HasPrecision(15, 4);
|
||||
entity.Property(e => e.ModifiedBy).IsUnicode(false);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<NestHeader>(entity =>
|
||||
{
|
||||
entity.Property(e => e.NestName).IsUnicode(false);
|
||||
entity.Property(e => e.CustID).IsUnicode(false);
|
||||
entity.Property(e => e.CustomerName).IsUnicode(false);
|
||||
entity.Property(e => e.Material).IsUnicode(false);
|
||||
entity.Property(e => e.MatDescription).IsUnicode(false);
|
||||
entity.Property(e => e.MatGrade).IsUnicode(false);
|
||||
entity.Property(e => e.Programmer).IsUnicode(false);
|
||||
entity.Property(e => e.Post).IsUnicode(false);
|
||||
entity.Property(e => e.Comments).IsUnicode(false);
|
||||
entity.Property(e => e.Remarks).IsUnicode(false);
|
||||
entity.Property(e => e.TypeOfGas).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined1).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined2).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined3).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined4).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined5).IsUnicode(false);
|
||||
entity.Property(e => e.UserDefined6).IsUnicode(false);
|
||||
entity.Property(e => e.ModifiedBy).IsUnicode(false);
|
||||
entity.Property(e => e.Path).IsUnicode(false);
|
||||
entity.Property(e => e.NestGenMethod).IsUnicode(false);
|
||||
entity.Property(e => e.FeedRateScenarios).IsUnicode(false);
|
||||
entity.Property(e => e.OutputJobCosting).IsUnicode(false);
|
||||
entity.Property(e => e.ReportNestedDrawingsOnly).IsUnicode(false);
|
||||
entity.Property(e => e.DisplayTimingInfo).IsUnicode(false);
|
||||
entity.Property(e => e.OutputPostTechTable).IsUnicode(false);
|
||||
entity.Property(e => e.WeightTypeForDisplay).IsUnicode(false);
|
||||
entity.Property(e => e.WeightTypeForCosting).IsUnicode(false);
|
||||
entity.Property(e => e.Errors).IsUnicode(false);
|
||||
entity.Property(e => e.DefPlateSize).IsUnicode(false);
|
||||
entity.Property(e => e.DefKerfDirection).IsUnicode(false);
|
||||
entity.Property(e => e.InUse).IsUnicode(false);
|
||||
entity.Property(e => e.ApplicationName).IsUnicode(false);
|
||||
entity.Property(e => e.Application).IsUnicode(false);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<PlateDetail>(entity =>
|
||||
{
|
||||
entity.Property(e => e.NestName).IsUnicode(false);
|
||||
entity.Property(e => e.Drawing).IsUnicode(false);
|
||||
entity.Property(e => e.DwgRevision).IsUnicode(false);
|
||||
entity.Property(e => e.LoopList).IsUnicode(false);
|
||||
entity.Property(e => e.DwgDesc).IsUnicode(false);
|
||||
entity.Property(e => e.WorkOrder).IsUnicode(false);
|
||||
entity.Property(e => e.Note).IsUnicode(false);
|
||||
entity.Property(e => e.Sales).IsUnicode(false);
|
||||
entity.Property(e => e.Remarks).IsUnicode(false);
|
||||
entity.Property(e => e.RequiredGrade).IsUnicode(false);
|
||||
entity.Property(e => e.JobNo).IsUnicode(false);
|
||||
entity.Property(e => e.Sequence).IsUnicode(false);
|
||||
entity.Property(e => e.Marking).IsUnicode(false);
|
||||
entity.Property(e => e.ModifiedBy).IsUnicode(false);
|
||||
entity.Property(e => e.LifetimeList).IsUnicode(false);
|
||||
entity.Property(e => e.CustPO).IsUnicode(false);
|
||||
entity.Property(e => e.CustID).IsUnicode(false);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<PlateHeader>(entity =>
|
||||
{
|
||||
entity.Property(e => e.NestName).IsUnicode(false);
|
||||
entity.Property(e => e.InvPlateName).IsUnicode(false);
|
||||
entity.Property(e => e.RemnantSize).IsUnicode(false);
|
||||
entity.Property(e => e.PlateSize).IsUnicode(false);
|
||||
entity.Property(e => e.HeatLot).IsUnicode(false);
|
||||
entity.Property(e => e.UpdateStatus).IsUnicode(false);
|
||||
entity.Property(e => e.ImageFile).IsUnicode(false);
|
||||
entity.Property(e => e.Note).IsUnicode(false);
|
||||
entity.Property(e => e.ProgramName).IsUnicode(false);
|
||||
entity.Property(e => e.ModifiedBy).IsUnicode(false);
|
||||
entity.Property(e => e.Location).IsUnicode(false);
|
||||
entity.Property(e => e.NestedSize).IsUnicode(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
99
PepLib.Core/Data/PlateDetail.cs
Normal file
99
PepLib.Core/Data/PlateDetail.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
namespace PepLib.Data
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
|
||||
[Table("PlateDetail")]
|
||||
public partial class PlateDetail
|
||||
{
|
||||
[Key]
|
||||
public int AutoInc { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string NestName { get; set; }
|
||||
|
||||
public int CopyID { get; set; }
|
||||
|
||||
public int? PlateNumber { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string Drawing { get; set; }
|
||||
|
||||
[StringLength(32)]
|
||||
public string DwgRevision { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string LoopList { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string DwgDesc { get; set; }
|
||||
|
||||
public double? DwgMatUtil { get; set; }
|
||||
|
||||
public double? DwgPercentCutTime { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string WorkOrder { get; set; }
|
||||
|
||||
public DateTime? OrderRecvDate { get; set; }
|
||||
|
||||
public DateTime? OrderDueDate { get; set; }
|
||||
|
||||
public int? QtyReq { get; set; }
|
||||
|
||||
public int? QtyNstd { get; set; }
|
||||
|
||||
public int? QtyAccepted { get; set; }
|
||||
|
||||
public int? QtyCut { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string Note { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string Sales { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string Remarks { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string RequiredGrade { get; set; }
|
||||
|
||||
public double? RequiredThickness { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string JobNo { get; set; }
|
||||
|
||||
[Column(TypeName = "text")]
|
||||
[Required]
|
||||
public string Sequence { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string Marking { get; set; }
|
||||
|
||||
public DateTime? ModifiedDate { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string ModifiedBy { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string LifetimeList { get; set; }
|
||||
|
||||
public int LifetimeLargest { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(254)]
|
||||
public string CustPO { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(20)]
|
||||
public string CustID { get; set; }
|
||||
}
|
||||
}
|
||||
117
PepLib.Core/Data/PlateHeader.cs
Normal file
117
PepLib.Core/Data/PlateHeader.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
namespace PepLib.Data
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
|
||||
[Table("PlateHeader")]
|
||||
public partial class PlateHeader
|
||||
{
|
||||
[Key]
|
||||
public int AutoInc { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(40)]
|
||||
public string NestName { get; set; }
|
||||
|
||||
public int CopyID { get; set; }
|
||||
|
||||
public int? PlateNumber { get; set; }
|
||||
|
||||
public int? DupNo { get; set; }
|
||||
|
||||
[StringLength(128)]
|
||||
public string InvPlateName { get; set; }
|
||||
|
||||
public double InvCostPerWeight { get; set; }
|
||||
|
||||
public double? RapidDist { get; set; }
|
||||
|
||||
public double? CutDist { get; set; }
|
||||
|
||||
public int? CutTime { get; set; }
|
||||
|
||||
public double? PlateWeight { get; set; }
|
||||
|
||||
public double? PlateCost { get; set; }
|
||||
|
||||
[StringLength(20)]
|
||||
public string RemnantSize { get; set; }
|
||||
|
||||
public double? RemnantArea { get; set; }
|
||||
|
||||
public double? RemnantCost { get; set; }
|
||||
|
||||
public double? RemnantWeight { get; set; }
|
||||
|
||||
[StringLength(20)]
|
||||
public string PlateSize { get; set; }
|
||||
|
||||
public int? PlateDuplicates { get; set; }
|
||||
|
||||
public double? PlateUtilization { get; set; }
|
||||
|
||||
public double? PlateMaterialUtil { get; set; }
|
||||
|
||||
public double? TotalArea1 { get; set; }
|
||||
|
||||
public double? TotalArea2 { get; set; }
|
||||
|
||||
public int? Status { get; set; }
|
||||
|
||||
public DateTime? Statusdate { get; set; }
|
||||
|
||||
public int? rStatus { get; set; }
|
||||
|
||||
public DateTime? rDateStamp { get; set; }
|
||||
|
||||
[StringLength(40)]
|
||||
public string HeatLot { get; set; }
|
||||
|
||||
[StringLength(20)]
|
||||
public string UpdateStatus { get; set; }
|
||||
|
||||
public double? ActualCutTime { get; set; }
|
||||
|
||||
public double? ActualStartTime { get; set; }
|
||||
|
||||
public double? ActualEndTime { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string ImageFile { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string Note { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string ProgramName { get; set; }
|
||||
|
||||
public DateTime? ModifiedDate { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string ModifiedBy { get; set; }
|
||||
|
||||
[StringLength(254)]
|
||||
public string Location { get; set; }
|
||||
|
||||
public DateTime? DateCut { get; set; }
|
||||
|
||||
public short InvImpAllocated { get; set; }
|
||||
|
||||
public double CombSavingDist { get; set; }
|
||||
|
||||
public int HeadRaises { get; set; }
|
||||
|
||||
public int RapidCount { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(25)]
|
||||
public string NestedSize { get; set; }
|
||||
|
||||
public double NestedLength { get; set; }
|
||||
|
||||
public double NestedWidth { get; set; }
|
||||
}
|
||||
}
|
||||
282
PepLib.Core/Drawing.cs
Normal file
282
PepLib.Core/Drawing.cs
Normal file
@@ -0,0 +1,282 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using PepLib.Codes;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Drawing
|
||||
{
|
||||
public DrawingInfo Info { get; set; }
|
||||
|
||||
public List<Loop> Loops { get; set; }
|
||||
|
||||
public Drawing()
|
||||
{
|
||||
Loops = new List<Loop>();
|
||||
}
|
||||
|
||||
public static Drawing Load(string nestfile)
|
||||
{
|
||||
var reader = new DrawingReader();
|
||||
reader.Read(nestfile);
|
||||
return reader.Drawing;
|
||||
}
|
||||
|
||||
public static Drawing Load(Stream stream)
|
||||
{
|
||||
var reader = new DrawingReader();
|
||||
reader.Read(stream);
|
||||
return reader.Drawing;
|
||||
}
|
||||
|
||||
public void ResolveLoops()
|
||||
{
|
||||
for (int i = 0; i < Loops.Count; ++i)
|
||||
{
|
||||
var loop = Loops[i];
|
||||
ResolveLoops(loop);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResolveLoops(Program pgm)
|
||||
{
|
||||
for (int i = 0; i < pgm.Count; ++i)
|
||||
{
|
||||
var code = pgm[i];
|
||||
|
||||
if (code.CodeType() != CodeType.SubProgramCall)
|
||||
continue;
|
||||
|
||||
var subpgmcall = (SubProgramCall)code;
|
||||
|
||||
var loop = GetLoop(subpgmcall.LoopId);
|
||||
|
||||
if (loop == null)
|
||||
throw new Exception("Loop not found");
|
||||
|
||||
subpgmcall.Loop = loop;
|
||||
}
|
||||
}
|
||||
|
||||
public Loop GetLoop(int id)
|
||||
{
|
||||
string name = GetLoopName(id);
|
||||
return GetLoop(name);
|
||||
}
|
||||
|
||||
|
||||
private Loop GetLoop(string name)
|
||||
{
|
||||
for (int i = 0; i < Loops.Count; ++i)
|
||||
{
|
||||
if (Loops[i].Name == name)
|
||||
return Loops[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetLoopName(int loopId)
|
||||
{
|
||||
return string.Format("{0}.loop-{1}", Info.Name, loopId.ToString().PadLeft(3, '0'));
|
||||
}
|
||||
|
||||
public static bool TryLoad(string nestfile, out Drawing drawing)
|
||||
{
|
||||
try
|
||||
{
|
||||
drawing = Load(nestfile);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
drawing = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryLoad(Stream stream, out Drawing drawing)
|
||||
{
|
||||
try
|
||||
{
|
||||
drawing = Load(stream);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
drawing = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region DrawingInfo wrapper properties
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return Info.Name; }
|
||||
set { Info.Name = value; }
|
||||
}
|
||||
|
||||
public string Revision
|
||||
{
|
||||
get { return Info.Revision; }
|
||||
set { Info.Revision = value; }
|
||||
}
|
||||
|
||||
public string Customer
|
||||
{
|
||||
get { return Info.Customer; }
|
||||
set { Info.Customer = value; }
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
get { return Info.Description; }
|
||||
set { Info.Description = value; }
|
||||
}
|
||||
|
||||
public string Comment
|
||||
{
|
||||
get { return Info.Comment; }
|
||||
set { Info.Comment = value; }
|
||||
}
|
||||
|
||||
public string Notes
|
||||
{
|
||||
get { return Info.Notes; }
|
||||
set { Info.Notes = value; }
|
||||
}
|
||||
|
||||
public string Source
|
||||
{
|
||||
get { return Info.Source; }
|
||||
set { Info.Source = value; }
|
||||
}
|
||||
|
||||
public DateTime CreationDate
|
||||
{
|
||||
get { return Info.CreationDate; }
|
||||
set { Info.CreationDate = value; }
|
||||
}
|
||||
|
||||
public DateTime LastModifiedDate
|
||||
{
|
||||
get { return Info.LastModifiedDate; }
|
||||
set { Info.LastModifiedDate = value; }
|
||||
}
|
||||
|
||||
public DateTime LastReferenceDate
|
||||
{
|
||||
get { return Info.LastReferenceDate; }
|
||||
set { Info.LastReferenceDate = value; }
|
||||
}
|
||||
|
||||
public int MachineNumber
|
||||
{
|
||||
get { return Info.MachineNumber; }
|
||||
set { Info.MachineNumber = value; }
|
||||
}
|
||||
|
||||
public ApplicationType Application
|
||||
{
|
||||
get { return Info.Application; }
|
||||
set { Info.Application = value; }
|
||||
}
|
||||
|
||||
public int MaterialNumber
|
||||
{
|
||||
get { return Info.MaterialNumber; }
|
||||
set { Info.MaterialNumber = value; }
|
||||
}
|
||||
|
||||
public string MaterialGrade
|
||||
{
|
||||
get { return Info.MaterialGrade; }
|
||||
set { Info.MaterialGrade = value; }
|
||||
}
|
||||
|
||||
public string Specification
|
||||
{
|
||||
get { return Info.Specification; }
|
||||
set { Info.Specification = value; }
|
||||
}
|
||||
|
||||
public string Hardness
|
||||
{
|
||||
get { return Info.Hardness; }
|
||||
set { Info.Hardness = value; }
|
||||
}
|
||||
|
||||
public GrainType Grain
|
||||
{
|
||||
get { return Info.Grain; }
|
||||
set { Info.Grain = value; }
|
||||
}
|
||||
|
||||
public string ProgrammedBy
|
||||
{
|
||||
get { return Info.ProgrammedBy; }
|
||||
set { Info.ProgrammedBy = value; }
|
||||
}
|
||||
|
||||
public string CreatedBy
|
||||
{
|
||||
get { return Info.CreatedBy; }
|
||||
set { Info.CreatedBy = value; }
|
||||
}
|
||||
|
||||
public string Errors
|
||||
{
|
||||
get { return Info.Errors; }
|
||||
set { Info.Errors = value; }
|
||||
}
|
||||
|
||||
public DrawingType Type
|
||||
{
|
||||
get { return Info.Type; }
|
||||
set { Info.Type = value; }
|
||||
}
|
||||
|
||||
public string UserDefined1
|
||||
{
|
||||
get { return Info.UserDefined1; }
|
||||
set { Info.UserDefined1 = value; }
|
||||
}
|
||||
|
||||
public string UserDefined2
|
||||
{
|
||||
get { return Info.UserDefined2; }
|
||||
set { Info.UserDefined2 = value; }
|
||||
}
|
||||
|
||||
public string UserDefined3
|
||||
{
|
||||
get { return Info.UserDefined3; }
|
||||
set { Info.UserDefined3 = value; }
|
||||
}
|
||||
|
||||
public string UserDefined4
|
||||
{
|
||||
get { return Info.UserDefined4; }
|
||||
set { Info.UserDefined4 = value; }
|
||||
}
|
||||
|
||||
public string UserDefined5
|
||||
{
|
||||
get { return Info.UserDefined5; }
|
||||
set { Info.UserDefined5 = value; }
|
||||
}
|
||||
|
||||
public string UserDefined6
|
||||
{
|
||||
get { return Info.UserDefined6; }
|
||||
set { Info.UserDefined6 = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
109
PepLib.Core/DrawingInfo.cs
Normal file
109
PepLib.Core/DrawingInfo.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class DrawingInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Revision { get; set; }
|
||||
|
||||
public string Customer { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public string Comment { get; set; }
|
||||
|
||||
public string Notes { get; set; }
|
||||
|
||||
public string Source { get; set; }
|
||||
|
||||
public DateTime CreationDate { get; set; }
|
||||
|
||||
public DateTime LastModifiedDate { get; set; }
|
||||
|
||||
public DateTime LastReferenceDate { get; set; }
|
||||
|
||||
public int MachineNumber { get; set; }
|
||||
|
||||
public ApplicationType Application { get; set; }
|
||||
|
||||
public int MaterialNumber { get; set; }
|
||||
|
||||
public string MaterialGrade { get; set; }
|
||||
|
||||
public string Specification { get; set; }
|
||||
|
||||
public string Hardness { get; set; }
|
||||
|
||||
public GrainType Grain { get; set; }
|
||||
|
||||
public string ProgrammedBy { get; set; }
|
||||
|
||||
public string CreatedBy { get; set; }
|
||||
|
||||
public string Errors { get; set; }
|
||||
|
||||
public DrawingType Type { get; set; }
|
||||
|
||||
public string UserDefined1 { get; set; }
|
||||
|
||||
public string UserDefined2 { get; set; }
|
||||
|
||||
public string UserDefined3 { get; set; }
|
||||
|
||||
public string UserDefined4 { get; set; }
|
||||
|
||||
public string UserDefined5 { get; set; }
|
||||
|
||||
public string UserDefined6 { get; set; }
|
||||
|
||||
public static DrawingInfo Load(string nestFile)
|
||||
{
|
||||
var reader = new DrawingInfoReader();
|
||||
reader.Read(nestFile);
|
||||
return reader.Info;
|
||||
}
|
||||
|
||||
public static DrawingInfo Load(Stream stream)
|
||||
{
|
||||
var reader = new DrawingInfoReader();
|
||||
reader.Read(stream);
|
||||
return reader.Info;
|
||||
}
|
||||
|
||||
public static bool TryLoad(string nestfile, out DrawingInfo drawingInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
drawingInfo = Load(nestfile);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
drawingInfo = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryLoad(Stream stream, out DrawingInfo drawingInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
drawingInfo = Load(stream);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
drawingInfo = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
12
PepLib.Core/DrawingType.cs
Normal file
12
PepLib.Core/DrawingType.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public enum DrawingType
|
||||
{
|
||||
None = 0x20,
|
||||
Drawing = 0x44,
|
||||
Product = 0x50,
|
||||
Rotary = 0x52,
|
||||
Tool = 0x54
|
||||
}
|
||||
}
|
||||
17
PepLib.Core/Generic.cs
Normal file
17
PepLib.Core/Generic.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public static class Generic
|
||||
{
|
||||
public static void Swap<T>(ref T a, ref T b)
|
||||
{
|
||||
T c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
PepLib.Core/GrainType.cs
Normal file
11
PepLib.Core/GrainType.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public enum GrainType
|
||||
{
|
||||
No = 0x0,
|
||||
Yes = 0x1,
|
||||
Soft = 0x2,
|
||||
Hard = 0x3
|
||||
}
|
||||
}
|
||||
10
PepLib.Core/IMovable.cs
Normal file
10
PepLib.Core/IMovable.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace PepLib
|
||||
{
|
||||
public interface IMovable
|
||||
{
|
||||
void Rotate(double angle);
|
||||
void Rotate(double angle, Vector origin);
|
||||
void Offset(double x, double y);
|
||||
void Offset(Vector voffset);
|
||||
}
|
||||
}
|
||||
100
PepLib.Core/IO/DrawingInfoReader.cs
Normal file
100
PepLib.Core/IO/DrawingInfoReader.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
public sealed class DrawingInfoReader
|
||||
{
|
||||
public DrawingInfo Info { get; private set; }
|
||||
|
||||
public DrawingInfoReader()
|
||||
{
|
||||
Info = new DrawingInfo();
|
||||
}
|
||||
|
||||
public DrawingInfoReader(DrawingInfo info)
|
||||
{
|
||||
Info = info;
|
||||
}
|
||||
|
||||
public void Read(Stream stream)
|
||||
{
|
||||
Info.Name = ReadString(0xC8, ref stream);
|
||||
Info.Revision = ReadString(0x20, ref stream);
|
||||
Info.CreationDate = DateTime.Parse(ReadString(0xA, ref stream));
|
||||
Info.LastModifiedDate = DateTime.Parse(ReadString(0xA, ref stream));
|
||||
Info.LastReferenceDate = DateTime.Parse(ReadString(0xA, ref stream));
|
||||
Info.Description = ReadString(0xC8, ref stream);
|
||||
Info.Customer = ReadString(0x40, ref stream);
|
||||
Info.Comment = ReadString(0x40, ref stream);
|
||||
Info.Notes = ReadString(0x400, ref stream);
|
||||
Info.Grain = (GrainType)ReadByte(ref stream);
|
||||
|
||||
stream.Seek(0x9, SeekOrigin.Current);
|
||||
|
||||
Info.MaterialNumber = int.Parse(ReadString(0x40, ref stream));
|
||||
Info.MaterialGrade = ReadString(0x10, ref stream);
|
||||
Info.ProgrammedBy = ReadString(0x40, ref stream);
|
||||
Info.CreatedBy = ReadString(0x40, ref stream);
|
||||
Info.Type = (DrawingType)ReadByte(ref stream);
|
||||
|
||||
stream.Seek(0x4, SeekOrigin.Current);
|
||||
|
||||
Info.Errors = ReadString(0x64, ref stream);
|
||||
Info.Hardness = ReadString(0x20, ref stream);
|
||||
Info.Specification = ReadString(0x40, ref stream);
|
||||
|
||||
stream.Seek(0x2, SeekOrigin.Current);
|
||||
|
||||
Info.UserDefined1 = ReadString(0x20, ref stream);
|
||||
Info.UserDefined2 = ReadString(0x20, ref stream);
|
||||
Info.UserDefined3 = ReadString(0x20, ref stream);
|
||||
Info.UserDefined4 = ReadString(0x40, ref stream);
|
||||
Info.UserDefined5 = ReadString(0x40, ref stream);
|
||||
Info.UserDefined6 = ReadString(0x40, ref stream);
|
||||
Info.MachineNumber = ReadByte(ref stream);
|
||||
|
||||
stream.Seek(0x1, SeekOrigin.Current);
|
||||
|
||||
Info.Application = (ApplicationType)ReadByte(ref stream);
|
||||
}
|
||||
|
||||
public void Read(string nestFile)
|
||||
{
|
||||
if (!File.Exists(nestFile))
|
||||
{
|
||||
var msg = string.Format("File Not Found: {0}", nestFile);
|
||||
throw new FileNotFoundException(msg);
|
||||
}
|
||||
|
||||
Stream stream = null;
|
||||
string name;
|
||||
|
||||
try
|
||||
{
|
||||
ZipHelper.ExtractByExtension(nestFile, ".dir", out name, out stream);
|
||||
Read(stream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadString(int length, ref Stream stream)
|
||||
{
|
||||
var buffer = new byte[length];
|
||||
stream.Read(buffer, 0, length);
|
||||
return Encoding.Default.GetString(buffer).Trim();
|
||||
}
|
||||
|
||||
private static byte ReadByte(ref Stream stream)
|
||||
{
|
||||
var buffer = new byte[0x1];
|
||||
stream.Read(buffer, 0, 1);
|
||||
return buffer[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
113
PepLib.Core/IO/DrawingReader.cs
Normal file
113
PepLib.Core/IO/DrawingReader.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using Ionic.Zip;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
public sealed class DrawingReader
|
||||
{
|
||||
public Drawing Drawing { get; private set; }
|
||||
|
||||
public DrawingReader()
|
||||
{
|
||||
Drawing = new Drawing();
|
||||
}
|
||||
|
||||
public DrawingReader(Drawing drawing)
|
||||
{
|
||||
Drawing = drawing;
|
||||
}
|
||||
|
||||
public void Read(Stream stream)
|
||||
{
|
||||
var zipStream = new ZipInputStream(stream);
|
||||
|
||||
ZipEntry theEntry;
|
||||
|
||||
while ((theEntry = zipStream.GetNextEntry()) != null)
|
||||
{
|
||||
var size = 2048;
|
||||
var data = new byte[size];
|
||||
var memstream = new MemoryStream();
|
||||
|
||||
while (true)
|
||||
{
|
||||
size = zipStream.Read(data, 0, data.Length);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
memstream.Write(data, 0, size);
|
||||
memstream.Flush();
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
memstream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var extension = Path.GetExtension(theEntry.FileName);
|
||||
|
||||
switch (extension)
|
||||
{
|
||||
case ".dir":
|
||||
LoadInfo(memstream);
|
||||
memstream.Close();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Regex.IsMatch(extension, "loop-\\d\\d\\d"))
|
||||
Drawing.Loops.Add(ReadLoop(theEntry.FileName, memstream));
|
||||
|
||||
memstream.Close();
|
||||
}
|
||||
|
||||
zipStream.Close();
|
||||
|
||||
Drawing.ResolveLoops();
|
||||
}
|
||||
|
||||
public void Read(string nestFile)
|
||||
{
|
||||
if (!File.Exists(nestFile))
|
||||
{
|
||||
var msg = string.Format("File Not Found: {0}", nestFile);
|
||||
throw new FileNotFoundException(msg);
|
||||
}
|
||||
|
||||
Stream stream = null;
|
||||
|
||||
try
|
||||
{
|
||||
stream = new FileStream(nestFile, FileMode.Open);
|
||||
Read(stream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadInfo(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
Drawing.Info = DrawingInfo.Load(stream);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.WriteLine(exception.Message);
|
||||
Debug.WriteLine(exception.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
private Loop ReadLoop(string name, Stream stream)
|
||||
{
|
||||
var reader = new LoopReader();
|
||||
reader.Read(name, stream);
|
||||
|
||||
return reader.Loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
PepLib.Core/IO/LoopReader.cs
Normal file
134
PepLib.Core/IO/LoopReader.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using PepLib.Codes;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
internal sealed class LoopReader
|
||||
{
|
||||
public Loop Loop { get; private set; }
|
||||
|
||||
public LoopReader()
|
||||
{
|
||||
Loop = new Loop();
|
||||
}
|
||||
|
||||
public LoopReader(Loop loop)
|
||||
{
|
||||
Loop = loop;
|
||||
}
|
||||
|
||||
public void Read(string name, Stream stream)
|
||||
{
|
||||
var pgm = Program.Load(stream);
|
||||
|
||||
Loop.Name = name;
|
||||
Loop.AddRange(pgm);
|
||||
LoadInfo();
|
||||
}
|
||||
|
||||
private void LoadInfo()
|
||||
{
|
||||
for (int i = Loop.Count - 1; i >= 0; --i)
|
||||
{
|
||||
var code = Loop[i];
|
||||
|
||||
if (code.CodeType() != CodeType.Comment)
|
||||
continue;
|
||||
|
||||
var comment = (Comment)code;
|
||||
|
||||
if (LoadInfo(comment.Value))
|
||||
Loop.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private bool LoadInfo(string value)
|
||||
{
|
||||
if (value.StartsWith("REF"))
|
||||
{
|
||||
ParseReferenceData(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value.StartsWith("DRAWING"))
|
||||
{
|
||||
ParseDrawingData(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value.StartsWith("DXF"))
|
||||
{
|
||||
ParseDxfData(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ParseReferenceData(string data)
|
||||
{
|
||||
var parts = data.Split(',');
|
||||
|
||||
if (parts.Length != 3)
|
||||
return;
|
||||
|
||||
int xindex = parts[0].IndexOf('X');
|
||||
parts[0] = parts[0].Remove(0, xindex);
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
|
||||
var xsplit = parts[0].Split('=');
|
||||
|
||||
if (xsplit.Length == 2)
|
||||
x = ReadDouble(xsplit[1]);
|
||||
|
||||
var ysplit = parts[1].Split('=');
|
||||
|
||||
if (ysplit.Length == 2)
|
||||
y = ReadDouble(ysplit[1]);
|
||||
|
||||
var datesplit = parts[2].Split('=');
|
||||
|
||||
if (datesplit.Length == 2)
|
||||
{
|
||||
DateTime date;
|
||||
DateTime.TryParse(datesplit[1], out date);
|
||||
Loop.LastReferenceDate = date;
|
||||
}
|
||||
|
||||
Loop.ReferencePoint = new Vector(x, y);
|
||||
}
|
||||
|
||||
private void ParseDrawingData(string data)
|
||||
{
|
||||
var index = data.IndexOf('=');
|
||||
|
||||
if (index == -1)
|
||||
Loop.DrawingName = string.Empty;
|
||||
|
||||
Loop.DrawingName = data.Remove(0, index + 1).Trim();
|
||||
}
|
||||
|
||||
private void ParseDxfData(string data)
|
||||
{
|
||||
var index = data.IndexOf('=');
|
||||
|
||||
if (index == -1)
|
||||
Loop.DxfPath = string.Empty;
|
||||
|
||||
Loop.DxfPath = data.Remove(0, index + 1).Trim();
|
||||
}
|
||||
|
||||
private static double ReadDouble(string s, double defaultValue = 0.0)
|
||||
{
|
||||
double f;
|
||||
|
||||
if (!double.TryParse(s, out f))
|
||||
return defaultValue;
|
||||
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
PepLib.Core/IO/MaterialDataReader.cs
Normal file
90
PepLib.Core/IO/MaterialDataReader.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
public class MaterialDataReader
|
||||
{
|
||||
public List<MaterialData> Materials { get; set; }
|
||||
|
||||
public MaterialDataReader()
|
||||
{
|
||||
Materials = new List<MaterialData>();
|
||||
}
|
||||
|
||||
public void Read(Stream stream)
|
||||
{
|
||||
const int dataLength = 2000;
|
||||
var count = stream.Length / dataLength;
|
||||
var binreader = new BinaryReader(stream);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var data = new MaterialData();
|
||||
|
||||
int id;
|
||||
int.TryParse(ReadString(64, ref stream), out id);
|
||||
data.Number = id;
|
||||
data.Grade = ReadString(16, ref stream);
|
||||
data.Name = ReadString(200, ref stream);
|
||||
data.Density = binreader.ReadDouble();
|
||||
stream.Seek(8, SeekOrigin.Current);
|
||||
data.Thickness = binreader.ReadDouble();
|
||||
|
||||
Materials.Add(data);
|
||||
|
||||
stream.Position = i * dataLength;
|
||||
}
|
||||
}
|
||||
|
||||
public void Read(string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
{
|
||||
var msg = string.Format("File Not Found: {0}", file);
|
||||
throw new FileNotFoundException(msg);
|
||||
}
|
||||
|
||||
Stream stream = null;
|
||||
|
||||
try
|
||||
{
|
||||
stream = File.OpenRead(file);
|
||||
Read(stream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadString(int length, ref Stream stream)
|
||||
{
|
||||
var buffer = new byte[length];
|
||||
stream.Read(buffer, 0, length);
|
||||
return Encoding.Default.GetString(buffer).Trim();
|
||||
}
|
||||
|
||||
private static byte ReadByte(ref Stream stream)
|
||||
{
|
||||
var buffer = new byte[0x1];
|
||||
stream.Read(buffer, 0, 1);
|
||||
return buffer[0];
|
||||
}
|
||||
}
|
||||
|
||||
public class MaterialData
|
||||
{
|
||||
public int Number { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Grade { get; set; }
|
||||
|
||||
public double Density { get; set; }
|
||||
|
||||
public double Thickness { get; set; }
|
||||
}
|
||||
}
|
||||
124
PepLib.Core/IO/NestInfoReader.cs
Normal file
124
PepLib.Core/IO/NestInfoReader.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
internal sealed class NestInfoReader
|
||||
{
|
||||
public NestInfo Info { get; private set; }
|
||||
|
||||
public NestInfoReader()
|
||||
{
|
||||
Info = new NestInfo();
|
||||
}
|
||||
|
||||
public NestInfoReader(NestInfo info)
|
||||
{
|
||||
Info = info;
|
||||
}
|
||||
|
||||
public void Read(Stream stream)
|
||||
{
|
||||
var binReader = new BinaryReader(stream);
|
||||
|
||||
Info.Name = ReadString(0xC8, ref stream);
|
||||
Info.DateCreated = DateTime.Parse(ReadString(0xA, ref stream));
|
||||
Info.DateLastModified = DateTime.Parse(ReadString(0xA, ref stream));
|
||||
Info.LoopCount = binReader.ReadInt16();
|
||||
Info.ProgramCount = binReader.ReadInt16();
|
||||
Info.Customer = ReadString(0x40, ref stream);
|
||||
Info.ProgrammedBy = ReadString(0x40, ref stream);
|
||||
Info.Comments = ReadString(0x40, ref stream);
|
||||
|
||||
// skip 2 bytes
|
||||
stream.Seek(0x2, SeekOrigin.Current);
|
||||
|
||||
Info.MaterialNumber = int.Parse(ReadString(0x40, ref stream));
|
||||
Info.MaterialGrade = ReadString(0x10, ref stream);
|
||||
|
||||
// skip 2 bytes
|
||||
stream.Seek(0x2, SeekOrigin.Current);
|
||||
|
||||
Info.Notes = ReadString(0x400, ref stream);
|
||||
Info.PostedAs = ReadString(0x64, ref stream);
|
||||
Info.Errors = ReadString(0x64, ref stream);
|
||||
Info.UserDefined1 = ReadString(0x20, ref stream);
|
||||
Info.UserDefined2 = ReadString(0x20, ref stream);
|
||||
Info.UserDefined3 = ReadString(0x20, ref stream);
|
||||
Info.UserDefined4 = ReadString(0x40, ref stream);
|
||||
Info.UserDefined5 = ReadString(0x40, ref stream);
|
||||
Info.UserDefined6 = ReadString(0x40, ref stream);
|
||||
Info.DefaultPlateSize = ReadString(0x1E, ref stream);
|
||||
Info.Kerf = ReadString(0x3, ref stream);
|
||||
|
||||
// skip 4 bytes
|
||||
stream.Seek(0x4, SeekOrigin.Current);
|
||||
|
||||
switch (ReadByte(ref stream))
|
||||
{
|
||||
case 0:
|
||||
Info.Status = StatusType.ToBeCut;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Info.Status = StatusType.Quote;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Info.Status = StatusType.HasBeenCut;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Info.Status = StatusType.Temp;
|
||||
break;
|
||||
|
||||
default:
|
||||
Info.Status = StatusType.ToBeCut;
|
||||
break;
|
||||
}
|
||||
|
||||
// skip 16 bytes
|
||||
stream.Seek(16, SeekOrigin.Current);
|
||||
|
||||
Info.PlateCount = binReader.ReadInt16();
|
||||
}
|
||||
|
||||
public void Read(string nestFile)
|
||||
{
|
||||
if (!File.Exists(nestFile))
|
||||
{
|
||||
var msg = string.Format("File Not Found: {0}", nestFile);
|
||||
throw new FileNotFoundException(msg);
|
||||
}
|
||||
|
||||
Stream stream = null;
|
||||
string name;
|
||||
|
||||
try
|
||||
{
|
||||
ZipHelper.ExtractByExtension(nestFile, ".dir", out name, out stream);
|
||||
Read(stream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadString(int length, ref Stream stream)
|
||||
{
|
||||
var buffer = new byte[length];
|
||||
stream.Read(buffer, 0, length);
|
||||
return Encoding.Default.GetString(buffer).Trim();
|
||||
}
|
||||
|
||||
private static byte ReadByte(ref Stream stream)
|
||||
{
|
||||
var buffer = new byte[0x1];
|
||||
stream.Read(buffer, 0, 1);
|
||||
return buffer[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
165
PepLib.Core/IO/NestReader.cs
Normal file
165
PepLib.Core/IO/NestReader.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using Ionic.Zip;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
public sealed class NestReader
|
||||
{
|
||||
public Nest Nest { get; private set; }
|
||||
|
||||
private readonly Dictionary<string, Stream> plates;
|
||||
private readonly Dictionary<string, Stream> loops;
|
||||
|
||||
public NestReader()
|
||||
: this(new Nest())
|
||||
{
|
||||
}
|
||||
|
||||
public NestReader(Nest nest)
|
||||
{
|
||||
Nest = nest;
|
||||
plates = new Dictionary<string, Stream>();
|
||||
loops = new Dictionary<string, Stream>();
|
||||
}
|
||||
|
||||
public void Read(Stream stream)
|
||||
{
|
||||
const string plateExtensionPattern = "plate-\\d\\d\\d";
|
||||
const string loopExtensionPattern = "loop-\\d\\d\\d";
|
||||
|
||||
var zipStream = new ZipInputStream(stream);
|
||||
|
||||
ZipEntry theEntry;
|
||||
|
||||
while ((theEntry = zipStream.GetNextEntry()) != null)
|
||||
{
|
||||
var size = 2048;
|
||||
var data = new byte[size];
|
||||
var memstream = new MemoryStream();
|
||||
|
||||
while (true)
|
||||
{
|
||||
size = zipStream.Read(data, 0, data.Length);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
memstream.Write(data, 0, size);
|
||||
memstream.Flush();
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
memstream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
var extension = Path.GetExtension(theEntry.FileName);
|
||||
|
||||
switch (extension)
|
||||
{
|
||||
case ".report":
|
||||
LoadReport(memstream);
|
||||
memstream.Close();
|
||||
continue;
|
||||
|
||||
case ".dwg-info":
|
||||
LoadDrawingInfo(memstream);
|
||||
memstream.Close();
|
||||
continue;
|
||||
|
||||
default:
|
||||
Debug.WriteLine("Unknown file: " + theEntry.FileName);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Regex.IsMatch(extension, loopExtensionPattern))
|
||||
loops.Add(theEntry.FileName, memstream);
|
||||
else if (Regex.IsMatch(extension, plateExtensionPattern))
|
||||
plates.Add(theEntry.FileName, memstream);
|
||||
}
|
||||
|
||||
zipStream.Close();
|
||||
|
||||
foreach (var loop in loops)
|
||||
Nest.Loops.Add(ReadLoop(loop.Key, loop.Value));
|
||||
|
||||
Nest.ResolveLoops();
|
||||
|
||||
foreach (var plate in plates)
|
||||
Nest.Plates.Add(ReadPlate(plate.Key, plate.Value));
|
||||
}
|
||||
|
||||
public void Read(string nestFile)
|
||||
{
|
||||
if (!File.Exists(nestFile))
|
||||
{
|
||||
var msg = string.Format("File Not Found: {0}", nestFile);
|
||||
throw new FileNotFoundException(msg);
|
||||
}
|
||||
|
||||
Stream stream = null;
|
||||
|
||||
try
|
||||
{
|
||||
stream = new FileStream(nestFile, FileMode.Open);
|
||||
Read(stream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadReport(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
Nest.Report = Report.Load(stream);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.WriteLine(exception.Message);
|
||||
Debug.WriteLine(exception.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadDrawingInfo(Stream stream)
|
||||
{
|
||||
var buffer = new byte[2000];
|
||||
|
||||
while (stream.Read(buffer, 0, buffer.Length) > 0)
|
||||
{
|
||||
var name = Encoding.Default.GetString(buffer, 200, 200).Trim();
|
||||
var qty = BitConverter.ToInt32(buffer, 432);
|
||||
|
||||
var drawing = new NestDrawing
|
||||
{
|
||||
Name = name,
|
||||
QtyRequired = qty
|
||||
};
|
||||
|
||||
Nest.Drawings.Add(drawing);
|
||||
}
|
||||
}
|
||||
|
||||
private Loop ReadLoop(string name, Stream stream)
|
||||
{
|
||||
var reader = new LoopReader();
|
||||
reader.Read(name, stream);
|
||||
|
||||
return reader.Loop;
|
||||
}
|
||||
|
||||
private Plate ReadPlate(string name, Stream stream)
|
||||
{
|
||||
var reader = new PlateReader();
|
||||
reader.Read(name, stream, Nest);
|
||||
|
||||
return reader.Plate;
|
||||
}
|
||||
}
|
||||
}
|
||||
338
PepLib.Core/IO/PlateReader.cs
Normal file
338
PepLib.Core/IO/PlateReader.cs
Normal file
@@ -0,0 +1,338 @@
|
||||
using System.IO;
|
||||
using PepLib.Codes;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
internal sealed class PlateReader
|
||||
{
|
||||
public Plate Plate { get; private set; }
|
||||
|
||||
public PlateReader()
|
||||
{
|
||||
Plate = new Plate();
|
||||
Plate.Duplicates = 1;
|
||||
}
|
||||
|
||||
public PlateReader(Plate plate)
|
||||
{
|
||||
Plate = plate;
|
||||
}
|
||||
|
||||
public void Read(string name, Stream stream, Nest nest)
|
||||
{
|
||||
var pos = new Vector(0, 0);
|
||||
var pgm = Program.Load(stream);
|
||||
|
||||
Plate.Name = name;
|
||||
|
||||
for (int i = 0; i < pgm.Count; i++)
|
||||
{
|
||||
var block = pgm[i];
|
||||
|
||||
switch (block.CodeType())
|
||||
{
|
||||
case CodeType.CircularMove:
|
||||
{
|
||||
var arc = (CircularMove)block;
|
||||
pos = arc.EndPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.LinearMove:
|
||||
{
|
||||
var line = (LinearMove)block;
|
||||
pos = line.EndPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.RapidMove:
|
||||
{
|
||||
var rapid = (RapidMove)block;
|
||||
pos = rapid.EndPoint;
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.Comment:
|
||||
{
|
||||
var comment = (Comment)block;
|
||||
LoadInfo(comment.Value);
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.SubProgramCall:
|
||||
{
|
||||
var subpgm = (SubProgramCall)block;
|
||||
var loop = nest.GetLoop(subpgm.LoopId);
|
||||
var part = Part.Create(loop, pos, AngleConverter.ToRadians(subpgm.Rotation));
|
||||
|
||||
var nextBlock = pgm[i + 1];
|
||||
|
||||
if (nextBlock.CodeType() == CodeType.Comment)
|
||||
{
|
||||
var comment = nextBlock as Comment;
|
||||
|
||||
if (comment.Value == "DISPLAY ONLY")
|
||||
{
|
||||
part.IsDisplayOnly = true;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
Plate.Parts.Add(part);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadInfo(string value)
|
||||
{
|
||||
if (value.StartsWith("POSTED FILES"))
|
||||
ParsePostedFiles(value);
|
||||
|
||||
else if (value.StartsWith("HEAT LOT"))
|
||||
ParseHeatLot(value);
|
||||
|
||||
else if (value.StartsWith("SPACING"))
|
||||
ParseSpacing(value);
|
||||
|
||||
else if (value.StartsWith("CUT A TOTAL OF "))
|
||||
ParseNumberOfDuplicates(value);
|
||||
|
||||
else if (value.StartsWith("EDGES,"))
|
||||
ParseEdgeSpacing(value);
|
||||
|
||||
else if (value.StartsWith("PLATE SCALING"))
|
||||
ParsePlateSize(value);
|
||||
|
||||
else if (value.StartsWith("MACHINE"))
|
||||
ParseMachine(value);
|
||||
|
||||
else if (value.StartsWith("MATERIAL"))
|
||||
ParseMaterial(value);
|
||||
|
||||
else if (value.StartsWith("GRADE"))
|
||||
ParseGrade(value);
|
||||
|
||||
else if (value.StartsWith("DESCRIPTION"))
|
||||
ParseDescription(value);
|
||||
|
||||
else if (value.StartsWith("PLATE THICKNESS"))
|
||||
ParseThickness(value);
|
||||
|
||||
else if (value.StartsWith("DENSITY"))
|
||||
ParseDensity(value);
|
||||
|
||||
else if (value.StartsWith("TORCHES"))
|
||||
ParseTorchCount(value);
|
||||
}
|
||||
|
||||
private void ParseNumberOfDuplicates(string data)
|
||||
{
|
||||
var parts = data.Split(' ');
|
||||
|
||||
if (parts.Length != 7)
|
||||
return;
|
||||
|
||||
int dup;
|
||||
int.TryParse(parts[4], out dup);
|
||||
|
||||
Plate.Duplicates = dup;
|
||||
}
|
||||
|
||||
private void ParsePostedFiles(string data)
|
||||
{
|
||||
if (data.Length < 14)
|
||||
return;
|
||||
|
||||
Plate.PostedFiles = data.Remove(0, 14).Trim();
|
||||
}
|
||||
|
||||
private void ParseHeatLot(string data)
|
||||
{
|
||||
if (data.Length < 9)
|
||||
return;
|
||||
|
||||
Plate.HeatLot = data.Remove(0, 9).Trim();
|
||||
}
|
||||
|
||||
private void ParseSpacing(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
double spacing;
|
||||
double.TryParse(parts[1], out spacing);
|
||||
|
||||
Plate.PartSpacing = spacing;
|
||||
}
|
||||
|
||||
private void ParseEdgeSpacing(string data)
|
||||
{
|
||||
var parts = data.Split(',');
|
||||
|
||||
if (parts.Length != 5)
|
||||
return;
|
||||
|
||||
var leftSplit = parts[1].Split('=');
|
||||
if (leftSplit.Length == 2)
|
||||
{
|
||||
double x;
|
||||
double.TryParse(leftSplit[1], out x);
|
||||
Plate.EdgeSpacing.Left = x;
|
||||
}
|
||||
|
||||
var bottomSplit = parts[2].Split('=');
|
||||
if (bottomSplit.Length == 2)
|
||||
{
|
||||
double x;
|
||||
double.TryParse(bottomSplit[1], out x);
|
||||
Plate.EdgeSpacing.Bottom = x;
|
||||
}
|
||||
|
||||
var rightSplit = parts[3].Split('=');
|
||||
if (rightSplit.Length == 2)
|
||||
{
|
||||
double x;
|
||||
double.TryParse(rightSplit[1], out x);
|
||||
Plate.EdgeSpacing.Right = x;
|
||||
}
|
||||
|
||||
var topSplit = parts[4].Split('=');
|
||||
if (topSplit.Length == 2)
|
||||
{
|
||||
double x;
|
||||
double.TryParse(topSplit[1], out x);
|
||||
Plate.EdgeSpacing.Top = x;
|
||||
}
|
||||
}
|
||||
|
||||
private void ParsePlateSize(string data)
|
||||
{
|
||||
var quadrantIndex = data.IndexOf("QUADRANT");
|
||||
|
||||
if (quadrantIndex != -1)
|
||||
{
|
||||
var plateData = data.Remove(quadrantIndex);
|
||||
var plateDataSplit = plateData.Split('=');
|
||||
if (plateDataSplit.Length == 2)
|
||||
{
|
||||
Size plateSize;
|
||||
Size.TryParse(plateDataSplit[1], out plateSize);
|
||||
Plate.Size = plateSize;
|
||||
}
|
||||
|
||||
var quadrantData = data.Remove(0, quadrantIndex);
|
||||
var quadrantDataSplit = quadrantData.Split('=');
|
||||
if (quadrantDataSplit.Length == 2)
|
||||
{
|
||||
int quadrant;
|
||||
int.TryParse(quadrantDataSplit[1], out quadrant);
|
||||
Plate.Quadrant = quadrant;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var plateDataSplit = data.Split('=');
|
||||
if (plateDataSplit.Length == 2)
|
||||
{
|
||||
Size plateSize;
|
||||
Size.TryParse(plateDataSplit[1], out plateSize);
|
||||
Plate.Size = plateSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseMachine(string data)
|
||||
{
|
||||
var parts = data.Split(',');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
var machineSplit = parts[0].Split('=');
|
||||
if (machineSplit.Length == 2)
|
||||
{
|
||||
int num;
|
||||
int.TryParse(machineSplit[1], out num);
|
||||
Plate.Machine.Id = num;
|
||||
}
|
||||
|
||||
Plate.Machine.Name = parts[1].Trim();
|
||||
}
|
||||
|
||||
private void ParseMaterial(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
int material;
|
||||
int.TryParse(parts[1], out material);
|
||||
|
||||
Plate.Material.Id = material;
|
||||
}
|
||||
|
||||
private void ParseGrade(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
Plate.Material.Grade = parts[1].Trim();
|
||||
}
|
||||
|
||||
private void ParseDescription(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
Plate.Description = parts[1].Trim();
|
||||
}
|
||||
|
||||
private void ParseThickness(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
double thickness;
|
||||
double.TryParse(parts[1], out thickness);
|
||||
|
||||
Plate.Thickness = thickness;
|
||||
}
|
||||
|
||||
private void ParseDensity(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
double density;
|
||||
double.TryParse(parts[1], out density);
|
||||
|
||||
Plate.Material.Density = density;
|
||||
}
|
||||
|
||||
private void ParseTorchCount(string data)
|
||||
{
|
||||
var parts = data.Split('=');
|
||||
|
||||
if (parts.Length != 2)
|
||||
return;
|
||||
|
||||
int torchCount;
|
||||
int.TryParse(parts[1], out torchCount);
|
||||
|
||||
Plate.TorchCount = torchCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
404
PepLib.Core/IO/ProgramReader.cs
Normal file
404
PepLib.Core/IO/ProgramReader.cs
Normal file
@@ -0,0 +1,404 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using PepLib.Codes;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
internal sealed class ProgramReader
|
||||
{
|
||||
private const int BufferSize = 200;
|
||||
private int codeIndex;
|
||||
private CodeBlock block;
|
||||
private CodeSection section;
|
||||
|
||||
public Program Program { get; private set; }
|
||||
|
||||
public ProgramReader()
|
||||
{
|
||||
Program = new Program();
|
||||
}
|
||||
|
||||
public ProgramReader(Program program)
|
||||
{
|
||||
Program = program;
|
||||
}
|
||||
|
||||
public void Read(Stream stream)
|
||||
{
|
||||
foreach (var line in GetLines(stream))
|
||||
{
|
||||
block = ParseBlock(line);
|
||||
ProcessCurrentBlock();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetLines(Stream stream)
|
||||
{
|
||||
var buffer = new byte[BufferSize];
|
||||
|
||||
while (stream.Read(buffer, 0, BufferSize) > 0)
|
||||
{
|
||||
yield return Encoding.ASCII.GetString(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private CodeBlock ParseBlock(string line)
|
||||
{
|
||||
var block = new CodeBlock();
|
||||
Code code = null;
|
||||
|
||||
for (int i = 0; i < line.Length; ++i)
|
||||
{
|
||||
var c = line[i];
|
||||
|
||||
if (char.IsLetter(c))
|
||||
block.Add((code = new Code(c)));
|
||||
else if (c == ':')
|
||||
{
|
||||
block.Add((new Code(c, line.Remove(0, i + 1).Trim())));
|
||||
break;
|
||||
}
|
||||
else if (code != null)
|
||||
code.Value += c;
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
private void ProcessCurrentBlock()
|
||||
{
|
||||
var code = GetFirstCode();
|
||||
|
||||
while (code != null)
|
||||
{
|
||||
switch (code.Id)
|
||||
{
|
||||
case ':':
|
||||
Program.Add(new Comment(code.Value));
|
||||
code = GetNextCode();
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
int value = int.Parse(code.Value);
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
section = CodeSection.Line;
|
||||
ReadLine(value == 0);
|
||||
code = GetCurrentCode();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
section = CodeSection.Arc;
|
||||
ReadArc(value == 2 ? RotationType.CW : RotationType.CCW);
|
||||
code = GetCurrentCode();
|
||||
break;
|
||||
|
||||
case 92:
|
||||
section = CodeSection.SubProgram;
|
||||
ReadSubProgram();
|
||||
code = GetCurrentCode();
|
||||
break;
|
||||
|
||||
case 40:
|
||||
Program.Add(new SetKerf() { Kerf = KerfType.None });
|
||||
code = GetNextCode();
|
||||
break;
|
||||
|
||||
case 41:
|
||||
Program.Add(new SetKerf() { Kerf = KerfType.Left });
|
||||
code = GetNextCode();
|
||||
break;
|
||||
|
||||
case 42:
|
||||
Program.Add(new SetKerf() { Kerf = KerfType.Right });
|
||||
code = GetNextCode();
|
||||
break;
|
||||
|
||||
default:
|
||||
code = GetNextCode();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
Program.Add(new SetFeedrate() { Value = double.Parse(code.Value) });
|
||||
code = GetNextCode();
|
||||
break;
|
||||
|
||||
default:
|
||||
code = GetNextCode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadLine(bool isRapid)
|
||||
{
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
var type = EntityType.Cut;
|
||||
|
||||
while (section == CodeSection.Line)
|
||||
{
|
||||
var code = GetNextCode();
|
||||
|
||||
if (code == null)
|
||||
{
|
||||
section = CodeSection.Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (code.Id)
|
||||
{
|
||||
case 'X':
|
||||
x = double.Parse(code.Value);
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
y = double.Parse(code.Value);
|
||||
break;
|
||||
|
||||
case ':':
|
||||
{
|
||||
var value = code.Value.Trim().ToUpper();
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case "EXTERNAL LEAD-IN":
|
||||
type = EntityType.ExternalLeadin;
|
||||
break;
|
||||
|
||||
case "EXTERNAL LEAD-OUT":
|
||||
type = EntityType.ExternalLeadout;
|
||||
break;
|
||||
|
||||
case "INTERNAL LEAD-IN":
|
||||
type = EntityType.InternalLeadin;
|
||||
break;
|
||||
|
||||
case "INTERNAL LEAD-OUT":
|
||||
type = EntityType.InternalLeadout;
|
||||
break;
|
||||
|
||||
case "DISPLAY":
|
||||
type = EntityType.Display;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
section = CodeSection.Unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isRapid)
|
||||
Program.Add(new RapidMove(x, y));
|
||||
else
|
||||
Program.Add(new LinearMove(x, y) { Type = type });
|
||||
}
|
||||
|
||||
private void ReadArc(RotationType rotation)
|
||||
{
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double i = 0;
|
||||
double j = 0;
|
||||
var type = EntityType.Cut;
|
||||
|
||||
while (section == CodeSection.Arc)
|
||||
{
|
||||
var code = GetNextCode();
|
||||
|
||||
if (code == null)
|
||||
{
|
||||
section = CodeSection.Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (code.Id)
|
||||
{
|
||||
case 'X':
|
||||
x = double.Parse(code.Value);
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
y = double.Parse(code.Value);
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
i = double.Parse(code.Value);
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
j = double.Parse(code.Value);
|
||||
break;
|
||||
|
||||
case ':':
|
||||
{
|
||||
var value = code.Value.Trim().ToUpper();
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case "EXTERNAL LEAD-IN":
|
||||
type = EntityType.ExternalLeadin;
|
||||
break;
|
||||
|
||||
case "EXTERNAL LEAD-OUT":
|
||||
type = EntityType.ExternalLeadout;
|
||||
break;
|
||||
|
||||
case "INTERNAL LEAD-IN":
|
||||
type = EntityType.InternalLeadin;
|
||||
break;
|
||||
|
||||
case "INTERNAL LEAD-OUT":
|
||||
type = EntityType.InternalLeadout;
|
||||
break;
|
||||
|
||||
case "DISPLAY":
|
||||
type = EntityType.Display;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
section = CodeSection.Unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Program.Add(new CircularMove()
|
||||
{
|
||||
EndPoint = new Vector(x, y),
|
||||
CenterPoint = new Vector(i, j),
|
||||
Rotation = rotation,
|
||||
Type = type
|
||||
});
|
||||
}
|
||||
|
||||
private void ReadSubProgram()
|
||||
{
|
||||
int l = 0;
|
||||
int r = 0;
|
||||
double p = 0;
|
||||
|
||||
while (section == CodeSection.SubProgram)
|
||||
{
|
||||
var code = GetNextCode();
|
||||
|
||||
if (code == null)
|
||||
{
|
||||
section = CodeSection.Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (code.Id)
|
||||
{
|
||||
case 'L':
|
||||
l = int.Parse(code.Value);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
r = int.Parse(code.Value);
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
p = double.Parse(code.Value);
|
||||
break;
|
||||
|
||||
default:
|
||||
section = CodeSection.Unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Program.Add(new SubProgramCall() { LoopId = l, RepeatCount = r, Rotation = p });
|
||||
}
|
||||
|
||||
private Code GetNextCode()
|
||||
{
|
||||
codeIndex++;
|
||||
|
||||
if (codeIndex >= block.Count)
|
||||
return null;
|
||||
|
||||
return block[codeIndex];
|
||||
}
|
||||
|
||||
private Code GetCurrentCode()
|
||||
{
|
||||
if (codeIndex >= block.Count)
|
||||
return null;
|
||||
|
||||
return block[codeIndex];
|
||||
}
|
||||
|
||||
private Code GetFirstCode()
|
||||
{
|
||||
if (block.Count == 0)
|
||||
return null;
|
||||
|
||||
codeIndex = 0;
|
||||
|
||||
return block[codeIndex];
|
||||
}
|
||||
|
||||
private class Code
|
||||
{
|
||||
public Code(char id)
|
||||
{
|
||||
Id = id;
|
||||
Value = string.Empty;
|
||||
}
|
||||
|
||||
public Code(char id, string value)
|
||||
{
|
||||
Id = id;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public char Id { get; private set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Id + Value;
|
||||
}
|
||||
}
|
||||
|
||||
private class CodeBlock : List<Code>
|
||||
{
|
||||
public void Add(char id, string value)
|
||||
{
|
||||
Add(new Code(id, value));
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
|
||||
foreach (var code in this)
|
||||
builder.Append(code.ToString() + " ");
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodeSection
|
||||
{
|
||||
Unknown,
|
||||
Arc,
|
||||
Line,
|
||||
SubProgram
|
||||
}
|
||||
}
|
||||
}
|
||||
378
PepLib.Core/IO/ReportReader.cs
Normal file
378
PepLib.Core/IO/ReportReader.cs
Normal file
@@ -0,0 +1,378 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
internal sealed class ReportReader
|
||||
{
|
||||
public Report Report { get; private set; }
|
||||
|
||||
public ReportReader()
|
||||
{
|
||||
Report = new Report();
|
||||
}
|
||||
|
||||
public ReportReader(Report report)
|
||||
{
|
||||
Report = report;
|
||||
}
|
||||
|
||||
public void Read(Stream stream)
|
||||
{
|
||||
var reader = new StreamReader(stream);
|
||||
|
||||
Report.Drawing dwg = null;
|
||||
Report.Plate plt = null;
|
||||
|
||||
var section = Section.Unknown;
|
||||
|
||||
string line;
|
||||
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
var equalIndex = line.IndexOf('=');
|
||||
|
||||
if (equalIndex != -1)
|
||||
{
|
||||
var valueIndex = equalIndex + 1;
|
||||
var key = line.Substring(0, equalIndex).Trim();
|
||||
var value = line.Substring(valueIndex, line.Length - valueIndex).Trim();
|
||||
|
||||
switch (section)
|
||||
{
|
||||
case Section.NestHeader:
|
||||
ReadNestHeaderData(key, value);
|
||||
break;
|
||||
|
||||
case Section.NestedPlates:
|
||||
ReadNestedPlatesData(key, value, plt);
|
||||
break;
|
||||
|
||||
case Section.QuantitiesNested:
|
||||
ReadQuantitiesNestedData(key, value, dwg);
|
||||
break;
|
||||
|
||||
case Section.Unknown:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var category = line.Trim();
|
||||
|
||||
switch (category)
|
||||
{
|
||||
case "Nest header":
|
||||
section = Section.NestHeader;
|
||||
continue;
|
||||
case "Nested plates":
|
||||
section = Section.NestedPlates;
|
||||
continue;
|
||||
case "Quantities nested":
|
||||
section = Section.QuantitiesNested;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (section)
|
||||
{
|
||||
case Section.NestedPlates:
|
||||
if (category.StartsWith("Plate"))
|
||||
Report.Plates.Add((plt = new Report.Plate()));
|
||||
break;
|
||||
|
||||
case Section.QuantitiesNested:
|
||||
if (category.StartsWith("Drawing"))
|
||||
Report.Drawings.Add((dwg = new Report.Drawing()));
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.WriteLine("Unknown category: " + category);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Read(string nestFile)
|
||||
{
|
||||
if (!File.Exists(nestFile))
|
||||
{
|
||||
var msg = string.Format("File Not Found: {0}", nestFile);
|
||||
throw new FileNotFoundException(msg);
|
||||
}
|
||||
|
||||
Stream stream = null;
|
||||
string name;
|
||||
|
||||
try
|
||||
{
|
||||
ZipHelper.ExtractByExtension(nestFile, ".report", out name, out stream);
|
||||
Read(stream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (stream != null)
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadNestHeaderData(string key, string value)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case "Program":
|
||||
Report.Name = value;
|
||||
break;
|
||||
|
||||
case "Customer name":
|
||||
Report.Customer = value;
|
||||
break;
|
||||
|
||||
case "Date programmed":
|
||||
DateTime date;
|
||||
DateTime.TryParse(value, out date);
|
||||
Report.DateProgrammed = date;
|
||||
break;
|
||||
|
||||
case "Material":
|
||||
Report.Material = value;
|
||||
break;
|
||||
|
||||
case "Programmed by":
|
||||
Report.ProgrammedBy = value;
|
||||
break;
|
||||
|
||||
case "Machine":
|
||||
Report.Machine = value;
|
||||
break;
|
||||
|
||||
case "Comments":
|
||||
Report.Comments = value;
|
||||
break;
|
||||
|
||||
case "Remarks":
|
||||
Report.Remarks = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.WriteLine(string.Format("Report.ReadNestHeaderData: \"{0}\" not implemented", key));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadNestedPlatesData(string key, string value, Report.Plate plt)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case "Plate number":
|
||||
plt.Name = value;
|
||||
break;
|
||||
|
||||
case "Thickness":
|
||||
plt.Thickness = ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "Plate Size":
|
||||
ReadPlateSize(value, plt);
|
||||
break;
|
||||
|
||||
case "Material":
|
||||
plt.MaterialNumber = ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Grade":
|
||||
plt.MaterialGrade = value;
|
||||
break;
|
||||
|
||||
case "Material Description":
|
||||
plt.MaterialDescription = value;
|
||||
break;
|
||||
|
||||
case "Dup plates":
|
||||
plt.Quantity = int.Parse(value);
|
||||
break;
|
||||
|
||||
case "Plate Util":
|
||||
plt.PlateUtilization = ParsePercent(value);
|
||||
break;
|
||||
|
||||
case "Material Util":
|
||||
plt.MaterialUtilization = ParsePercent(value);
|
||||
break;
|
||||
|
||||
case "Total Area1":
|
||||
plt.Area1 = ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "Total Area2":
|
||||
plt.Area2 = ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "Bubble pierces":
|
||||
plt.BubblePierceCount = ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Total cutting time":
|
||||
ReadCuttingTime(value, Report);
|
||||
break;
|
||||
|
||||
case "Cutting feedrate":
|
||||
Report.CutFeedrate = ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Rapid feedrate":
|
||||
Report.RapidFeedrate = ParseInt32(value);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.WriteLine(string.Format("Report.ReadNestedPlatesData: \"{0}\" not implemented", key));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadQuantitiesNestedData(string key, string value, Report.Drawing dwg)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case "Customer Name":
|
||||
dwg.Customer = value;
|
||||
break;
|
||||
|
||||
case "Drawing Name":
|
||||
dwg.Name = value;
|
||||
break;
|
||||
|
||||
case "Revision":
|
||||
dwg.Revision = value;
|
||||
break;
|
||||
|
||||
case "Qty Req":
|
||||
dwg.QtyRequired = ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Qty Nstd":
|
||||
dwg.QtyNested = ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "# of Pierces":
|
||||
dwg.PierceCount = ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Intersections":
|
||||
dwg.IntersectionCount = ParseInt32(value);
|
||||
break;
|
||||
|
||||
case "Area1*":
|
||||
dwg.Area1 = ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "Area2**":
|
||||
dwg.Area2 = ParseDouble(value);
|
||||
break;
|
||||
|
||||
case "% of Material":
|
||||
dwg.PercentOfMaterial = ParsePercent(value);
|
||||
break;
|
||||
|
||||
case "% of Time":
|
||||
dwg.PercentOfCutTime = ParsePercent(value);
|
||||
dwg.TotalCutTime =
|
||||
TimeSpan.FromTicks((long)(Report.TotalCutTime.Ticks * dwg.PercentOfCutTime / 100.0));
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.WriteLine(string.Format("Report.ReadQuantitiesNestedData: \"{0}\" not implemented", key));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadPlateSize(string value, Report.Plate plt)
|
||||
{
|
||||
var a = value.ToUpper().Split('X');
|
||||
|
||||
var x = float.Parse(a[0]);
|
||||
var y = float.Parse(a[1]);
|
||||
|
||||
if (x < y)
|
||||
{
|
||||
plt.Width = x;
|
||||
plt.Length = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
plt.Width = y;
|
||||
plt.Length = x;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadCuttingTime(string value, Report report)
|
||||
{
|
||||
var parts = value.Split(',');
|
||||
|
||||
int hrs = 0, min = 0, sec = 0;
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
if (part.Contains("hr"))
|
||||
hrs = int.Parse(part.Remove(part.IndexOf("hr")));
|
||||
|
||||
else if (part.Contains("min"))
|
||||
min = int.Parse(part.Remove(part.IndexOf("min")));
|
||||
|
||||
else if (part.Contains("sec"))
|
||||
sec = int.Parse(part.Remove(part.IndexOf("sec")));
|
||||
}
|
||||
|
||||
report.TotalCutTime = new TimeSpan(hrs, min, sec);
|
||||
}
|
||||
|
||||
private static double ParsePercent(string s, double defaultValue = 0.0)
|
||||
{
|
||||
var t = s.TrimEnd('%', ' ');
|
||||
double f;
|
||||
|
||||
if (!double.TryParse(t, out f))
|
||||
{
|
||||
Debug.WriteLine("Failed to convert \"" + s + "\" from percent string to double");
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private static double ParseDouble(string s, double defaultValue = 0.0)
|
||||
{
|
||||
double f;
|
||||
|
||||
if (!double.TryParse(s, out f))
|
||||
{
|
||||
Debug.WriteLine("Failed to convert \"" + s + "\" from string to double");
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
private static int ParseInt32(string s, int defaultValue = 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!int.TryParse(s, out i))
|
||||
{
|
||||
Debug.WriteLine("Failed to convert \"" + s + "\" from string to int");
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private enum Section
|
||||
{
|
||||
Unknown,
|
||||
NestHeader,
|
||||
NestedPlates,
|
||||
QuantitiesNested,
|
||||
}
|
||||
}
|
||||
}
|
||||
104
PepLib.Core/IniConfig.cs
Normal file
104
PepLib.Core/IniConfig.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class IniConfig
|
||||
{
|
||||
public List<Node> Nodes;
|
||||
|
||||
public IniConfig()
|
||||
{
|
||||
Nodes = new List<Node>();
|
||||
}
|
||||
|
||||
private static int LeadingWhitespaceCount(string s)
|
||||
{
|
||||
for (int i = 0; i < s.Length; ++i)
|
||||
if (s[i] != ' ') return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Node FindNode(string path)
|
||||
{
|
||||
return FindNode(path, Nodes);
|
||||
}
|
||||
|
||||
private Node FindNode(string path, List<Node> nodes)
|
||||
{
|
||||
var a = path.Split('/');
|
||||
|
||||
var b = nodes.FirstOrDefault(node =>
|
||||
{
|
||||
if (node is KeyNode)
|
||||
{
|
||||
var c = node as KeyNode;
|
||||
return c.Name.ToUpper() == a[0].ToUpper();
|
||||
}
|
||||
else
|
||||
{
|
||||
return node.Value == a[0].Trim();
|
||||
}
|
||||
});
|
||||
|
||||
string path2 = string.Empty;
|
||||
|
||||
for (int i = 1; i < a.Length; ++i)
|
||||
path2 += a[i] + '/';
|
||||
|
||||
if (b == null || a.Length == 1)
|
||||
return b;
|
||||
else
|
||||
return FindNode(path2.TrimEnd('/'), b.Children);
|
||||
}
|
||||
|
||||
public static IniConfig Load(string file)
|
||||
{
|
||||
var doc = new IniConfig();
|
||||
var reader = new StreamReader(file);
|
||||
|
||||
Node currentNode = null;
|
||||
string line;
|
||||
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
int spaces = LeadingWhitespaceCount(line) / 2;
|
||||
var node = new Node();
|
||||
node.Value = line.Trim();
|
||||
|
||||
var keyNode = KeyNode.Parse(node);
|
||||
|
||||
if (keyNode != null)
|
||||
node = keyNode;
|
||||
|
||||
int currentdepth = currentNode != null ? currentNode.Level : 0;
|
||||
|
||||
if (spaces == 0)
|
||||
doc.Nodes.Add(node);
|
||||
else if (spaces == currentdepth)
|
||||
currentNode.Parent.AddChild(node);
|
||||
else if (spaces > currentdepth)
|
||||
currentNode.AddChild(node);
|
||||
else if (spaces < currentdepth)
|
||||
{
|
||||
var n = currentNode.Parent;
|
||||
|
||||
while (spaces < n.Level)
|
||||
n = n.Parent;
|
||||
|
||||
n.Parent.AddChild(node);
|
||||
}
|
||||
|
||||
currentNode = node;
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
PepLib.Core/KerfType.cs
Normal file
10
PepLib.Core/KerfType.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public enum KerfType
|
||||
{
|
||||
None,
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
}
|
||||
57
PepLib.Core/Loop.cs
Normal file
57
PepLib.Core/Loop.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using PepLib.Codes;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Loop : Program
|
||||
{
|
||||
public Loop()
|
||||
{
|
||||
Mode = ProgrammingMode.Incremental;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public Vector ReferencePoint { get; set; }
|
||||
|
||||
public DateTime LastReferenceDate { get; set; }
|
||||
|
||||
public string DrawingName { get; set; }
|
||||
|
||||
public string DxfPath { get; set; }
|
||||
|
||||
public override void Rotate(double angle)
|
||||
{
|
||||
base.Rotate(angle);
|
||||
ReferencePoint = ReferencePoint.Rotate(angle);
|
||||
}
|
||||
|
||||
public override void Rotate(double angle, Vector origin)
|
||||
{
|
||||
base.Rotate(angle, origin);
|
||||
ReferencePoint = ReferencePoint.Rotate(angle);
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
var loop = new Loop()
|
||||
{
|
||||
Name = this.Name,
|
||||
ReferencePoint = this.ReferencePoint,
|
||||
LastReferenceDate = this.LastReferenceDate,
|
||||
DrawingName = this.DrawingName,
|
||||
DxfPath = this.DxfPath,
|
||||
Rotation = this.Rotation
|
||||
};
|
||||
|
||||
var codes = new ICode[this.Count];
|
||||
|
||||
for (int i = 0; i < this.Count; ++i)
|
||||
codes[i] = this[i].Clone();
|
||||
|
||||
loop.AddRange(codes);
|
||||
|
||||
return loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
PepLib.Core/Machine.cs
Normal file
9
PepLib.Core/Machine.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace PepLib
|
||||
{
|
||||
public class Machine
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
11
PepLib.Core/Material.cs
Normal file
11
PepLib.Core/Material.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace PepLib
|
||||
{
|
||||
public class Material
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Grade { get; set; }
|
||||
|
||||
public double Density { get; set; }
|
||||
}
|
||||
}
|
||||
55
PepLib.Core/MathHelper.cs
Normal file
55
PepLib.Core/MathHelper.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public static class MathHelper
|
||||
{
|
||||
public const double HalfPI = Math.PI * 0.5;
|
||||
public const double TwoPI = Math.PI * 2.0;
|
||||
|
||||
public static double NormalizeAngleRad(double angle)
|
||||
{
|
||||
double r = angle % TwoPI;
|
||||
return r < 0 ? TwoPI + r : r;
|
||||
}
|
||||
|
||||
public static double NormalizeAngleDeg(double angle)
|
||||
{
|
||||
double r = angle % 360.0;
|
||||
return r < 0 ? 360.0 + r : r;
|
||||
}
|
||||
|
||||
public static bool IsAngleBetween(double angle, double a1, double a2, bool reversed = false)
|
||||
{
|
||||
if (reversed)
|
||||
Generic.Swap(ref a1, ref a2);
|
||||
|
||||
var diff = NormalizeAngleRad(a2 - a1);
|
||||
|
||||
// full circle
|
||||
if (a2.IsEqualTo(a1))
|
||||
return true;
|
||||
|
||||
a1 = NormalizeAngleRad(angle - a1);
|
||||
a2 = NormalizeAngleRad(a2 - angle);
|
||||
|
||||
return diff >= a1 - Tolerance.Epsilon ||
|
||||
diff >= a2 - Tolerance.Epsilon;
|
||||
}
|
||||
|
||||
public static double RoundDownToNearest(double num, double factor)
|
||||
{
|
||||
return factor == 0 ? num : Math.Floor(num / factor) * factor;
|
||||
}
|
||||
|
||||
public static double RoundUpToNearest(double num, double factor)
|
||||
{
|
||||
return factor == 0 ? num : Math.Ceiling(num / factor) * factor;
|
||||
}
|
||||
|
||||
public static double RoundToNearest(double num, double factor)
|
||||
{
|
||||
return factor == 0 ? num : Math.Round(num / factor) * factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
PepLib.Core/Nest.cs
Normal file
134
PepLib.Core/Nest.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using PepLib.Codes;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Nest
|
||||
{
|
||||
public Nest()
|
||||
{
|
||||
Report = new Report();
|
||||
Loops = new List<Loop>();
|
||||
Plates = new List<Plate>();
|
||||
Drawings = new List<NestDrawing>();
|
||||
}
|
||||
|
||||
public Report Report { get; set; }
|
||||
|
||||
public List<Loop> Loops { get; set; }
|
||||
|
||||
public List<Plate> Plates { get; set; }
|
||||
|
||||
public List<NestDrawing> Drawings { get; set; }
|
||||
|
||||
public void ResolveLoops()
|
||||
{
|
||||
for (int i = 0; i < Loops.Count; ++i)
|
||||
{
|
||||
var loop = Loops[i];
|
||||
ResolveLoops(loop);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResolveLoops(Program pgm)
|
||||
{
|
||||
for (int i = 0; i < pgm.Count; ++i)
|
||||
{
|
||||
var code = pgm[i];
|
||||
|
||||
if (code.CodeType() != CodeType.SubProgramCall)
|
||||
continue;
|
||||
|
||||
var subpgmcall = (SubProgramCall)code;
|
||||
|
||||
var loop = GetLoop(subpgmcall.LoopId);
|
||||
|
||||
if (loop == null)
|
||||
throw new Exception("Loop not found");
|
||||
|
||||
subpgmcall.Loop = loop;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetQtyNested(string drawing)
|
||||
{
|
||||
int qty = 0;
|
||||
|
||||
foreach (var plate in Plates)
|
||||
qty += plate.GetQtyNested(drawing);
|
||||
|
||||
return qty;
|
||||
}
|
||||
|
||||
private Loop GetLoop(string name)
|
||||
{
|
||||
for (int i = 0; i < Loops.Count; ++i)
|
||||
{
|
||||
if (Loops[i].Name == name)
|
||||
return Loops[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Loop GetLoop(int id)
|
||||
{
|
||||
var ext = $".loop-{id.ToString().PadLeft(3, '0')}";
|
||||
|
||||
for (int i = 0; i < Loops.Count; ++i)
|
||||
{
|
||||
if (Loops[i].Name.EndsWith(ext))
|
||||
return Loops[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Nest Load(string nestfile)
|
||||
{
|
||||
var reader = new NestReader();
|
||||
reader.Read(nestfile);
|
||||
return reader.Nest;
|
||||
}
|
||||
|
||||
public static Nest Load(Stream stream)
|
||||
{
|
||||
var reader = new NestReader();
|
||||
reader.Read(stream);
|
||||
return reader.Nest;
|
||||
}
|
||||
|
||||
public static bool TryLoad(string nestfile, out Nest nest)
|
||||
{
|
||||
try
|
||||
{
|
||||
nest = Load(nestfile);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
nest = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryLoad(Stream stream, out Nest nest)
|
||||
{
|
||||
try
|
||||
{
|
||||
nest = Load(stream);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
nest = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
PepLib.Core/NestDrawing.cs
Normal file
14
PepLib.Core/NestDrawing.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class NestDrawing
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public int QtyRequired { get; set; }
|
||||
}
|
||||
}
|
||||
68
PepLib.Core/NestIndex.cs
Normal file
68
PepLib.Core/NestIndex.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class NestIndex
|
||||
{
|
||||
public string Directory { get; set; }
|
||||
|
||||
public List<NestInfo> Entries;
|
||||
|
||||
public NestIndex()
|
||||
{
|
||||
Entries = new List<NestInfo>();
|
||||
}
|
||||
|
||||
public string GetPath(NestInfo entry)
|
||||
{
|
||||
return Path.Combine(Directory, entry.Name + ".zip");
|
||||
}
|
||||
|
||||
public static NestIndex LoadFromDir(string directory)
|
||||
{
|
||||
var file = Path.Combine(directory, "pepfiles.lfn");
|
||||
return Load(file);
|
||||
}
|
||||
|
||||
public static NestIndex Load(string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
var index = new NestIndex() { Directory = Path.GetDirectoryName(file) };
|
||||
var stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
var reader = new StreamReader(stream);
|
||||
var buffer = new char[4000];
|
||||
|
||||
while (reader.Read(buffer, 0, buffer.Length) > 0)
|
||||
{
|
||||
var memstream = new MemoryStream(Encoding.ASCII.GetBytes(buffer));
|
||||
var inforeader = new NestInfoReader();
|
||||
|
||||
inforeader.Read(memstream);
|
||||
index.Entries.Add(inforeader.Info);
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
public static NestIndex Build(string directory)
|
||||
{
|
||||
var index = new NestIndex() { Directory = directory };
|
||||
|
||||
foreach (var file in System.IO.Directory.GetFiles(directory, "*.zip"))
|
||||
{
|
||||
var reader = new NestInfoReader();
|
||||
reader.Read(file);
|
||||
index.Entries.Add(reader.Info);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
99
PepLib.Core/NestInfo.cs
Normal file
99
PepLib.Core/NestInfo.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class NestInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public DateTime DateCreated { get; set; }
|
||||
|
||||
public DateTime DateLastModified { get; set; }
|
||||
|
||||
public StatusType Status { get; set; }
|
||||
|
||||
public int LoopCount { get; set; }
|
||||
|
||||
public int ProgramCount { get; set; }
|
||||
|
||||
public int PlateCount { get; set; }
|
||||
|
||||
public string Comments { get; set; }
|
||||
|
||||
public string Customer { get; set; }
|
||||
|
||||
public string ProgrammedBy { get; set; }
|
||||
|
||||
public int MaterialNumber { get; set; }
|
||||
|
||||
public string MaterialGrade { get; set; }
|
||||
|
||||
public string Notes { get; set; }
|
||||
|
||||
public string DefaultPlateSize { get; set; }
|
||||
|
||||
public string Kerf { get; set; }
|
||||
|
||||
public string PostedAs { get; set; }
|
||||
|
||||
public string Errors { get; set; }
|
||||
|
||||
public string UserDefined1 { get; set; }
|
||||
|
||||
public string UserDefined2 { get; set; }
|
||||
|
||||
public string UserDefined3 { get; set; }
|
||||
|
||||
public string UserDefined4 { get; set; }
|
||||
|
||||
public string UserDefined5 { get; set; }
|
||||
|
||||
public string UserDefined6 { get; set; }
|
||||
|
||||
public static NestInfo Load(string nestFile)
|
||||
{
|
||||
var reader = new NestInfoReader();
|
||||
reader.Read(nestFile);
|
||||
return reader.Info;
|
||||
}
|
||||
|
||||
public static NestInfo Load(Stream stream)
|
||||
{
|
||||
var reader = new NestInfoReader();
|
||||
reader.Read(stream);
|
||||
return reader.Info;
|
||||
}
|
||||
|
||||
public static bool TryLoad(string nestFile, out NestInfo nestInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
nestInfo = Load(nestFile);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
nestInfo = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryLoad(Stream stream, out NestInfo nestInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
nestInfo = Load(stream);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
nestInfo = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
88
PepLib.Core/Node.cs
Normal file
88
PepLib.Core/Node.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Node
|
||||
{
|
||||
private Node parent;
|
||||
|
||||
public List<Node> Children;
|
||||
|
||||
public Node()
|
||||
{
|
||||
Children = new List<Node>();
|
||||
}
|
||||
|
||||
public Node Parent
|
||||
{
|
||||
get { return parent; }
|
||||
set
|
||||
{
|
||||
parent = value;
|
||||
UpdateDepth();
|
||||
}
|
||||
}
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
private void UpdateDepth()
|
||||
{
|
||||
if (Parent != null)
|
||||
Level = Parent.Level + 1;
|
||||
else
|
||||
Level = 0;
|
||||
|
||||
foreach (var node in Children)
|
||||
node.Parent = this;
|
||||
}
|
||||
|
||||
public int Level { get; protected set; }
|
||||
|
||||
public void AddChild(Node node)
|
||||
{
|
||||
node.Parent = this;
|
||||
Children.Add(node);
|
||||
}
|
||||
|
||||
public void Write(TextWriter writer)
|
||||
{
|
||||
writer.WriteLine("".PadLeft(Level * 2) + this.ToString());
|
||||
|
||||
foreach (var node in Children)
|
||||
node.Write(writer);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
|
||||
public class KeyNode : Node
|
||||
{
|
||||
public string Name;
|
||||
|
||||
public static KeyNode Parse(Node node)
|
||||
{
|
||||
var index = node.Value.IndexOf('=');
|
||||
|
||||
if (index == -1)
|
||||
return null;
|
||||
|
||||
return new KeyNode()
|
||||
{
|
||||
Name = node.Value.Remove(index),
|
||||
Value = node.Value.Remove(0, index + 1).Trim()
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}={1}", Name, Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
125
PepLib.Core/Part.cs
Normal file
125
PepLib.Core/Part.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Part : IMovable
|
||||
{
|
||||
private Loop baseLoop;
|
||||
private Vector location;
|
||||
|
||||
private Part()
|
||||
{
|
||||
BoundingBox = new Box();
|
||||
}
|
||||
|
||||
public Box BoundingBox { get; protected set; }
|
||||
|
||||
public Vector Location
|
||||
{
|
||||
get { return location; }
|
||||
set
|
||||
{
|
||||
BoundingBox.Offset(value - location);
|
||||
location = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return baseLoop.Name; }
|
||||
set { baseLoop.Name = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference point relative to the part location.
|
||||
/// </summary>
|
||||
public Vector ReferencePoint
|
||||
{
|
||||
get { return baseLoop.ReferencePoint; }
|
||||
set { baseLoop.ReferencePoint = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference point relative to the zero point.
|
||||
/// </summary>
|
||||
public Vector AbsoluteReferencePoint
|
||||
{
|
||||
get { return baseLoop.ReferencePoint + location; }
|
||||
set { baseLoop.ReferencePoint = value - location; }
|
||||
}
|
||||
|
||||
public DateTime LastReferenceDate
|
||||
{
|
||||
get { return baseLoop.LastReferenceDate; }
|
||||
set { baseLoop.LastReferenceDate = value; }
|
||||
}
|
||||
|
||||
public string DrawingName
|
||||
{
|
||||
get { return baseLoop.DrawingName; }
|
||||
set { baseLoop.DrawingName = value; }
|
||||
}
|
||||
|
||||
public string DxfPath
|
||||
{
|
||||
get { return baseLoop.DxfPath; }
|
||||
set { baseLoop.DxfPath = value; }
|
||||
}
|
||||
|
||||
public double Rotation
|
||||
{
|
||||
get { return baseLoop.Rotation; }
|
||||
}
|
||||
|
||||
public bool IsDisplayOnly { get; set; } = false;
|
||||
|
||||
public void Rotate(double angle)
|
||||
{
|
||||
baseLoop.Rotate(angle);
|
||||
location = Location.Rotate(angle);
|
||||
UpdateBounds();
|
||||
}
|
||||
|
||||
public void Rotate(double angle, Vector origin)
|
||||
{
|
||||
baseLoop.Rotate(angle);
|
||||
location = Location.Rotate(angle, origin);
|
||||
UpdateBounds();
|
||||
}
|
||||
|
||||
public void Offset(double x, double y)
|
||||
{
|
||||
location = new Vector(location.X + x, location.Y + y);
|
||||
BoundingBox.Offset(x, y);
|
||||
}
|
||||
|
||||
public void Offset(Vector voffset)
|
||||
{
|
||||
location += voffset;
|
||||
BoundingBox.Offset(voffset);
|
||||
}
|
||||
|
||||
public Program Program
|
||||
{
|
||||
get { return baseLoop; }
|
||||
}
|
||||
|
||||
public void UpdateBounds()
|
||||
{
|
||||
BoundingBox = baseLoop.GetBoundingBox();
|
||||
BoundingBox.Offset(Location);
|
||||
}
|
||||
|
||||
public static Part Create(Loop loop, Vector location, double rotation = 0.0)
|
||||
{
|
||||
var part = new Part();
|
||||
part.baseLoop = (Loop)loop.Clone();
|
||||
part.baseLoop.Mode = ProgrammingMode.Incremental;
|
||||
part.baseLoop.Rotate(rotation);
|
||||
part.Location = location;
|
||||
part.UpdateBounds();
|
||||
|
||||
return part;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
PepLib.Core/PartListExtensions.cs
Normal file
42
PepLib.Core/PartListExtensions.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public static class PartListExtensions
|
||||
{
|
||||
public static Box GetBoundingBox(this List<Part> parts)
|
||||
{
|
||||
if (parts.Count == 0)
|
||||
return new Box();
|
||||
|
||||
var firstpart = parts[0];
|
||||
|
||||
double minX = firstpart.BoundingBox.X;
|
||||
double minY = firstpart.BoundingBox.Y;
|
||||
double maxX = firstpart.BoundingBox.X + firstpart.BoundingBox.Width;
|
||||
double maxY = firstpart.BoundingBox.Y + firstpart.BoundingBox.Height;
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
var box = part.BoundingBox;
|
||||
|
||||
if (box.Left < minX)
|
||||
minX = box.Left;
|
||||
|
||||
if (box.Right > maxX)
|
||||
maxX = box.Right;
|
||||
|
||||
if (box.Bottom < minY)
|
||||
minY = box.Bottom;
|
||||
|
||||
if (box.Top > maxY)
|
||||
maxY = box.Top;
|
||||
}
|
||||
|
||||
return new Box(minX, minY, maxX - minX, maxY - minY);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
PepLib.Core/PepLib.Core.csproj
Normal file
18
PepLib.Core/PepLib.Core.csproj
Normal file
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNetZip" Version="1.16.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.10">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.10" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
266
PepLib.Core/Plate.cs
Normal file
266
PepLib.Core/Plate.cs
Normal file
@@ -0,0 +1,266 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Plate : IMovable
|
||||
{
|
||||
public Plate()
|
||||
: this(60, 120)
|
||||
{
|
||||
}
|
||||
|
||||
public Plate(double width, double length)
|
||||
: this(new Size(width, length))
|
||||
{
|
||||
}
|
||||
|
||||
public Plate(Size size)
|
||||
{
|
||||
EdgeSpacing = new Spacing();
|
||||
Size = size;
|
||||
Machine = new Machine();
|
||||
Material = new Material();
|
||||
Parts = new List<Part>();
|
||||
Quadrant = 1;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string PostedFiles { get; set; }
|
||||
|
||||
public string HeatLot { get; set; }
|
||||
|
||||
public double Thickness { get; set; }
|
||||
|
||||
public double PartSpacing { get; set; }
|
||||
|
||||
public Spacing EdgeSpacing { get; set; }
|
||||
|
||||
public Size Size { get; set; }
|
||||
|
||||
public Machine Machine { get; set; }
|
||||
|
||||
public Material Material { get; set; }
|
||||
|
||||
public List<Part> Parts { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
|
||||
public int Duplicates { get; set; }
|
||||
|
||||
public int Quadrant { get; set; }
|
||||
|
||||
public int TorchCount { get; set; }
|
||||
|
||||
public void Rotate90CCW(bool keepSameQuadrant = true)
|
||||
{
|
||||
Size = new Size(Size.Width, Size.Height);
|
||||
|
||||
Rotate(MathHelper.HalfPI);
|
||||
|
||||
if (keepSameQuadrant)
|
||||
{
|
||||
switch (Quadrant)
|
||||
{
|
||||
case 1:
|
||||
Offset(Size.Width, 0);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Offset(0, Size.Height);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Offset(-Size.Width, 0);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
Offset(0, -Size.Height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Quadrant = Quadrant > 3 ? 1 : Quadrant + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void Rotate90CW(bool keepSameQuadrant = true)
|
||||
{
|
||||
const double oneAndHalfPI = Math.PI * 1.5;
|
||||
|
||||
Size = new Size(Size.Width, Size.Height);
|
||||
|
||||
Rotate(oneAndHalfPI);
|
||||
|
||||
if (keepSameQuadrant)
|
||||
{
|
||||
switch (Quadrant)
|
||||
{
|
||||
case 1:
|
||||
Offset(0, Size.Height);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
Offset(-Size.Width, 0);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
Offset(0, -Size.Height);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
Offset(Size.Width, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Quadrant = Quadrant < 2 ? 4 : Quadrant - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void Rotate180(bool keepSameQuadrant = true)
|
||||
{
|
||||
if (keepSameQuadrant)
|
||||
{
|
||||
Vector centerpt;
|
||||
|
||||
switch (Quadrant)
|
||||
{
|
||||
case 1:
|
||||
centerpt = new Vector(Size.Width * 0.5, Size.Height * 0.5);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
centerpt = new Vector(-Size.Width * 0.5, Size.Height * 0.5);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
centerpt = new Vector(-Size.Width * 0.5, -Size.Height * 0.5);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
centerpt = new Vector(Size.Width * 0.5, -Size.Height * 0.5);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
Rotate(Math.PI, centerpt);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rotate(Math.PI);
|
||||
Quadrant = (Quadrant + 2) % 4;
|
||||
|
||||
if (Quadrant == 0)
|
||||
Quadrant = 4;
|
||||
}
|
||||
}
|
||||
|
||||
public void Rotate(double angle)
|
||||
{
|
||||
for (int i = 0; i < Parts.Count; ++i)
|
||||
{
|
||||
var part = Parts[i];
|
||||
part.Rotate(angle);
|
||||
}
|
||||
}
|
||||
|
||||
public void Rotate(double angle, Vector origin)
|
||||
{
|
||||
for (int i = 0; i < Parts.Count; ++i)
|
||||
{
|
||||
var part = Parts[i];
|
||||
part.Rotate(angle, origin);
|
||||
}
|
||||
}
|
||||
|
||||
public void Offset(double x, double y)
|
||||
{
|
||||
for (int i = 0; i < Parts.Count; ++i)
|
||||
{
|
||||
var part = Parts[i];
|
||||
part.Offset(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void Offset(Vector voffset)
|
||||
{
|
||||
for (int i = 0; i < Parts.Count; ++i)
|
||||
{
|
||||
var part = Parts[i];
|
||||
part.Offset(voffset);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetQtyNested(string drawing)
|
||||
{
|
||||
var name = drawing.ToUpper();
|
||||
|
||||
return Parts.Count(p => p.DrawingName.ToUpper() == name);
|
||||
}
|
||||
|
||||
public Box GetBoundingBox(bool includeParts)
|
||||
{
|
||||
var plateBox = new Box();
|
||||
|
||||
switch (Quadrant)
|
||||
{
|
||||
case 1:
|
||||
plateBox.X = 0;
|
||||
plateBox.Y = 0;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
plateBox.X = (float)-Size.Width;
|
||||
plateBox.Y = 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
plateBox.X = (float)-Size.Width;
|
||||
plateBox.Y = (float)-Size.Height;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
plateBox.X = 0;
|
||||
plateBox.Y = (float)-Size.Height;
|
||||
break;
|
||||
|
||||
default:
|
||||
return new Box();
|
||||
}
|
||||
|
||||
plateBox.Width = Size.Width;
|
||||
plateBox.Height = Size.Height;
|
||||
|
||||
if (!includeParts)
|
||||
return plateBox;
|
||||
|
||||
var boundingBox = new Box();
|
||||
var partsBox = Parts.GetBoundingBox();
|
||||
|
||||
boundingBox.X = partsBox.Left < plateBox.Left
|
||||
? partsBox.Left
|
||||
: plateBox.Left;
|
||||
|
||||
boundingBox.Y = partsBox.Bottom < plateBox.Bottom
|
||||
? partsBox.Bottom
|
||||
: plateBox.Bottom;
|
||||
|
||||
boundingBox.Width = partsBox.Right > plateBox.Right
|
||||
? partsBox.Right - boundingBox.X
|
||||
: plateBox.Right - boundingBox.X;
|
||||
|
||||
boundingBox.Height = partsBox.Top > plateBox.Top
|
||||
? partsBox.Top - boundingBox.Y
|
||||
: plateBox.Top - boundingBox.Y;
|
||||
|
||||
return boundingBox;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
PepLib.Core/PlateListExtensions.cs
Normal file
41
PepLib.Core/PlateListExtensions.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public static class PlateListExtensions
|
||||
{
|
||||
public static void JoinLikePlates(this List<Report.Plate> plates)
|
||||
{
|
||||
START:
|
||||
|
||||
for (int i = 0; i < plates.Count; ++i)
|
||||
{
|
||||
var p1 = plates[i];
|
||||
|
||||
for (int j = 0; j < plates.Count; ++j)
|
||||
{
|
||||
var p2 = plates[j];
|
||||
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
if (p1.Width != p2.Width)
|
||||
continue;
|
||||
|
||||
if (p1.Length != p2.Length)
|
||||
continue;
|
||||
|
||||
if (p1.MaterialDescription != p2.MaterialDescription)
|
||||
continue;
|
||||
|
||||
if (p1.Thickness != p2.Thickness)
|
||||
continue;
|
||||
|
||||
p1.Quantity += p2.Quantity;
|
||||
plates.Remove(p2);
|
||||
goto START;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
367
PepLib.Core/Program.cs
Normal file
367
PepLib.Core/Program.cs
Normal file
@@ -0,0 +1,367 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using PepLib.Codes;
|
||||
using PepLib.IO;
|
||||
using System;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Program : List<ICode>, IMovable
|
||||
{
|
||||
private ProgrammingMode mode;
|
||||
|
||||
public Program(ProgrammingMode mode = ProgrammingMode.Absolute)
|
||||
{
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
public ProgrammingMode Mode
|
||||
{
|
||||
get { return mode; }
|
||||
set
|
||||
{
|
||||
if (value == ProgrammingMode.Absolute)
|
||||
SetProgrammingModeAbs();
|
||||
else
|
||||
SetProgrammingModeInc();
|
||||
}
|
||||
}
|
||||
|
||||
public double Rotation { get; protected set; }
|
||||
|
||||
private void SetProgrammingModeInc()
|
||||
{
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
return;
|
||||
|
||||
var pos = new Vector(0, 0);
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
var motion = code as Motion;
|
||||
|
||||
if (motion != null)
|
||||
{
|
||||
var pos2 = motion.EndPoint;
|
||||
motion.Offset(-pos.X, -pos.Y);
|
||||
pos = pos2;
|
||||
}
|
||||
}
|
||||
|
||||
mode = ProgrammingMode.Incremental;
|
||||
}
|
||||
|
||||
private void SetProgrammingModeAbs()
|
||||
{
|
||||
if (mode == ProgrammingMode.Absolute)
|
||||
return;
|
||||
|
||||
var pos = new Vector(0, 0);
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
var motion = code as Motion;
|
||||
|
||||
if (motion != null)
|
||||
{
|
||||
motion.Offset(pos);
|
||||
pos = motion.EndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
mode = ProgrammingMode.Absolute;
|
||||
}
|
||||
|
||||
public virtual void Rotate(double angle)
|
||||
{
|
||||
var mode = Mode;
|
||||
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
if (code.CodeType() == CodeType.SubProgramCall)
|
||||
{
|
||||
var subpgm = (SubProgramCall)code;
|
||||
|
||||
if (subpgm.Loop != null)
|
||||
subpgm.Loop.Rotate(angle);
|
||||
}
|
||||
|
||||
if (code is IMovable == false)
|
||||
continue;
|
||||
|
||||
var code2 = (IMovable)code;
|
||||
|
||||
code2.Rotate(angle);
|
||||
}
|
||||
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
|
||||
Rotation = MathHelper.NormalizeAngleRad(Rotation + angle);
|
||||
}
|
||||
|
||||
public virtual void Rotate(double angle, Vector origin)
|
||||
{
|
||||
var mode = Mode;
|
||||
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
if (code.CodeType() == CodeType.SubProgramCall)
|
||||
{
|
||||
var subpgm = (SubProgramCall)code;
|
||||
|
||||
if (subpgm.Loop != null)
|
||||
subpgm.Loop.Rotate(angle);
|
||||
}
|
||||
|
||||
if (code is IMovable == false)
|
||||
continue;
|
||||
|
||||
var code2 = (IMovable)code;
|
||||
|
||||
code2.Rotate(angle, origin);
|
||||
}
|
||||
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
|
||||
Rotation = MathHelper.NormalizeAngleRad(Rotation + angle);
|
||||
}
|
||||
|
||||
public void Offset(double x, double y)
|
||||
{
|
||||
var mode = Mode;
|
||||
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
if (code is IMovable == false)
|
||||
continue;
|
||||
|
||||
var code2 = (IMovable)code;
|
||||
|
||||
code2.Offset(x, y);
|
||||
}
|
||||
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
}
|
||||
|
||||
public void Offset(Vector voffset)
|
||||
{
|
||||
var mode = Mode;
|
||||
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
if (code is IMovable == false)
|
||||
continue;
|
||||
|
||||
var code2 = (IMovable)code;
|
||||
|
||||
code2.Offset(voffset);
|
||||
}
|
||||
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
}
|
||||
|
||||
public Box GetBoundingBox()
|
||||
{
|
||||
var origin = new Vector(0, 0);
|
||||
return GetBoundingBox(ref origin);
|
||||
}
|
||||
|
||||
private Box GetBoundingBox(ref Vector pos)
|
||||
{
|
||||
double minX = 0.0;
|
||||
double minY = 0.0;
|
||||
double maxX = 0.0;
|
||||
double maxY = 0.0;
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
switch (code.CodeType())
|
||||
{
|
||||
case CodeType.LinearMove:
|
||||
{
|
||||
var line = (LinearMove)code;
|
||||
var pt = Mode == ProgrammingMode.Absolute ?
|
||||
line.EndPoint :
|
||||
line.EndPoint + pos;
|
||||
|
||||
if (pt.X > maxX)
|
||||
maxX = pt.X;
|
||||
else if (pt.X < minX)
|
||||
minX = pt.X;
|
||||
|
||||
if (pt.Y > maxY)
|
||||
maxY = pt.Y;
|
||||
else if (pt.Y < minY)
|
||||
minY = pt.Y;
|
||||
|
||||
pos = pt;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.RapidMove:
|
||||
{
|
||||
var line = (RapidMove)code;
|
||||
var pt = Mode == ProgrammingMode.Absolute
|
||||
? line.EndPoint
|
||||
: line.EndPoint + pos;
|
||||
|
||||
if (pt.X > maxX)
|
||||
maxX = pt.X;
|
||||
else if (pt.X < minX)
|
||||
minX = pt.X;
|
||||
|
||||
if (pt.Y > maxY)
|
||||
maxY = pt.Y;
|
||||
else if (pt.Y < minY)
|
||||
minY = pt.Y;
|
||||
|
||||
pos = pt;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.CircularMove:
|
||||
{
|
||||
var arc = (CircularMove)code;
|
||||
var radius = arc.CenterPoint.DistanceTo(arc.EndPoint);
|
||||
|
||||
Vector endpt;
|
||||
Vector centerpt;
|
||||
|
||||
if (Mode == ProgrammingMode.Incremental)
|
||||
{
|
||||
endpt = arc.EndPoint + pos;
|
||||
centerpt = arc.CenterPoint + pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
endpt = arc.EndPoint;
|
||||
centerpt = arc.CenterPoint;
|
||||
}
|
||||
|
||||
double minX1;
|
||||
double minY1;
|
||||
double maxX1;
|
||||
double maxY1;
|
||||
|
||||
if (pos.X < endpt.X)
|
||||
{
|
||||
minX1 = pos.X;
|
||||
maxX1 = endpt.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
minX1 = endpt.X;
|
||||
maxX1 = pos.X;
|
||||
}
|
||||
|
||||
if (pos.Y < endpt.Y)
|
||||
{
|
||||
minY1 = pos.Y;
|
||||
maxY1 = endpt.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
minY1 = endpt.Y;
|
||||
maxY1 = pos.Y;
|
||||
}
|
||||
|
||||
var startAngle = pos.AngleFrom(centerpt);
|
||||
var endAngle = endpt.AngleFrom(centerpt);
|
||||
|
||||
// switch the angle to counter clockwise.
|
||||
if (arc.Rotation == RotationType.CW)
|
||||
Generic.Swap(ref startAngle, ref endAngle);
|
||||
|
||||
startAngle = MathHelper.NormalizeAngleRad(startAngle);
|
||||
endAngle = MathHelper.NormalizeAngleRad(endAngle);
|
||||
|
||||
if (MathHelper.IsAngleBetween(MathHelper.HalfPI, startAngle, endAngle))
|
||||
maxY1 = centerpt.Y + radius;
|
||||
|
||||
if (MathHelper.IsAngleBetween(Math.PI, startAngle, endAngle))
|
||||
minX1 = centerpt.X - radius;
|
||||
|
||||
const double oneHalfPI = Math.PI * 1.5;
|
||||
|
||||
if (MathHelper.IsAngleBetween(oneHalfPI, startAngle, endAngle))
|
||||
minY1 = centerpt.Y - radius;
|
||||
|
||||
if (MathHelper.IsAngleBetween(MathHelper.TwoPI, startAngle, endAngle))
|
||||
maxX1 = centerpt.X + radius;
|
||||
|
||||
if (maxX1 > maxX)
|
||||
maxX = maxX1;
|
||||
|
||||
if (minX1 < minX)
|
||||
minX = minX1;
|
||||
|
||||
if (maxY1 > maxY)
|
||||
maxY = maxY1;
|
||||
|
||||
if (minY1 < minY)
|
||||
minY = minY1;
|
||||
|
||||
pos = endpt;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.SubProgramCall:
|
||||
{
|
||||
var subpgm = (SubProgramCall)code;
|
||||
var box = subpgm.Loop.GetBoundingBox(ref pos);
|
||||
|
||||
if (box.Left < minX)
|
||||
minX = box.Left;
|
||||
|
||||
if (box.Right > maxX)
|
||||
maxX = box.Right;
|
||||
|
||||
if (box.Bottom < minY)
|
||||
minY = box.Bottom;
|
||||
|
||||
if (box.Top > maxY)
|
||||
maxY = box.Top;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Box(minX, minY, maxX - minX, maxY - minY);
|
||||
}
|
||||
|
||||
public static Program Load(Stream stream)
|
||||
{
|
||||
var reader = new ProgramReader();
|
||||
reader.Read(stream);
|
||||
return reader.Program;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
PepLib.Core/ProgrammingMode.cs
Normal file
8
PepLib.Core/ProgrammingMode.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace PepLib
|
||||
{
|
||||
public enum ProgrammingMode
|
||||
{
|
||||
Absolute,
|
||||
Incremental
|
||||
}
|
||||
}
|
||||
53
PepLib.Core/Report.Drawing.cs
Normal file
53
PepLib.Core/Report.Drawing.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public partial class Report
|
||||
{
|
||||
public class Drawing
|
||||
{
|
||||
public string Customer { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Revision { get; set; }
|
||||
|
||||
public int QtyRequired { get; set; }
|
||||
|
||||
public int QtyNested { get; set; }
|
||||
|
||||
public int QtyRemaining
|
||||
{
|
||||
get { return QtyRequired - QtyNested; }
|
||||
}
|
||||
|
||||
public double CutDistance { get; set; }
|
||||
|
||||
public double ScribeDistance { get; set; }
|
||||
|
||||
public double BevelDistance { get; set; }
|
||||
|
||||
public TimeSpan TotalCutTime { get; set; }
|
||||
|
||||
public int PierceCount { get; set; }
|
||||
|
||||
public int IntersectionCount { get; set; }
|
||||
|
||||
public double Area1 { get; set; }
|
||||
|
||||
public double Area2 { get; set; }
|
||||
|
||||
public bool IncludeRemnantInCost { get; set; }
|
||||
|
||||
public double NetWeight1 { get; set; }
|
||||
|
||||
public double NetWeight2 { get; set; }
|
||||
|
||||
public double GrossWeight { get; set; }
|
||||
|
||||
public double PercentOfMaterial { get; set; }
|
||||
|
||||
public double PercentOfCutTime { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
35
PepLib.Core/Report.Plate.cs
Normal file
35
PepLib.Core/Report.Plate.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public partial class Report
|
||||
{
|
||||
public class Plate
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public double Thickness { get; set; }
|
||||
|
||||
public double Width { get; set; }
|
||||
|
||||
public double Length { get; set; }
|
||||
|
||||
public int MaterialNumber { get; set; }
|
||||
|
||||
public string MaterialGrade { get; set; }
|
||||
|
||||
public string MaterialDescription { get; set; }
|
||||
|
||||
public int Quantity { get; set; }
|
||||
|
||||
public double PlateUtilization { get; set; }
|
||||
|
||||
public double MaterialUtilization { get; set; }
|
||||
|
||||
public double Area1 { get; set; }
|
||||
|
||||
public double Area2 { get; set; }
|
||||
|
||||
public int BubblePierceCount { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
125
PepLib.Core/Report.cs
Normal file
125
PepLib.Core/Report.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public partial class Report
|
||||
{
|
||||
public Report()
|
||||
{
|
||||
Drawings = new List<Report.Drawing>();
|
||||
Plates = new List<Report.Plate>();
|
||||
}
|
||||
|
||||
public List<Report.Drawing> Drawings { get; set; }
|
||||
|
||||
public List<Report.Plate> Plates { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Customer { get; set; }
|
||||
|
||||
public DateTime DateProgrammed { get; set; }
|
||||
|
||||
public string Material { get; set; }
|
||||
|
||||
public string ProgrammedBy { get; set; }
|
||||
|
||||
public string Machine { get; set; }
|
||||
|
||||
public string Comments { get; set; }
|
||||
|
||||
public string Remarks { get; set; }
|
||||
|
||||
public TimeSpan TotalCutTime { get; set; }
|
||||
|
||||
public double TotalGasUsed { get; set; }
|
||||
|
||||
public double TotalRapidDistance { get; set; }
|
||||
|
||||
public int TotalHeadRaises { get; set; }
|
||||
|
||||
public double CutFeedrate { get; set; }
|
||||
|
||||
public double RapidFeedrate { get; set; }
|
||||
|
||||
public TimeSpan PierceTime { get; set; }
|
||||
|
||||
public int PlateCount()
|
||||
{
|
||||
return Plates.Sum(plate => plate.Quantity);
|
||||
}
|
||||
|
||||
public int ProgramCount()
|
||||
{
|
||||
return Plates.Count;
|
||||
}
|
||||
|
||||
public double CutDistance()
|
||||
{
|
||||
return Drawings.Sum(dwg => dwg.CutDistance);
|
||||
}
|
||||
|
||||
public double ScribeDistance()
|
||||
{
|
||||
return Drawings.Sum(dwg => dwg.ScribeDistance);
|
||||
}
|
||||
|
||||
public double BevelDistance()
|
||||
{
|
||||
return Drawings.Sum(dwg => dwg.BevelDistance);
|
||||
}
|
||||
|
||||
public int TotalPierceCount()
|
||||
{
|
||||
return Drawings.Sum(dwg => dwg.PierceCount);
|
||||
}
|
||||
|
||||
public static Report Load(string nestFile)
|
||||
{
|
||||
var reader = new ReportReader();
|
||||
reader.Read(nestFile);
|
||||
return reader.Report;
|
||||
}
|
||||
|
||||
public static Report Load(Stream stream)
|
||||
{
|
||||
var reader = new ReportReader();
|
||||
reader.Read(stream);
|
||||
return reader.Report;
|
||||
}
|
||||
|
||||
public static bool TryLoad(string nestfile, out Report report)
|
||||
{
|
||||
try
|
||||
{
|
||||
report = Load(nestfile);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
report = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryLoad(Stream stream, out Report report)
|
||||
{
|
||||
try
|
||||
{
|
||||
report = Load(stream);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
report = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
PepLib.Core/RotationType.cs
Normal file
16
PepLib.Core/RotationType.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public enum RotationType
|
||||
{
|
||||
/// <summary>
|
||||
/// Clockwise
|
||||
/// </summary>
|
||||
CW,
|
||||
|
||||
/// <summary>
|
||||
/// Counter-Clockwise
|
||||
/// </summary>
|
||||
CCW
|
||||
}
|
||||
}
|
||||
45
PepLib.Core/Size.cs
Normal file
45
PepLib.Core/Size.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
namespace PepLib
|
||||
{
|
||||
public class Size
|
||||
{
|
||||
public Size(double height, double width)
|
||||
{
|
||||
Height = height;
|
||||
Width = width;
|
||||
}
|
||||
|
||||
public double Height { get; set; }
|
||||
|
||||
public double Width { get; set; }
|
||||
|
||||
public static Size Parse(string size)
|
||||
{
|
||||
var a = size.ToUpper().Split('X');
|
||||
|
||||
var height = double.Parse(a[0]);
|
||||
var width = double.Parse(a[1]);
|
||||
|
||||
return new Size(height, width);
|
||||
}
|
||||
|
||||
public static bool TryParse(string s, out Size size)
|
||||
{
|
||||
try
|
||||
{
|
||||
size = Parse(s);
|
||||
}
|
||||
catch
|
||||
{
|
||||
size = new Size(0, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} x {1}", Height, Width);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
PepLib.Core/Spacing.cs
Normal file
27
PepLib.Core/Spacing.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Spacing
|
||||
{
|
||||
public Spacing()
|
||||
: this(0, 0, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public Spacing(double l, double b, double r, double t)
|
||||
{
|
||||
Left = l;
|
||||
Bottom = b;
|
||||
Right = r;
|
||||
Top = t;
|
||||
}
|
||||
|
||||
public double Left { get; set; }
|
||||
|
||||
public double Bottom { get; set; }
|
||||
|
||||
public double Right { get; set; }
|
||||
|
||||
public double Top { get; set; }
|
||||
}
|
||||
}
|
||||
11
PepLib.Core/StatusType.cs
Normal file
11
PepLib.Core/StatusType.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public enum StatusType
|
||||
{
|
||||
ToBeCut,
|
||||
Quote,
|
||||
HasBeenCut,
|
||||
Temp
|
||||
}
|
||||
}
|
||||
14
PepLib.Core/Tolerance.cs
Normal file
14
PepLib.Core/Tolerance.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public static class Tolerance
|
||||
{
|
||||
public const double Epsilon = 0.0001;
|
||||
|
||||
public static bool IsEqualTo(this double a, double b, double tolerance = Epsilon)
|
||||
{
|
||||
return Math.Abs(b - a) <= tolerance;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
PepLib.Core/Util.cs
Normal file
32
PepLib.Core/Util.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public static class Util
|
||||
{
|
||||
public static string GetNestFileFormat(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
var name = Path.GetFileName(filename);
|
||||
var ext = Path.GetExtension(name);
|
||||
|
||||
if (name.LastIndexOf(ext) > 5 && !name.Contains("-"))
|
||||
name = name.Insert(5, "-");
|
||||
|
||||
if (name.LastIndexOf(ext) > 8 && char.IsLetter(name[8]))
|
||||
name = name.Remove(8, 1);
|
||||
|
||||
return Path.Combine(Path.GetDirectoryName(filename), name);
|
||||
}
|
||||
catch (SystemException ex)
|
||||
{
|
||||
Debug.WriteLine(ex.Message);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
124
PepLib.Core/Vector.cs
Normal file
124
PepLib.Core/Vector.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public struct Vector
|
||||
{
|
||||
public double X;
|
||||
public double Y;
|
||||
|
||||
public Vector(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public double DistanceTo(Vector pt)
|
||||
{
|
||||
double vx = pt.X - this.X;
|
||||
double vy = pt.Y - this.Y;
|
||||
|
||||
return Math.Sqrt(vx * vx + vy * vy);
|
||||
}
|
||||
|
||||
public double DistanceTo(double x, double y)
|
||||
{
|
||||
double vx = x - this.X;
|
||||
double vy = y - this.Y;
|
||||
|
||||
return Math.Sqrt(vx * vx + vy * vy);
|
||||
}
|
||||
|
||||
public double Angle()
|
||||
{
|
||||
return MathHelper.NormalizeAngleRad(Math.Atan2(Y, X));
|
||||
}
|
||||
|
||||
public double AngleTo(Vector pt)
|
||||
{
|
||||
return (pt - this).Angle();
|
||||
}
|
||||
|
||||
public double AngleFrom(Vector pt)
|
||||
{
|
||||
return (this - pt).Angle();
|
||||
}
|
||||
|
||||
public static Vector operator +(Vector pt1, Vector pt2)
|
||||
{
|
||||
return new Vector(pt1.X + pt2.X, pt1.Y + pt2.Y);
|
||||
}
|
||||
|
||||
public static Vector operator -(Vector pt1, Vector pt2)
|
||||
{
|
||||
return new Vector(pt1.X - pt2.X, pt1.Y - pt2.Y);
|
||||
}
|
||||
|
||||
public static Vector operator -(Vector pt)
|
||||
{
|
||||
return new Vector(-pt.X, -pt.Y);
|
||||
}
|
||||
|
||||
public static bool operator ==(Vector pt1, Vector pt2)
|
||||
{
|
||||
return pt1.DistanceTo(pt2) <= Tolerance.Epsilon;
|
||||
}
|
||||
|
||||
public static bool operator !=(Vector pt1, Vector pt2)
|
||||
{
|
||||
return !(pt1 == pt2);
|
||||
}
|
||||
|
||||
public Vector Rotate(double angle)
|
||||
{
|
||||
var v = new Vector();
|
||||
|
||||
double cos = Math.Cos(angle);
|
||||
double sin = Math.Sin(angle);
|
||||
|
||||
v.X = X * cos - Y * sin;
|
||||
v.Y = X * sin + Y * cos;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public Vector Rotate(double angle, Vector origin)
|
||||
{
|
||||
var v = new Vector();
|
||||
var pt = this - origin;
|
||||
|
||||
double cos = Math.Cos(angle);
|
||||
double sin = Math.Sin(angle);
|
||||
|
||||
v.X = pt.X * cos - pt.Y * sin + origin.X;
|
||||
v.Y = pt.X * sin + pt.Y * cos + origin.Y;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public Vector Clone()
|
||||
{
|
||||
return new Vector(X, Y);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is Vector))
|
||||
return false;
|
||||
|
||||
var pt = (Vector)obj;
|
||||
|
||||
return (X.IsEqualTo(pt.X)) && (Y.IsEqualTo(pt.Y));
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[Vector: X:{0}, Y:{1}]", X, Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
116
PepLib.Core/ZipHelper.cs
Normal file
116
PepLib.Core/ZipHelper.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using Ionic.Zip;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public static class ZipHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the files that match the specified pattern.
|
||||
/// </summary>
|
||||
/// <param name="file">Input zip file.</param>
|
||||
/// <param name="pattern">Pattern to match.</param>
|
||||
/// <param name="names">Names of the files that match the pattern.</param>
|
||||
/// <param name="streams">Data of the files that match the pattern.</param>
|
||||
/// <returns></returns>
|
||||
public static int ExtractByPattern(string file, string pattern, out string[] names, out Stream[] streams)
|
||||
{
|
||||
var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
|
||||
var zipStream = new ZipInputStream(fileStream);
|
||||
var nameList = new List<string>();
|
||||
var streamList = new List<Stream>();
|
||||
|
||||
ZipEntry theEntry;
|
||||
|
||||
while ((theEntry = zipStream.GetNextEntry()) != null)
|
||||
{
|
||||
if (!Regex.IsMatch(theEntry.FileName, pattern))
|
||||
continue;
|
||||
|
||||
nameList.Add(theEntry.FileName);
|
||||
|
||||
var memstream = new MemoryStream();
|
||||
var size = 2048;
|
||||
var data = new byte[size];
|
||||
|
||||
while (true)
|
||||
{
|
||||
size = zipStream.Read(data, 0, data.Length);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
memstream.Write(data, 0, size);
|
||||
memstream.Flush();
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
memstream.Seek(0, SeekOrigin.Begin);
|
||||
streamList.Add(memstream);
|
||||
}
|
||||
|
||||
zipStream.Close();
|
||||
|
||||
names = nameList.ToArray();
|
||||
streams = streamList.ToArray();
|
||||
|
||||
return streams.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the first file found that matches the specified file extension.
|
||||
/// </summary>
|
||||
/// <param name="file">Input zip file.</param>
|
||||
/// <param name="extension">Extension to match.</param>
|
||||
/// <param name="name">The name of the file that matches the file extension.</param>
|
||||
/// <param name="stream">The data of the file that matches the file extension.</param>
|
||||
/// <returns></returns>
|
||||
public static bool ExtractByExtension(string file, string extension, out string name, out Stream stream)
|
||||
{
|
||||
var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
|
||||
var zipStream = new ZipInputStream(fileStream);
|
||||
var memstream = new MemoryStream();
|
||||
|
||||
ZipEntry theEntry;
|
||||
|
||||
while ((theEntry = zipStream.GetNextEntry()) != null)
|
||||
{
|
||||
if (Path.GetExtension(theEntry.FileName) != extension)
|
||||
continue;
|
||||
|
||||
int size = 2048;
|
||||
var data = new byte[size];
|
||||
|
||||
while (true)
|
||||
{
|
||||
size = zipStream.Read(data, 0, data.Length);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
memstream.Write(data, 0, size);
|
||||
memstream.Flush();
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
zipStream.Close();
|
||||
memstream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
stream = memstream;
|
||||
name = theEntry.FileName;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
zipStream.Close();
|
||||
memstream.Close();
|
||||
|
||||
stream = null;
|
||||
name = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user