Skip to content

Commit

Permalink
Merge pull request #365 from lsj8706/feat/#360-솝탬프-개선
Browse files Browse the repository at this point in the history
  • Loading branch information
lsj8706 authored Apr 10, 2024
2 parents 00f67cc + e10b732 commit 9dea61a
Show file tree
Hide file tree
Showing 23 changed files with 1,387 additions and 559 deletions.
47 changes: 32 additions & 15 deletions SOPT-iOS/Projects/Data/Sources/Repository/RankingRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,39 @@ import Domain
import Networks

public class RankingRepository {
private let rankService: RankService
private let cancelBag = CancelBag()
public init(service: RankService) {
self.rankService = service
}

private let rankService: RankService
private let cancelBag = CancelBag()

public init(service: RankService) {
self.rankService = service
}
}

extension RankingRepository: RankingRepositoryInterface {
public func fetchRankingListModel(isCurrentGeneration: Bool) -> AnyPublisher<[Domain.RankingModel], Error> {
return self.rankService
.fetchRankingList(isCurrentGeneration: isCurrentGeneration)
.map({ entity in
entity.map { $0.toDomain() }
})
.eraseToAnyPublisher()
}
public func fetchRankingListModel(isCurrentGeneration: Bool) -> AnyPublisher<[Domain.RankingModel], Error> {
return self.rankService
.fetchRankingList(isCurrentGeneration: isCurrentGeneration)
.map({ entity in
entity.map { $0.toDomain() }
})
.eraseToAnyPublisher()
}

public func fetchPartRanking() -> AnyPublisher<[Domain.PartRankingModel], Error> {
return self.rankService
.fetchPartRanking()
.map {
$0.map { $0.toDomain() }
}.eraseToAnyPublisher()
}

public func fetchRankingListInPart(part: String) -> AnyPublisher<[RankingModel], Error> {
return self.rankService
.fetchRankingListInPart(part: part)
.map {
$0.map { $0.toDomain() }
}
.eraseToAnyPublisher()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// PartRankingTransform.swift
// Data
//
// Created by Aiden.lee on 2024/04/05.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import Foundation

import Core
import Domain
import Networks

extension PartRankingEntity {
public func toDomain() -> PartRankingModel {
return .init(part: part, rank: rank, points: points)
}
}

29 changes: 29 additions & 0 deletions SOPT-iOS/Projects/Domain/Sources/Model/PartRankingModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// PartRankingModel.swift
// Domain
//
// Created by Aiden.lee on 2024/04/05.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import Foundation

public struct PartRankingModel: Hashable {
public let part: String
public let rank: Int
public let points: Int

public init(part: String, rank: Int, points: Int) {
self.part = part
self.rank = rank
self.points = points
}
}

public struct PartRankingChartModel: Hashable {
public let ranking: [PartRankingModel]

public init(ranking: [PartRankingModel]) {
self.ranking = ranking
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
import Combine

public protocol RankingRepositoryInterface {
func fetchRankingListModel(isCurrentGeneration: Bool) -> AnyPublisher<[RankingModel], Error>
func fetchRankingListModel(isCurrentGeneration: Bool) -> AnyPublisher<[RankingModel], Error>
func fetchPartRanking() -> AnyPublisher<[Domain.PartRankingModel], Error>
func fetchRankingListInPart(part: String) -> AnyPublisher<[RankingModel], Error>
}
117 changes: 71 additions & 46 deletions SOPT-iOS/Projects/Domain/Sources/UseCase/RankingUseCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,57 +11,82 @@ import Combine
import Core

public protocol RankingUseCase {
func fetchRankingList(isCurrentGeneration: Bool)
func findMyRanking()
var rankingListModelFetched: CurrentValueSubject<[RankingModel], Error> { get }
var myRanking: PassthroughSubject<(section: Int, item: Int), Error> { get set }
func fetchRankingList(isCurrentGeneration: Bool)
func fetchRankingList(part: String)
func findMyRanking()
func fetchPartRanking()

var rankingListModelFetched: CurrentValueSubject<[RankingModel], Error> { get }
var myRanking: PassthroughSubject<(section: Int, item: Int), Error> { get set }
var partRanking: PassthroughSubject<[PartRankingModel], Error> { get }
}

public class DefaultRankingUseCase {

private let repository: RankingRepositoryInterface
private var cancelBag = CancelBag()
public var rankingListModelFetched = CurrentValueSubject<[RankingModel], Error>([])
public var myRanking = PassthroughSubject<(section: Int, item: Int), Error>()

public init(repository: RankingRepositoryInterface) {
self.repository = repository
}

private let repository: RankingRepositoryInterface
private var cancelBag = CancelBag()
public var rankingListModelFetched = CurrentValueSubject<[RankingModel], Error>([])
public var myRanking = PassthroughSubject<(section: Int, item: Int), Error>()
public let partRanking = PassthroughSubject<[PartRankingModel], Error>()

public init(repository: RankingRepositoryInterface) {
self.repository = repository
}
}

extension DefaultRankingUseCase: RankingUseCase {
public func fetchRankingList(isCurrentGeneration: Bool) {
self.repository
.fetchRankingListModel(isCurrentGeneration: isCurrentGeneration)
.map { model in
var newModel = model
let myRankingIndex = self.findMyRankingIndex(model: model)
newModel[myRankingIndex].setMyRanking(true)
return newModel
}
.withUnretained(self)
.sink { completion in
print(completion)
} receiveValue: { owner, model in
owner.rankingListModelFetched.send(model)
}.store(in: self.cancelBag)
}

public func findMyRanking() {
let myRankingIndex = self.findMyRankingIndex(model: rankingListModelFetched.value)

if myRankingIndex > 2 {
myRanking.send((1, myRankingIndex - 3))
} else {
myRanking.send((0, 0))
}
}

private func findMyRankingIndex(model: [RankingModel]) -> Int {
let myUserName = UserDefaultKeyList.User.soptampName
let index = model.firstIndex { model in
model.username == myUserName
} ?? 0
return index
public func fetchRankingList(isCurrentGeneration: Bool) {
self.repository
.fetchRankingListModel(isCurrentGeneration: isCurrentGeneration)
.map { model in
var newModel = model
let myRankingIndex = self.findMyRankingIndex(model: model)
newModel[myRankingIndex].setMyRanking(true)
return newModel
}
.withUnretained(self)
.sink { completion in
print(completion)
} receiveValue: { owner, model in
owner.rankingListModelFetched.send(model)
}.store(in: self.cancelBag)
}

public func fetchPartRanking() {
self.repository
.fetchPartRanking()
.sink { completion in
print(completion)
} receiveValue: { [weak self] rankingModels in
self?.partRanking.send(rankingModels)
}.store(in: cancelBag)
}

public func fetchRankingList(part: String) {
self.repository
.fetchRankingListInPart(part: part)
.sink { completion in
print(completion)
} receiveValue: { [weak self] rankingModels in
self?.rankingListModelFetched.send(rankingModels)
}.store(in: cancelBag)
}

public func findMyRanking() {
let myRankingIndex = self.findMyRankingIndex(model: rankingListModelFetched.value)

if myRankingIndex > 2 {
myRanking.send((1, myRankingIndex - 3))
} else {
myRanking.send((0, 0))
}
}

private func findMyRankingIndex(model: [RankingModel]) -> Int {
let myUserName = UserDefaultKeyList.User.soptampName
let index = model.firstIndex { model in
model.username == myUserName
} ?? 0
return index
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// Part.swift
// StampFeatureInterface
//
// Created by Aiden.lee on 2024/04/06.
// Copyright © 2024 SOPT-iOS. All rights reserved.
//

import Foundation

public enum Part: String, CaseIterable {
case plan = "기획"
case design = "디자인"
case web = ""
case ios = "아요"
case android = "안드"
case server = "서버"

public func uppercasedName() -> String {
switch self {
case .plan: return "PLAN"
case .design: return "DESIGN"
case .web: return "WEB"
case .ios: return "IOS"
case .android: return "ANDROID"
case .server: return "SERVER"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import BaseFeatureDependency
public enum RankingViewType {
case all
case currentGeneration(info: UsersActiveGenerationStatusViewResponse)
case partRanking
case individualRankingInPart(part: Part)
}

public protocol StampFeatureViewBuildable {
Expand All @@ -29,5 +31,6 @@ public protocol StampFeatureViewBuildable {
completionHandler: (() -> Void)?
) -> MissionCompletedViewControllable
func makeRankingVC(rankingViewType: RankingViewType) -> RankingViewControllable
func makePartRankingVC(rankingViewType: RankingViewType) -> PartRankingViewControllable
func makeStampGuideVC() -> StampGuideViewControllable
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,27 @@ import Domain

public protocol MissionListViewControllable: ViewControllable & MissionListCoordinatable { }
public protocol MissionListCoordinatable {
var onSwiped: (() -> Void)? { get set }
var onNaviBackTap: (() -> Void)? { get set }
var onRankingButtonTap: ((RankingViewType) -> Void)? { get set }
var onCurrentGenerationRankingButtonTap: ((RankingViewType) -> Void)? { get set }
var onGuideTap: (() -> Void)? { get set }
var onCellTap: ((MissionListModel, _ username: String?) -> Void)? { get set }
var onSwiped: (() -> Void)? { get set }
var onNaviBackTap: (() -> Void)? { get set }
var onPartRankingButtonTap: ((RankingViewType) -> Void)? { get set }
var onCurrentGenerationRankingButtonTap: ((RankingViewType) -> Void)? { get set }
var onGuideTap: (() -> Void)? { get set }
var onCellTap: ((MissionListModel, _ username: String?) -> Void)? { get set }
}
public protocol ListDetailViewControllable: ViewControllable & ListDetailCoordinatable { }
public protocol ListDetailCoordinatable {
var onComplete: ((StarViewLevel, (() -> Void)?) -> Void)? { get set }
var onComplete: ((StarViewLevel, (() -> Void)?) -> Void)? { get set }
}
public protocol MissionCompletedViewControllable: ViewControllable { }
public protocol RankingViewControllable: ViewControllable & RankingCoordinatable { }
public protocol RankingCoordinatable {
var onCellTap: ((_ username: String, _ sentence: String) -> Void)? { get set }
var onSwiped: (() -> Void)? { get set }
var onNaviBackTap: (() -> Void)? { get set }
var onCellTap: ((_ username: String, _ sentence: String) -> Void)? { get set }
var onNaviBackTap: (() -> Void)? { get set }
}

public protocol PartRankingCoordinatable {
var onCellTap: ((_ part: Part) -> Void)? { get set }
var onNaviBackTap: (() -> Void)? { get set }
}
public protocol PartRankingViewControllable: ViewControllable & PartRankingCoordinatable { }
public protocol StampGuideViewControllable: ViewControllable { }
Loading

0 comments on commit 9dea61a

Please sign in to comment.