Initial commit for first version of project

This commit is contained in:
Dennis Nemec
2026-09-02 20:54:36 +02:00
parent 3d9f1ab6bc
commit 992bb32025
56 changed files with 5139 additions and 31 deletions

View File

@ -0,0 +1,81 @@
//
// Project.swift
// GasTankAR
//
// Created by Dennis Nemec on 25.08.26.
//
import Foundation
import SwiftData
import ARKit
@Model
final class Project {
/// Identifier given by the user for the project. In DOCUframe terms
/// it is the LeadID.
var leadID: String
/// Customer name to link the project to.
var customerName: String
var creationDate: Date
/// Der für das Projekt ausgewählte Tank. Jedes Projekt hat genau einen Tank.
/// `Tank` ist `Codable`, daher persistiert SwiftData das direkt als Attribut.
var tank: Tank
/// Archivierte `ARWorldMap` (via `NSKeyedArchiver`). Wegen der Größe extern gespeichert.
@Attribute(.externalStorage) var worldMapData: Data?
/// Welt-Transform des platzierten Tanks (Position, Rotation, Skalierung) als
/// 16 Floats (spaltenweise). Zusammen mit der WorldMap wird der Tank so wiederhergestellt.
var tankTransform: [Float]?
/// Im AR-Modus aufgenommene Fotos. Werden beim Löschen des Projekts mitentfernt.
@Relationship(deleteRule: .cascade, inverse: \ProjectPhoto.project)
var photos: [ProjectPhoto] = []
init(
leadID: String,
customerName: String,
creationDate: Date,
tank: Tank = Tank(),
worldMapData: Data? = nil,
tankTransform: [Float]? = nil
) {
self.leadID = leadID
self.customerName = customerName
self.creationDate = creationDate
self.tank = tank
self.worldMapData = worldMapData
self.tankTransform = tankTransform
}
/// Human-readable title combining the lead identifier and customer name.
var title: String {
"\(leadID) – \(customerName)"
}
/// Up to two uppercased initials derived from the customer name, for use as an avatar.
var initials: String {
let letters = customerName
.split(whereSeparator: { $0 == " " || $0 == "&" })
.prefix(2)
.compactMap { $0.first }
return String(letters).uppercased()
}
/// Gespeicherte Session der getrackten Welt. (De-)serialisiert `worldMapData`.
/// Berechnete Property – wird von SwiftData nicht persistiert.
var worldMap: ARWorldMap? {
get {
guard let worldMapData else { return nil }
return try? NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: worldMapData)
}
set {
worldMapData = newValue.flatMap {
try? NSKeyedArchiver.archivedData(withRootObject: $0, requiringSecureCoding: true)
}
}
}
}