Newbie: Written a Chess Grading App: Having Coding Issue

Hi, I’m Dave,

I have written a simple app for displaying grade/ratings results and changes in grade through the results of a win/loss or draw of Chess games played in my local area. I have successfully put it on TestFlight. There is an issue that I want to address.

I have a number of IF statements in my code… and it is difficult to express the new totals of the grades which are accumulated by gains and losses in the games people play.

I would like to use newGrade = newGrade + (increase/decrease due to win/loss or draw)

But I can’t seem to do this.

I am a Physicist and have used different programming languages to Swift.

If you would like me to present code or explain things in more detail then I will try.

I hope I can solve this issue as if would make the app much more functional.

I will leave if there for now and hope this will spark some interest in what I am trying to do!

Thanks and Kind Regards,

Dave

Can you post the relevant code? To format it correctly, surround the code above and below with three back quotes ( ``` I think that’s what they’re called) like this:

var sampleCode: String

And welcome to the group.

Hi, I’m a bit nervous showing code for the first time in case I’ve made loads of coding mistakes, but it is there below. I have removed the pInctot variable (//) which doesn’t work in IF statements. I’ve put in a screenshot, if it uploads properly, which shows the numbers I would like to add up circled in red. Hope this all makes sense. Dave

import SwiftUI
import Foundation


struct ScoresView: View
{
    
    //    var value1: Int
    //    var value2: Int
    //    var diff: Int
    
    var gradeOpponent: String = ""
    var forPlayerID: String = ""
    var forPlayerGrade: String = ""
    var oInc: Double = 0.0
    let m: Int = 0
    
    
    
    var scores = ScoreList.loadCSV(from: "GamesGwentFile")
    var players = PlayerList.loadCSV(from: "players")
    
    var body: some View
    {
        
        
        List()
        {
            
            ForEach(scores.filter { $0.player1.contains(forPlayerID) || $0.player2.contains(forPlayerID)})
            {
                score in
                                   
                    
                    VStack(spacing: 5)
                    {
                        HStack
                        {
                            
                            if forPlayerID == score.player1 {
                                
                                
                                Text( score.player2 )
                                    .font(.system(size: 20, weight: .bold, design: .default))
                                Spacer()
                                if score.result == "1" {
                                    Text("Win")
                                } else if score.result == "0" {
                                    Text("Loss")
                                } else {
                                    Text( "Draw" )
                                }
                            }
                            
                            
                            if forPlayerID == score.player2 {
                                Text( score.player1 )
                                    .font(.system(size: 20, weight: .bold, design: .default))
                                Spacer()
                                if score.result == "1" {
                                    Text("Loss")
                                } else if score.result == "0" {
                                    Text("Win")
                                } else {
                                    Text( "Draw" )
                                }
                                
                            }
                        }
                        Text(score.dateID + " - " + score.event)
                            .font(.system(size:12, weight: .light, design: .default))
                        
                        let myString = score.Ra
                        let oInc = Double(myString)!
       
                        
                        if score.player1 == forPlayerID {
                            Text(score.player2 + " is graded " + score.finRatingP2)
                                .font(.system(size:14, weight: .light, design: .default))
                        } else {
                            Text(score.player1 + " is graded " + score.finRatingP1)
                                .font(.system(size:14, weight: .light, design: .default))
                        }
                        
                        if oInc > 0 && score.player1 == forPlayerID {
                            //                      let pIncTot = pIncTot + oInc
                            Text(forPlayerID + " gained " + score.Ra + " points. ")
                                .font(.system(size:12, weight: .semibold, design: .default))
                            //                       Text("\(Int(pGrade+oInc))")
                            
                        } else if oInc > 0 && score.player2 == forPlayerID {
                            
                            Text(forPlayerID + " lost " + score.Rb + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                        } else if oInc < 0 && score.player1 == forPlayerID {
                            
                            Text(forPlayerID + " lost " + score.Ra + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                        } else if oInc < 0 && score.player2 == forPlayerID {
                            
                            Text(forPlayerID + " gained " + score.Rb + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                        }
                        
                    }
            
                    
                }.navigationTitle(forPlayerID + " " + forPlayerGrade)
                Text("No further games for \(forPlayerID)")
                .font(.system(size: 10, weight: .light, design: .default))
                
          
            
        }
    }
}




struct ScoresView_Previews: PreviewProvider {
    static var previews: some View {
        ScoresView(forPlayerID: "Jonathan LB Blackburn", forPlayerGrade:"2240")
    }
}

When you say

What do you mean “you can’t seem to do this”? What happens when you have that code?

Just some thoughts:

  1. You can code something like: “newGrade += increase” to update the grade, assuming it’s a numeric.
  2. I don’t know if this is part of the problem, but are you aware of State variables? You define one as follows:
@State private var newGrade = 0
   .
   .
   .
Text("The new grade is \(newGrade)")

Then, whenever newGrade changes, the display is automatically updated to show the new value.

Let me know if that helps or not.

Hi, Thanks Pete for your help.

I tried to do as you say:

    var gradeOpponent: String = ""
    var forPlayerID: String = ""
    var forPlayerGrade: String = ""
    var oInc: Double = 0.0
//    @State private var pGrade: Int = 0

    
    
    var scores = ScoreList.loadCSV(from: "GamesGwentFile")
    var players = PlayerList.loadCSV(from: "players")
    
    var body: some View
    {

Here is the calculation part:


                        let myString = score.Ra
                        let oInc = Double(myString)!
                        
//                        let nyString = forPlayerGrade
//                        let pGrade = Int(nyString)!
                        
                        if score.player1 == forPlayerID {
                            Text(score.player2 + " is graded " + score.finRatingP2)
                                .font(.system(size:14, weight: .light, design: .default))
                        } else {
                            Text(score.player1 + " is graded " + score.finRatingP1)
                                .font(.system(size:14, weight: .light, design: .default))
                        }
                        
                        if oInc > 0 && score.player1 == forPlayerID {
//                            pGrade += oInc
                            Text(forPlayerID + " gained " + score.Ra + " points. ")
                                .font(.system(size:12, weight: .semibold, design: .default))
 //                           Text("\(pGrade)")
                            
                        } else if oInc > 0 && score.player2 == forPlayerID {
                            
                            Text(forPlayerID + " lost " + score.Rb + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                        } else if oInc < 0 && score.player1 == forPlayerID {
                            
                            Text(forPlayerID + " lost " + score.Ra + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                        } else if oInc < 0 && score.player2 == forPlayerID {
                            
                            Text(forPlayerID + " gained " + score.Rb + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                        }

but it comes up with:

== PREVIEW UPDATE ERROR:

CompileDylibError: Failed to build ScoresView.swift

Compiling failed: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

I think it is to do with the array containing all string data and having to convert the relevant data to double manually.

Do you think I should copy the array somehow to have the relevant date already as Int and Double type before doing the calculations?

I’m not sure exactly how this is done though.

Thanks for your help.

Dave

One problem I see is where you have

pGrade += oInc

pGrade is an Int while oInc is a Double. Swift doesn’t like that.
You can try

pGrade += Int(oInc)

Is this what you meant when you said “I can’t seem to do this”?

I think the main problem is that I read a CSV file at a String of data and it incorporates the data as Strings in the array. When I try to convert the data to Doubles or Ints it seems that Swift can cope maybe?

The error message still says to breakdown the code into distinct sub expressions.

Is this possible?

Here is the code:

import SwiftUI
import Foundation


struct ScoresView: View
{
    
    //    var value1: Int
    //    var value2: Int
    //    var diff: Int
    
    var gradeOpponent: String = ""
    var forPlayerID: String = ""
    var forPlayerGrade: String = ""
    var mystring: String = ""
    var nyString: String = ""
    
    @State private var pGrade: Int = 0
    @State private var oInc: Int = 0
    
    
    var scores = ScoreList.loadCSV(from: "GamesGwentFile")
    var players = PlayerList.loadCSV(from: "players")
    
    var body: some View
    {
//        let scoreDoubleArray = scores.map { Double($0) ?? 0 }

        List()
        {
            
            ForEach(scores.filter { $0.player1.contains(forPlayerID) || $0.player2.contains(forPlayerID)})
            {
                score in


                    
                    VStack(spacing: 5)
                    {
                        HStack
                        {
                            
                            if forPlayerID == score.player1 {
                                
                                
                                Text( score.player2 )
                                    .font(.system(size: 20, weight: .bold, design: .default))
                                Spacer()
                                if score.result == "1" {
                                    Text("Win")
                                } else if score.result == "0" {
                                    Text("Loss")
                                } else {
                                    Text( "Draw" )
                                }
                            }
                            
                            
                            if forPlayerID == score.player2 {
                                Text( score.player1 )
                                    .font(.system(size: 20, weight: .bold, design: .default))
                                Spacer()
                                if score.result == "1" {
                                    Text("Loss")
                                } else if score.result == "0" {
                                    Text("Win")
                                } else {
                                    Text( "Draw" )
                                }
                                
                            }
                        }
                        Text(score.dateID + " - " + score.event)
                            .font(.system(size:12, weight: .light, design: .default))

                        var myString = score.Ra
                        var oInc = Int(myString)!

                        var nyString = forPlayerGrade
                        pGrade = Int(nyString)!
/*
                        if score.player1 == forPlayerID {
                            Text(score.player2 + " is graded " + score.finRatingP2)
                                .font(.system(size:14, weight: .light, design: .default))
                        } else {
                            Text(score.player1 + " is graded " + score.finRatingP1)
                                .font(.system(size:14, weight: .light, design: .default))
                        }
*/
                        if oInc > 0 && score.player1 == forPlayerID {
                            
                            Text(forPlayerID + " gained " + score.Ra + " points. ")
                                .font(.system(size:12, weight: .semibold, design: .default))
                            pGrade += Int(oInc)
                            Text("\(Int(pGrade))")
                            
                        } else if oInc > 0 && score.player2 == forPlayerID {
                            
                            Text(forPlayerID + " lost " + score.Rb + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                            pGrade += Int(oInc)
                            Text("\(Int(pGrade))")
                            
                        } else if oInc < 0 && score.player1 == forPlayerID {
                            
                            Text(forPlayerID + " lost " + score.Ra + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                            pGrade += Int(oInc)
                            Text("\(Int(pGrade))")
                            
                        } else if oInc < 0 && score.player2 == forPlayerID {
                            
                            Text(forPlayerID + " gained " + score.Rb + " points.")
                                .font(.system(size:12, weight: .semibold, design: .default))
                            pGrade += Int(oInc)
                            Text("\(Int(pGrade))")
                            
                        }
                        
                    }
            
                    
                }.navigationTitle(forPlayerID + " " + forPlayerGrade)
                Text("No further games for \(forPlayerID)")
                .font(.system(size: 10, weight: .light, design: .default))
                
          
            
        }
    }
}




struct ScoresView_Previews: PreviewProvider {
    static var previews: some View {
        ScoresView(forPlayerID: "Jonathan LB Blackburn", forPlayerGrade:"2390")
    }
}

Note that you cannot include computations of any type inside a view other than declare a constant (a let). In other words you cannot do this:

var myString = score.Ra
var oInc = Int(myString)!

var nyString = forPlayerGrade
pGrade = Int(nyString)!

or this:

} else if oInc < 0 && score.player2 == forPlayerID {

    Text(forPlayerID + " gained " + score.Rb + " points.")
        .font(.system(size:12, weight: .semibold, design: .default))
    pGrade += Int(oInc)  //  You can't do this as the code does not return a view.
    Text("\(Int(pGrade))")
}

As an alternative you could do this by placing the computation inside the Text element:

} else if oInc < 0 && score.player2 == forPlayerID {

    Text(forPlayerID + " gained " + score.Rb + " points.")
        .font(.system(size:12, weight: .semibold, design: .default))
    // pGrade += Int(oInc)  //  You can't do this as the code does not return a view.
    Text("\(Int(pGrade += Int(oInc))")
}