feat(back-end): db connections implemented and created users

This commit is contained in:
2026-02-11 14:53:46 +01:00
parent e5183590c5
commit 8fac8ac892
11 changed files with 225 additions and 99 deletions

View File

@@ -1,11 +0,0 @@
package com.printcalculator.model;
import java.math.BigDecimal;
public record CostBreakdown(
BigDecimal materialCost,
BigDecimal machineCost,
BigDecimal energyCost,
BigDecimal subtotal,
BigDecimal markup
) {}

View File

@@ -1,27 +1,15 @@
package com.printcalculator.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.List;
public class QuoteResult {
private double totalPrice;
private String currency;
private PrintStats stats;
@JsonIgnore
private CostBreakdown breakdown;
@JsonIgnore
private List<String> notes;
private double setupCost;
public QuoteResult(double totalPrice, String currency, PrintStats stats, CostBreakdown breakdown, List<String> notes, double setupCost) {
public QuoteResult(double totalPrice, String currency, PrintStats stats, double setupCost) {
this.totalPrice = totalPrice;
this.currency = currency;
this.stats = stats;
this.breakdown = breakdown;
this.notes = notes;
this.setupCost = setupCost;
}
@@ -36,14 +24,6 @@ public class QuoteResult {
public PrintStats getStats() {
return stats;
}
public CostBreakdown getBreakdown() {
return breakdown;
}
public List<String> getNotes() {
return notes;
}
public double getSetupCost() {
return setupCost;

View File

@@ -17,7 +17,15 @@ public class GCodeParser {
// ; estimated printing time = 1h 2m 3s
// ; filament used [g] = 12.34
// ; filament used [mm] = 1234.56
private static final Pattern TIME_PATTERN = Pattern.compile(";\\s*estimated printing time.*=\\s*(.*)", Pattern.CASE_INSENSITIVE);
private static final Pattern TOTAL_ESTIMATED_TIME_PATTERN = Pattern.compile(
";\\s*.*total\\s+estimated\\s+time\\s*[:=]\\s*([^;]+)",
Pattern.CASE_INSENSITIVE);
private static final Pattern MODEL_PRINTING_TIME_PATTERN = Pattern.compile(
";\\s*.*model\\s+printing\\s+time\\s*[:=]\\s*([^;]+)",
Pattern.CASE_INSENSITIVE);
private static final Pattern TIME_PATTERN = Pattern.compile(
";\\s*(?:estimated\\s+printing\\s+time|estimated\\s+print\\s+time|print\\s+time).*[:=]\\s*(.*)",
Pattern.CASE_INSENSITIVE);
private static final Pattern FILAMENT_G_PATTERN = Pattern.compile(";\\s*filament used \\[g\\]\\s*=\\s*(.*)");
private static final Pattern FILAMENT_MM_PATTERN = Pattern.compile(";\\s*filament used \\[mm\\]\\s*=\\s*(.*)");
@@ -43,6 +51,22 @@ public class GCodeParser {
System.out.println("DEBUG: Found potential time line: '" + line + "'");
}
Matcher totalTimeMatcher = TOTAL_ESTIMATED_TIME_PATTERN.matcher(line);
if (totalTimeMatcher.find()) {
timeFormatted = totalTimeMatcher.group(1).trim();
seconds = parseTimeString(timeFormatted);
System.out.println("GCodeParser: Found total estimated time: " + timeFormatted + " (" + seconds + "s)");
continue;
}
Matcher modelTimeMatcher = MODEL_PRINTING_TIME_PATTERN.matcher(line);
if (modelTimeMatcher.find()) {
timeFormatted = modelTimeMatcher.group(1).trim();
seconds = parseTimeString(timeFormatted);
System.out.println("GCodeParser: Found model printing time: " + timeFormatted + " (" + seconds + "s)");
continue;
}
Matcher timeMatcher = TIME_PATTERN.matcher(line);
if (timeMatcher.find()) {
timeFormatted = timeMatcher.group(1).trim();
@@ -72,21 +96,60 @@ public class GCodeParser {
}
private long parseTimeString(String timeStr) {
// Formats: "1d 2h 3m 4s" or "1h 20m 10s"
long totalSeconds = 0;
Matcher d = Pattern.compile("(\\d+)d").matcher(timeStr);
if (d.find()) totalSeconds += Long.parseLong(d.group(1)) * 86400;
// Formats: "1d 2h 3m 4s", "1h 20m 10s", "01:23:45", "12:34"
String lower = timeStr.toLowerCase();
double totalSeconds = 0;
boolean matched = false;
Matcher h = Pattern.compile("(\\d+)h").matcher(timeStr);
if (h.find()) totalSeconds += Long.parseLong(h.group(1)) * 3600;
Matcher d = Pattern.compile("(\\d+(?:\\.\\d+)?)\\s*d").matcher(lower);
if (d.find()) {
totalSeconds += Double.parseDouble(d.group(1)) * 86400;
matched = true;
}
Matcher m = Pattern.compile("(\\d+)m").matcher(timeStr);
if (m.find()) totalSeconds += Long.parseLong(m.group(1)) * 60;
Matcher h = Pattern.compile("(\\d+(?:\\.\\d+)?)\\s*h").matcher(lower);
if (h.find()) {
totalSeconds += Double.parseDouble(h.group(1)) * 3600;
matched = true;
}
Matcher s = Pattern.compile("(\\d+)s").matcher(timeStr);
if (s.find()) totalSeconds += Long.parseLong(s.group(1));
Matcher m = Pattern.compile("(\\d+(?:\\.\\d+)?)\\s*m").matcher(lower);
if (m.find()) {
totalSeconds += Double.parseDouble(m.group(1)) * 60;
matched = true;
}
return totalSeconds;
Matcher s = Pattern.compile("(\\d+(?:\\.\\d+)?)\\s*s").matcher(lower);
if (s.find()) {
totalSeconds += Double.parseDouble(s.group(1));
matched = true;
}
if (matched) {
return Math.round(totalSeconds);
}
long daySeconds = 0;
Matcher dayPrefix = Pattern.compile("(\\d+)\\s*d").matcher(lower);
if (dayPrefix.find()) {
daySeconds = Long.parseLong(dayPrefix.group(1)) * 86400;
}
Matcher hms = Pattern.compile("(\\d{1,2}):(\\d{2}):(\\d{2})").matcher(lower);
if (hms.find()) {
long hours = Long.parseLong(hms.group(1));
long minutes = Long.parseLong(hms.group(2));
long seconds = Long.parseLong(hms.group(3));
return daySeconds + hours * 3600 + minutes * 60 + seconds;
}
Matcher ms = Pattern.compile("(\\d{1,2}):(\\d{2})").matcher(lower);
if (ms.find()) {
long minutes = Long.parseLong(ms.group(1));
long seconds = Long.parseLong(ms.group(2));
return daySeconds + minutes * 60 + seconds;
}
return 0;
}
}

View File

@@ -6,7 +6,6 @@ import com.printcalculator.entity.FilamentVariant;
import com.printcalculator.entity.PricingPolicy;
import com.printcalculator.entity.PricingPolicyMachineHourTier;
import com.printcalculator.entity.PrinterMachine;
import com.printcalculator.model.CostBreakdown;
import com.printcalculator.model.PrintStats;
import com.printcalculator.model.QuoteResult;
import com.printcalculator.repository.FilamentMaterialTypeRepository;
@@ -18,10 +17,7 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
@Service
public class QuoteCalculator {
@@ -101,22 +97,7 @@ public class QuoteCalculator {
BigDecimal markupFactor = BigDecimal.ONE.add(policy.getMarkupPercent().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP));
BigDecimal totalPrice = subtotal.multiply(markupFactor).setScale(2, RoundingMode.HALF_UP);
BigDecimal markupAmount = totalPrice.subtract(subtotal);
CostBreakdown breakdown = new CostBreakdown(
materialCost.setScale(2, RoundingMode.HALF_UP),
machineCost.setScale(2, RoundingMode.HALF_UP),
energyCost.setScale(2, RoundingMode.HALF_UP),
subtotal.setScale(2, RoundingMode.HALF_UP),
markupAmount.setScale(2, RoundingMode.HALF_UP)
);
List<String> notes = new ArrayList<>();
notes.add("Policy: " + policy.getPolicyName());
notes.add("Machine: " + machine.getPrinterDisplayName());
notes.add("Material: " + variant.getVariantDisplayName());
return new QuoteResult(totalPrice.doubleValue(), "CHF", stats, breakdown, notes, fixedFee.doubleValue());
return new QuoteResult(totalPrice.doubleValue(), "CHF", stats, fixedFee.doubleValue());
}
private BigDecimal calculateMachineCost(PricingPolicy policy, BigDecimal hours) {

View File

@@ -74,4 +74,40 @@ class GCodeParserTest {
tempFile.delete();
}
@Test
void parse_colonFormattedTime_returnsCorrectStats() throws IOException {
File tempFile = File.createTempFile("test_colon", ".gcode");
try (FileWriter writer = new FileWriter(tempFile)) {
writer.write("; generated by OrcaSlicer\n");
writer.write("; print time: 01:02:03\n");
writer.write("; filament used [g] = 7.5\n");
}
GCodeParser parser = new GCodeParser();
PrintStats stats = parser.parse(tempFile);
assertEquals(3723L, stats.printTimeSeconds());
assertEquals("01:02:03", stats.printTimeFormatted());
tempFile.delete();
}
@Test
void parse_totalEstimatedTimeInline_returnsCorrectStats() throws IOException {
File tempFile = File.createTempFile("test_total", ".gcode");
try (FileWriter writer = new FileWriter(tempFile)) {
writer.write("; generated by OrcaSlicer\n");
writer.write("; model printing time: 5m 17s; total estimated time: 5m 21s\n");
writer.write("; filament used [g] = 2.0\n");
}
GCodeParser parser = new GCodeParser();
PrintStats stats = parser.parse(tempFile);
assertEquals(321L, stats.printTimeSeconds());
assertEquals("5m 21s", stats.printTimeFormatted());
tempFile.delete();
}
}