Jump to content



Photo
- - - - -

Is there a reliable way to add commas to a large score?


  • Please log in to reply
10 replies to this topic

#1 CrimsonTurtle8

CrimsonTurtle8

    Enthusiast

  • Members
  • PipPipPip
  • 240 posts
  • Location:US

  • Flag: ---------

  • Favorite Pinball: Theatre of Magic

Posted 26 March 2024 - 03:55 PM

I'd like to have my scores displayed like 1,000,000 but the code I stole from a forum post doesn't seem to always work -- which is FormatNumber(Score, 0, -1, 0, -1). Is this a famous way to format it to add commas? Is there another way? I get an error loading my high score with this code. Thanks!



#2 EpeCreaciones

EpeCreaciones

    Hobbyist

  • Members
  • PipPip
  • 39 posts

  • Flag: Spain

  • Favorite Pinball: Tales of Arabian Nights

Posted 27 March 2024 - 02:55 AM

Hi how's everything? I hope it's ok.
 
You see, there is a way to manually format numbers for what you are looking for although it has to be done through coding.
 
 
I'll explain basically what it is, and how it worked for me.
 
Let's take any number with more than 4 digits, why 4 digits? because we will place the point for thousands units every 3 digits (or the comma to taste, although I prefer to reserve the comma for decimals and the point for thousand units).
 
1) First you have to convert the number into a text string.
 
2) then you have to read the resulting string from right to left, that is, from ones to hundreds, and so on. I use a FOR NEXT loop.
 
3) We place the first unit figure on the screen, and then we count them by grouping them three by three. For every three figures we will add the point that marks the thousand units with respect to the previous group of three figures. NOTE: taking into account that three figures are hundreds, that is, we will only add that thousand point if that fourth figure exists (1 unit + 3 figures to its left = 1 thousand unit). Example: we will put 1,000, not .999 (in addition to looking strange, it is confused with a decimal number)
 
 
 
Let's get to the nougat: (example code taken from Capt. Nemo)
 
 

Dim Score 'for your Score
Score = 0

Dim CadenaPuntos 'variable que almacena el valor en String de la variable numerica Score
CadenaPuntos = ""

Dim parametro 'variable que pasa el valor en String de la variable CadenaPuntos a las Subs ConversorDigital y ConversorDigitalUdMil
parametro = ""
Dim GraficoNumerico  'devuelve la conversion del caracter de cadena de texto en string de las dos Subs anteriores, en un valor de string del gráfico png
GraficoNumerico = ""

Dim GraficoNumerico_ud 
GraficoNumerico_ud = ""
Dim GraficoNumerico_dec
GraficoNumerico_dec = ""

Dim DigitosDMD 'los indices de las Array comienzan en 0 para el primer digit1
DigitosDMD = Array(digit1, digit2, digit3, digit4, digit5, digit6, digit7, digit8, digit9, digit10, digit11, digit12, digit13)

'NOTA: Usaremos 13 dígitos, es decir Score = (0 = 0.000.000.000.000 - 9.999.999.999.999) Usa tú los que necesites.

Dim indiceCadena 'inidice que recorre la cadena de la puntuación convertida en caracter de derecha a izda. y la coloca en los flasher del DMD
indiceCadena = 0

Dim CuentaUnidades
CuentaUnidades = 0

Dim Multiplier 'for playfield multipliers
Multiplier = 1 'todo numero multiplicado por cero es cero -> (N * 0) = 0; todo numero multiplicado por 1 es el mismo número -> (N * 1) = N;


Sub AddScore(points) 'we also need to Dim Score in the beginning of script. all Variables should go in the beginning of script.
	Score = Score + (points * Multiplier)

	'prevenir overflow, dar vuelta al marcador
	'guarda record máximo prefijado como en los Game and Watch
	If Score >= 9999999999999 Then
		'New Record obtenido, asignación manual y guardado de nuevo Record
		HighScore = 9999999999999
		Savehs
		'reinicia el marcador
		Score = Score - HighScore 'continuar con el marcador sin el desbordamiento, es lo mismo que poner Score = 0
	End If

'conversion de Score a String
	CadenaPuntos = CStr(Score)

	'primera unidad de CadenaPuntos fuera del bucle For Next
	ConversorDigital( Mid(StrReverse(CadenaPuntos),1,1) ) 'funciona
	DigitosDMD(0).ImageA = GraficoNumerico 'así usa el primer espacio, el de indice 0 inicial del Array
	'nota, hay un desfase de -1 entre el indice de la cadena String (1..13) y el indice del Array (0..12) ajustar el desfase con DigitosDMD(indiceCadena -1)
	'inicia contador de unidades de millar
	CuentaUnidades = 0


	If Len(CadenaPuntos) > 1 And Len(CadenaPuntos) <= 13 Then '> 1 si hay decenas o más, <= 13 ancho máximo del display Score DMD (digit13) evita error de overflow
		For indiceCadena = 2 to Len(CadenaPuntos)
		CuentaUnidades = CuentaUnidades + 1
			If CuentaUnidades = 3 Then 'unidad de millar, teniendo en cuenta que ya hemos saltado el primer dígito de unidad de forma manual
				ConversorDigitalUdMil( Mid(StrReverse(CadenaPuntos),indiceCadena,1) ) 'funciona
				DigitosDMD(indiceCadena -1).ImageA = GraficoNumerico
				CuentaUnidades = 0
			Else 'son decenas o centenas
				ConversorDigital( Mid(StrReverse(CadenaPuntos),indiceCadena,1) ) 'funciona
				'para evitar que invierta el orden de la cifra (123 ptos se convierten en grafico 321) se usa la funcion StrReverse
				'dibuja cada flasher del DMD de puntuacion, recorriendolos de derecha a izda.

				'muestra solo el digito de unidades, como si el indiceCadena no avanzada a la derecha del digito anterior
				DigitosDMD(indiceCadena -1).ImageA = GraficoNumerico
			End If 'unidades de millar
		Next 'indiceCadena
	End If 'Len > 1
End If

End Sub 'AddScore




Sub ConversorDigital(parametro) 'sub para convertir de caracter de cadena de texto string a gráfico png
'NOTA: estos graficos son sólo de dígitos numéricos (0) al (9)
	Select Case parametro
		'numéricos
		Case ""
			GraficoNumerico = "d_spc"
		Case "0"
			GraficoNumerico = "d0_c"
		Case "1"
			GraficoNumerico = "d1_c"
		Case "2"
			GraficoNumerico = "d2_c"
		Case "3"
			GraficoNumerico = "d3_c"
		Case "4"
			GraficoNumerico = "d4_c"
		Case "5"
			GraficoNumerico = "d5_c"
		Case "6"
			GraficoNumerico = "d6_c"
		Case "7"
			GraficoNumerico = "d7_c"
		Case "8"
			GraficoNumerico = "d8_c"
		Case "9"
			GraficoNumerico = "d9_c"
	End Select
End Sub



Sub ConversorDigitalUdMil(parametro) 'sub para convertir de caracter numérico con punto de unidades de millar, de cadena de texto string a gráfico png
'NOTA: estos graficos NO son sólo de números, el grafico ya incluye un punto detrás del digito correspondiente, por ejemplo del (0.) al (9.)
	Select Case parametro
		Case ""
			GraficoNumerico = "d_spc"
		Case "0"
			GraficoNumerico = "d0a_c"
		Case "1"
			GraficoNumerico = "d1a_c"
		Case "2"
			GraficoNumerico = "d2a_c"
		Case "3"
			GraficoNumerico = "d3a_c"
		Case "4"
			GraficoNumerico = "d4a_c"
		Case "5"
			GraficoNumerico = "d5a_c"
		Case "6"
			GraficoNumerico = "d6a_c"
		Case "7"
			GraficoNumerico = "d7a_c"
		Case "8"
			GraficoNumerico = "d8a_c"
		Case "9"
			GraficoNumerico = "d9a_c"
	End Select
End Sub



'Esto puede ser útil

Sub Limpia_Score_DMD 'limpa el DMD, sustituyendo cada flasher del DMD de Score por una imagen "en blanco" transparente, funciona como CLS
	'nota, hay un desfase de -1 entre el indice de la cadena String (1..13) y el indice del Array (0..12) ajustar el desfase con DigitosDMD(indiceCadena -1)
	For indiceCadena = 1 to 13 'el array de DigitosDMD 0..12
		DigitosDMD(indiceCadena -1).ImageA = "d_spc"
	Next 'indiceCadena
End Sub

If you are going to use a reel like in the older EMs, you need a point symbol, which replaces the corresponding digit, and run the next thousand unit to the left of that punctuation symbol. This would be like using base 11 notation (0 through 9 and the .) Something like (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, .)
 
Unless you leave the gap already made to mark the thousand units and graphically group the digits by 3. (something like 0.000.000.000.000 and move only the corresponding digits without altering the X.XXX.XXX place points. XXX,000).
 
As you can see, my solution is to exchange graphics in each thousand unit, for an equivalent graph that already has the mimllar unit point embedded. So the corresponding number is read "followed." I don't know if I explain myself.
 
 
 
Greetings.
 
EpeC.


#3 Fusionwerks

Fusionwerks

    Poorly recovering pinball addict

  • Platinum Supporter
  • 344 posts

  • Flag: United States of America

  • Favorite Pinball: JP (DE), Elvira's HoH, ToM

Posted 27 March 2024 - 02:13 PM

you could try this: it is in most of JP's tables ( i commented out the lines with explanations)

 

Function FormatScore(ByVal Num) ' Function declaration with a parameter Num
    dim i ' Declare a local variable i for the loop
    dim NumString ' Declare a local variable NumString to hold the formatted score
    NumString = CStr(abs(Num)) ' Convert the absolute value of Num to a string and store it in NumString
    For i = Len(NumString)-3 to 1 step -3 ' Loop through NumString in steps of 3 from the third-to-last character to the first
        if IsNumeric(mid(NumString, i, 1)) then ' Check if the character at position i in NumString is numeric
            NumString = left(NumString, i-1) & chr(asc(mid(NumString, i, 1)) + 128) & right(NumString, Len(NumString)- i) ' Replace the character at position i with its ASCII code plus 128
        end if
    Next ' Move to the next iteration of the loop
    FormatScore = NumString ' Return the formatted score string
End function ' End of the function
 
This function takes a numeric input and converts it to a string, and formats it with commas every three digits from right to left

Edited by Fusionwerks, 27 March 2024 - 02:15 PM.


#4 CrimsonTurtle8

CrimsonTurtle8

    Enthusiast

  • Members
  • PipPipPip
  • 240 posts
  • Location:US

  • Flag: ---------

  • Favorite Pinball: Theatre of Magic

Posted 27 March 2024 - 02:26 PM

 

you could try this: it is in most of JP's tables ( i commented out the lines with explanations)

 

Function FormatScore(ByVal Num) ' Function declaration with a parameter Num
    dim i ' Declare a local variable i for the loop
    dim NumString ' Declare a local variable NumString to hold the formatted score
    NumString = CStr(abs(Num)) ' Convert the absolute value of Num to a string and store it in NumString
    For i = Len(NumString)-3 to 1 step -3 ' Loop through NumString in steps of 3 from the third-to-last character to the first
        if IsNumeric(mid(NumString, i, 1)) then ' Check if the character at position i in NumString is numeric
            NumString = left(NumString, i-1) & chr(asc(mid(NumString, i, 1)) + 128) & right(NumString, Len(NumString)- i) ' Replace the character at position i with its ASCII code plus 128
        end if
    Next ' Move to the next iteration of the loop
    FormatScore = NumString ' Return the formatted score string
End function ' End of the function
 
This function takes a numeric input and converts it to a string, and formats it with commas every three digits from right to left

 

Okay that makes sense to me. How do I specifically link this to just the score and indicate that THIS chunk of code needs to triggered for the score amounts that the table updates on the fly?

 

Do I type "FormatScore(Score)" every time I need to insert a score into the code? Just a guess. Like:

 

ScoreText.Text = "SCORE: " & FormatScore(Score)

 

or 

 

ScoreText.Text = "Hurry up awarded! " & FormatScore(Hurryupvalue) & " points!"

 

??

 

And do I leave ByVal Num in there?? I see the nums referenced later but idk how ByVal applies or what it does. 

 

 

As you can tell, I'm very much an amateur and I build tables mostly by assembling pieces of code I've learned, and not so much by understanding WHY they say what they say hahaha. Thanks for your help.


Edited by CrimsonTurtle8, 27 March 2024 - 02:29 PM.


#5 Fusionwerks

Fusionwerks

    Poorly recovering pinball addict

  • Platinum Supporter
  • 344 posts

  • Flag: United States of America

  • Favorite Pinball: JP (DE), Elvira's HoH, ToM

Posted 27 March 2024 - 02:45 PM

this particular piece of code is actually part of a larger group of functions that are all in most of JP's tables (this one specifically is from his Serious Sam 2 table) This was just an example to show you how you could adapt to your script. I suggest you look into maybe adopting his method.

It uses FlexDmd and his Reduced Display Driver Functions (based on script by Black)

 

As for learning code, i have personally learned a ton by just copying a piece of code and pasting it into ChatGPT and asking it to "comment out and explain each line in the code" It does a pretty good job of helping you to understand whats going on "under the hood" in a piece of script.



#6 CrimsonTurtle8

CrimsonTurtle8

    Enthusiast

  • Members
  • PipPipPip
  • 240 posts
  • Location:US

  • Flag: ---------

  • Favorite Pinball: Theatre of Magic

Posted 27 March 2024 - 02:54 PM

Oh dang uses Flex etc as in won't work without it? That's way over my head. This seems like an easy thing VP developers should integrate natively into the software like FP. Who wouldn't want a set of numbers to automatically be divided into commas? Oh well. The FormatScore thing I was using works for everything except loading the high score and simultaneously displaying it. Maybe I can load it... declare the variable, then display the score as a separate line of code without getting an error...



#7 Fusionwerks

Fusionwerks

    Poorly recovering pinball addict

  • Platinum Supporter
  • 344 posts

  • Flag: United States of America

  • Favorite Pinball: JP (DE), Elvira's HoH, ToM

Posted 27 March 2024 - 03:35 PM

try this:

add this function to your script

 

Function FormatScore(ByVal Num)
    Dim i
    Dim NumString, Temp
    NumString = CStr(Abs(Num))
    ' Insert commas every three digits from the right
    For i = Len(NumString) - 3 To 1 Step -3
        NumString = Left(NumString, i) & "," & Right(NumString, Len(NumString) - i)
    Next
    FormatScore = NumString
End Function
 
THEN this:
 
Dim Score 'a variable
score = 1000000
 
ScoreText.Text = FormatScore(score) & " Points"
 
would display:
 
1,000,000 Points
 


#8 CrimsonTurtle8

CrimsonTurtle8

    Enthusiast

  • Members
  • PipPipPip
  • 240 posts
  • Location:US

  • Flag: ---------

  • Favorite Pinball: Theatre of Magic

Posted 27 March 2024 - 11:00 PM

 

try this:

add this function to your script

 

Function FormatScore(ByVal Num)
    Dim i
    Dim NumString, Temp
    NumString = CStr(Abs(Num))
    ' Insert commas every three digits from the right
    For i = Len(NumString) - 3 To 1 Step -3
        NumString = Left(NumString, i) & "," & Right(NumString, Len(NumString) - i)
    Next
    FormatScore = NumString
End Function
 
THEN this:
 
Dim Score 'a variable
score = 1000000
 
ScoreText.Text = FormatScore(score) & " Points"
 
would display:
 
1,000,000 Points
 

 

Aw darn I had high hopes but I get this error message:

 

Type mismatch: 'Num'



#9 Fusionwerks

Fusionwerks

    Poorly recovering pinball addict

  • Platinum Supporter
  • 344 posts

  • Flag: United States of America

  • Favorite Pinball: JP (DE), Elvira's HoH, ToM

Posted 28 March 2024 - 01:16 AM

whatever is inside of the parenthesis will get formatted with commas, either a variable or a specified number, BUT it has to be a numeric value. That might be why you are getting that error. Otherwise you can use this and it will ignore anything that isnt numeric from the string

 

Function FormatScore(ByVal Num)
    Dim i
    Dim NumString
    NumString = CStr(Abs(Num))
    
    ' Remove any non-numeric characters from the string
    Dim regEx: Set regEx = New RegExp
    regEx.IgnoreCase = True
    regEx.Global = True
    regEx.Pattern = "[^\d]"  ' Match any character that is not a digit
    NumString = regEx.Replace(NumString, "")
    
    ' Insert commas every three digits from the right
    For i = Len(NumString) - 3 To 1 Step -3
        NumString = Left(NumString, i) & "," & Right(NumString, Len(NumString) - i)
    Next
    
    FormatScore = NumString
End Function

 

your not using any letters inside the parenthesis right? I mean besides any variable name of course...

 

try this blank test table. look at the script from lines 40-61

Attached Files


Edited by Fusionwerks, 28 March 2024 - 01:26 AM.


#10 Fusionwerks

Fusionwerks

    Poorly recovering pinball addict

  • Platinum Supporter
  • 344 posts

  • Flag: United States of America

  • Favorite Pinball: JP (DE), Elvira's HoH, ToM

Posted 28 March 2024 - 02:10 AM

just as an FYI, here is the explanation of what each of the 5 parameters do in your first example:

FormatNumber(Score, 0, -1, 0, -1)

  1. Expression(number): This is the number you want to format. In your example, it's whatever value is defined in the variable "Score".

  2. NumDigitsAfterDecimal(integer): This parameter specifies the number of digits to display after the decimal point. In your example, it's 0, indicating that no decimal places should be displayed.

  3. IncludeLeadingDigit(integer): This parameter determines whether a leading zero is displayed for fractional values when the number of digits after the decimal separator is less than the value specified by NumDigitsAfterDecimal. In your example, it's -1, which means the default behavior is used (no leading zero).

  4. UseParensForNegativeNumbers(integer): This parameter specifies whether to enclose negative numbers in parentheses. If this parameter is 0, negative numbers are prefixed with a minus sign; if it's -1, negative numbers are enclosed in parentheses. In your example, it's 0, indicating negative numbers are prefixed with a minus sign.

  5. GroupDigits(integer): This parameter determines whether digits are grouped using the group delimiter specified in your system's regional settings. If this parameter is 0, no digit grouping is applied; if it's -1, digit grouping is applied. In your example, it's -1, indicating that digit grouping should be applied.


Edited by Fusionwerks, 28 March 2024 - 02:12 AM.


#11 jpsalas

jpsalas

    Grand Schtroumpf

  • VIP
  • 6,427 posts
  • Location:I'm Spanish, but I live in Oslo (Norway)

  • Flag: Norway

  • Favorite Pinball: I like both new and old, but I guess I prefer modern tables with some rules and goals to achieve.



Posted 28 March 2024 - 05:47 AM

Keep your scores as numbers and only use the FormatNumber(Score, 0, -1, 0, -1) for displaying the score in the DMD. Save and Load your normal scores, not the formatted scores.


These are my tables, sorted by date, all them playable with VPX 7 or newer:

vp.jpg

After 18 years making tables, it is time to take a rest and let new authors do their thing.

I guess at last I'll play some more pinball :). But I'm sure I'll make some table updates from time to time :)