feat: integrate CocoaPods for macos tactical app and update environment configurations
This commit is contained in:
+129
-104
@@ -70,7 +70,8 @@ export class MapsService {
|
||||
profile: profile,
|
||||
locale: locale === 'en' ? 'ar' : locale, // Default to Arabic if not specified or fallback
|
||||
calc_points: true,
|
||||
points_encoded: true,
|
||||
points_encoded: false, // JSON arrays for reliable 3D elevation (SRTM)
|
||||
elevation: true, // ← SRTM: طلب إحداثيات 3D [lng, lat, elevation] + ascend/descend
|
||||
instructions: steps || true, // Always request instructions to extract route name
|
||||
};
|
||||
|
||||
@@ -160,7 +161,8 @@ export class MapsService {
|
||||
const hr = now.getHours();
|
||||
const dow = now.getDay();
|
||||
|
||||
const coords = this.decodePolyline(route.points);
|
||||
const coords3D = this.extractCoords3D(route.points);
|
||||
const coords: [number, number][] = coords3D.map(c => [c[0], c[1]]); // 2D for traffic grid
|
||||
const trafficFactor = this.trafficGrid.getTrafficFactor(coords, hr, dow);
|
||||
|
||||
const baseDuration = route.time / 1000;
|
||||
@@ -172,7 +174,8 @@ export class MapsService {
|
||||
|
||||
// Process all paths to add metadata (Real Street Names, Tags, Elevation & Slope Warnings, Eco/Fuel metrics)
|
||||
const processedPaths = paths.map((p: any, index: number) => {
|
||||
const pCoords = this.decodePolyline(p.points);
|
||||
const pCoords3D = this.extractCoords3D(p.points);
|
||||
const pCoords: [number, number][] = pCoords3D.map(c => [c[0], c[1]]); // 2D for traffic grid
|
||||
const pTrafficFactor = this.trafficGrid.getTrafficFactor(pCoords, hr, dow);
|
||||
const pBaseDuration = p.time / 1000;
|
||||
const pDuration = Math.round(pBaseDuration * pTrafficFactor);
|
||||
@@ -196,8 +199,12 @@ export class MapsService {
|
||||
finalRouteName = index === 0 ? 'المسار المباشر الأسرع' : 'مسار بديل عبر الطرق الموازية';
|
||||
}
|
||||
|
||||
// Analyze slopes and enrich instructions
|
||||
const { enrichedInstructions, slopeSummary } = this.enrichInstructionsWithSlopeAnalysis(p.instructions, pCoords);
|
||||
// Analyze slopes using REAL 3D elevation from SRTM satellite data
|
||||
const { enrichedInstructions, slopeSummary } = this.enrichInstructionsWithSlopeAnalysis(p.instructions, pCoords3D);
|
||||
|
||||
// Override with GraphHopper's authoritative SRTM ascend/descend values when available
|
||||
if (typeof p.ascend === 'number') slopeSummary.totalAscentMeters = Math.round(p.ascend);
|
||||
if (typeof p.descend === 'number') slopeSummary.totalDescentMeters = Math.round(p.descend);
|
||||
|
||||
// Calculate Energy, Fuel Consumption & Eco Cost (combining Distance + Ascent/Descent Physics + Traffic/Time Delays)
|
||||
const ecoMetrics = this.calculateEcoAndFuelMetrics(
|
||||
@@ -229,7 +236,8 @@ export class MapsService {
|
||||
tags,
|
||||
distance: p.distance,
|
||||
duration: pDuration,
|
||||
points: p.points,
|
||||
// Return standard Google-encoded Polyline string
|
||||
points: this.encodePolyline(pCoords3D.map(c => [c[0], c[1]])),
|
||||
bbox: p.bbox,
|
||||
instructions: steps ? enrichedInstructions : undefined,
|
||||
elevationSummary: slopeSummary,
|
||||
@@ -290,16 +298,27 @@ export class MapsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enriches turn-by-turn routing instructions with steep slope / incline warnings
|
||||
* Enriches turn-by-turn routing instructions with calibrated slope / incline warnings.
|
||||
* Uses smoothed REAL SRTM 3D elevation data to eliminate raster quantization noise.
|
||||
*/
|
||||
private enrichInstructionsWithSlopeAnalysis(instructions: any[], coords: [number, number][]) {
|
||||
if (!instructions || !coords || coords.length < 2) {
|
||||
private enrichInstructionsWithSlopeAnalysis(instructions: any[], rawCoords3D: [number, number, number][]) {
|
||||
if (!instructions || !rawCoords3D || rawCoords3D.length < 2) {
|
||||
return {
|
||||
enrichedInstructions: instructions,
|
||||
slopeSummary: { totalAscentMeters: 0, totalDescentMeters: 0, maxInclinePercent: 0, maxDeclinePercent: 0, steepWarningsCount: 0, steepWarnings: [] }
|
||||
};
|
||||
}
|
||||
|
||||
// 1. Apply Gaussian/Weighted 3-point smoothing on elevation to remove SRTM 30m grid noise
|
||||
const coords3D: [number, number, number][] = rawCoords3D.map((pt, i, arr) => {
|
||||
if (i === 0 || i === arr.length - 1) return pt;
|
||||
const prev = arr[i - 1][2];
|
||||
const curr = pt[2];
|
||||
const next = arr[i + 1][2];
|
||||
const smoothedEle = (prev + 2 * curr + next) / 4;
|
||||
return [pt[0], pt[1], smoothedEle];
|
||||
});
|
||||
|
||||
let totalAscent = 0;
|
||||
let totalDescent = 0;
|
||||
let maxInclinePercent = 0;
|
||||
@@ -308,44 +327,63 @@ export class MapsService {
|
||||
|
||||
const enrichedInstructions = instructions.map((inst: any) => {
|
||||
const interval = inst.interval || [0, 0];
|
||||
const startIdx = Math.min(interval[0], coords.length - 1);
|
||||
const endIdx = Math.min(interval[1], coords.length - 1);
|
||||
const startIdx = Math.min(interval[0], coords3D.length - 1);
|
||||
const endIdx = Math.min(interval[1], coords3D.length - 1);
|
||||
|
||||
// 1. Localize text into 100% fluent Arabic
|
||||
// Localize text into 100% fluent Arabic
|
||||
const localizedBaseText = this.localizeInstructionToArabic(inst.text);
|
||||
|
||||
if (startIdx < endIdx) {
|
||||
const c1 = coords[startIdx];
|
||||
const c2 = coords[endIdx];
|
||||
const e1 = this.estimateElevation(c1[1], c1[0]);
|
||||
const e2 = this.estimateElevation(c2[1], c2[0]);
|
||||
const elevDiff = e2 - e1;
|
||||
const dist = Math.max(30, inst.distance || this.haversineDistance(c1[1], c1[0], c2[1], c2[0]) || 1);
|
||||
// Walk segments within this instruction with noise threshold (>= 0.8m)
|
||||
let stepAscent = 0;
|
||||
let stepDescent = 0;
|
||||
for (let i = startIdx; i < endIdx; i++) {
|
||||
const eDiff = coords3D[i + 1][2] - coords3D[i][2];
|
||||
if (eDiff >= 0.8) stepAscent += eDiff;
|
||||
else if (eDiff <= -0.8) stepDescent += Math.abs(eDiff);
|
||||
}
|
||||
|
||||
if (elevDiff > 0.3) totalAscent += elevDiff;
|
||||
else if (elevDiff < -0.3) totalDescent += Math.abs(elevDiff);
|
||||
totalAscent += stepAscent;
|
||||
totalDescent += stepDescent;
|
||||
|
||||
// Grade percentage: (rise / run) * 100
|
||||
const rawSlope = (elevDiff / dist) * 100;
|
||||
const slopePercent = Math.max(-16, Math.min(16, Math.round(rawSlope)));
|
||||
// Net elevation change for this instruction
|
||||
const netElevDiff = coords3D[endIdx][2] - coords3D[startIdx][2];
|
||||
const dist = Math.max(30, inst.distance || 1);
|
||||
|
||||
// Grade percentage: (net rise / run) * 100
|
||||
const rawSlope = (netElevDiff / dist) * 100;
|
||||
const clampedRaw = Math.max(-16, Math.min(16, Math.round(rawSlope)));
|
||||
|
||||
// Dampen slope severity by 3% as requested (e.g. 13% -> 10%, -13% -> -10%)
|
||||
let slopePercent = 0;
|
||||
if (clampedRaw > 0) {
|
||||
slopePercent = Math.max(0, clampedRaw - 3);
|
||||
} else if (clampedRaw < 0) {
|
||||
slopePercent = Math.min(0, clampedRaw + 3);
|
||||
}
|
||||
|
||||
if (slopePercent > maxInclinePercent) maxInclinePercent = slopePercent;
|
||||
if (slopePercent < maxDeclinePercent) maxDeclinePercent = slopePercent;
|
||||
|
||||
// Warning only for steep grades (6% or higher is standard civil road warning threshold)
|
||||
// Civil road standard: warnings apply to meaningful, sustained grades
|
||||
// (Distance >= 100m OR significant vertical change >= 12m)
|
||||
const isSustainedSegment = dist >= 100 || Math.abs(netElevDiff) >= 12;
|
||||
let warning_ar: string | null = null;
|
||||
if (slopePercent >= 6) {
|
||||
warning_ar = `⚠️ تنبيه: صعود حاد (+${slopePercent}%)`;
|
||||
steepWarnings.push({ text: localizedBaseText, slopePercent, type: 'incline', street: inst.street_name });
|
||||
} else if (slopePercent <= -6) {
|
||||
warning_ar = `⚠️ تنبيه: منحدر شديد (${slopePercent}%) - خفف السرعة`;
|
||||
steepWarnings.push({ text: localizedBaseText, slopePercent, type: 'decline', street: inst.street_name });
|
||||
|
||||
if (isSustainedSegment) {
|
||||
if (slopePercent >= 8) {
|
||||
warning_ar = `⚠️ تنبيه: صعود حاد (+${slopePercent}%)`;
|
||||
steepWarnings.push({ text: localizedBaseText, slopePercent, type: 'incline', street: inst.street_name });
|
||||
} else if (slopePercent <= -8) {
|
||||
warning_ar = `⚠️ تنبيه: منحدر شديد (${slopePercent}%) - خفف السرعة`;
|
||||
steepWarnings.push({ text: localizedBaseText, slopePercent, type: 'decline', street: inst.street_name });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...inst,
|
||||
slopePercent,
|
||||
elevationChangeMeters: Math.round(elevDiff),
|
||||
elevationChangeMeters: Math.round(netElevDiff),
|
||||
slopeWarning: warning_ar || undefined,
|
||||
text: warning_ar ? `${localizedBaseText} (${warning_ar})` : localizedBaseText
|
||||
};
|
||||
@@ -597,72 +635,7 @@ export class MapsService {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Universal Analytical Topographic Digital Elevation Model (DEM) for the Entire Map of Jordan.
|
||||
* Continuous, seamless mathematical surface modeling all provinces, mountain crests, valleys, and plateaus.
|
||||
*/
|
||||
private estimateElevation(lat: number, lng: number): number {
|
||||
// 1. Boundary guard (default fallback for global coordinates outside Jordan)
|
||||
if (lat < 29.0 || lat > 33.5 || lng < 34.5 || lng > 39.5) {
|
||||
return 700;
|
||||
}
|
||||
|
||||
// 2. Rift Valley Axis (Wadi Araba, Dead Sea, Jordan Valley)
|
||||
// The rift axis runs along a slightly tilted meridian (Lng ~35.56 in North, ~35.00 in South)
|
||||
const riftLng = 35.00 + (lat - 29.5) * (35.56 - 35.00) / (33.0 - 29.5);
|
||||
const distFromRiftLng = lng - riftLng; // Negative = West of rift, Positive = East of rift
|
||||
|
||||
// Elevation along the Rift Valley floor
|
||||
let riftFloorElev: number;
|
||||
if (lat >= 32.7) riftFloorElev = -200 + (lat - 32.7) * 200; // Sea of Galilee / Yarmouk (-200m to 0m)
|
||||
else if (lat >= 31.5) riftFloorElev = -430 + Math.pow((lat - 31.5) / 1.2, 2) * 230; // Dead Sea to Deir Alla (-430m to -200m)
|
||||
else if (lat >= 30.5) riftFloorElev = -430 + (31.5 - lat) * 450; // Dead Sea south to Gharandal (-430m to +20m)
|
||||
else riftFloorElev = 20 + (lat - 29.5) * 80; // Wadi Araba to Aqaba (+20m to +100m)
|
||||
|
||||
// Crest Elevation of the Eastern Mountain Ridge (Ajloun -> Balqa -> Karak -> Tafila -> Shobak -> Ras En Naqb)
|
||||
let highlandCrestElev: number;
|
||||
const crestDistanceDeg = 0.28; // Distance in degrees from Rift axis to the mountain crest (~28 km)
|
||||
if (lat >= 32.2) highlandCrestElev = 1050 + (lat - 32.2) * 100; // Ajloun / Jerash (1050m - 1200m)
|
||||
else if (lat >= 31.8) highlandCrestElev = 980 + (lat - 31.8) * 150; // Salt / West Amman (980m - 1040m)
|
||||
else if (lat >= 31.3) highlandCrestElev = 820 + (lat - 31.3) * 200; // Madaba / Central (820m - 920m)
|
||||
else if (lat >= 30.7) highlandCrestElev = 1100 + (31.3 - lat) * 400; // Karak / Tafila (1100m - 1340m)
|
||||
else if (lat >= 29.9) highlandCrestElev = 1450 + (30.7 - lat) * 150; // Dana / Shobak / Ras En Naqb (1450m - 1570m)
|
||||
else highlandCrestElev = 850 - (29.9 - lat) * 800; // Drop to Aqaba Mountains
|
||||
|
||||
// 3. Physical Cross-Section Profile across Jordan (East-West Topography)
|
||||
let elev: number;
|
||||
if (distFromRiftLng <= 0) {
|
||||
// In the Rift or Western escarpment
|
||||
const wFraction = Math.min(1, Math.abs(distFromRiftLng) / 0.15);
|
||||
elev = riftFloorElev + (700 - riftFloorElev) * (wFraction * wFraction);
|
||||
} else if (distFromRiftLng <= crestDistanceDeg) {
|
||||
// Steep ascent from Rift Valley floor to Mountain Crest
|
||||
const ascentFraction = distFromRiftLng / crestDistanceDeg; // 0 (Rift) -> 1 (Mountain Crest)
|
||||
// S-curve steep escarpment (Sigmoid transition)
|
||||
const sCurve = Math.sin((ascentFraction - 0.5) * Math.PI) * 0.5 + 0.5;
|
||||
elev = riftFloorElev + (highlandCrestElev - riftFloorElev) * sCurve;
|
||||
} else {
|
||||
// East of Mountain Crest: Gentle slope down into the Eastern Plateaus and Basins
|
||||
const eastDistDeg = distFromRiftLng - crestDistanceDeg;
|
||||
let easternBasePlateau = 680;
|
||||
if (lat >= 32.4) easternBasePlateau = 560; // Irbid / Ramtha Plateau
|
||||
else if (lat >= 31.9) easternBasePlateau = 580; // Amman East / Zarqa Basin
|
||||
else if (lat >= 31.4) easternBasePlateau = 720; // Airport / Qatranah
|
||||
else easternBasePlateau = 850; // Maan / Southern Desert Plateau
|
||||
|
||||
// Decay from Mountain Crest towards Eastern Base Plateau
|
||||
const plateauDecay = Math.exp(-eastDistDeg / 0.35);
|
||||
elev = easternBasePlateau + (highlandCrestElev - easternBasePlateau) * plateauDecay;
|
||||
|
||||
// Eastern Desert Azraq depression (Lng 36.8, Lat 31.8)
|
||||
const azraqDist = Math.hypot((lat - 31.83) * 1.1, (lng - 36.82));
|
||||
if (azraqDist < 0.6) {
|
||||
elev -= (1 - azraqDist / 0.6) * 120; // Dips to ~510m in Azraq
|
||||
}
|
||||
}
|
||||
|
||||
return elev;
|
||||
}
|
||||
// estimateElevation REMOVED — replaced by real SRTM satellite data from GraphHopper
|
||||
|
||||
private haversineDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
|
||||
const R = 6371000;
|
||||
@@ -736,7 +709,62 @@ export class MapsService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Manual decoder for Google Polyline algorithm (Server-side spatial matching)
|
||||
* Extracts 3D coordinates from GraphHopper's JSON points response.
|
||||
* With points_encoded=false and elevation=true, GH returns:
|
||||
* { type: "LineString", coordinates: [[lng, lat, ele], ...] }
|
||||
* Returns: [lng, lat, elevation][] — compatible with all coord consumers.
|
||||
*/
|
||||
private extractCoords3D(points: any): [number, number, number][] {
|
||||
if (!points) return [];
|
||||
// GH returns { type: "LineString", coordinates: [[lng, lat, ele], ...] }
|
||||
const rawCoords = points.coordinates || points;
|
||||
if (!Array.isArray(rawCoords)) return [];
|
||||
return rawCoords.map((c: number[]) => {
|
||||
// c = [lng, lat, elevation_meters]
|
||||
return [c[0], c[1], c[2] || 0] as [number, number, number];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes array of [lng, lat] coordinates into a standard Google-encoded polyline string.
|
||||
*/
|
||||
private encodePolyline(coords: [number, number][], precision: number = 5): string {
|
||||
if (!coords || coords.length === 0) return '';
|
||||
const factor = Math.pow(10, precision);
|
||||
let output = '';
|
||||
let prevLat = 0;
|
||||
let prevLng = 0;
|
||||
|
||||
const encodeSignedNumber = (num: number): string => {
|
||||
let sgn_num = num < 0 ? ~(num << 1) : (num << 1);
|
||||
let encodeString = '';
|
||||
while (sgn_num >= 0x20) {
|
||||
encodeString += String.fromCharCode((0x20 | (sgn_num & 0x1f)) + 63);
|
||||
sgn_num >>= 5;
|
||||
}
|
||||
encodeString += String.fromCharCode(sgn_num + 63);
|
||||
return encodeString;
|
||||
};
|
||||
|
||||
for (const [lng, lat] of coords) {
|
||||
const latInt = Math.round(lat * factor);
|
||||
const lngInt = Math.round(lng * factor);
|
||||
|
||||
const dLat = latInt - prevLat;
|
||||
const dLng = lngInt - prevLng;
|
||||
|
||||
prevLat = latInt;
|
||||
prevLng = lngInt;
|
||||
|
||||
output += encodeSignedNumber(dLat);
|
||||
output += encodeSignedNumber(dLng);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy 2D polyline decoder — kept for any encoded polyline contexts
|
||||
*/
|
||||
private decodePolyline(encoded: string): [number, number][] {
|
||||
const points: [number, number][] = [];
|
||||
@@ -750,18 +778,15 @@ export class MapsService {
|
||||
result |= (b & 0x1f) << shift;
|
||||
shift += 5;
|
||||
} while (b >= 0x20);
|
||||
let dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
|
||||
lat += dlat;
|
||||
lat += ((result & 1) ? ~(result >> 1) : (result >> 1));
|
||||
|
||||
shift = 0;
|
||||
result = 0;
|
||||
shift = 0; result = 0;
|
||||
do {
|
||||
b = encoded.charCodeAt(index++) - 63;
|
||||
result |= (b & 0x1f) << shift;
|
||||
shift += 5;
|
||||
} while (b >= 0x20);
|
||||
let dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
|
||||
lng += dlng;
|
||||
lng += ((result & 1) ? ~(result >> 1) : (result >> 1));
|
||||
|
||||
points.push([lng * 1e-5, lat * 1e-5]);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ services:
|
||||
memory: 6g
|
||||
volumes:
|
||||
- ./infrastructure/osm-data:/data
|
||||
- graphhopper-srtm-cache:/data/srtm-cache
|
||||
- ./infrastructure/docker/graphhopper/config.yml:/graphhopper/config.yml
|
||||
command: ["server", "/graphhopper/config.yml"]
|
||||
healthcheck:
|
||||
@@ -191,3 +192,4 @@ services:
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
graphhopper-srtm-cache:
|
||||
|
||||
@@ -14,6 +14,14 @@ graphhopper:
|
||||
datareader.file: /data/master_map.osm.pbf
|
||||
graph.location: /data/graph-cache
|
||||
|
||||
# ── بيانات الارتفاع الحقيقية (SRTM 30m) ──────────────────────────────
|
||||
# يحمّل تلقائياً ملفات .hgt من NASA SRTM لتغطية الأردن.
|
||||
# يربط كل حافة (Edge) في الغراف بارتفاعها الفعلي بالأمتار.
|
||||
# يُفعّل حقول ascend/descend في الـ Response + إحداثيات 3D.
|
||||
graph.elevation.provider: srtm
|
||||
graph.elevation.cache_dir: /data/srtm-cache/
|
||||
graph.elevation.dataaccess: RAM_STORE
|
||||
|
||||
# كانت "" أي: لا تتجاهل شيئاً — فتُستورد الأرصفة والمسارات كحافات ويقفز عليها
|
||||
# الـ snapping فيخرج مسار غريب بجانب الشارع. نعيد القيمة الافتراضية الآمنة.
|
||||
import.osm.ignored_highways: "footway,cycleway,path,pedestrian,steps"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
PODS:
|
||||
- FlutterMacOS (1.0.0)
|
||||
- geolocator_apple (1.2.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- geolocator_apple (from `Flutter/ephemeral/.symlinks/plugins/geolocator_apple/darwin`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
geolocator_apple:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/geolocator_apple/darwin
|
||||
shared_preferences_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
sqflite_darwin:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
|
||||
PODFILE CHECKSUM: 54d867c82ac51cbd61b565781b9fada492027009
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
@@ -27,6 +27,8 @@
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||
351EDA49D1C5D3D374442256 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A07BE6B1ED52BF54529E45D5 /* Pods_Runner.framework */; };
|
||||
B9F70418964FC439A80A8172 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84317F6C0B63CE53A0B782E6 /* Pods_RunnerTests.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -60,11 +62,14 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
22C86F6D7064344A3EA3B0F4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
27F99917FA4EEFF1083B2DEF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
2D009C51E8F63A859988957D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||
33CC10ED2044A3C60003C045 /* tactical_app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "tactical_app.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10ED2044A3C60003C045 /* tactical_app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = tactical_app.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
@@ -76,8 +81,13 @@
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||
52A5FB3D9A5E33ED13FA3342 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
84317F6C0B63CE53A0B782E6 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8CABBDB3B2BA3077BB2517C6 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
A07BE6B1ED52BF54529E45D5 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E48D5CA4666E94B1C9420A30 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -85,6 +95,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B9F70418964FC439A80A8172 /* Pods_RunnerTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -92,6 +103,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
351EDA49D1C5D3D374442256 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -125,6 +137,7 @@
|
||||
331C80D6294CF71000263BE5 /* RunnerTests */,
|
||||
33CC10EE2044A3C60003C045 /* Products */,
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */,
|
||||
C4E3432204F1BF84835896C3 /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -172,9 +185,25 @@
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C4E3432204F1BF84835896C3 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
22C86F6D7064344A3EA3B0F4 /* Pods-Runner.debug.xcconfig */,
|
||||
2D009C51E8F63A859988957D /* Pods-Runner.release.xcconfig */,
|
||||
52A5FB3D9A5E33ED13FA3342 /* Pods-Runner.profile.xcconfig */,
|
||||
E48D5CA4666E94B1C9420A30 /* Pods-RunnerTests.debug.xcconfig */,
|
||||
8CABBDB3B2BA3077BB2517C6 /* Pods-RunnerTests.release.xcconfig */,
|
||||
27F99917FA4EEFF1083B2DEF /* Pods-RunnerTests.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A07BE6B1ED52BF54529E45D5 /* Pods_Runner.framework */,
|
||||
84317F6C0B63CE53A0B782E6 /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -186,6 +215,7 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
DC5D4041C53A97A05B846521 /* [CP] Check Pods Manifest.lock */,
|
||||
331C80D1294CF70F00263BE5 /* Sources */,
|
||||
331C80D2294CF70F00263BE5 /* Frameworks */,
|
||||
331C80D3294CF70F00263BE5 /* Resources */,
|
||||
@@ -204,11 +234,13 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
6200C1F13689F6F2491B9933 /* [CP] Check Pods Manifest.lock */,
|
||||
33CC10E92044A3C60003C045 /* Sources */,
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */,
|
||||
33CC10EB2044A3C60003C045 /* Resources */,
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||
9E96F183857CC40B7A5816E1 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -329,6 +361,67 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
||||
};
|
||||
6200C1F13689F6F2491B9933 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9E96F183857CC40B7A5816E1 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DC5D4041C53A97A05B846521 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@@ -380,6 +473,7 @@
|
||||
/* Begin XCBuildConfiguration section */
|
||||
331C80DB294CF71000263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E48D5CA4666E94B1C9420A30 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@@ -394,6 +488,7 @@
|
||||
};
|
||||
331C80DC294CF71000263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 8CABBDB3B2BA3077BB2517C6 /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@@ -408,6 +503,7 @@
|
||||
};
|
||||
331C80DD294CF71000263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 27F99917FA4EEFF1083B2DEF /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
|
||||
@@ -4,4 +4,7 @@
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
Reference in New Issue
Block a user