import 'package:uuid/uuid.dart'; /// Kitűzési pont állapota. enum StakeoutStatus { pending, staked, skipped } /// Kitűzendő pont — szeizmikus line/station modellel. /// /// A pont természetes azonosítója a (lineId, station) páros. A rekord a /// TERV-koordinátákat ÉS a kitűzéskori MÉRT pozíciót is tárolja, az /// inline/crossline eltérésekkel együtt — így az export nemcsak azt /// dokumentálja, MIT tűztünk ki, hanem azt is, MILYEN pontossággal. /// /// A séma szinkron-kész (uuid, updated_at, deleted_at, sync_status, /// created_by, device_id) — a Supabase-oldal a 4. ütemben épül rá. class StakeoutPoint { final int? id; final String uuid; final int projectId; // ── Identitás ──────────────────────────────────────────────────── final String lineId; // szeizmikus vonal azonosító ('' = vonal nélküli) final int station; // numerikus állomásszám (kötelező!) final String name; // megjelenítendő név (alapból a station szövege) final String pointType; // geofon / forras / egyeb — SPS-re előkészítve final String source; // csv / geojson / supabase / offset / kezi // ── Terv-koordináták (mindkét rendszerben tárolva) ─────────────── final double planEovY; final double planEovX; final double? planEovZ; final double planLat; final double planLon; // ── Állapot + mért adatok ──────────────────────────────────────── final StakeoutStatus status; final double? measuredEovY; final double? measuredEovX; final double? measuredEovZ; final double? measuredLat; final double? measuredLon; final double? devInline; // vonal menti eltérés (m, + = station-növekedés felé) final double? devCrossline; // vonalra merőleges eltérés (m, + = jobbra) final double? devDz; // magassági eltérés (m, terv − mért) final int? fixQuality; // GGA quality tároláskor (4 = RTK fixed) final double? accuracy; // vízszintes hiba tároláskor (m) final double? tiltDeg; // rúd-dőlés tároláskor (később: libella-modul) final DateTime? stakedAt; // ── Eltolt (transzverzális) pont ───────────────────────────────── final bool isOffset; final String? parentUuid; // az eredeti tervpont uuid-ja final double? offsetDist; // eltolás nagysága (m) final double? offsetBearing; // eltolás iránya (fok, EOV-észak = 0) // ── Szinkron / audit ───────────────────────────────────────────── final String? createdBy; final String? deviceId; final DateTime createdAt; final DateTime updatedAt; final DateTime? deletedAt; final String syncStatus; StakeoutPoint({ this.id, String? uuid, required this.projectId, this.lineId = '', required this.station, String? name, this.pointType = 'geofon', this.source = 'csv', required this.planEovY, required this.planEovX, this.planEovZ, required this.planLat, required this.planLon, this.status = StakeoutStatus.pending, this.measuredEovY, this.measuredEovX, this.measuredEovZ, this.measuredLat, this.measuredLon, this.devInline, this.devCrossline, this.devDz, this.fixQuality, this.accuracy, this.tiltDeg, this.stakedAt, this.isOffset = false, this.parentUuid, this.offsetDist, this.offsetBearing, this.createdBy, this.deviceId, DateTime? createdAt, DateTime? updatedAt, this.deletedAt, this.syncStatus = 'pending', }) : uuid = uuid ?? const Uuid().v4(), name = name ?? station.toString(), createdAt = createdAt ?? DateTime.now(), updatedAt = updatedAt ?? DateTime.now(); /// Teljes azonosító megjelenítésre: "L1024 · 105" vagy csak "105". String get displayId => lineId.isEmpty ? name : '$lineId · $name'; StakeoutPoint copyWith({ int? id, StakeoutStatus? status, double? measuredEovY, double? measuredEovX, double? measuredEovZ, double? measuredLat, double? measuredLon, double? devInline, double? devCrossline, double? devDz, int? fixQuality, double? accuracy, double? tiltDeg, DateTime? stakedAt, DateTime? updatedAt, String? syncStatus, }) { return StakeoutPoint( id: id ?? this.id, uuid: uuid, projectId: projectId, lineId: lineId, station: station, name: name, pointType: pointType, source: source, planEovY: planEovY, planEovX: planEovX, planEovZ: planEovZ, planLat: planLat, planLon: planLon, status: status ?? this.status, measuredEovY: measuredEovY ?? this.measuredEovY, measuredEovX: measuredEovX ?? this.measuredEovX, measuredEovZ: measuredEovZ ?? this.measuredEovZ, measuredLat: measuredLat ?? this.measuredLat, measuredLon: measuredLon ?? this.measuredLon, devInline: devInline ?? this.devInline, devCrossline: devCrossline ?? this.devCrossline, devDz: devDz ?? this.devDz, fixQuality: fixQuality ?? this.fixQuality, accuracy: accuracy ?? this.accuracy, tiltDeg: tiltDeg ?? this.tiltDeg, stakedAt: stakedAt ?? this.stakedAt, isOffset: isOffset, parentUuid: parentUuid, offsetDist: offsetDist, offsetBearing: offsetBearing, createdBy: createdBy, deviceId: deviceId, createdAt: createdAt, updatedAt: updatedAt ?? DateTime.now(), deletedAt: deletedAt, syncStatus: syncStatus ?? 'pending', ); } Map toMap() => { if (id != null) 'id': id, 'uuid': uuid, 'project_id': projectId, 'line_id': lineId, 'station': station, 'name': name, 'point_type': pointType, 'source': source, 'plan_eov_y': planEovY, 'plan_eov_x': planEovX, 'plan_eov_z': planEovZ, 'plan_lat': planLat, 'plan_lon': planLon, 'status': status.name, 'measured_eov_y': measuredEovY, 'measured_eov_x': measuredEovX, 'measured_eov_z': measuredEovZ, 'measured_lat': measuredLat, 'measured_lon': measuredLon, 'dev_inline': devInline, 'dev_crossline': devCrossline, 'dev_dz': devDz, 'fix_quality': fixQuality, 'accuracy': accuracy, 'tilt_deg': tiltDeg, 'staked_at': stakedAt?.toIso8601String(), 'is_offset': isOffset ? 1 : 0, 'parent_uuid': parentUuid, 'offset_dist': offsetDist, 'offset_bearing': offsetBearing, 'created_by': createdBy, 'device_id': deviceId, 'created_at': createdAt.toIso8601String(), 'updated_at': updatedAt.toIso8601String(), 'deleted_at': deletedAt?.toIso8601String(), 'sync_status': syncStatus, }; factory StakeoutPoint.fromMap(Map m) => StakeoutPoint( id: m['id'] as int?, uuid: m['uuid'] as String, projectId: m['project_id'] as int, lineId: (m['line_id'] as String?) ?? '', station: m['station'] as int, name: (m['name'] as String?) ?? '${m['station']}', pointType: (m['point_type'] as String?) ?? 'geofon', source: (m['source'] as String?) ?? 'csv', planEovY: (m['plan_eov_y'] as num).toDouble(), planEovX: (m['plan_eov_x'] as num).toDouble(), planEovZ: (m['plan_eov_z'] as num?)?.toDouble(), planLat: (m['plan_lat'] as num).toDouble(), planLon: (m['plan_lon'] as num).toDouble(), status: StakeoutStatus.values.firstWhere((s) => s.name == m['status'], orElse: () => StakeoutStatus.pending), measuredEovY: (m['measured_eov_y'] as num?)?.toDouble(), measuredEovX: (m['measured_eov_x'] as num?)?.toDouble(), measuredEovZ: (m['measured_eov_z'] as num?)?.toDouble(), measuredLat: (m['measured_lat'] as num?)?.toDouble(), measuredLon: (m['measured_lon'] as num?)?.toDouble(), devInline: (m['dev_inline'] as num?)?.toDouble(), devCrossline: (m['dev_crossline'] as num?)?.toDouble(), devDz: (m['dev_dz'] as num?)?.toDouble(), fixQuality: m['fix_quality'] as int?, accuracy: (m['accuracy'] as num?)?.toDouble(), tiltDeg: (m['tilt_deg'] as num?)?.toDouble(), stakedAt: m['staked_at'] != null ? DateTime.tryParse(m['staked_at'] as String) : null, isOffset: (m['is_offset'] as int? ?? 0) == 1, parentUuid: m['parent_uuid'] as String?, offsetDist: (m['offset_dist'] as num?)?.toDouble(), offsetBearing: (m['offset_bearing'] as num?)?.toDouble(), createdBy: m['created_by'] as String?, deviceId: m['device_id'] as String?, createdAt: DateTime.tryParse((m['created_at'] as String?) ?? '') ?? DateTime.now(), updatedAt: DateTime.tryParse((m['updated_at'] as String?) ?? '') ?? DateTime.now(), deletedAt: m['deleted_at'] != null ? DateTime.tryParse(m['deleted_at'] as String) : null, syncStatus: (m['sync_status'] as String?) ?? 'pending', ); }