Skip to content

Commit

Permalink
Merge pull request #383 from boostcampwm-2021/dev
Browse files Browse the repository at this point in the history
[Branching] Merge to Main branch
  • Loading branch information
sustainable-git authored Dec 3, 2021
2 parents 2bed1ce + 7b0fe44 commit 065ddfa
Show file tree
Hide file tree
Showing 155 changed files with 19,752 additions and 393 deletions.
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/refactor-request-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: Refactor Request Template
about: Refactor 작업 필요시 사용하는 기본 템플릿
title: "[REFACTOR]"
labels: Refactor
assignees: ''

---

## 구조 설명
> 팀원이 이해할 수 있도록 자세하게 구체적으로 작성합니다. 담당자도 함께 할당해주세요.
- 현재 구조
1. MVC 입니다

- 개선될 구조
1. MVVM 입니다

## 기대하는 결과
> 구체적으로 어떤 결과가 나오게 수정해야 하는지 작성합니다.
## 참고자료
> 보여지는 뷰의 경우 스크린샷도 함께 첨부합니다.
18 changes: 18 additions & 0 deletions .github/ISSUE_TEMPLATE/test-request-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
name: Test Request Template
about: Test 추가 필요시 사용하는 기본 템플릿
title: "[TEST]"
labels: Test
assignees: ''

---

## 테스트를 추가할 Scene을 입력하세요 ex) MapScene
### 테스트를 추가할 파일을 입력하세요 ex) MapViewModel

- 필요시 추가 설명 작성

## 🤔 완료 조건

- [ ] CheckPoint1
- [ ] CheckPoint2
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- [ ] 신규 기능 추가
- [ ] 버그 수정
- [ ] 리펙토링
- [ ] 테스트 코드 작성
- [ ] 문서 업데이트

### 체크리스트
Expand Down
44 changes: 44 additions & 0 deletions MountainGenerator/Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Extensions.swift
// MountainGenerator
//
// Created by Jiwon Yoon on 2021/11/25.
//

import Foundation

protocol URLQueryParameterStringConvertible {
var queryParameters: String {get}
}

extension Dictionary : URLQueryParameterStringConvertible {
/**
This computed property returns a query parameters string from the given NSDictionary. For
example, if the input is @{@"day":@"Tuesday", @"month":@"January"}, the output
string will be @"day=Tuesday&month=January".
@return The computed parameters string.
*/
var queryParameters: String {
var parts: [String] = []
for (key, value) in self {
let part = String(format: "%@=%@",
String(describing: key).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!,
String(describing: value).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
parts.append(part as String)
}
return parts.joined(separator: "&")
}

}

extension URL {
/**
Creates a new URL by adding the given query parameters.
@param parametersDictionary The query parameter dictionary to add.
@return A new URL.
*/
func appendingQueryParameters(_ parametersDictionary : Dictionary<String, String>) -> URL {
let URLString : String = String(format: "%@?%@", self.absoluteString, parametersDictionary.queryParameters)
return URL(string: URLString)!
}
}
82 changes: 82 additions & 0 deletions MountainGenerator/GeoCoderResponse.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// GeoCoderResponse.swift
// MountainGenerator
//
// Created by Jiwon Yoon on 2021/11/25.
//

import Foundation

struct GeoCodeDTO: Codable {
let results: [Result]
let status: String

enum CodingKeys: String, CodingKey {
case results = "results"
case status = "status"
}
}

// MARK: - Result
struct Result: Codable {
let addressComponents: [AddressComponent]
let formattedAddress: String
let geometry: Geometry
let placeID: String
let plusCode: PlusCode?
let types: [String]

enum CodingKeys: String, CodingKey {
case addressComponents = "address_components"
case formattedAddress = "formatted_address"
case geometry
case placeID = "place_id"
case plusCode = "plus_code"
case types
}
}

// MARK: - AddressComponent
struct AddressComponent: Codable {
let longName, shortName: String
let types: [String]

enum CodingKeys: String, CodingKey {
case longName = "long_name"
case shortName = "short_name"
case types
}
}

// MARK: - Geometry
struct Geometry: Codable {
let location: Location
let locationType: String
let viewport: Viewport

enum CodingKeys: String, CodingKey {
case location
case locationType = "location_type"
case viewport
}
}

// MARK: - Location
struct Location: Codable {
let lat, lng: Double
}

// MARK: - Viewport
struct Viewport: Codable {
let northeast, southwest: Location
}

// MARK: - PlusCode
struct PlusCode: Codable {
let compoundCode, globalCode: String

enum CodingKeys: String, CodingKey {
case compoundCode = "compound_code"
case globalCode = "global_code"
}
}
40 changes: 40 additions & 0 deletions MountainGenerator/MountainModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// MountainModel.swift
// MountainGenerator
//
// Created by Jiwon Yoon on 2021/11/25.
//

import Foundation

struct MountainInfo: Codable {
let mountainName, mountainRegion, mountainHeight, mountainShortDescription: String

enum CodingKeys: String, CodingKey {
case mountainName = "MNTN_NM"
case mountainRegion = "MNTN_LOCPLC_REGION_NM"
case mountainHeight = "MNTN_HG_VL"
case mountainShortDescription = "DETAIL_INFO_DTCONT"
}
}

struct MountainWithLocation: Codable, Hashable {
let mountain: MountainInfo
let latitude: Double
let longitude: Double

enum CodingKeys: String, CodingKey {
case mountain = "mountain"
case latitude = "latitude"
case longitude = "longitude"
}
// 위도와 경도가 같을시 같은 데이터로 취급
func hash(into hasher: inout Hasher) {
hasher.combine(latitude)
hasher.combine(longitude)
}

static func ==(lhs: MountainWithLocation, rhs: MountainWithLocation) -> Bool {
return lhs.longitude == rhs.longitude && lhs.latitude == rhs.latitude
}
}
98 changes: 98 additions & 0 deletions MountainGenerator/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// main.swift
// MountainGenerator
//
// Created by Jiwon Yoon on 2021/11/25.
//
// Mac Command Line Tool

import Foundation

var processedMountains = Set<MountainWithLocation>()

func readJSON() -> [MountainInfo] {
let data = try? Data(contentsOf: URL(fileURLWithPath: "/Users/jiwonyoon/Desktop/Mountains.json"))
let decoded = try? JSONDecoder().decode([MountainInfo].self, from: data!)

return decoded ?? []
}

// 국내에 없거나, 자연 지형(natural feature)이 아니면 산 데이터로 인정 하지 않음
func isValidMountain(response: GeoCodeDTO?) -> Bool {
guard let response = response,
let addressComponents = response.results.first?.addressComponents,
let types = response.results.first?.types else {
return false
}
var isInKorea = false
let isNaturalFeature = types.contains("natural_feature")

for addressComponent in addressComponents {
if addressComponent.longName == "대한민국" || addressComponent.shortName == "KR" {
isInKorea = true
break
}
}
return isInKorea && isNaturalFeature
}

func sendRequest(for mountain: MountainInfo) {
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)

guard var URL = URL(string: "https://maps.googleapis.com/maps/api/geocode/json") else { return }
let URLParams = [
"address": "\(mountain.mountainRegion) \(mountain.mountainName)",
"key": "비밀임",
"language": "ko",
]
URL = URL.appendingQueryParameters(URLParams)
var request = URLRequest(url: URL)
request.httpMethod = "GET"

let task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
if let data = data, (error == nil) {
let dto = try? JSONDecoder().decode(GeoCodeDTO.self, from: data)
// 검색해도 위치정보가 나오지 않을 경우.
guard let latitude = dto?.results.first?.geometry.location.lat,
let longitude = dto?.results.first?.geometry.location.lng,
isValidMountain(response: dto) else {
print("not a valid Mountain!")
return
}

let mountainWithLocation = MountainWithLocation(mountain: mountain, latitude: latitude, longitude: longitude)
processedMountains.insert(mountainWithLocation)
print("\(mountainWithLocation.mountain.mountainName), \(mountainWithLocation.latitude), \(mountainWithLocation.longitude)")

}
else {
// Failure
print("URL Session Task Failed: %@", error!.localizedDescription);
}
})
task.resume()
session.finishTasksAndInvalidate()
}


let mountains = readJSON()
print(mountains.count)

for mountain in mountains {
print("requesting: \(mountain.mountainName)")
sendRequest(for: mountain)
// 너무 리퀘스트를 동시에 보내면 구글 API가 응답하지 않음!
sleep(1)
}
let mountainsWithLocation = Array(processedMountains)
//이후 json 파일로 저장

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
if let jsonData = try? encoder.encode(mountainsWithLocation),
let jsonString = String(data: jsonData, encoding: String.Encoding.utf8) {

let pathWithFileName = URL(string: "/Users/jiwonyoon/Desktop/")?.appendingPathComponent("MountainsWithLocation.json")
try jsonString.write(to: pathWithFileName!, atomically: true, encoding: .utf8)
}
Loading

0 comments on commit 065ddfa

Please sign in to comment.