Skip to content

Commit

Permalink
✨ feature/pixel map (#26)
Browse files Browse the repository at this point in the history
* ✨ Map Model, API 구현

* ✨ 지도 렌더링 구현

* 🐛 Rank API 응답 모델 수정
  • Loading branch information
O-O-wl authored Jan 3, 2021
1 parent 98b4608 commit c0a578c
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 45 deletions.
12 changes: 8 additions & 4 deletions Dear-World/Dear-World.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
3902F12425970E5600A3DF8C /* Number+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3902F12325970E5600A3DF8C /* Number+.swift */; };
3902F12A259714D800A3DF8C /* RankerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3902F129259714D800A3DF8C /* RankerTableViewCell.swift */; };
3914D9E6259F3FA1009765B0 /* Message.Model.Messages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3914D9E5259F3FA1009765B0 /* Message.Model.Messages.swift */; };
393E0D4025A23A12000DB3B9 /* World.Model.Map.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393E0D3F25A23A12000DB3B9 /* World.Model.Map.swift */; };
393E0D4525A23A7B000DB3B9 /* World.API.Map.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393E0D4425A23A7B000DB3B9 /* World.API.Map.swift */; };
3958257B25948E41007325AB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3958257A25948E41007325AB /* AppDelegate.swift */; };
3958258425948E43007325AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3958258325948E43007325AB /* Assets.xcassets */; };
3958258725948E43007325AB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3958258525948E43007325AB /* LaunchScreen.storyboard */; };
Expand Down Expand Up @@ -61,7 +63,6 @@
39E9F7E025A1BC3C00BC2CC2 /* NoticeBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E9F7DF25A1BC3C00BC2CC2 /* NoticeBadge.swift */; };
39E9F7E625A1C80300BC2CC2 /* WorldMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E9F7E525A1C80300BC2CC2 /* WorldMap.swift */; };
39E9F7ED25A1C84900BC2CC2 /* WorldMap.Model.Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E9F7EC25A1C84900BC2CC2 /* WorldMap.Model.Country.swift */; };
39EED22E259CFEB8007452E1 /* World.Model.Ranker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39EED22D259CFEB8007452E1 /* World.Model.Ranker.swift */; };
39EED23C259D00F8007452E1 /* CheeringMapReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39EED23B259D00F8007452E1 /* CheeringMapReactor.swift */; };
39EED241259D0227007452E1 /* Revision.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39EED240259D0227007452E1 /* Revision.swift */; };
39F0C1632597B34F00A7001F /* UIView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39F0C1622597B34F00A7001F /* UIView+.swift */; };
Expand Down Expand Up @@ -110,6 +111,8 @@
3902F12325970E5600A3DF8C /* Number+.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = "Number+.swift"; sourceTree = "<group>"; tabWidth = 2; };
3902F129259714D800A3DF8C /* RankerTableViewCell.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = RankerTableViewCell.swift; sourceTree = "<group>"; tabWidth = 2; };
3914D9E5259F3FA1009765B0 /* Message.Model.Messages.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = Message.Model.Messages.swift; path = "Dear-World/Source/Presentation/Scene/Main/Message.Model.Messages.swift"; sourceTree = SOURCE_ROOT; tabWidth = 2; };
393E0D3F25A23A12000DB3B9 /* World.Model.Map.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.Model.Map.swift; sourceTree = "<group>"; };
393E0D4425A23A7B000DB3B9 /* World.API.Map.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.API.Map.swift; sourceTree = "<group>"; };
3958257725948E41007325AB /* Dear-World.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Dear-World.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3958257A25948E41007325AB /* AppDelegate.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; tabWidth = 2; };
3958258325948E43007325AB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -144,7 +147,6 @@
39E9F7DF25A1BC3C00BC2CC2 /* NoticeBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeBadge.swift; sourceTree = "<group>"; };
39E9F7E525A1C80300BC2CC2 /* WorldMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorldMap.swift; sourceTree = "<group>"; };
39E9F7EC25A1C84900BC2CC2 /* WorldMap.Model.Country.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorldMap.Model.Country.swift; sourceTree = "<group>"; };
39EED22D259CFEB8007452E1 /* World.Model.Ranker.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = World.Model.Ranker.swift; sourceTree = "<group>"; tabWidth = 2; };
39EED23B259D00F8007452E1 /* CheeringMapReactor.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = CheeringMapReactor.swift; sourceTree = "<group>"; tabWidth = 2; };
39EED240259D0227007452E1 /* Revision.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Revision.swift; sourceTree = "<group>"; };
39F0C1622597B34F00A7001F /* UIView+.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = "UIView+.swift"; sourceTree = "<group>"; tabWidth = 2; };
Expand Down Expand Up @@ -469,8 +471,8 @@
isa = PBXGroup;
children = (
39658FBA259AE55C0050D180 /* World.Model.Rank.swift */,
39EED22D259CFEB8007452E1 /* World.Model.Ranker.swift */,
39658FBF259AE58C0050D180 /* World.Model.Country.swift */,
393E0D3F25A23A12000DB3B9 /* World.Model.Map.swift */,
);
path = Model;
sourceTree = "<group>";
Expand All @@ -479,6 +481,7 @@
isa = PBXGroup;
children = (
39658FB5259AE5250050D180 /* World.API.Rank.swift */,
393E0D4425A23A7B000DB3B9 /* World.API.Map.swift */,
);
path = API;
sourceTree = "<group>";
Expand Down Expand Up @@ -733,12 +736,12 @@
3902F118259704AF00A3DF8C /* AboutViewController.swift in Sources */,
3902F12425970E5600A3DF8C /* Number+.swift in Sources */,
39EED23C259D00F8007452E1 /* CheeringMapReactor.swift in Sources */,
393E0D4525A23A7B000DB3B9 /* World.API.Map.swift in Sources */,
39F0C18B2598799200A7001F /* Network.swift in Sources */,
3971EB37259A9C550084E6DC /* Message.API.SendMessage.swift in Sources */,
395826122596322B007325AB /* DiscoverViewController.swift in Sources */,
395A4177259DF9F900F10531 /* MainTabBarController.swift in Sources */,
3971EB18259A7BC10084E6DC /* Emoji.swift in Sources */,
39EED22E259CFEB8007452E1 /* World.Model.Ranker.swift in Sources */,
3902F1132597049D00A3DF8C /* SendMessageViewController.swift in Sources */,
3914D9E6259F3FA1009765B0 /* Message.Model.Messages.swift in Sources */,
39F0C1A02598877600A7001F /* NetworkError.swift in Sources */,
Expand All @@ -763,6 +766,7 @@
3971EB24259A7C420084E6DC /* Emoji.Model.Random.swift in Sources */,
39F0C1632597B34F00A7001F /* UIView+.swift in Sources */,
3971EB1F259A7C0E0084E6DC /* Emoji.API.Random.swift in Sources */,
393E0D4025A23A12000DB3B9 /* World.Model.Map.swift in Sources */,
3902F1052596F26D00A3DF8C /* CheeringMapViewController.swift in Sources */,
39F0C1B72598927C00A7001F /* ErrorView.swift in Sources */,
39672DC12598E95A001D7E69 /* TextView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ extension WorldMap.Model {
Location(x: 20, y: 26),
Location(x: 20, y: 27),
Location(x: 20, y: 28),
Location(x: 21, y: 26),
Location(x: 21, y: 26)
]
)
static let CA: Country = Country(
Expand Down Expand Up @@ -1155,7 +1155,7 @@ extension WorldMap.Model {
Location(x: 40, y: 21),
Location(x: 41, y: 16),
Location(x: 41, y: 17),
Location(x: 41, y: 18),
Location(x: 41, y: 18)
]
)
static let FI: Country = Country(
Expand All @@ -1170,7 +1170,7 @@ extension WorldMap.Model {
Location(x: 43, y: 16),
Location(x: 43, y: 17),
Location(x: 43, y: 18),
Location(x: 43, y: 19),
Location(x: 43, y: 19)
]
)
static let EE: Country = Country(
Expand Down Expand Up @@ -1582,7 +1582,7 @@ extension WorldMap.Model {
Location(x: 51, y: 31),
Location(x: 52, y: 29),
Location(x: 52, y: 30),
Location(x: 52, y: 31),
Location(x: 52, y: 31)
]
)
static let AF: Country = Country(
Expand Down Expand Up @@ -1678,7 +1678,7 @@ extension WorldMap.Model {
Location(x: 60, y: 25),
Location(x: 60, y: 26),
Location(x: 61, y: 25),
Location(x: 62, y: 25),
Location(x: 62, y: 25)
]
)
static let KP: Country = Country(
Expand Down Expand Up @@ -1737,7 +1737,7 @@ extension WorldMap.Model {
name: "Vietnam",
locations: [
Location(x: 60, y: 33),
Location(x: 60, y: 34),
Location(x: 60, y: 34)
]
)
static let TW: Country = Country(
Expand All @@ -1746,7 +1746,7 @@ extension WorldMap.Model {
locations: [
Location(x: 58, y: 33),
Location(x: 58, y: 34),
Location(x: 59, y: 33),
Location(x: 59, y: 33)
]
)
static let MY: Country = Country(
Expand All @@ -1761,7 +1761,7 @@ extension WorldMap.Model {
name: "Nepal",
locations: [
Location(x: 54, y: 30),
Location(x: 55, y: 30),
Location(x: 55, y: 30)
]
)
static let LK: Country = Country(
Expand Down
18 changes: 18 additions & 0 deletions Dear-World/Dear-World/Source/Domain/World/API/World.API.Map.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// World.API.Map.swift
// Dear-World
//
// Created by dongyoung.lee on 2021/01/04.
//

import Alamofire
import Foundation

extension World.API {
struct Map: ServiceAPI {
typealias Response = World.Model.Map

var method: HTTPMethod { .get }
var path: String { "api/v1/countries/count" }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extension World.Model {
}
}
}
extension World.Model {
extension World.Model.Country {
struct Status: Decodable {
let id: Int
let messageCount: Int
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// World.Model.Map.swift
// Dear-World
//
// Created by dongyoung.lee on 2021/01/04.
//

import Foundation

extension World.Model {
struct Map: Decodable {
let countries: [Country]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ import Foundation

extension World.Model {
struct Rank: Decodable {
let ranking: [Ranker]
let ranking: [Country]
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@ final class RankerTableViewCell: UITableViewCell {
}

// MARK: 🔩 Configuration
func configure(with ranker: World.Model.Ranker, ranking: Int) {
func configure(with country: World.Model.Country, ranking: Int) {
rankLabel.attributedText = formatRank(ranking)
countryNameLabel.text = ranker.country.name
countryFlagLabel.text = ranker.country.emoji
messageCountLabel.text = ranker.messageCount.formatted
countryNameLabel.text = country.name
countryFlagLabel.text = country.emoji
messageCountLabel.text = country.status?.messageCount.formatted
}

private func formatRank(_ rank: Int) -> NSAttributedString {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ final class CheeringMapReactor: Reactor {
}

enum Mutation {
case setRankers([Model.Ranker])
case setRankers([Model.Country])
case setCountries([Model.Country])
}

struct State {
var messageCount: Int = 100_000
@Revision var rankers: [Model.Ranker] = []
@Revision var rankers: [Model.Country] = []
@Revision var countries: [Model.Country] = []
@Revision var selectedCountries: [Model.Country] = []
}

Expand All @@ -33,10 +35,16 @@ final class CheeringMapReactor: Reactor {
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case .viewDidLoad:
return Network.request(API.Rank())
.map { $0?.ranking }
.filterNil()
.map { .setRankers($0) }
return .merge(
Network.request(API.Map())
.map { $0?.countries }
.filterNil()
.map { .setCountries($0) },
Network.request(API.Rank())
.map { $0?.ranking }
.filterNil()
.map { .setRankers($0) }
)

case .tapLikeAt(let index):
return .empty()
Expand All @@ -47,8 +55,11 @@ final class CheeringMapReactor: Reactor {
func reduce(state: State, mutation: Mutation) -> State {
var newState = currentState
switch mutation {
case .setRankers(let rankers):
newState.rankers = rankers
case .setRankers(let countries):
newState.rankers = countries

case .setCountries(let countries):
newState.countries = countries

default:
()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ final class CheeringMapViewController: UIViewController, ReactorKit.View {
setupUI()
}

// MARK: 🔗 Bind
func bind(reactor: CheeringMapReactor) {
reactor.state
.map { $0.messageCount }
Expand All @@ -64,6 +65,14 @@ final class CheeringMapViewController: UIViewController, ReactorKit.View {
cell.cheerUpButton.anchorView = self?.view
}.disposed(by: disposeBag)

reactor.state
.distinctUntilChanged(\.$countries)
.map { $0.countries }
.subscribe(onNext: { [weak self] in
self?.worldMapView.drawCountries($0)
})
.disposed(by: disposeBag)

rankingTableView.rx.didScroll
.map { [weak self] in self?.rankingTableView.contentOffset.y }
.filterNil()
Expand All @@ -72,6 +81,9 @@ final class CheeringMapViewController: UIViewController, ReactorKit.View {
.subscribe(onNext: { [weak self] y in
guard let self = self else { return }
self.updateLayouts(y)
if let countries = self.reactor?.currentState.countries {
self.worldMapView.drawCountries(countries)
}
})
.disposed(by: disposeBag)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ final class PixelMapView: UIView {
}

func drawCountries(_ countries: [Model.Country]) {
layoutIfNeeded()
self.layer.sublayers?.removeAll()
countries.forEach { drawCountry($0) }
}

Expand Down Expand Up @@ -55,7 +57,7 @@ final class PixelMapView: UIView {
)
let path: UIBezierPath = UIBezierPath(
arcCenter: center,
radius: locationSize.width,
radius: locationSize.width / 2,
startAngle: CGFloat(0),
endAngle: CGFloat(Double.pi * 2),
clockwise: true
Expand Down

0 comments on commit c0a578c

Please sign in to comment.