How to create a table of records?

Find quick help here to get you started with Hollywood
User avatar
Juan Carlos
Posts: 887
Joined: Mon Sep 06, 2010 1:02 pm

Re: How to create a table of records?

Post by Juan Carlos »

Thank you jPV for your advices, I have a code in a little program that is works, here is, and I remove the item money.

Code: Select all

Tabla Hall Of Fame.
Global hallfametable={
    {name="Joe", points=100},
    {name="Juan", points=80},
    {name="Lucia", points=78},
    {name="Ines", points=45},
    {name="Rene", points=21},
    {name="Megan", points=120},
    {name="Megan", points=150},
    {name="Rodrigo", points=6},
    {name="Laura", points=5},
    {name="Jack", points=4}
  }

/**************************************************************************************************/
@DISPLAY {Title="Hall of Fame", Width=480, Height=350, Color=#BLACK, Borderless=False, NoClose=False,
	 KeepProportions=True, Sizeable=False, NoModeSwitch=True}
/**************************************************************************************************/
Function p_AddScore(name$, points)
    ; Insert the new score in the table:
    InsertItem(hallfametable, {name=name$, points=points})

    ; Sort the table with a custom sort function:
    Sort(hallfametable, p_SortFunc)

    ; If there are more than 10 entries, remove the last one:
    If ListItems(hallfametable) > 10 Then RemoveItem(hallfametable, -1)
EndFunction

Function p_SortFunc(a, b)
   If a.points = b.points
      ;Si los puntos son iguales que ordene por el nombre.
      Return(a.name > b.name)
   Else
      ;Ordena por defecto por puntuación más alta.
      Return(a.points > b.points)
   EndIf
EndFunction

Function p_ShowRecords()
  Cls()
  SetFont(#SANS, 28)
  SetFontColor(#RED)
  SetFontStyle(#ANTIALIAS)
  SetFontStyle(#EDGE, #YELLOW, 1)
  TextOut(100, 10, "NAME")
  TextOut(300, 10, "SCORE")

  ;Lista de records.
  Saltoy=40
  SetFont(#SANS, 24)
  SetFontColor(#YELLOW)
  SetFontStyle(#ANTIALIAS)
  ;Print the table
  For Local i = 0 To ListItems(hallfametable) - 1
     TextOut(110, Saltoy, hallfametable[i].name)
     TextOut(310, Saltoy, hallfametable[i].points)
     Saltoy=Add(Saltoy, 30)
  Next
EndFunction

Function p_EnterRecords()
  Nombre$=StringRequest("Enter your name", "Enter your name", "", #ALL, 8)
  If Nombre$=""
     p_ShowRecords()
  Else
    Puntua=StringRequest("ENTER POINTS", "Enter the points", "", #NUMERICAL, 4)
    If Puntua=""
       Puntua=0
       p_ShowRecords()
    Else
       ;if is Ok, the new items has a new valor.
       name$=Nombre$
       points=ToNumber(Puntua)
    
       p_AddScore(name$, points)
    
       p_ShowRecords()
    EndIf
  EndIf
EndFunction

p_EnterRecords()

EscapeQuit(True)
Repeat
   WaitEvent
Forever
Now I have the other doubt, how write the new record if your new score is higther than a score in the list and if it's true, now open the requester to write your name, if your score is low of the scores table, not write your name.

Thank you for your time and patience jPV, perhaps we will have a library of basic codes for cases as this, one Hall of Fame, Menus with visual effects, etc. as there are in CSS and javascript for example.
User avatar
jPV
Posts: 603
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: How to create a table of records?

Post by jPV »

In games users don't enter their points manually, but game calculates them somehow. So I would suggest that p_EnterRecords() would take a points variable which your code will enter for it.

We can check the last score in the table if the new points value is bigger than it contains, and ask for the player name only if it's bigger. I used ListItems() instead of static number for the last score index, because this way it works more generally if you want to have different amount of records shown or if the amount of records is below the maximum.

Also in your code there's p_ShowRecords() in both If and Else blocks, no need to write it twice, just show it in any case... just some code size optimizing ;)

Here's my version of the p_EnterRecords() function:

Code: Select all

Function p_EnterRecords(points)
  ; If points is bigger than the points value in the last item of the table, then ask for a name
  If points > hallfametable[ListItems(hallfametable) - 1].points
    Local Nombre$ = StringRequest("Enter your name", "Enter your name", "", #ALL, 8)
    If Nombre$
      ;if is Ok, the new items has a new valor.
      p_AddScore(Nombre$, points)
    EndIf
  EndIf

  ; Let's show the records table in any case.
  p_ShowRecords()
EndFunction

Puntua = Rnd(4) + 3 ; Random test value
DebugPrint(Puntua)

p_EnterRecords(Puntua)
BTW. you should pay attention if variables are Local or Global. In Hollywood (and Lua), variables become Global if you don't declare them Local separately (or if a variable isn't a function parameter). If you use some variables only inside a function or code block, it's better to make it Local to avoid problems with unexpected variable contents and to have better performance. Some other languages (like Python) have it other way around, and with them variables become Local unless defined as Global, but have to remember how this is in each language.

For example:

Code: Select all

Function p_Bla(myparam)
  Local variable1 = 1
  variable2 = 2
EndFunction
myparam and variable1 are local (shown in the function only), but variable2 is global (shown everywhere in the code).

In this case Saltoy and Nombre$ would be better as locals... and in your original p_EnterRecords() Nombre$, Puntua, name$, and points should have been locals.
User avatar
Juan Carlos
Posts: 887
Joined: Mon Sep 06, 2010 1:02 pm

Re: How to create a table of records?

Post by Juan Carlos »

Hi again jPV, the enter the points hadnle is to test the code, for the game the varible points is update for the game but for test reasons I wrote the code just like that, aslo I have seen other problem to save the table as in this example:

Code: Select all

;Tabla Hall Of Fame.
existe1=Exists("HLE-Hall.sav") ;We check the exist the file with the records.
If existe1=True
   OpenFile(1, "HLE-Hall.sav", #MODE_READ)
   newhallfametable=ReadTable(1, {Adapter="default"})
   CloseFile(1)

Else
  Global hallfametable={
    {name="Joe", points=100},
    {name="Juan", points=80},
    {name="Lucia", points=78},
    {name="Ines", points=45},
    {name="Rene", points=21},
    {name="Megan", points=120},
    {name="Megan", points=150},
    {name="Rodrigo", points=6},
    {name="Laura", points=5},
    {name="Jack", points=4}
  }
EndIf

/**************************************************************************************************/
@DISPLAY {Title="Hall of Fame", Width=480, Height=350, Color=#BLACK, Borderless=False, NoClose=False,
	 KeepProportions=True, Sizeable=False, NoModeSwitch=True}
/**************************************************************************************************/

Function p_Decorado()
  InstallEventHandler({OnKeyDown=p_Teclado})

  Cls()
  SetFont(#SANS, 30)
  SetFontColor(#WHITE)
  SetFontStyle(#ANTIALIAS)
  SetFontStyle(#EDGE, #BLUE, 1)
  TextOut(20, 10, "1. SEE THE SCORES")
  TextOut(20, 40, "2. ENTER NEW SCORE")
  TextOut(20, 70, "3. SAVE NEW SCORE")
EndFunction

/****** KEYBOARD *****/
Function p_Teclado(msg)
  Switch(msg.action)
     Case "OnKeyDown":
	/* Show records */
	If msg.key="1"
	   p_ShowRecords()
	EndIf

	/* Enter new record */
	If msg.key="2"
	   p_EnterRecords()
	EndIf

	/* Save records */
	If msg.key="3"
	   p_SaveTabla()
	EndIf

	/* Exit */
	If msg.key="ESC"
	   End()
	EndIf
  EndSwitch
EndFunction

Function p_Teclado2(msg)
  Switch(msg.action)
     Case "OnKeyDown":
	/* Exit to Menu */
	If msg.key="ESC"
	   p_Decorado()
	EndIf
  EndSwitch
EndFunction
/**************************************************************************************************/

Function p_AddScore(name$, points)
    ; Insert the new score in the table:
    InsertItem(hallfametable, {name=name$, points=points})

    ; Sort the table with a custom sort function:
    Sort(hallfametable, p_SortFunc)

    ; If there are more than 10 entries, remove the last one:
    If ListItems(hallfametable) > 10 Then RemoveItem(hallfametable, -1)
EndFunction

Function p_SortFunc(a, b)
   If a.points = b.points
      ;Si los puntos son iguales que ordene por el nombre.
      Return(a.name > b.name)
   Else
      ;Ordena por defecto por puntuación más alta.
      Return(a.points > b.points)
   EndIf
EndFunction

Function p_ShowRecords()
  InstallEventHandler({OnKeyDown=p_Teclado2})

  Cls()
  SetFont(#SANS, 28)
  SetFontColor(#RED)
  SetFontStyle(#ANTIALIAS)
  SetFontStyle(#EDGE, #YELLOW, 1)
  TextOut(100, 10, "NAME")
  TextOut(300, 10, "SCORE")

  ;Lista de records.
  Saltoy=40
  SetFont(#SANS, 24)
  SetFontColor(#YELLOW)
  SetFontStyle(#ANTIALIAS)
  ;Print the table
  For Local i = 0 To ListItems(hallfametable) - 1
     TextOut(110, Saltoy, hallfametable[i].name)
     TextOut(310, Saltoy, hallfametable[i].points)
     Saltoy=Add(Saltoy, 30)
  Next
EndFunction

Function p_EnterRecords()
  Nombre$=StringRequest("Enter your name", "Enter your name", "", #ALL, 8)
  If Nombre$=""
     p_ShowRecords()
  Else
    Puntua=StringRequest("ENTER POINTS", "Enter the points", "", #NUMERICAL, 4)
    If Puntua=""
       Puntua=0
       p_ShowRecords()
    Else
       ;if is Ok, the new items has a new valor.
       name$=Nombre$
       points=ToNumber(Puntua)
    
       p_AddScore(name$, points)
    
       p_ShowRecords()

    EndIf
  EndIf
EndFunction

Function p_SaveTabla()
  OpenFile(1, "HLE-Hall.sav", #MODE_WRITE)
  WriteTable(1, hallfametable, {Adapter="default"})
  CloseFile(1)
EndFunction
/******************************** FIN DE LAS FUNCIONES *************************************/
p_Decorado()

/* Comandos de salida y finalización */
EscapeQuit(False)
Repeat
   WaitEvent
Forever
But the result of save the table is this:
[
{
"points": 300,
"name": "Juilo"
},
{
"points": 150,
"name": "Megan"
},
{
"points": 120,
"name": "Megan"
},
{
"points": 100,
"name": "Joe"
},
{
"points": 80,
"name": "Juan"
},
{
"points": 78,
"name": "Lucia"
},
{
"points": 45,
"name": "Ines"
},
{
"points": 21,
"name": "Rene"
},
{
"points": 6,
"name": "Rodrigo"
},
{
"points": 5,
"name": "Laura"
}
]
When the program read the table gives problem because the table has all that, instead of only name and points.
User avatar
Juan Carlos
Posts: 887
Joined: Mon Sep 06, 2010 1:02 pm

Re: How to create a table of records?

Post by Juan Carlos »

I admit that the instructions as this "hallfametable[ListItems(hallfametable) - 1].points" surpass me, I learnded Turbo C in 1994-1995 and when I want continue learning the Vortex At-Once inside of my Amiga 500 crashed the 286 and the Dice C enviroment was impossible, I left the programmation and when I was back found Hollywood more easy but the syntasix with the oriented object . surpass me, I am sorry because my doubts can look of beginner, but is the update of programming skills step to step.
User avatar
jPV
Posts: 603
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: How to create a table of records?

Post by jPV »

Juan Carlos wrote: Tue Jan 11, 2022 7:27 pm But the result of save the table is this:
The result is just fine. Hollywood writes tables in the common JSON format and that works... but if you want to hide the results from users (so that they can't modify the score list with a text editor), you could use Adapter = "inbuilt" instead.

When the program read the table gives problem because the table has all that, instead of only name and points.
No, you have a bug elsewhere, the data file is ok.

You read the table into the "newhallfametable" variable, but you don't use that anywhere. You should read it to the "hallfametable" variable, because that's what you use elsewhere in the code. This change on the 5th line makes your program to work:

Code: Select all

hallfametable=ReadTable(1, {Adapter="default"})
User avatar
jPV
Posts: 603
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: How to create a table of records?

Post by jPV »

Juan Carlos wrote: Tue Jan 11, 2022 7:35 pm I admit that the instructions as this "hallfametable[ListItems(hallfametable) - 1].points" surpass me
I'll try to explain...

hallfametable[] has 10 items in this case and as table indexes start from 0, there are items in indexes from 0 to 9. So the last item is hallfametable[9] and as the item itself is a table (with string indices instead of numbers) which has "points" item, we get the content of the points with hallfametable[9].points and this would work too in our program if we keep using the fixed amount of items in the table.

But if the amount of items would be unknown, we can first check how many items there are in the table and that can be done with ListItems(hallfametable) which will give 10 as the result in this case. And as indexes started from 0 and not from 1, we must decrease it by one. So, ListItems(hallfametable) - 1 gives the correct index number for the last item, which is 9 in our case.

I just combined the result of "ListItems(hallfametable) - 1" to be given directly as an item index for the hallfametable[] table on the same code line.

It could be splitted in the code like this too, if it'd be more clear:

Code: Select all

Local totalitems = ListItems(hallfametable)
Local lastindex = totalitems - 1
Local lastpoints = hallfametable[lastindex].points
User avatar
Juan Carlos
Posts: 887
Joined: Mon Sep 06, 2010 1:02 pm

Re: How to create a table of records?

Post by Juan Carlos »

One more time thank you jPV for your time and king explanation, now I hope use more the table with more items, because it opens too much possibilities to make games and programs.
Post Reply