Android Question Need help with structures

KKmac

Member
I have been using Visual Studio for 12+ years. This is my first go around with B4A. I can't seem to find the right answer for creating structures. For example, in Visual Studio

Structure PersonDefinition
Dim Name as String
Dim Address as String
Dim City as String
Dim Age as Integer
End Structure

Dim Person() as PersonDefinition

So I can have Person(0) as a person, Person(1) as a different person, etc.
Person(0).Name = "Kevin"or Person(1).Age = 30.
If I want to sort that array, I can create keys for the sorting by column, such as age.

The only way I found (so far) to create this structure in B4A is:

Dim PersonDefinition(Name as String, Address as String, City as String, Age as Int)
Dim Person() as PersonDefinition

If this is the right way, then how would I sort this by age, or alphabetically by name?

I found one place that said to put it in a list, then sort the list. I did that, and it worked, to a degree.
However, I couldn't just use MySortList(0).Name to get the info I need.

It's very clear to me that the terminology is vastly different for the same thing, such as in VS, they are Forms, where B4A is Pages.
I can't seem to locate the proper term for structures. I have read about arrays, collections, and maps. But they aren't very clear. I guess it's just not clicking yet.

Also, my example is shortened. In my "structure", I have far more declaration, such as First Name, Last Name, Address, City, State, Zip, Email, Phone, and so on.

While there are a number of coding similarities, this really isn't visual basic. At least not the one I know.

One more obstacle, My Person declaration itself is multi-array.

Dim Person(5, 20) as PersonDefinition

Kinda hard to explain why I am doing this. I have an event with contestants, and the first array represents each round of competition.
People get eliminated each round, so the second declaration (20) will decrease each round.

I need to be able to sort this mess. I could do this all day long in VS, but things are different here.
I almost never ask for help in a forum, but I am stumped.

Can anyone shed some light on what I have right, wrong, and what I should be doing instead.

Thanks
 

KKmac

Member
Array = RedimPreserve(Array, #) did not work. Don't know if I need to import a library or something.

I ended up writing my own Redim subroutine.

I created a temporary array larger than the original, then copied the contents of the original array into the matching indexes of the new temp array, leaving the expanded part blank.

Then replaced the original with the new array.

I know B4A is very different from VB, but with VB, I know how to do what I want.
As Yoda wisely said "I must unlearn, what I have learned!"

Image buying a car, but how it starts, steers, throttles and brakes are very different than what we know.
That is what I am struggling with.

While I am using lists for some of my stuff, I could not figure out how to use lists for a different part.

As I stated earlier, am creating an app for tasting beer.
We sample different beers blindly, then score each one.

Keeping score requires tracking the Round, Judge, Beer Entry, and Scoring Category
Usually, we have 4 categories for scoring. We can have up to 15 judges (each with a beer entry).
Thus the reason for Redim Array.
If there is a tie, then we need addition rounds of serving to break the tie.

I created a matrix style array to do this. ScoreSheet(CurrentRound, SelectedJudge, SelectedEntry, Category) as Int

CurrentRound = the round of sampling. Zero is the first round
SelectedJudge = The scoresheet from any one judge. Anywhere up to 15 (the real limit is 24)
SelectedEntry = The beer that was sampled. Everyone that comes submits something is secret.
SelectedCategory = The scoring category for each entry served. Anywhere from 1 to 8 user definable categories .

So a real world example would look like Scoresheet(0, 2, 1, 3) = 3, which would be the score of the first round, judge 3, beer entry 2, 4th category
This is the part I could not figure out how to do in a list. This would have been an indexing nightmare, as I am not very familiar with lists.

The scoresheet for a single judge would look like:
Round 1 judge 3

'The first beer sampled
Scoresheet(0, 2, 0, 0) = 4
Scoresheet(0, 2, 0, 1) = 3
Scoresheet(0, 2, 0, 2) = 3
Scoresheet(0, 2, 0, 3) = 4

The second beer sampled
Scoresheet(0, 2, 1, 0) = 2
Scoresheet(0, 2, 1, 1) = 4
Scoresheet(0, 2, 1, 2) = 3
Scoresheet(0, 2, 1, 3) = 2

and so on, based on a scale of 1 to 5.

I have made great progress with my app, and what I have done is working.

I can register guests, serve and assign serving order to each entry, (so we know what order the entries were serve in),
enter scores per judge and calculate total scores, and even determine the winning position,
such as 1st place, 2nd place, etc. This has error detection, so if an error was made entering scores, it notifies the user.
If a user is disqualified, it will not count that judges scores, and much more.
Still got more to do, like writing info to file, reading data from file, and other user options.

Typically, when I need help, I will Google it first and try to make sense of what comes up.
YouTube is another place I search, but many of the B4A tutorials are by people with heavy accents, not English, poor audio, or very slow in getting to the point.
I really hate watching a video for 20 minutes to realize the answer I need is not in it.

I do appreciate everyone's help and concern for my progress. I am doing well and if I need anything else, I will absolutely ask.

Thanks.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Here is an example using a List and custom Type.

B4X:
Sub Process_Globals
    Type ScoreSheet (CurrentRound As Int, SelectedJudge As Int, SelectedEntry As Int, SelectedCategory As Int, Score As Int)
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
  
    Dim ScoreSheets As List
    ScoreSheets.Initialize
 
    ScoreSheets.Add(CreateScoreSheet(0, 2, 0, 0, 4))
    ScoreSheets.Add(CreateScoreSheet(0, 2, 0, 1, 3))
    ScoreSheets.Add(CreateScoreSheet(0, 2, 0, 2, 3))
    ScoreSheets.Add(CreateScoreSheet(0, 2, 0, 3, 4))
    Log("Total scores for Round 1, Judge 3, Entry 1 = " & CalculateScoreByRoundJudgeEntry(ScoreSheets, 0, 2, 0))

    ScoreSheets.Add(CreateScoreSheet(0, 2, 1, 0, 2))
    ScoreSheets.Add(CreateScoreSheet(0, 2, 1, 1, 4))
    ScoreSheets.Add(CreateScoreSheet(0, 2, 1, 2, 3))
    ScoreSheets.Add(CreateScoreSheet(0, 2, 1, 3, 2))
    Log("Total scores for Round 1, Judge 3, Entry 2  = " & CalculateScoreByRoundJudgeEntry(ScoreSheets, 0, 2, 1))
 
    Log("Total scores for Round 1, Judge 3 = " & CalculateScoreByRoundJudge(ScoreSheets, 0, 2))
 
    Log("Score for Round 1, Judge 3, Entry 1, Category 4 before setting new value = " & GetScoreByRoundJudgeEntryCategory(ScoreSheets, 0, 2, 0, 3))
    ' Update score for Round 1, Judge 3, Entry 1, Category 4 from 4 to 1
    SetScoreByRoundJudgeEntryCategory(ScoreSheets, 0, 2, 0, 3, 1)
    Log("Score for Round 1, Judge 3, Entry 1, Category 4 after setting new value = " & GetScoreByRoundJudgeEntryCategory(ScoreSheets, 0, 2, 0, 3))
 
    Log("Total scores for Round 1, Judge 3 after setting new score = " & CalculateScoreByRoundJudge(ScoreSheets, 0, 2))
End Sub

Sub GetScoreByRoundJudgeEntryCategory (ScoreSheetList As List, CurrentRound As Int, SelectedJudge As Int, SelectedEntry As Int, SelectedCategory As Int) As Int
    For Each item As ScoreSheet In ScoreSheetList
        If item.CurrentRound = CurrentRound And _
        item.SelectedJudge = SelectedJudge And _
        item.SelectedEntry = SelectedEntry And _
        item.SelectedCategory = SelectedCategory Then
            Return item.Score
        End If
    Next
    Return 0 ' not found
End Sub

Sub SetScoreByRoundJudgeEntryCategory (ScoreSheetList As List, CurrentRound As Int, SelectedJudge As Int, SelectedEntry As Int, SelectedCategory As Int, Score As Int)
    For Each item As ScoreSheet In ScoreSheetList
        If item.CurrentRound = CurrentRound And _
        item.SelectedJudge = SelectedJudge And _
        item.SelectedEntry = SelectedEntry And _
        item.SelectedCategory = SelectedCategory Then
             item.Score = Score
        End If
    Next
End Sub

Sub CalculateScoreByRoundJudgeEntry (ScoreSheetList As List, CurrentRound As Int, SelectedJudge As Int, SelectedEntry As Int) As Int
    Dim TotalScore As Int
    For Each item As ScoreSheet In ScoreSheetList
        If item.CurrentRound = CurrentRound And _
        item.SelectedJudge = SelectedJudge And _
        item.SelectedEntry = SelectedEntry Then
            TotalScore = TotalScore + item.Score
        End If
    Next
    Return TotalScore
End Sub

Sub CalculateScoreByRoundJudge (ScoreSheetList As List, CurrentRound As Int, SelectedJudge As Int) As Int
    Dim TotalScore As Int
    For Each item As ScoreSheet In ScoreSheetList
        If item.CurrentRound = CurrentRound And _
        item.SelectedJudge = SelectedJudge Then
            TotalScore = TotalScore + item.Score
        End If
    Next
    Return TotalScore
End Sub

Public Sub CreateScoreSheet (CurrentRound As Int, SelectedJudge As Int, SelectedEntry As Int, SelectedCategory As Int, Score As Int) As ScoreSheet
    Dim t1 As ScoreSheet
    t1.Initialize
    t1.CurrentRound = CurrentRound
    t1.SelectedJudge = SelectedJudge
    t1.SelectedEntry = SelectedEntry
    t1.SelectedCategory = SelectedCategory
    t1.Score = Score
    Return t1
End Sub

Output:
B4X:
Total scores for Round 1, Judge 3, Entry 1 = 14
Total scores for Round 1, Judge 3, Entry 2  = 11
Total scores for Round 1, Judge 3 = 25
Score for Round 1, Judge 3, Entry 1, Category 4 before setting new value = 4
Score for Round 1, Judge 3, Entry 1, Category 4 after setting new value = 1
Total scores for Round 1, Judge 3 after setting new score = 22

Take note: This is not the best approach because if you add duplicate items into the list, this will cause inaccuracy of results. So use it with caution.
I still recommend to use SQL as a more better solution.
 

Attachments

  • Structures.zip
    14.5 KB · Views: 32
Last edited:
Upvote 0

KKmac

Member
Wow. That's a lot to take in.

I did look them over and a good portion makes sense. I guess I just needed to see the right example.

I will go over your codes more thoroughly in the near future. As for now, what I have is working and I don't want to take a chance of screwing something up
because I may not fully understand whats happening in your codes (yet).

I do heavily appreciate the detailed reply. This should help me a lot in learning B4A.

Just to add a bit more detail about my app, each person samples a beer entry, and rates it (1 to 5) in 4 categories.
This can be from 1 to 8 categories, depending on the user.
Each category (per entry) is totaled for an entry score (by each person).

The score of each entry by all persons are then added.

Ex:
----------------------------------------------------------------------------------------
Judge 1 Category 1 Category 2 Category 3 Category 4 Total
Entry 1 3 2 2 3 10
Entry 2 4 5 4 5 18
Entry 3 4 3 3 3 13
----------------------------------------------------------------------------------------
Judge 2 Category 1 Category 2 Category 3 Category 4 Total
Entry 1 5 5 4 4 18
Entry 2 3 3 3 3 12
Entry 3 2 3 2 2 9
----------------------------------------------------------------------------------------
Judge 3 Category 1 Category 2 Category 3 Category 4 Total
Entry 1 1 2 2 2 7
Entry 2 4 4 4 4 16
Entry 3 3 5 3 4 15
----------------------------------------------------------------------------------------
Entry 1 Score = 35 (10 + 18 + 7)
Entry 2 Score = 46 (18 + 12 + 16)
Entry 3 Score = 37 (13 + 9 + 15)

In the example above, Entry 2 won since it had the highest score. The person that brought that beer is the winner.

As you can see, adding scores can (and is) confusing when trying to add scores on paper. The constant repetition of numbers confuses everyone that tries.
All I need to do is make sure I enter the number on the scoresheet as they wrote them, and this does the math.

Not asking this right now, but I would like (in the future) to make a separate app that people can install on the phones to enter the scores.
Once they enter their scores, they can send them to this main app via WiFi. I wouldn't need to manually enter the scores.
This is something I've never done, even in VB. I am researching Peer to Peer networking but I'm not really ready to start trying.
When I am ready, I will definitely be reaching out.

Thanks again for the incredible reply. This will help a lot.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
The idea is first try to visualize the scoreboard on an Excel.

You need to picture the "columns" of variables that involved.
Then every entry of score is a "row".

This is the same concept if you use SQL database.

Talking about my code above, take an example below:
CreateScoreSheet(0, 2, 0, 0, 4)
The first 4 parameters are considered "fixed" or predefined. The 5th parameter is representing the score which is the value that need to be changed or updated, which ranges from 1 to 5 as you mentioned.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Some people especially who are new to programming feel difficult to understand the concept of beginning an index of an array or List with 0.

When I use SQL, I always start with ID = 1 for my first entry therefore my brain does not need to think about index 0.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
By using SQL table, you name the items in the same group with an English word for the column name.
This help you to understand what it is without referring the order of the array. You can use different order of columns anytime you like.
When doing calculation, there is some buildin function such as the keyword SUM to total up the values. There are other keywords for sorting and filtering.
It is also a better solution to store the big dataset in a single file instead of managing multiple individual text files.
 
Upvote 1

aeric

Expert
Licensed User
Longtime User
You can do a lot of "magic" using SQL.

For example, you can run a single query to calculate the total scores and know who is the winner sorted by place 1st, 2nd and 3rd without writing more programming logic.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Let me represent your data in SQLite.

1729747851750.png

To get the results by Judges in Round 1:
SQL:
SELECT "Round", "Judge", "Entry", SUM("Score") AS "Total"
FROM "Scoresheet"
GROUP BY "Round", "Judge", "Entry"
1729748028491.png

To get the final results for Round 1:
SQL:
SELECT "Round", "Entry", SUM("Score") AS "Total"
FROM "Scoresheet"
GROUP BY "Round", "Entry"
1729748178708.png


To sort the score by highest first,
SQL:
SELECT "Round", "Entry", SUM("Score") AS "Total"
FROM "Scoresheet"
GROUP BY "Round", "Entry"
ORDER BY "Total" DESC
1729748344173.png


I attached an SQLite db for you. You can open it with DB Browser for SQLite. Go to Browse Data tab and select the drop down where I already created the "View". An Excel file is attached too.

1729748877709.png


Now you see how powerful it is? :)
 

Attachments

  • Scoresheet.zip
    9.2 KB · Views: 31
Upvote 0

KKmac

Member
The passion everyone has in helping me with this is truly unbelievable!

As (I think) I stated before, I know how to do all of what I am trying to do, in visual basic / visual studio.
It's learning how it's done in B4A. Different language!

The visualization you provided helped me a lot. The code samples also helped a lot.

Before the code samples were provided, I visualized how it would look in a list format.
I actually did visualize it in an Excel spreadsheet style.
The sample codes and images you provided matched exactly how I envisioned it.

I guess I was trying to not overload the list with too much data. (Duh, that's what's it's for)
I wasn't sure if I needed a separate scoresheet list for each judge or if everything should be in just one list.
I was questioning whether a different list per round was needed.
Maybe it was a lack of self confidence as to why I didn't go with it.

I looked at your sample codes more intently, and understand them now.
But I am so deep into my project that going back and changing what is already working will set me back quite a bit and could cause a bunch of new problems.

I am confident my workaround codes will be just fine, as they resemble VB code.

This is my second time write this app, and I really don't want to start again.

I appreciate everyone taking time to help me with this, and as I move forward, I will apply everything you've taught me.
I know things will get easier as time goes on. It's not like I've never programmed before. I just need time to learn this language.

Thanks again to everyone who helped me. I am truly grateful.

Perhaps, when I am ready, you can help me with the peer to peer WiFi data transfer.
I will start a new thread for that when I am ready.

Thanks again, you rock!!
 
Upvote 0
Top