Skip to content

Commit

Permalink
feat: ability to quickly simulate an entire tourney
Browse files Browse the repository at this point in the history
  • Loading branch information
mvirgo committed Apr 23, 2021
1 parent 0fecc6f commit 6c2732e
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 21 deletions.
92 changes: 85 additions & 7 deletions foam-madness/Controller/BracketCreationViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class BracketCreationViewController: UIViewController, UITextFieldDelegate {

// MARK: Other variables
var dataController: DataController!
var isSimulated: Bool!
var context: NSManagedObjectContext!
var tournament: Tournament!
var tournamentName: String!
Expand All @@ -40,6 +41,8 @@ class BracketCreationViewController: UIViewController, UITextFieldDelegate {
context = dataController.viewContext
// Set text field delegate so keyboard is handled appropriately
self.tourneyNameTextField.delegate = self
// Set button title & hand switch details
setButtonAndHandSwitch()
}

override func viewWillDisappear(_ animated: Bool) {
Expand All @@ -55,6 +58,19 @@ class BracketCreationViewController: UIViewController, UITextFieldDelegate {
}

// MARK: Other functions
func setButtonAndHandSwitch() {
// Set button title & hand switch based on whether it is a simulation
if isSimulated {
createTournamentButton.setTitle("Sim Tournament", for: .normal)
dominantHandLabel.isHidden = true
handSwitch.isHidden = true
} else {
createTournamentButton.setTitle("Create Tournament", for: .normal)
dominantHandLabel.isHidden = false
handSwitch.isHidden = false
}
}

func loadBracket() {
// Update taskLabel for current task
taskLabel.text = "Loading bracket..."
Expand Down Expand Up @@ -123,9 +139,17 @@ class BracketCreationViewController: UIViewController, UITextFieldDelegate {
progressBar.progress += 0.10
}

func alertUser(title: String, message: String) {
func alertUser(title: String, message: String, _ endTournament: Bool) {
let alertVC = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertVC.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
if endTournament {
// Segue to table view of all playable games when done
alertVC.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
self.segueToGamesTable()
}))
} else {
// Come back to view after
alertVC.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
}
self.present(alertVC, animated: true, completion: nil)
}

Expand All @@ -146,6 +170,7 @@ class BracketCreationViewController: UIViewController, UITextFieldDelegate {
tournament.name = tournamentName!
tournament.createdDate = Date()
tournament.isWomens = isWomens
tournament.isSimulated = isSimulated
// Make sure it is saved
saveData()
// Add 5% to progress bar
Expand Down Expand Up @@ -290,7 +315,7 @@ class BracketCreationViewController: UIViewController, UITextFieldDelegate {

func createTournamentGames() {
taskLabel.text = "Creating tournament games..."
// Note: This function is essentially hard-coded for 2020 bracket style
// Note: This function is essentially hard-coded for current bracket style
// Create First Four if Men's tournament
if !isWomens {
createFirstFour()
Expand All @@ -312,21 +337,69 @@ class BracketCreationViewController: UIViewController, UITextFieldDelegate {
return TourneyHelper.fetchData(dataController, predicate, "Tournament").count == 0
}

func simulateTournament() {
var id: Int16
var winner: String = ""
taskLabel.text = "Simulating tournament games..."
// Get correct starting id (hard-coded for current bracket style)
if isWomens {
id = 4
} else {
id = 0
}
// Loop through and simulate all games
while true {
let game = tournament.games?.filtered(using: NSPredicate(format: "tourneyGameId == %@", NSNumber(value: id))).first as! Game
let gameTeams = game.teams?.allObjects as! [Team]
// Ensure proper order of teams
let team1, team2 : Team
if gameTeams[0].id == game.team1Id {
team1 = gameTeams[0]
team2 = gameTeams[1]
} else {
team1 = gameTeams[1]
team2 = gameTeams[0]
}
// Simulate the game
SimHelper.simSingleGame(dataController, game, team1, team2)
// Complete the game
winner = GameHelper.completeGame(dataController, game, team1, team2).name!
id += 1
// Break if done with tournament
if tournament.completion {
break
}
}
// Make sure all is saved
saveData()
// Notify user of winner
let title = "Tournament Complete"
let message = "\(winner) wins the tournament! (Sim)"
alertUser(title: title, message: message, true)
}

func segueToGamesTable() {
performSegue(withIdentifier: "showNewTourneyGames", sender: nil)
}

// MARK: IBActions
@IBAction func createTournamentButtonPressed(_ sender: Any) {
// Set the tournament name based on user input
let name = tourneyNameTextField.text
if name != "" {
if checkExistingNames(name!) { // New tourney name
tournamentName = tourneyNameTextField.text
if isSimulated {
tournamentName += " (Sim)"
}
} else {
// Tell user to find a new name
alertUser(title: "Invalid Name", message: "Tournament name already taken.")
alertUser(title: "Invalid Name", message: "Tournament name already taken.", false)
return
}
} else {
// Tell user to input a name
alertUser(title: "Invalid Name", message: "Tournament name cannot be blank.")
alertUser(title: "Invalid Name", message: "Tournament name cannot be blank.", false)
return
}
// Hide the text field and button
Expand All @@ -352,8 +425,13 @@ class BracketCreationViewController: UIViewController, UITextFieldDelegate {
createTournamentGames()
// End activity indicator motion
activityIndicator.stopAnimating()
// Segue to table view of all playable games
performSegue(withIdentifier: "showNewTourneyGames", sender: nil)
// Simulate, if applicable
if isSimulated {
simulateTournament()
} else {
// Segue to table view of all playable games
segueToGamesTable()
}
}

@IBAction func handSwitchClicked(_ sender: Any) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import CoreData
class SelectInitialBracketViewController: UITableViewController {
// MARK: Variables
var dataController: DataController!
var isSimulated: Bool!
var chosenBracketFile = ""
let brackets = ["2020 Joe Lunardi's Bracketology": "bracketology2020",
"2020 Womens - Charlie Creme's Bracketology": "womensBracketology2020",
Expand Down Expand Up @@ -55,6 +56,8 @@ class SelectInitialBracketViewController: UITableViewController {
vc.bracketLocation = chosenBracketFile
// Send data controller as well
vc.dataController = dataController
// And whether or not simulated
vc.isSimulated = isSimulated
}
}
}
9 changes: 9 additions & 0 deletions foam-madness/Controller/SelectScreenViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class SelectScreenViewController: UIViewController {
performSegue(withIdentifier: "selectBracket", sender: sender)
}

@IBAction func simulateTournamentButtonPressed(_ sender: Any) {
performSegue(withIdentifier: "selectSimulation", sender: sender)
}

@IBAction func viewCompletedTournamentButtonPressed(_ sender: Any) {
performSegue(withIdentifier: "chooseCompletedTournament", sender: sender)
}
Expand All @@ -72,6 +76,11 @@ class SelectScreenViewController: UIViewController {
case "selectBracket":
let vc = segue.destination as! SelectInitialBracketViewController
vc.dataController = dataController
vc.isSimulated = false
case "selectSimulation":
let vc = segue.destination as! SelectInitialBracketViewController
vc.dataController = dataController
vc.isSimulated = true
case "chooseExistingTournament":
let vc = segue.destination as! SelectTournamentViewController
vc.dataController = dataController
Expand Down
21 changes: 14 additions & 7 deletions foam-madness/Controller/TournamentGamesViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,8 @@ class TournamentGamesViewController: UIViewController, UITableViewDelegate, UITa

override func viewDidLoad() {
super.viewDidLoad()
// Add a page title
navigationItem.title = "\(tournament.name!) Games"
// Hide original back button to make one that only goes to Main Menu
navigationItem.hidesBackButton = true
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Main Menu", style: .plain, target: self, action: #selector(self.backToMainMenu))
// Add right stats button
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Stats", style: .plain, target: self, action: #selector(self.statsButtonPressed))
// Set the navigation bar
setNavigationBar()
// Set delegate and datasource for the game table view
self.gameTableView.delegate = self
self.gameTableView.dataSource = self
Expand All @@ -58,6 +53,18 @@ class TournamentGamesViewController: UIViewController, UITableViewDelegate, UITa
}

// MARK: Other functions
func setNavigationBar() {
// Add a page title
navigationItem.title = "\(tournament.name!) Games"
// Hide original back button to make one that only goes to Main Menu
navigationItem.hidesBackButton = true
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Main Menu", style: .plain, target: self, action: #selector(self.backToMainMenu))
// Add right stats button, if not simulated
if (!tournament.isSimulated) {
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Stats", style: .plain, target: self, action: #selector(self.statsButtonPressed))
}
}

func getGamesForRound() {
// Make sure games is now empty
games.removeAll(keepingCapacity: true)
Expand Down
2 changes: 1 addition & 1 deletion foam-madness/Model/ABOUT.rtf
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

\f0 Both men's and women's tournament brackets are available.\
\
You may simulate, and therefore not play, individual tournament games (but not single games) where desired; the winner will be based on historical win probabilities, as used for shooting hand determination in a non-simulated game. Note that no statistics will be recorded, and the winner of the game will be given a winning score of 1 to 0.
You may simulate, and therefore not play, individual tournament games (but not single games), or even an entire tournament, where desired; the winner will be based on historical win probabilities, as used for shooting hand determination in a non-simulated game. Note that no statistics will be recorded, and the winner of each game will be given a winning score of 1 to 0.
\f1 \
\

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@
<attribute name="completion" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="completionDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="createdDate" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="isSimulated" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="isWomens" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="name" optional="YES" attributeType="String"/>
<relationship name="games" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Game" inverseName="tournament" inverseEntity="Game"/>
</entity>
<elements>
<element name="Game" positionX="-328.8125" positionY="-220.640625" width="128" height="509"/>
<element name="Team" positionX="-104.3984375" positionY="0.80859375" width="128" height="105"/>
<element name="Tournament" positionX="-550.69921875" positionY="27.625" width="128" height="135"/>
<element name="Tournament" positionX="-550.69921875" positionY="27.625" width="128" height="134"/>
</elements>
</model>
Loading

0 comments on commit 6c2732e

Please sign in to comment.