max_score_TinyWebDB
How to share Top Ten Daily Scores in TinyWebDB
Abe Getzler
April 2020
How to share Top Ten Daily Scores in TinyWebDB
A practical approach to a solution
Global score_labels and name_labels
When TWDBReadForUpdate.ValueStored
Background
This sample app is meant to show how to keep track of maximum scores in a shared online tag/value database. I chose TinyWebDB for this exercise because it is the most primitive of the available tag/value databases, lacking
- Locking
- SQL Update
- Indices
- A GetAllTags facility.
I am using MIT’s default TinyWebDB for this, because I have no interest in going into the database business, and I chose daily topics in this app to avoid having to worry about MIT’s periodic flushes of their TinyWebDB instance.
The App
The app keeps a daily topic and a sorted (descending) list of scores and associated names. They are kept in a dict under a tag containing today’s date, to allow a fresh topic and set of scores every day. For alignment ease, 20 Labels are lined up (see Designer.) The Add button initiates an update with the new score and name in the text boxes.
The shared update problem
Because of the structure of TinyWebDB, we are prevented from locking out other users from rewriting today’s score list while we are entering our new score. We don’t want to post a stale copy of the max score list after another user has updated the list, overwriting their new score.
A practical approach to a solution
We can’t entirely prevent this without some advanced features, but we can minimize the chances that a conflict will happen if we use two separate TinyWebDB components,
- One component for just showing the latest scores, and
- Another component to grab the latest scores and immediately rewrite them with the new score.
Timing tests using the Companion shows under 200 ms elapsed between the arrival of the current scores for update and the completion of a rewrite. So this is okay for an entertainment app. Do not use this for a banking app. You will lose money eventually!
Designer
The top text box for today’s category is usually disabled for input, unless the player is the first to open the app today, when he can choose today’s topic.
Underneath the category are two text boxes, for input of a new score and associated name, and the Add button to request the addition. The top ten scores and their names are next, lined up in two parallel vertical arrangements of labels.
A List Picker for debugging is at the bottom. (We’re all programmers here, right?)
Unseen components include two TinyWebDB controls,
- TWDBInitialRead for simple read-only access, and
- TWDBReadForUpdate for the quick read-then-update sequence.
Blocks
Screen1.Initialize
At startup, we build today’s TinyWebDB tag using value procedure TodaysTag:
I JOIN today’s date with some nonsense unlikely text to avoid conflicts with the other million MIT TinyWebDB users.
I then issue a read from the TWDBInitialread control to get a preview of today’s category and high scores, later to arrive in the TWDBInitialRead.GotValue event.
I log what I just did, for debugging.
Because I don’t know what’s coming back from the data base yet, I hide most of the GUI until I have more data.
TWDBInitialRead.GotValue
We capture and clean today’s Category and scores.
We show the input fields for entering a new score.
If today’s Category came back empty, announce to our user that he can set today’s category, if he is quick, and enable input to the category text box. Otherwise, disable the Category text box and just call the procedure to display the global webReturnDict into the score labels and name Labels.
Category
Global category_key
This is a constant, to avoid typing errors specifying dictionary keys.
Global scores_key
This is a constant, to avoid typing errors specifying dictionary keys.
Default_webreturn
This value procedure is responsible for insuring that all successive references to the global web_return_dict variable can safely assume that it is a dictionary with appropriate keys and values, even if the valueFromWebDB came back empty.
Global web_return_dict
This global will serve as the in-memory copy of the high scores. It is an AI2 dictionary type.
Display
Some details about displaying the Category and high scores:
A non-empty text box with today’s Category takes precedence over what came back from TinywebDB.
Top ten labels are cleared before filling from TinyWebDB’s return, so that a short list can be shown without embarrassing empty labels.
We guard against falling off the ends of our score list, name list, and label lists.
Scores come in pairs from the dictionary’s scores section.
Scores
Global score_labels and name_labels
When btnAdd.Click
When the user clicks the Add button, all we can do is check if his score is positive, then initiate the read-update sequence by issuing a GetValue from the TWBDBReadForUpdate control.
TWBDBReadForUpdate.GotValue
When the dictionary arrives for update, we start with the Category.
If it arrives empty and we have a Category waiting in our Category text box, we win, and get to set today’s category. Otherwise, if both categories are nonblank but don’t match, we tell the user he was too slow to post his new category. (Aww.)
If we have a new score waiting in our text boxes, we add it to the newly arrived scores, and send it out immediately back to TinyWebDB via TWDBReadForUpdate .
We then display our new merged scores.
set_Category
updated_scores
This value procedure returns a copy of the old high score list, with a new high score and name inserted according to descending score value. A zero stopper value (Beat my score!) is added at the end if the list is empty, to simplify the loops that searches for the proper insertion point.
When TWDBReadForUpdate.ValueStored
After we are satisfied that our scores have been stored, we show that by clearing the two input text boxes. (The category stays the same all day.)
For good measure, we request a refresh from the data base to keep the display current.
This app in the Gallery
ai2.appinventor.mit.edu/?galleryId=5568973378289664