Skip to content

Commit

Permalink
Merge pull request #16 from ehdrhelr/feature/iOS/game-play-view
Browse files Browse the repository at this point in the history
[iOS] 로그인 화면 + 게임 선택 화면 + 게임 진행 화면
  • Loading branch information
Lia316 authored May 7, 2021
2 parents 508cb5a + 7c185b1 commit bb085cb
Show file tree
Hide file tree
Showing 28 changed files with 1,787 additions and 39 deletions.
193 changes: 179 additions & 14 deletions iOS/baseball-game/baseball-game.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Binary file not shown.
11 changes: 11 additions & 0 deletions iOS/baseball-game/baseball-game/AppCycle/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)

let rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "LoginViewController") as LoginViewController

let navigationViewController = UINavigationController(rootViewController: rootViewController)

window?.rootViewController = navigationViewController
}
}

127 changes: 121 additions & 6 deletions iOS/baseball-game/baseball-game/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,24 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bc6-zR-OBT">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<!--Login View Controller-->
<scene sceneID="vgB-wA-gkL">
<objects>
<viewController storyboardIdentifier="LoginViewController" id="acG-MO-tPJ" customClass="LoginViewController" customModule="baseball_game" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Rbm-Wg-nXP">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="ump-1U-kn2">
<rect key="frame" x="106" y="287" width="202" height="34"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="로그인 해보시지" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zsQ-El-PkC">
<rect key="frame" x="82" y="87" width="250" height="87"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="26"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fnZ-6B-4DN">
<rect key="frame" x="161" y="358" width="92" height="66"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<state key="normal" title="확인"/>
<connections>
<action selector="okButtonTouched:" destination="acG-MO-tPJ" eventType="touchUpInside" id="jde-2f-lwj"/>
</connections>
</button>
</subviews>
<viewLayoutGuide key="safeArea" id="usz-km-bvy"/>
<color key="backgroundColor" systemColor="systemGray6Color"/>
</view>
<navigationItem key="navigationItem" id="aMp-h1-3sO"/>
<connections>
<outlet property="IDTextField" destination="ump-1U-kn2" id="0Xr-ng-afF"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="XGK-4h-xgL" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="84.057971014492765" y="114.50892857142857"/>
</scene>
<!--Selection View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
<viewController storyboardIdentifier="SelectionViewController" id="BYZ-38-t0r" customClass="SelectionViewController" customModule="baseball_game" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TEj-De-JFw">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="게임 목록" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZaK-Yz-YEw">
<rect key="frame" x="146.5" y="74" width="121.5" height="39.5"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="33"/>
<color key="textColor" systemColor="systemGray5Color"/>
<nil key="highlightedColor"/>
</label>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="120" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="Qom-Qz-GeO">
<rect key="frame" x="10" y="158.5" width="394" height="658.5"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" rowHeight="120" id="pQd-GF-lQg">
<rect key="frame" x="0.0" y="24.5" width="394" height="120"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="pQd-GF-lQg" id="l8i-ge-Lwi">
<rect key="frame" x="0.0" y="0.0" width="394" height="120"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" red="0.040723347715822478" green="0.09781032958678347" blue="0.18880824850063127" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<constraints>
<constraint firstItem="ZaK-Yz-YEw" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="30" id="Fs8-Bi-8jH"/>
<constraint firstItem="Qom-Qz-GeO" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="10" id="Khu-x6-Cnc"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="Qom-Qz-GeO" secondAttribute="trailing" constant="10" id="KvQ-2G-981"/>
<constraint firstItem="Qom-Qz-GeO" firstAttribute="top" secondItem="ZaK-Yz-YEw" secondAttribute="bottom" constant="45" id="SgB-QY-JC0"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="Qom-Qz-GeO" secondAttribute="bottom" constant="45" id="THc-gh-Veh"/>
<constraint firstItem="ZaK-Yz-YEw" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="X5R-nH-yDi"/>
<constraint firstItem="TEj-De-JFw" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="iaF-GG-hhr"/>
<constraint firstAttribute="bottom" secondItem="TEj-De-JFw" secondAttribute="bottom" id="jha-K5-GAK"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="TEj-De-JFw" secondAttribute="trailing" id="pKw-q4-jRU"/>
<constraint firstItem="TEj-De-JFw" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" id="sdR-iG-9cO"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="pCT-Ol-cD7"/>
<connections>
<outlet property="backgroundView" destination="TEj-De-JFw" id="msw-kk-e3V"/>
<outlet property="gameListTableView" destination="Qom-Qz-GeO" id="3md-l4-Ihh"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1042.0289855072465" y="114.50892857142857"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="V5N-W2-hhL">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="bc6-zR-OBT" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="CfT-9w-1yW">
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="acG-MO-tPJ" kind="relationship" relationship="rootViewController" id="5nd-sF-m8A"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iIS-6P-iFA" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-826.08695652173924" y="114.50892857142857"/>
</scene>
</scenes>
<resources>
<systemColor name="systemGray5Color">
<color red="0.89803921568627454" green="0.89803921568627454" blue="0.91764705882352937" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemGray6Color">
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>
119 changes: 119 additions & 0 deletions iOS/baseball-game/baseball-game/GamePlay/GamePlayViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// ViewController.swift
// baseball-game
//
// Created by Song on 2021/05/03.
//

import UIKit
import Combine

class GamePlayViewController: UIViewController {

@IBOutlet weak var pitchListTableView: UITableView!
@IBOutlet weak var pitchButton: UIButton!
@IBOutlet weak var teamScoreView: TeamScoreView!
@IBOutlet weak var inningLabel: UILabel!
@IBOutlet weak var turnLabel: UILabel!
@IBOutlet weak var pitcherInfoView: PitcherInfoView!
@IBOutlet weak var batterInfoView: PitcherInfoView!

enum ViewID {
static let storyboard = "GamePlay"
static let controller = "gamePlay"
static let segue = "selectPitcher"
static let cell = "pitchListCell"
}

private var gamePlayViewModel: GamePlayViewModel!
private var dataSource: UITableViewDiffableDataSource<Int, Pitch>!

private let isUserHomeSide = true
private var cancelBag = Set<AnyCancellable>()

override func viewDidLoad() {
super.viewDidLoad()
self.gamePlayViewModel = GamePlayViewModel(isUserHomeSide)
self.pitchButton.isHidden = true
gamePlayViewModel.requestGame()
configureDataSource()
bind()
}

private func bind() {
gamePlayViewModel.$gameManager
.receive(on: DispatchQueue.main)
.sink { [weak self] gameManager in
guard let gameManager = gameManager else { return }
self?.updateViews(with: gameManager)
}
.store(in: &cancelBag)

gamePlayViewModel.$pitches
.receive(on: DispatchQueue.main)
.sink { [weak self] pitches in
guard let pitches = pitches else { return }
self?.createSnapshot(from: pitches)
}
.store(in: &cancelBag)

gamePlayViewModel.$error
.receive(on: DispatchQueue.main)
.sink { error in
guard let error = error else { return }
print(error) ///사용자에게 에러 표시하는 부분 미구현
}.store(in: &cancelBag)
}

@IBAction func pitcherChangeTouched(_ sender: Any) {
performSegue(withIdentifier: ViewID.segue, sender: nil)
}

private func updateViews(with gameManager: GameManagable) {
teamScoreView.updateTeamNames(from: gameManager.teams())
teamScoreView.updateScores(from: gameManager.scores())
inningLabel.text = gameManager.inning()
pitcherInfoView.updateLabels(from: gameManager.pitcher())
batterInfoView.updateLabels(from: gameManager.batter())

guard let isUserDefense = gameManager.isUserDefense() else { return }

if isUserDefense {
self.pitchButton.isHidden = false
turnLabel.text = GameManager.Role.defense
pitcherInfoView.highlight()
batterInfoView.unhighlight()
} else {
self.pitchButton.isHidden = true
turnLabel.text = GameManager.Role.offense
pitcherInfoView.unhighlight()
batterInfoView.highlight()
}
}
}

extension GamePlayViewController {

private func configureDataSource() {
self.dataSource = UITableViewDiffableDataSource.init(tableView: pitchListTableView) {
(tableView, indexPath, pitch) -> UITableViewCell in

guard let cell = self.pitchListTableView.dequeueReusableCell(withIdentifier: ViewID.cell) as? PitchListTableViewCell else {
return PitchListTableViewCell()
}

let index = indexPath.row
cell.updateLabels(count: index, result: pitch.result, log: pitch.log)

return cell
}
}

private func createSnapshot(from pitches: [Pitch]) {
var snapshot = NSDiffableDataSourceSnapshot<Int, Pitch>()

snapshot.appendSections([0])
snapshot.appendItems(pitches, toSection: 0)
self.dataSource.apply(snapshot)
}
}
24 changes: 24 additions & 0 deletions iOS/baseball-game/baseball-game/GamePlay/Model/GameManagable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// GameManagable.swift
// baseball-game
//
// Created by Song on 2021/05/06.
//

import Foundation

protocol GameManagable {

func teams() -> [String: String]

func scores() -> [String: Int]

func inning() -> String

func pitcher() -> Player

func batter() -> Player

func isUserDefense() -> Bool?

}
Loading

0 comments on commit bb085cb

Please sign in to comment.