Moving AnyLogic agents according to database table - anylogic

My model has a collection of trucks, where the Source block provides each truck with a unique ID. I also have a database containing information on the vehicles' movements.
No column has unique values, but together the trip_start_date and vehicle_id should be a unique set. I'm trying to structure a moveTo block such that when a date in the trip_start_time column is reached during the model runtime, then the agent with that vehicle_id as a parameter will move to the lat/long in a certain amount of time.
However, I'm getting an "empty database value result." I'm wondering if this is because it's expecting every model date to have an entry? I considered making a function that's called when a date in the database is encountered, but I was told that the moveTo block should be able to handle this activity. Help in resolving this issue would be greatly appreciated!

The way you are trying to use the MoveTo block is not correct. It is hard to explain here but I think you need to go through a few tutorials inside help to get a better fundamental understanding.
However, below is a reproducible example of the behavior I think you want to implement, but using agent-based approach instead of a process-centric or discrete event approach.
I have an agent called Vehicle with a ID called vehicle ID.
There is a Dynamic event has all the parameters found in the DB
Then at the start of the model, we generate all the moveTo events found in the Database using the code below.
List<Tuple> rows = selectFrom(db_table)
.where(db_table.vehicle_id.eq(vehicleID))
.list();
for (Tuple row : rows) {
//What is the start time of the movement
double timeToTripBegin = dateToTime(row.get( db_table.trip_begin_time ));
//Lets create a new movement event to trigger the movement int he future
create_MoveToLocation(timeToTripBegin,
row.get( db_table.latitude ),
row.get( db_table.longitude ),
row.get( db_table.trip_duration_h ));
}
This event will then execute the move to when the time arrives

Related

Trigger NOTIFY only on points that are in a certain PostGIS region

I would like to trigger NOTIFY only on points that are in a certain PostGIS region. I have a table called car. I want to get a NOTIFYcation every time a car updates it's coordinate or a new car is updated, but only in a certain region. Essentially I want to monitor for changes in rows that have a point that is located in the region of my interest.
I would be grateful for any hints in the right direction. Thank you in advance.
if I understand correctly, you should follow a method like this,
1- fist of all you create a "view" which is return boolean value if your point of car and region interacts with each other. For this st_contains or st_intersects function be useful.
2- Create a trigger on the car table and the trigger should run every action of update or insert.
3- The trigger affects rows just be returned of the first view that you make
this might not be the best way but I think it can solve your situation.

Access paramters of Anylogic agent population created from db

OK... let me retry the question.
I'll just walk through the steps I (wrongly) assumed would work.
Create a data table in excel with passenger info (id, flight_time, type, class, qty...), note that the table is sorted by id... not flight_time.
Import this database into anylogic.
Create a population of agents (Passenger/Passengers) from the data table (one/row).
Create a schedule that addresses the Start Column as flight_time and Value column as qty (for this job I'm only sending one passenger at a time therefore qty = 1 for each row).
Set the pedSource to arrive according to schedule and to use the Passenger Agent as the New pedestrian.
So here is where I'm losing it. When I run this model the new Passengers do not have any parameters associated from the data table. The pedestrian id is some weird number (say 3000 or so). I can click on the Passengers icon during run time and scroll through the created agents (all of the parameter data is there and correctly assigned), but I'm not sure how to associate the new Agents in the run-time model with the population of Passengers agents.
Am I missing a step here? I was thinking that if I import a population of agents from a data table and then have each show up at a particular time in the model that I could then do some calculations with regard to each such as ped.exitTime = time() - ped.flightTime - ped.bufferTime.
I'm just not understanding why the table data is not available for use during run-time through ped? Is there another mapping step that must be performed to push the data to the ped agnets?
I'm at an impasse at this point. I hope this question is described more clearly and your feedback is appreciated.
Several things are wrong here.
You do not create agents in a pop first and then try to reuse them in a PedSource. The latter creates agents itself.
You don't seem to create pedestrians but just agents
you are not mapping the data to parameters
Quick guide to help:
create custom agent type "MyPed" . Make sure its "use in flowchart" property is set to "Pedestrian"
add 1 param into "MyPed" for each dbase table column
set your PedSource to "calls of inject()" function for its arrivals
delete your schedule, you cannot get the data you need
USe a DynamicEvent. Include 1 parameter argument for each dbase column. On Startup of main, loop across all dbase entries and create a dynamic event with the current row-data.
in the action of the DynEvent, call myPedSource.inject(1) and then manually fill that ped with the data from the arguments
This is not straightforward, especially the DynEvent stuff. So do more research in the AL help to understand these and how they work, check example models...

How to reset an auto-incremented value when another value changes?

I'm actually working on a PostgreSQL DB structure and I'm having hard time figuring out how to solve a problem.
The DB will be recording data regarding architectural objects.
The main table, "object",have attributes that describe the object with information like type, localization, etc.
One of these attributes is a serial named object_num.
Another table is called "code" which contains a code made of three letters corresponding to the town where the mission is conducted.
Example :
I'm working on an architectural inventory for the city of Paris. The code_name will be PRS and the first entry (aka the first architectural entity : house, bridge, etc) will be associated to object_num 001.
So PRS001 will be a unique identifier referring to this specific architectural entity.
Things going on, I might end up with quite a few entries, for example entry PRS745.
Say this mission isn't finished yet but a new one starts for the city of Bordeaux, where BDX is going to identify the inventory. It would be great that the identifier for the first entry will be BDX001 rather than BDX746 (auto-increment).
Considering this, it will be also nice that, going back to the Paris mission after a few records for the Bordeaux mission (say BDX211), the next value will start back at (PRS)745 rather than (BDX)211.
So, is it possible to reset the value of a serial to 1 when using a new code ?
And is it possible to start back serial increment from the last value of a specific code ?
I guess you can perform this task with constraints and checks, but I'm not really familiar with these and am a bit lost...
Thanks for your help,
Yrkoutsk
You could create separate sequences for each code_name and grab your auo-increment based on the code_name:
CREATE SEQUENCE PRS START 1;
CREATE SEQUENCE BDX START 1;
insert into your_table (object_num, code_name, other_data)
values ( code_name||lpad(nextval(code_name)::char,3,'0')
, code_name, other_data);
You will have to create a new sequence every time you add a new code_name otherwise the db will end up throwing an error when you try accessing the nonexistent sequence.

How to plot data using custom objects in AnyLogic?

I'm building an ArrayList that contains object of type "TimeRecord" (a object that I have defined). Each TimeRecord object contains the following fields:
ID -> identifier of the field
StartTime -> time when an object pass in a specific point of my network
StopTime -> time when an object pass in another specific point of my network
Each time field is populated with the AnyLogic time() function and has the aim to collect the time between two point in my network. Is it possible to pass a list with the time differences StopTime - StartTime to a chart object to plot the the time of every request?
Yes, you can use a dataset and update it using an event. For instance:
Drag a dataset to main (probably, to use a histogram dataset is a good idea in your case , it depends on what you want to show)
Drag an event to main to be updated every n times.
In the field action of the event you can add something like this:
dataset.reset();
for (TimeRecord t : YourArrayList) {
dataset.add(t.StopTime - t.StartTime);
}
Another way to do this, without using a loop, it is to create a variable at the agent level to record start time, and then when the agent finishes what is doing add to the dataset the difference between stop and start.
Anyway, add a plot, and specify the corresponding dataset in the data field.

Salesforce- Trigger - Deleting object

Hello fellow code lovers, I am attempting to learn apex code and stuck on a problem. Since most of you guys here are avid code lovers and excited about problem solving, I figured I could ran by problem by.
I am attempting to Create a Trigger on an object called Book that does the following:
On Delete, all associated Chapters are also deleted
There is also an object named Chapter that is has a lookup to book.
Here is my attempt. This is my first ever attempt at apex so please be patient. Is anyone willing to dabble in this piece of code?
trigger DeleteChaptersTrigger on Book__c (before delete) {
List<Book__c> book = Trigger.old;
List<Chapter__c> chapters = new List<Chapter__c>();
Set set = new Set();
for (Book__c b :books){
if ()
}
}
You need to write all trigger with consideration that the trigger might be processing many records at any one time so you need to bulkify your trigger code.
Here are the variables that available on the trigger object.
You want to get all the record ids that will be deleted. Use the keyset method on the oldmap to get this info without looping and creating your own collection. Then you can just delete the records returned from the query.
trigger DeleteChaptersTrigger on Book__c (before delete) {
Set<string> bookids = Trigger.oldMap.keyset();
delete [SELECT Id FROM Chapter__c WHERE Book__c IN :bookids];
}
Apex code is unlike other languages where it gets confused with reuse of used words, like set as a variable name. Apex is also case insensitive.
Since you have full control, I recommend changing the way your custom objects are related to each other.
A chapter has no meaning/value without a book so we want to change the relationship between the two.
Remove the lookup on the Chapter object and replace it with a master-detail. When a master record gets deleted, Salesforce automatically deletes the detail related records. This is what you want, and without coding.