From 3475100995dd52d53a85760e57d1ff63def68f13 Mon Sep 17 00:00:00 2001 From: Howon Date: Sat, 30 Nov 2024 18:40:46 +0900 Subject: [PATCH 1/4] running machine.py revise --- src/ai/runningmachine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ai/runningmachine.py b/src/ai/runningmachine.py index c83de4f..b360bc7 100644 --- a/src/ai/runningmachine.py +++ b/src/ai/runningmachine.py @@ -150,4 +150,4 @@ def print_filtered_files(gpx_files, center_coords, radius, elevation, convenienc track_preference = input("Track preference (LOW, MEDIUM, HIGH): ").strip() # 결과 출력 - print_filtered_files(gpx_files, center_coords, radius_threshold, elevation_preference, convenience_preference, track_preference) + print_filtered_files(gpx_files, center_coords, radius_threshold, elevation_preference, convenience_preference, track_preference) \ No newline at end of file From 86d557f77559e4fee8e8e6f15bcaa706066fd1e4 Mon Sep 17 00:00:00 2001 From: Howon Date: Sun, 1 Dec 2024 14:51:38 +0900 Subject: [PATCH 2/4] AI: [feat] runningmachine.py revise_loading problem fix --- src/ai/runningmachine.py | 66 +++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/src/ai/runningmachine.py b/src/ai/runningmachine.py index b360bc7..80bcf25 100644 --- a/src/ai/runningmachine.py +++ b/src/ai/runningmachine.py @@ -27,32 +27,39 @@ import gpxpy import pandas as pd from geopy.distance import geodesic +from concurrent.futures import ThreadPoolExecutor # CSV 파일 로드 함수 def load_csv(file_path): return pd.read_csv(file_path) if os.path.exists(file_path) else None -# GPX 파일 로드 함수 +# GPX 파일 로드 함수 (병렬 처리) def load_gpx_files(directory_path): gpx_files = [] if not os.path.exists(directory_path): return gpx_files - # GPX 파일만 찾아서 로드 - for file_name in os.listdir(directory_path): + def process_file(file_name): if file_name.endswith(".gpx"): file_path = os.path.join(directory_path, file_name) try: with open(file_path, 'r', encoding='utf-8') as gpx_file: gpx_data = gpxpy.parse(gpx_file) - gpx_files.append((file_name, gpx_data)) + return (file_name, gpx_data) except Exception as e: print(f"Error in file {file_name}: {e}") + return None + return None + + # 병렬로 GPX 파일 처리 + with ThreadPoolExecutor() as executor: + results = executor.map(process_file, os.listdir(directory_path)) + gpx_files = [result for result in results if result is not None] + return gpx_files -# 선호도 매핑 및 GPX 파일 필터링 +# GPX 파일 필터링 함수 def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, elevation, convenience, track): - # 선호도 매핑 elevation_mapping = {"LOW": "Beginner", "MEDIUM": "Advanced", "HIGH": "Expert"} convenience_mapping = { "LOW": ["No_Facilities", "Essential_Facilities", "Enhanced_Facilities"], @@ -60,12 +67,11 @@ def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, e "HIGH": ["Enhanced_Facilities"], } track_mapping = { - "LOW": ["NonTrack"], # LOW는 NonTrack만 - "MEDIUM": ["NonTrack", "Track"], # MEDIUM은 NonTrack, Track - "HIGH": ["Track"], # HIGH는 Track만 + "LOW": ["NonTrack"], + "MEDIUM": ["NonTrack", "Track"], + "HIGH": ["Track"], } - # 선호도 설정 elevation_pref = elevation_mapping.get(elevation.upper()) convenience_pref = convenience_mapping.get(convenience.upper(), []) track_pref = track_mapping.get(track.upper(), []) @@ -74,23 +80,28 @@ def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, e # GPX 파일 필터링 for file_name, gpx_data in gpx_files: - # 선호도 매핑 필터링 + # 파일 이름 선호도 필터링 if not ( (elevation_pref in file_name) and any(c in file_name for c in convenience_pref) and any(t in file_name for t in track_pref) ): - continue # 선호도에 맞지 않으면 건너뛰기 + continue - # GPX 파일 내에서 포인트를 체크하여 반경 내에 있는지 확인 + # 첫 번째 점만으로 반경 체크 for track in gpx_data.tracks: for segment in track.segments: + if segment.points: + first_point_coords = (segment.points[0].latitude, segment.points[0].longitude) + if geodesic(center_coords, first_point_coords).meters > radius: + break + # 트랙 포인트 중 하나라도 반경 내에 있으면 추가 for point in segment.points: point_coords = (point.latitude, point.longitude) distance = geodesic(center_coords, point_coords).meters if distance <= radius: - matching_files.append((file_name, gpx_data, distance)) # 거리 추가 - break # 반경 내에 있으면 더 이상 탐색할 필요 없음 + matching_files.append((file_name, gpx_data, distance)) + break else: continue break @@ -100,54 +111,39 @@ def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, e return matching_files -# 가까운 파일을 거리 기준으로 정렬하고 5개로 제한 +# 가까운 파일 정렬 및 제한 def sort_and_limit_by_distance(matching_files, limit=5): - # 거리 기준으로 정렬 (가장 가까운 것부터) - matching_files.sort(key=lambda x: x[2]) - - # 5개로 제한 - return matching_files[:limit] + return sorted(matching_files, key=lambda x: x[2])[:limit] # 결과 출력 함수 def print_filtered_files(gpx_files, center_coords, radius, elevation, convenience, track): - # 선호도와 반경에 맞는 파일 필터링 matching_files = filter_gpx_within_radius_and_preferences( gpx_files, center_coords, radius, elevation, convenience, track ) - - # 5개로 제한 closest_files = sort_and_limit_by_distance(matching_files, limit=5) - # 필터링된 파일 출력 if closest_files: - # 가장 가까운 5개 경로 출력 for file_name, _, distance in closest_files: - print(f"{file_name}") + print(f"{file_name} ({distance:.2f} meters)") else: print(f"No files found within {radius / 1000:.2f} km.") # 메인 실행 if __name__ == "__main__": - # CSV 파일 경로 toilet_csv_path = 'C:/Users/정호원/OneDrive/바탕 화면/gpx 수집/code/final_toilet.csv' conv_csv_path = 'C:/Users/정호원/OneDrive/바탕 화면/gpx 수집/code/final_conv.csv' - # CSV 파일 로드 toilet_data = load_csv(toilet_csv_path) conv_data = load_csv(conv_csv_path) - # GPX 파일 디렉토리 및 로드 gpx_directory = "C:/Users/정호원/OneDrive/바탕 화면/gpx 수집/gpx" gpx_files = load_gpx_files(gpx_directory) - # 기본 위치 및 반경 center_coords = (37.511989, 127.091) - radius_threshold = 2500 # meters + radius_threshold = 2500 - # 사용자 입력 elevation_preference = input("Elevation preference (LOW, MEDIUM, HIGH): ").strip() convenience_preference = input("Convenience preference (LOW, MEDIUM, HIGH): ").strip() track_preference = input("Track preference (LOW, MEDIUM, HIGH): ").strip() - # 결과 출력 - print_filtered_files(gpx_files, center_coords, radius_threshold, elevation_preference, convenience_preference, track_preference) \ No newline at end of file + print_filtered_files(gpx_files, center_coords, radius_threshold, elevation_preference, convenience_preference, track_preference) From c4cdbcae7882aca62a0f1e68053f8547cfb6263c Mon Sep 17 00:00:00 2001 From: Howon Date: Sun, 1 Dec 2024 15:13:48 +0900 Subject: [PATCH 3/4] AI:[feat] runningmachine.py revise --- src/ai/runningmachine.py | 76 ++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/ai/runningmachine.py b/src/ai/runningmachine.py index 80bcf25..5e4eaa0 100644 --- a/src/ai/runningmachine.py +++ b/src/ai/runningmachine.py @@ -31,12 +31,21 @@ # CSV 파일 로드 함수 def load_csv(file_path): - return pd.read_csv(file_path) if os.path.exists(file_path) else None + try: + if os.path.exists(file_path): + return pd.read_csv(file_path) + else: + print(f"File not found: {file_path}") + return None + except Exception as e: + print(f"Error loading CSV file {file_path}: {e}") + return None # GPX 파일 로드 함수 (병렬 처리) def load_gpx_files(directory_path): gpx_files = [] if not os.path.exists(directory_path): + print(f"Directory not found: {directory_path}") return gpx_files def process_file(file_name): @@ -51,7 +60,6 @@ def process_file(file_name): return None return None - # 병렬로 GPX 파일 처리 with ThreadPoolExecutor() as executor: results = executor.map(process_file, os.listdir(directory_path)) gpx_files = [result for result in results if result is not None] @@ -59,7 +67,7 @@ def process_file(file_name): return gpx_files # GPX 파일 필터링 함수 -def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, elevation, convenience, track): +def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, elevation, convenience, track, fallback=False): elevation_mapping = {"LOW": "Beginner", "MEDIUM": "Advanced", "HIGH": "Expert"} convenience_mapping = { "LOW": ["No_Facilities", "Essential_Facilities", "Enhanced_Facilities"], @@ -78,36 +86,38 @@ def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, e matching_files = [] - # GPX 파일 필터링 for file_name, gpx_data in gpx_files: - # 파일 이름 선호도 필터링 - if not ( - (elevation_pref in file_name) and - any(c in file_name for c in convenience_pref) and - any(t in file_name for t in track_pref) - ): - continue - - # 첫 번째 점만으로 반경 체크 - for track in gpx_data.tracks: - for segment in track.segments: - if segment.points: - first_point_coords = (segment.points[0].latitude, segment.points[0].longitude) - if geodesic(center_coords, first_point_coords).meters > radius: - break - # 트랙 포인트 중 하나라도 반경 내에 있으면 추가 - for point in segment.points: - point_coords = (point.latitude, point.longitude) - distance = geodesic(center_coords, point_coords).meters - if distance <= radius: - matching_files.append((file_name, gpx_data, distance)) - break + try: + if not fallback: + # 선호도 필터링 + if not ( + (elevation_pref in file_name) and + any(c in file_name for c in convenience_pref) and + any(t in file_name for t in track_pref) + ): + continue + + # 반경 체크 + for track in gpx_data.tracks: + for segment in track.segments: + if segment.points: + first_point_coords = (segment.points[0].latitude, segment.points[0].longitude) + if geodesic(center_coords, first_point_coords).meters > radius: + break + for point in segment.points: + point_coords = (point.latitude, point.longitude) + distance = geodesic(center_coords, point_coords).meters + if distance <= radius: + matching_files.append((file_name, gpx_data, distance)) + break + else: + continue + break else: continue break - else: - continue - break + except Exception as e: + print(f"Error processing GPX data in file {file_name}: {e}") return matching_files @@ -120,11 +130,17 @@ def print_filtered_files(gpx_files, center_coords, radius, elevation, convenienc matching_files = filter_gpx_within_radius_and_preferences( gpx_files, center_coords, radius, elevation, convenience, track ) + + if not matching_files: # 만족되는 게 없을 때 + matching_files = filter_gpx_within_radius_and_preferences( + gpx_files, center_coords, radius, elevation, convenience, track, fallback=True + ) + closest_files = sort_and_limit_by_distance(matching_files, limit=5) if closest_files: for file_name, _, distance in closest_files: - print(f"{file_name} ({distance:.2f} meters)") + print(f"{file_name}") else: print(f"No files found within {radius / 1000:.2f} km.") From ceae533168c6f10122c3413b64606c9255459523 Mon Sep 17 00:00:00 2001 From: Howon Date: Sun, 1 Dec 2024 15:33:52 +0900 Subject: [PATCH 4/4] AI:[feat] runningmachine.py revise --- src/ai/runningmachine.py | 102 ++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 40 deletions(-) diff --git a/src/ai/runningmachine.py b/src/ai/runningmachine.py index 5e4eaa0..1092043 100644 --- a/src/ai/runningmachine.py +++ b/src/ai/runningmachine.py @@ -35,17 +35,14 @@ def load_csv(file_path): if os.path.exists(file_path): return pd.read_csv(file_path) else: - print(f"File not found: {file_path}") return None except Exception as e: - print(f"Error loading CSV file {file_path}: {e}") return None # GPX 파일 로드 함수 (병렬 처리) def load_gpx_files(directory_path): gpx_files = [] if not os.path.exists(directory_path): - print(f"Directory not found: {directory_path}") return gpx_files def process_file(file_name): @@ -56,7 +53,6 @@ def process_file(file_name): gpx_data = gpxpy.parse(gpx_file) return (file_name, gpx_data) except Exception as e: - print(f"Error in file {file_name}: {e}") return None return None @@ -67,7 +63,7 @@ def process_file(file_name): return gpx_files # GPX 파일 필터링 함수 -def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, elevation, convenience, track, fallback=False): +def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, elevation, convenience, track): elevation_mapping = {"LOW": "Beginner", "MEDIUM": "Advanced", "HIGH": "Expert"} convenience_mapping = { "LOW": ["No_Facilities", "Essential_Facilities", "Enhanced_Facilities"], @@ -84,40 +80,33 @@ def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, e convenience_pref = convenience_mapping.get(convenience.upper(), []) track_pref = track_mapping.get(track.upper(), []) + def is_matching(file_name): + # 파일 이름 기반 필터링 + return ( + (elevation_pref in file_name) and + any(c in file_name for c in convenience_pref) and + any(t in file_name for t in track_pref) + ) + matching_files = [] - for file_name, gpx_data in gpx_files: - try: - if not fallback: - # 선호도 필터링 - if not ( - (elevation_pref in file_name) and - any(c in file_name for c in convenience_pref) and - any(t in file_name for t in track_pref) - ): - continue - - # 반경 체크 - for track in gpx_data.tracks: - for segment in track.segments: - if segment.points: - first_point_coords = (segment.points[0].latitude, segment.points[0].longitude) - if geodesic(center_coords, first_point_coords).meters > radius: - break - for point in segment.points: - point_coords = (point.latitude, point.longitude) - distance = geodesic(center_coords, point_coords).meters - if distance <= radius: - matching_files.append((file_name, gpx_data, distance)) - break - else: - continue - break - else: - continue - break - except Exception as e: - print(f"Error processing GPX data in file {file_name}: {e}") + def process_gpx(file_name, gpx_data): + if not is_matching(file_name): + return None + + for track in gpx_data.tracks: + for segment in track.segments: + if segment.points: + first_point_coords = (segment.points[0].latitude, segment.points[0].longitude) + distance = geodesic(center_coords, first_point_coords).meters + if distance <= radius: + return (file_name, gpx_data, distance) + return None + + # 병렬 처리로 필터링 + with ThreadPoolExecutor() as executor: + results = executor.map(lambda x: process_gpx(*x), gpx_files) + matching_files = [result for result in results if result is not None] return matching_files @@ -125,15 +114,48 @@ def filter_gpx_within_radius_and_preferences(gpx_files, center_coords, radius, e def sort_and_limit_by_distance(matching_files, limit=5): return sorted(matching_files, key=lambda x: x[2])[:limit] +# 추가 경로 채우기 함수 (Elevation 조건 한정) +def fill_additional_files(gpx_files, matching_files, center_coords, elevation, radius, limit=5): + selected_files = {file[0] for file in matching_files} + + elevation_mapping = {"LOW": "Beginner", "MEDIUM": "Advanced", "HIGH": "Expert"} + elevation_pref = elevation_mapping.get(elevation.upper()) + + def process_gpx(file_name, gpx_data): + if file_name in selected_files or elevation_pref not in file_name: + return None + for track in gpx_data.tracks: + for segment in track.segments: + if segment.points: + first_point_coords = (segment.points[0].latitude, segment.points[0].longitude) + distance = geodesic(center_coords, first_point_coords).meters + if distance <= radius: + return (file_name, gpx_data, distance) + return None + + # 병렬 처리로 추가 파일 탐색 + with ThreadPoolExecutor() as executor: + results = executor.map(lambda x: process_gpx(*x), gpx_files) + additional_files = [result for result in results if result is not None] + + # 가까운 거리 순으로 정렬 후 추가 + additional_files = sorted(additional_files, key=lambda x: x[2]) + for file in additional_files: + if len(matching_files) >= limit: + break + matching_files.append(file) + + return matching_files + # 결과 출력 함수 def print_filtered_files(gpx_files, center_coords, radius, elevation, convenience, track): matching_files = filter_gpx_within_radius_and_preferences( gpx_files, center_coords, radius, elevation, convenience, track ) - if not matching_files: # 만족되는 게 없을 때 - matching_files = filter_gpx_within_radius_and_preferences( - gpx_files, center_coords, radius, elevation, convenience, track, fallback=True + if len(matching_files) < 5: + matching_files = fill_additional_files( + gpx_files, matching_files, center_coords, elevation, radius ) closest_files = sort_and_limit_by_distance(matching_files, limit=5)