Smalltalk, increment a value from a dictionary of counters - dictionary

im working on Smalltalk, i have "tweets" collection, each tweet have "user" and i want to count the tweets by user in a dictionary.
So i have to add a counter in each key of the dictionary, and have to add keys for the first time i get the user.
I was thinking in this code for the add, i want to know if is human redeable and efficient or is there a better way to do it
tweetCountUserFrom: tweet in: aDictionary
| user |
user := tweet user.
aDictionary at: user ifAbsentPut: 0.
aDictionary at: user put: (result at: user) + 1

Your code is clear enough (even though it likely includes a mistake as the result variable should have been aDictionary instead). Anyway, the intention is clear and does (or is expected to do) the same a well-known object does, which is Bag. So, let's see how the code would have been with an instance of Bag (it is always a good idea to become increasingly familiar with the Collection hierarchy of Smalltalk). Here is how you could arrive at the same result
tweetCountUserFrom: tweet in: aBag
aBag add: tweet user
That's it!
When it is time for you to see how many tweets a user has authored, you will only need to evaluate
aBag occurrencesOf: user
Internally, aBag will hold a Dictionary and will maintain it the way you intended in your code. However, by using an existing object you will keep your code simpler, shorter and easier to read and maintain. You will also decrease the probability of failure as Bags have been kicking around for more than 40 years now, so there is little chance for them to decieve you.

Related

MS Project: How to set daily actual work for a task using a JavaScript Add-In?

I want to synchronize data for actual work from a web-based application of my company with MS Project. I am currently developing an Add-In with JavaScript in order to achieve this:
The red circle in my screenshot shows the data that I want to set programmatically. However, I have no idea how to achieve this.
I understand that I can get Task GUIDs and then set task fields using the task GUID and the field ID. This way I can save the cumulative actual work, but not per day like in my screenshot.
The API Docs on the MS Office Website are rather hard to read and navigate. Any help would be apprechiated!
Let's first separate the language from the operation.
Operationally, based on your circle, you want to set work for a task to happen on individual days? This is done using timeScaleData, see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2003/aa206255(v=office.11) . When I did something similar (in VBA), I had to (1) get an array of time scale values, then (2) walk/iterate through that array and set work to those days:
set timeScaleValsArry = myTask.Assignments(1).TimeScaleData(startDay, endDay, pjAssignmentTimeScaledWork, daily)
for a = 1 to timeScaleValsArry.Count
timeScaleValsArry[a].value = hoursToWorkThatDay
next
Breaking down the elements above:
myTask is the task (of type task) I want to manipulate.
Assignments is an array representing each resource assigned to the task; for my purposes, I only ever had 1 resource assigned, hence the index of (1).
TimeScaleData is the function that returns the the array starting on the day startDay (whatever you want that to be), endDay, pjAssignmentTimeScaledWork which tells this function what data we want to work with (being work, but there are alternates ), and daily which is the frequency you want to work with (for instance you can go down to minutes, or up to years).
Then the returned array timeScaleValsArry is walked, and inside the loop the daily assignment for each value is manipulated. You'd need to customize this part to meet your needs; alternatively, you don't even need to loop if you always had three days: just hard code the array indices.
As far as language, clearly this is do-able in VBA. Doing this in C# as a VSTO addin has very similar syntax. I'd presume for JavaScript (what are you using, ScriptLab?) would also have similar syntax.

Check if record already exists when doing a buffer-copy

I have a piece of code which does a Buffer-Copy method, but is there any way to check before doing the buffer copy of the record already exists? I do not want to check 'unique keys' in my data dictionary.
This is the code I have at this moment:
CREATE QUERY hQuery.
hQuery:SET-BUFFERS(hBuffer).
hQuery:QUERY-PREPARE("FOR EACH " + hBuffer:NAME + " NO-LOCK ").
hQuery:QUERY-OPEN().
hQuery:GET-FIRST().
DO WHILE NOT hQuery:QUERY-OFF-END:
DO TRANSACTION ON ERROR UNDO:
hDBBuffer:BUFFER-CREATE().
hDBBuffer:BUFFER-COPY(hBuffer) NO-ERROR.
It is unclear what you are trying to accomplish and why you don't want to check unique keys "in my data dictionary" or even what you mean by that.
Your example code is very sketchy and incomplete, maybe someone else can figure out what you are trying to do and why, but I am at a loss to divine the purpose behind it. The use of handles and dynamic queries is especially puzzling. There doesn't seem to be a reason for that or any need to do that.
None the less, if I were coding a routine to copy a buffer, couldn't look up unique indexes in the dictionary, and wanted to pro-actively avoid potential collisions I might write something like this:
define temp-table oLine like orderLine.
for each orderline no-lock:
find oLine of orderLine no-error.
if not available( oLine ) then create oLine.
buffer-copy orderLine to oline.
end.
(Using static coding to keep the example simple.)
(I wouldn't really use OF - it is on my personal forbidden list, I think it is terrible from a documentation and maintenance perspective.)
I believe, as Tom has mentioned in his reply, it'd be most appropriate to have another dynamic query directed at the hDBBuffer using the BUFFER-FIELDs and BUFFER-VALUEs from hBuffer and check the NUM-RESULTS after you use QUERY-OPEN. Then delete the query for memory purposes.
But yes, you would be looking for the metadata unique keys to achieve that. I understand you don't want to do it, but it's REALLY the best way, can't stress it enough.
Now if you would really like to check for the existence of ALL the record data, look into the BUFFER-COMPARE method. You could create a second dynamic query, then cycle all records there by using buffer-compare to match the entire record you're looking at to the one you're assessing whether to create, or list the ones you wish to include or exclude. This approach is way less performatic, though, please keep that in mind.

Game Maker Studio Score, My Score resets when going to the next room

I'm having a problem regarding the scores in my game, My game is about answering questions using jumbled letters and when the player gets one correct answer, the game should add +1 to the game score and move to the next level (which is in the next room) and will generate another question, and keeping your last score which is 1. My problem is, the score just keeps on resetting to a value of 0 when moved into the next room. I want it to continuously add +1 even when I go to the next rooms. Thankyou in advance.
There are many solutions.
1) Set your score controller object as persistent
This is the best, as you don't need to do anything else, and in fact, it's a good rule to have one object as a persistent controller.
2) You can save your score to the file and load it each time this object (that stores the variable) is being created
This requires save\load manipulation, and in some cases (e.g you don't want to have ANY persistent objects) can be better, but I highly doubt.
You are not giving enough details about how are you storing the score value.
That may be cause by many issue in the way you are making the game, so im going to try to give all solutions to all possible scenarios:
1) Storing Score in Object Variable
This way may have two different sub scenarios:
a) Going to Next Room after Right answer
b) Restart the same room
This completly reset the variable on the object because the object is destroyed and then created again initilizing again the variables it hold when the room is created.
For this the solution is simply: set persistent true, you can do it from the form object properties (the interface that pop up when you open a object) or using gml on the create event of the object:
object: CREATE event
persistent = true;
This will make the object even if is repeated on the room created to no to create it again, so the event CREATE will no be never repeated again.
2) Storing the Score in variable of the room using Room Creation Event
In this scenario happeng the same that above, its just a local variable the room but exists only for the room and will only exists during the room until its restarted or leaved.
In this case the best is to transform this variable to a global instance in the following way:
global.points = 0;
And this is the best way to store score for you game.
Just remember no to put it in a create event of a not persistent object or it will be reseted to ZERO everything that object is created.
In that case you can check if the variable exists and then if not initializing it:
if (variable_global_exists("points") == true) {
global.points = 0;
}
Now if you want to save it you need to use file functions which is another question.

Dynamodb data model for process/transaction monitoring

I am wanting to keep track of multi stage processing job.
Likely just need the following fields
batchId (guid) | eventId (guid) | statusId (int) | timestamp | message (string)
There are relatively small number of events per batch.
I want to be able to easily query events that have a statusId less than n (still being processed or didn't finish processing).
Would using multiple rows for each status change, and querying for latest status be the best approach? I would use global secondary index but StatusId does not seem like a good candidate for hashkey (less than 10 statuses).
Instead of using multiple rows for every status change, if you updated the same event row instead, you could use a technique described in the DynamoDB documentation in the section 'Use a Calculated Value'. Basically this would involve adding another attribute (say 'derivedStatusId') which would be derived by appending a random number to statusId at the time of writing to DynamoDB. For example, for a statusId of 2, derivedStatusId could be one of {"2-00", "2-01", .. "2-99"}. Setting up a Global Secondary Index on derivedStatusId would give you some fan-out that will help in preventing the index from becoming hot.
If you are sure that you will use this index for only unfinished events, then removing the derivedStatusId attribute from the record when it transitions to a finished status will remove it from index as well - which may be a good property if events are expected to finish processing eventually, and if they stay around forever. This technique is called "Sparse Index" and is described in more detail here.
From your question, it seems like keeping status history recording is a desired property (I assume this because you want to have multiple rows for status changes). Consider putting this historical information in the same row. DynamoDB supports list data types and also has a generous 400KB item limit which may just allow you to capture all the desired historical information in the same record.

"User Preferences" Database Table Design

I'm looking to create a table for user preferences and can't figure the best way to do it. The way that the ASP.NET does it by default seems extremely awkward, and would like to avoid that. Currently, I'm using one row per user, where I have a different column for each user preference (not normalized, I know).
So, the other idea that I had come up with was to split the Preferences themselves up into their own table, and then have a row PER preference PER user in a user preferences table; however, this would mean each preference would need to be the exact same datatype, which also doesn't sound too appealing to me.
So, my question is: What is the best/most logical way to design a database to hold user preference values?
Some of the ideas that I try to avoid in database work, is data duplication and unnecessary complication. You also want to avoid "insert, update, and deletion anomalies". Having said that, storing user preferences in one table with each row = one user and the columns, the different preferences that are available, makes sense.
Now if you can see these preferences being used in any other form or fashion in your database, like multiple objects (not just users) using the same preferences, then you'll want to go down your second route and reference the preferences with FK/PK pairs.
As for what you've described I see no reason why the first route won't work.
I usually do this:
Users table (user_id, .... etc.)
.
Options table (option_id, data_type, ... etc.)
(list of things that can be set by user)
.
Preferences table (user_id, option_id, setting)
I use the new SQLVARIANT data type for the setting field so it can be different data types and record the data type of the option as part of the option definition in the Options table for casting it back to the right type when queried.
If you store all your user preferences in a single row of a User table you will have a maintenance nightmare!
Use one row per preference, per user and store the preference value as a varchar (length 255 say, or some value large enough to meet your requirements). You will have to convert values in/out of this column obviously.
The only situation where this won't work easily is if you want to store some large binary data as a User preference, but I have not found that to be a common requirement.
Real quick, one method:
User(UserID, UserName, ...)
PreferenceDataType(PreferenceDataTypeID, PreferenceDataTypeName)
PreferenceDataValue(PreferenceDataValueID, PreferenceDataTypeID, IntValue, VarcharValue, BitValue, ...)
Preference(PreferenceID, PreferenceDataTypeID, PreferenceName, ...)
UserHasPreference(UserID, PreferenceID, PreferenceDataValueID)

Resources