Discuss Scratch

Studio04040807
Scratcher
100+ posts

Encoding usernames into cloud data

Scratch usernames have an upper limit of 20 characters, and can only contain characters out of the following:
  • English letters (case-insensitive, so A and a are treated the same)
  • Digits 0-9
  • Special characters - and _
Tested by putting invalid usernames in the sign-up page until I discovered all the limits.
This gives 38 possible characters that can be in a username and up to 20 characters (the lower limit is 3 characters)
However, if a username was encoded into 20 numbers that each could be one of 38 possible values, there would be no way to detect if a username was under 20 characters. I solved this by using 20 numbers with 39 possible values, with the 39th representing null.
20 numbers with 39 values each can be represented in 32 digits. (39^20=66266211231824447117620880943201, which is 32 digits long.) However, Scratch loses precision when handling numbers this large, so I decided to split the username into 2 sections, each represented by 10 numbers with 39 values. This still has a total of 32 digits, since 39^10=8140406085191601, which is 16 digits long.
32 digits is convenient for cloud variable storage since cloud variables have a limit of 256 digits, meaning exactly 8 usernames could be stored in a cloud variable.

Following are the scripts I made: (Each block uses the “output” variable as an output, and uses “i” for incrementing through the input and “number” in middle steps processing half the username. allowedChars is a list containing the 38 allowed characters, which can be in any order but the order has to stay the same.)
define username to number (username::custom-arg)
set [output v] to () //clear output
set [i v] to (0) //preapare i to start incrementing
repeat (2) //processing the two halves of the username
set [number v] to (0) //number is the variable in which we will encode this half of the username
repeat (10) //repeating 10 times for the 10 characters in this half
change [i v] by (1) //increment i (not reset in the loop because it will be used for chars 1-10 and chars 11-20)
set [number v] to ((39)*(number)) //multiply number by 39, essentially shifting over to allow for next character
change [number v] by (item # of (letter (i) of (username::custom-arg)) in [allowedChars v]::list) //add the next character using allowedChars as an encoding table
end
set [output v] to (join (number)(output)) //this will result in the first half being after the last half
end
repeat until <(length of (output))=(32)> //padding output if it is too short
set [output v] to (join (0)(output))

define number to username (number)
set [output v] to () //clear output
set [i v] to (0) //prepare i for incrementing
repeat (2) //two halves of the username
set [number v] to () //clearing number for the next part
repeat (16) //loop that sets (number) to half of the input
change [i v] by (1)
set [number v] to (join (number::variables)(letter (i) of (number::custom-arg)))
end
repeat (10) //10 characters
set [output v] to (join (item ((number::variables) mod (39)) of [allowedChars v])(output))//adds rightmost character to left of output
set [number v] to ([floor v] of ((number::variables)/(39))) //removes rightmost character from number
Here is a project that should demonstrate these blocks by showing the 8 most recent users to view the project

Last edited by Studio04040807 (March 17, 2020 22:57:00)

imfh
Scratcher
1000+ posts

Encoding usernames into cloud data

Here's the way I encode usernames. It works pretty well and is currently holding 22 usernames along with 2-3 digit scores in the first 2 cloud variables. Link: Leaderboard Demo

The way it works is first by encoding each character into a 2 digit number. The number must always be two digits long, so a 1 would become 01. These encoded numbers are then joined together. abc => 010203.

Next, so the program can tell how long the username is, a number higher than 64 is added to the end. Since there isn't a character represented by a number higher than 64, the program can find the end of the username. abc => 01020364

In addition, a number representing the length of the score is added to the 64. You can also set a minimum length and say 64 means the min length. Score 123 => 64 + 2 = 66

Finally, the score is added to the end of the number. abc score 123 => 010203 67 123 (no spaces in the actual thing). With this format, the usernames and scores can be stored side by side and separated later.

Powered by DjangoBB