How do I see the returned value(s) of a function in Alloy? - alloy

I'm trying to understand how functions work in Alloy, and an important part of that is testing them. For example I've got this code:
open util/ordering[Time] // enforces total order on Time
sig Time {} // instances denote timestamps
sig File {
time : Time // every file has exactly one timestamp
}
fun getTime[F : set File] : Time {
{t : Time | some f : F | all x : F | f.time = t && gte[f.time,x.time]}
}
The getTime function is meant to return the time value of the file(s) with the greatest timestamp, out of the given set of files. I've made the function, and I believe it should work as intended, but I have no clue how to actually test that. I know I can run functions in Alloy, but I can't figure out how to create a sample set of files to use as input. Whenever I do manage to get something to run, nowhere in the resulting visualization does it show what the function outputted.

In the visualization, you can open the "Evaluator" with a button in the toolbar.
There you can enter stuff like:
univ
to get a list of all atoms. And:
getTime[File$0]
to evaluate a function.

Related

Creating Test data for ArangoDB

Hi I would like to insert random test data into an edge collection called Transaction with the fields _id, Amount and TransferType with random data. I have written the following code below, but it is showing a syntax error.
FOR i IN 1..30000
INSERT {
_id: CONCAT('Transaction/', i),
Amount:RAND(),
Time:Rand(DATE_TIMESTAMP),
i > 1000 || u.Type_of_Transfer == "NEFT" ? u.Type_of_Transfer == "IMPS"
} INTO Transaction OPTIONS { ignoreErrors: true }
Your code has multiple issues:
When you are creating a new document you can either not specify the _key key and Arango will create one for you, or you specify one as a string to be used. _id as a key will be ignored.
RAND() produces a random number between 0 and 1, so it needs to be multiplied in order to make it into the range you want you might need to round it, if you need integer values.
DATE_TIMESTAMP is a function and you have given it as a parameter to the RAND() function which needs no parameter. But because it generates a numerical timestamp (milliseconds since 1970-01-01 00:00 UTC), actually it's not needed. The only thing you need is the random number generation shifted to a range that makes sense (ie: not in the 1970s)
The i > 1000 ... line is something I could only guess what it wanted to be. Here the key for the JSON object is missing. You are referencing a u variable that is not defined anywhere. I see the first two parts of a ternary operator expression (cond ? true_value : false_value) but the : is missing. My best guess is that you wanted to create a Type_of_transfer key with value of "NEFT" when i>1000 and "IMPS" when i<=1000
So, I rewrote your AQL and tested it
FOR i IN 1..30000
INSERT {
_key: TO_STRING(i),
Amount: RAND()*1000,
Time: ROUND(RAND()*100000000+1603031645000),
Type_of_Transfer: i > 1000 ? "NEFT" : "IMPS"
} INTO Transaction OPTIONS { ignoreErrors: true }

IBM Doors DXL: can't iterate over objects in module

I have a rather peculiar problem with IBM Doors, using its DXL language:
I CAN get a variable to the module I want to access:
our_mod = module "<path_including_filename_of_module>"
I can NOT perform any of the usual functions pertaining to modules on that variable, e.g.:
name (our_mod) //or entering the string consisting of path + filename directly)
it gives me the error output: "incorrect arguments for fucntion (name)"
BUT, if I search through the folder containing the module, I can grab it via its filename:
Item x
Item my_module
for x in my_folder do
{
if (name(x) == "<filename>")
{
my_module = x
}
}
THEN I can perform name(my_module) or type (my_module):
returns the filename and "Formal" as expected
But even if I get the module that way, I still can NOT iterate over the objects inside that module like with
Object o
for o in my_module do // ...in all my_module... does not work either, same error msg
{
//Do what I came to do...
}
It just gives me the error message "incorrect arguments for (do)"
If anybody had any idea whatsoever as to what might be causing this, would be much obliged.
thanks and regards
There are several data types in DXL that have something to do with modules, all of them have different access functions (perms). E.g. variables of type Item are good for iterating over "everything in a folder or project". If you want to iterate over objects, you need a variable of type Module. As you already found out, the perm "module (string)" does NOT return data of type Module. It returns either a variable of type bool or of type ModName_ (which is a module reference, not a module), depending on the data type where you assign the result. For details, see e.g. the perms list on Tony Goodman's page at http://www.smartdxl.com/downloads/undoc31.html.
In DXL, make sure that you ALWAYS declare variables with a type, never use Auto-Declare if you want to keep your sanity (if you say print our_mod in your upper example you will find that you got a bool, which of course has neither a name nor a type).
For getting a variable of type Module, you first need to open the module (like in real life :) :)). You can open it using edit, share or read. E.g. like this
Module m = read ("/path/to/my_mod", false /* display */, true /* load standard view */)
if null m then error "could not open the module"
Object o
for o in entire m do {print o."Absolute Number" ""}
close m

How does the update diff work in AzerothCore?

The worldserver source code is full of Update methods that take as input a diff integer value:
How does it work?
And how is this linked to the "Update time diff" from the .server info command?
To fully understand how this works, it's necessary to have a look at the main World run process.
WorldRunnable::run()
File: src/server/worldserver/WorldThread/WorldRunnable.cpp
The method void WorldRunnable::run() is the "Main heartbeat for the World". This method runs the whole world process.
Inside it, there is a while loop that runs as long as the world is supposed to keep running:
void WorldRunnable::run()
{
uint32 realCurrTime = 0;
uint32 realPrevTime = getMSTime();
///- While we have not World::m_stopEvent, update the world
while (!World::IsStopped())
{
++World::m_worldLoopCounter;
realCurrTime = getMSTime();
uint32 diff = getMSTimeDiff(realPrevTime, realCurrTime);
sWorld->Update( diff );
realPrevTime = realCurrTime;
uint32 executionTimeDiff = getMSTimeDiff(realCurrTime, getMSTime());
devDiffTracker.Update(executionTimeDiff);
avgDiffTracker.Update(executionTimeDiff > WORLD_SLEEP_CONST ? executionTimeDiff : WORLD_SLEEP_CONST);
// ... some more code here
}
// at this point the world process is terminating
// ... some more code here
What this loop really does is basically:
1) calculate the elapsed time (in milliseconds) since the previous iteration, this will be the diff
2) call the sWorld->Update( diff ); function, that contains all the world process logic (see below) and passing the diff to it
3) calculate how much time it took to run sWorld->Update( diff ); and update the devDiffTracker and its average avgDiffTracker. These values will be displayed by the .server info command.
World::Update(uint32 diff)
File: src/server/game/World/World.cpp
The World::Update(uint32 diff) function gets constantly called by the main worldserver loop process and every time it takes in input the amount diff of elapsed time since the last call.
This function is responsible for constantly updating the world, this is where all the magic happens.
Timers
There are a set of timers (defined in World.h that are being updated within the World::Update function:
/// Timers for different object refresh rates
enum WorldTimers
{
WUPDATE_AUCTIONS,
WUPDATE_WEATHERS,
WUPDATE_UPTIME,
WUPDATE_CORPSES,
WUPDATE_EVENTS,
WUPDATE_CLEANDB,
WUPDATE_AUTOBROADCAST,
WUPDATE_MAILBOXQUEUE,
WUPDATE_PINGDB,
WUPDATE_5_SECS,
WUPDATE_COUNT
};
For example, WUPDATE_AUTOBROADCAST is responsible for the period global messages defined in the acore_auth.autobroadcast table.
Tasks
The World::Update function also takes care of many timed-tasks, for example:
/// Handle daily quests reset time
if (m_gameTime > m_NextDailyQuestReset)
ResetDailyQuests();
Calling Update(diff) functions of Managers
In AzerothCore there are singleton classes called Managers (Mgr) that handle specific parts of the game. For example BattlegroundMgr handles the Battlegrounds (BGs).
Those classes have their own Update(uint32 diff) functions and they are called by World::Update that passes down the diff to them, for example:
sBattlegroundMgr->Update(diff);
sOutdoorPvPMgr->Update(diff);
sBattlefieldMgr->Update(diff);
/// ... there are more!
OnWorldUpdate hook
Last but not least, it calls sScriptMgr->OnWorldUpdate(diff);.
This is part of the AzerothCore Module System, and defines a hook that can be used by third-part modules to attach custom logic to the World::Update function.

IntentDialog matches only once at the start in bot framework

I have a simple piece of code where I want to run a first run operation in the beginning and let the default dialog handle everything else. In the code below.
bot.dialog('/firstRun', [firstRun1])
function firstRun1(session) {
session.replaceDialog('/')
}
bot.dialog('/', new builder.IntentDialog()
.matches(/wishlist/, '/wishlist')
.matches(/exclusive/, '/exclusive')
.onDefault('/runCampaign')
)
bot.dialog('/wishlist', (session, args) => {
session.endDialog('Add to wishlist')
})
bot.dialog('/exclusive', (session, args) => {
session.endDialog('Exclusive')
})
bot.dialog('/runCampaign', [runCampaign1])
function runCampaign1(session) {
session.send('default')
}
My problem is right here. When the person types exclusive I believe the default dialog will run its matches and should ideally trigger exclusive no matter how many times but for some reason its not happening that way as per the screenshot below. Once a person types exclusive or wishlist at the start it always runs the default at the bottom, how can I fix this. Also how to share data commonly between the different match clauses in the IntentDialog, lets say I want to have some variable session.dialogData.name across the matches and the default
UPDATE 1
Instead of saying session.endDialog inside the 2 areas in my code above, I simply wrote session.send() without ending any dialogs and now nothing happens when i type exclusive or wishlist. Am I missing something?
You should always call session.endDialog if you want to return to the calling(previous) dialog.
In your first example:
|current dialog|user input|next dialog|
|first run |go | / |
| / |whishlist | / |
| / |freak |runCampaign|
|runCampaign |<any> |runCampaign|
as you didn't call session.endDialog in the runCampaign dialog, you will always be in it and on any user input the 'default' will be printed.
In you second example, you missed to type "whishlist", so you immediately got into the runCampaign dialog. So, you changes to send there not called. But if you were typed 'whislist' as in the first example before "freak", you would have gotten into wishlist and you would always have printed "Added to wishlist" on any input.

How to maintain counters with LinqToObjects?

I have the following c# code:
private XElement BuildXmlBlob(string id, Part part, out int counter)
{
// return some unique xml particular to the parameters passed
// remember to increment the counter also before returning.
}
Which is called by:
var counter = 0;
result.AddRange(from rec in listOfRecordings
from par in rec.Parts
let id = GetId("mods", rec.CKey + par.UniqueId)
select BuildXmlBlob(id, par, counter));
Above code samples are symbolic of what I am trying to achieve.
According to the Eric Lippert, the out keyword and linq does not mix. OK fair enough but can someone help me refactor the above so it does work? A colleague at work mentioned accumulator and aggregate functions but I am novice to Linq and my google searches were bearing any real fruit so I thought I would ask here :).
To Clarify:
I am counting the number of parts I might have which could be any number of them each time the code is called. So every time the BuildXmlBlob() method is called, the resulting xml produced will have a unique element in there denoting the 'partNumber'.
So if the counter is currently on 7, that means we are processing 7th part so far!! That means XML returned from BuildXmlBlob() will have the counter value embedded in there somewhere. That's why I need it somehow to be passed and incremented every time the BuildXmlBlob() is called per run through.
If you want to keep this purely in LINQ and you need to maintain a running count for use within your queries, the cleanest way to do so would be to make use of the Select() overloads that includes the index in the query to get the current index.
In this case, it would be cleaner to do a query which collects the inputs first, then use the overload to do the projection.
var inputs =
from recording in listOfRecordings
from part in recording.Parts
select new
{
Id = GetId("mods", recording.CKey + part.UniqueId),
Part = part,
};
result.AddRange(inputs.Select((x, i) => BuildXmlBlob(x.Id, x.Part, i)));
Then you wouldn't need to use the out/ref parameter.
XElement BuildXmlBlob(string id, Part part, int counter)
{
// implementation
}
Below is what I managed to figure out on my own:.
result.AddRange(listOfRecordings.SelectMany(rec => rec.Parts, (rec, par) => new {rec, par})
.Select(#t => new
{
#t,
Id = GetStructMapItemId("mods", #t.rec.CKey + #t.par.UniqueId)
})
.Select((#t, i) => BuildPartsDmdSec(#t.Id, #t.#t.par, i)));
I used resharper to convert it into a method chain which constructed the basics for what I needed and then i simply tacked on the select statement right at the end.

Resources