0

I am new to programming and Swift is my first programming language that I am learning, I apologize if the answer to the question is too obvious. My app requires amount of players to be added and number of teams the user wishes to divide the players into. With even numbers my tableView works fine, if the user inserts 6 players and selects 2 teams they will be divided into 2 teams of 3 and so on with even numbers but if the user inserts 7 players and divides it into 2 teams it will do the same but the extra player will not appear. I wish for the the odd number of players to always appear in the last section of the tableView with any odd number of players the user inserts while the rest of the sections are even. I've tried different things in my func cellForRowAt to achieve this but with no luck. Here is my code:

import UIKit
import CoreData
import ChameleonFramework

class ShuffledTableViewController: UITableViewController {


override func viewDidLoad() {
    super.viewDidLoad()
    
    navigationController?.navigationBar.tintColor = UIColor.yellow
    loadedShuffledPlayers()
    tableView.reloadData()
    tableView.register(UINib(nibName: "ShuffledTableViewCell", bundle: nil), forCellReuseIdentifier: "shuffledCell")
    
}

//Player comes from core data
var shuffledPlayers = [Player]()

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var numberOfTeams = Int()

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return shuffledPlayers.count / numberOfTeams
    
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "shuffledCell", for: indexPath) as! ShuffledTableViewCell
    
    let rowsPerSection = shuffledPlayers.count / numberOfTeams
    let rowInSection = indexPath.row + rowsPerSection * indexPath.section
    
    cell.shuffledLabel.text = shuffledPlayers[rowInSection].names
    cell.shuffledLabel.textColor = UIColor.randomFlat().lighten(byPercentage: 10)
    cell.backgroundColor = UIColor.black
   
    
    return cell
}

func loadedShuffledPlayers(){
    
    let request: NSFetchRequest<Player> = Player.fetchRequest()
    do{
        shuffledPlayers = try context.fetch(request).shuffled()
    }catch{
        print("Error loading data from core data. \(error)")
    }
    
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return numberOfTeams
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return "Team # \(section + 1)"
    
}


override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int){
    
    let header = view as! UITableViewHeaderFooterView
    header.textLabel?.textColor = UIColor.white
}

}

Chamoy
  • 41
  • 7
  • 1
    You should look into the difference between`/` and `%` in Swift (and programming in general) – AdamPro13 Mar 10 '22 at 05:55
  • First you should compute all your numbers outside the dataSource methods and keep the result as view controller properties or in a playlist model . Then use method to get number of teams, number of players for each team, not affected players, players in each team,… – Ptit Xav Mar 10 '22 at 07:17

2 Answers2

1

Let's say we have 11 players and 3 teams...

If we calculate the number of players per team using Integer division, we get 11 / 3 == 3 ... but 3 teams (sections) of 3 players only gets us to 9 players, and we have 2 "leftover" players.

So, we want a result of 3 sections, containing:

3 players
4 players (3 plus one of the leftovers)
4 players (3 plus one of the leftovers)

First, let's get the Integer value of players per team:

// total number of players
let numPlayers = shuffledPlayers.count
    
// Integer value of players per team
let playersPerTeam = numPlayers / numberOfTeams

Next, we'll use the Modulo operator to get the "extra players":

// modulo (remainder) of "extra players"
let mod: Int = numPlayers % numberOfTeams
    

In this example of 11 players / 3 teams, mod == 2, which means the last 2 teams each need an extra player.

So, we check to see if the team (section) is greater than or equal to the number of teams minus the count of "extra players":

// if section is greater than or equal to
//  number of teams minus "extra players"
if section >= numberOfTeams - mod {
    // return players per team Plus 1
    return playersPerTeam + 1
}
// else return players per team
return playersPerTeam

The full func now looks like this:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    // total number of players
    let numPlayers = shuffledPlayers.count
    
    // Integer value of players per team
    let playersPerTeam = numPlayers / numberOfTeams
    
    // modulo (remainder) of "extra players"
    let mod: Int = numPlayers % numberOfTeams
    
    // if section is greater than or equal to
    //  number of teams minus "extra players"
    if section >= numberOfTeams - mod {
        // return players per team Plus 1
        return playersPerTeam + 1
    }
    // else return players per team
    return playersPerTeam

}

Of course, I'm assuming you're doing your own user-entry validation, to avoid something like "7 players split into 12 teams".

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • This works exactly as I intended to, I really appreciate the code example and notes it helped me understand everything and that I need to learn more about remainder operations. Thank you!!! @DonMag – Chamoy Mar 10 '22 at 15:28
0
//there is the problem, your number of rows in last section is wrong
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return shuffledPlayers.count / numberOfTeams
// if shuffledPlayers.count = 7 and numberOfTeams = 2, the result is 3
//so you should do something like that:
/*
* if section == numberOfTeams {
*    return shuffledPlayers.count % numberOfTeams + shuffledOlayers.count / numberOfTeams
* } else { 
*    return shuffledOlayers.count / numberOfTeams
* }
*/
}
Kang
  • 63
  • 6
  • I have tried your code but it seems to do the same, it cuts the odd player from the tableView and only shows the even number of players. – Chamoy Mar 10 '22 at 13:15