Applescript for Illustrator: How can I make multiple items? - performance

I'm using Applescript to add a large number of polygons in Adobe Illustrator. The program is quite slow, however. Is it possible to add a list of items all at once?
Current code (works but slow):
repeat while X < 2000
repeat while Y < 2000
set myPath to make new polygon in layer 1 with properties {center point:{Y, -1*X}}
set Y to Y + 1
end repeat
set X to X + 1
end repeat
I'd like to build a list, and create a single command to place polygons at every position on the list.
Any ideas?

If you're willing to sacrifice editability, it might be faster if you rasterize every so often to remove all the objects:
tell application id "com.adobe.illustrator"
tell current document
rasterize source art every page item with options {resolution:150, antialiasing method:art optimized, color model:grayscale rasterization}
end tell
end tell
Add this into your code in such a way that it runs once every 1000 shapes or so (after the inner loop would run it every 2000 times). This is a trade off you have to make here, because your loop will create 4 million objects.
What exactly are you trying to do? Tell us your desired outcome and we might be able to find you a better, faster solution.

Related

Getting started with screenshot inventory recognition

I kinda wanna work on something for personal interest but I've hit a bit of a brick wall on the theory aspect due to lack of experience and would appreciate any help with it.
(I marked the main questions with 1) and 2) since it got a bit messy writing this, I apologize for that)
Here's what I want to do:
Load up a screenshot from a phone game inventory, which will have multiple items in squares and below it a count of how many you own.
Divide all of the items into smaller images, compare those images with item images on my PC and if it matches, add the count of the item into a container with the item name.
So the end result would be logging the inventory I have in the game, into a file on my pc which I can then use from then on..
I've had a basic course in coding before so I think I can do the value comparison, loop to compare the processed smaller images and then saving it etc.
What I'm stumped on however is the initial process of loading up the image, then cutting that image up into multiple smaller ones based on rectangles and then comparing those smaller ones with images I prepared beforehand of the same items..
) Not so much on the process itself but moreso on what tools could I use? What Libraries, already existing functions etc that could help with that?
I would appreciate any hints towards stuff that could be used for this.
If it helps I have some familiarity with Java, JS, C and Python.. though I'm not really opposed to picking up something new if it would help me here
So the process, in my head would look something akin to:
Add screenshot -> run function to cut up image into smaller images based on rectangles (top left to bottom right) -> save smaller images to something like an array -> via loop compare array of cut up items with array of item images on pc -> if match, add it into an exportable list along with its Name and Count which I want to do some processing with later..
(process on the side, via OCR presumably? Add all the item count numbers into an array too which will then be fed into the final list at the end of it to the corresponding item)
) Would this be feasible? Would precision of image comparison be a problem when doing this?
(maybe its my way of googling but results that came up seemed to be more about just full image comparison rather than dividing one image into multiple and then comparing those smaller ones..)

Godot : How to instantiate a scene from a list of possible scenes

I am trying to create a game in which procedural generation will be like The Binding of Isaac one : successive rooms selected from a list. I think I will be able to link them together and all, but I have a problem : How do I choose a room from a list ?
My first thought is to create folders containing scenes, something like
zone_1
basic_rooms
room_1.tscn
room_2.tscn
special_rooms
...
zone_2
...
and to select a random scene from the folder I need, for example a random basic room from the first zone would be a random scene from zone_1/basic_rooms.
The problem is that I have no idea if this a good solution as it will create lots of scenes, and that I don't know how to do this properly. Do I simply use a string containing the folder path, or are there better ways ? Then I suppose I get all the files in the folder, choose one randomly, load it and instanciate it, but again, I'm not sure.
I think I got a little lost in my explainations, but to summarize, I am searching for a way to select a room layout from a list, and don't know how to do.
What you suggest would work.
You can instance scene by this pattern:
var room_scene = load("res://zone/room_type/room_1.tscn")
var room_instance = room_scene.instance()
parent.add_child(room_instance)
I'll also remind you to give a position to the room_instance.
So, as you said, you can build the string you pass to load.
I'll suggest to put hat logic in an autoload and call it where you need it.
However, the above code will stop the game while it is loading the scene. Instead do Background Loading with ResourceLoader.
First you need to call load_interactive which will give you a ResourceInteractiveLoader object:
loader = ResourceLoader.load_interactive(path)
Then you need to call poll on the loader. Until it returns ERR_FILE_EOF. In which case you can get the scene with get_resource:
if loader.poll() == ERR_FILE_EOF:
scene = loader.get_resource()
Otherwise, it means that call to poll wasn't enough to finish loading.
The idea is to spread the calls to poll across multiple frames (e.g. by calling it from _process).
You can call get_stage_count to get the number of times you need to call poll, and get_stage will tell you how many you have called it so far.
Thus, you can use them to compute the progress:
var progress = float(loader.get_stage()) / loader.get_stage_count()
That gives you a value from 0 to 1. Where 0 is not loaded at all, and 1 is done. Multiply by 100 to get a percentage to display. You may also use it for a progress bar.
The problem is that I have no idea if this a good solution as it will create lots of scenes
This is not a problem.
Do I simply use a string containing the folder path
Yes.
Then I suppose I get all the files in the folder, choose one randomly
Not necessarily.
You can make sure that all the scenes in the folder have the same name, except for a number, then you only need to know how many scenes are in the folder, and pick a number.
However, you may not want full randomness. Depending on your approach to generate the rooms, you may want to:
Pick the room based on the connections it has. To make sure it connects to adjacent rooms.
Have weighs for how common or rare a room should be.
Thus, it would be useful to have a file with that information (e.g. a json or a csv file). Then your autoload code responsible for loading scenes would load that file into a data structure (e.g. a dictionary or an array), from where it can pick what scene to load, considering any weighs or constraints specified there.
I will assume that your rooms exist on a grid, and can have doors for NORTH, SOUTH, EAST, WEST. I will also assume that the player can backtrack, so the layout must be persistent.
I don't know how far ahead you will generate. You can choose to generate all the map at once, or generate rooms as the player attempt to enter, or generate a few rooms ahead.
If you are going to generate as the player attempts to enter, you will want an room transition animation where you can hide the scene loading (with the Background Loading approach).
However, you should not generate a room that has already been generated. Thus, keep a literal grid (an array) where you can store if a room has been generated. You would first check the grid (the array), and if it has been generated, there is nothing to do. But if it hasn't, then you need to pick a room at random.
But wait! If you are entering - for example - from the south, the room you pick must have a south door to go back. If you organize the rooms by the doors they have, then you can pick from the rooms that have south doors - in this example.
In fact, you need to consider the doors of any neighbor rooms you have already generated. Thus, store in the grid (the array) what doors the room that was generated has. So you can later read from the array to see what doors the new room needs. If there is no room, decide at random if you want a door there. Then pick a room at random, from the sets that have the those doors.
Your sets of rooms would be, the combinations of NORTH, SOUTH, EAST, WEST. A way to generate the list, is to give each direction a power of two. For example:
NORTH = 1
SOUTH = 2
EAST = 4
WEST = 8
Then to figure out the sets, you can count, and the binary representation gives the doors. For example 10 = 8 + 2 -> WEST and SOUTH.
Those are your sets of rooms. To reiterate, look at the already generated neighbors for doors going into the room you are going to generate. If there is no room, decide at random if you want a door there. That should tell you from what set of rooms you need to pick to generate.
This is similar to the approach auto-tile solution use. You may want to read how that works.
Now assuming the rooms in the set have weights (so some rooms are more common and others are rarer), and you need to pick at random.
This is the general algorithm:
Sum the weights.
Normalize the weights (Divide the weights by the sum, so they add up to 1).
Accumulate the normalized weights.
Generate a random number from 0 to 1, and what is the last accumulated normalized weight that is greater than the random number we got.
Since, presumably, you will be picking rooms from the same set multiple times, you can calculate and store the accumulated normalized weights (let us call them final weights), so you don't compute them every time.
You can compute them like this:
var total_weight:float = 0.0
for option in options:
total_weight = total_weight + option.weight
var final_weight:float = 0.0
var final_weights:Array = []
for option in options:
var normalized_weight = option.weight / total_weight
final_weight = final_weight + normalized_weight
final_weights.append(final_weight)
Then you can pick like this:
var randomic:float = randf()
for index in final_weights.size():
if final_weights[index] > randomic:
return options[index]
Once you have picked what room to generate, you can load it (e.g. with the Background Loading approach), instance it, and add it to the scene tree. Remember to give a position in the world.
Also remember to update the grid (the array) information. You picked a room from a set that have certain doors. You want to store that to take into account to generate the adjacent rooms.
And, by the way, if you need large scale path-finding (for something going from a room to another), you can use that grid too.

extracting either two or one intervals in a tier

I'm new to praat scripting so bear with me: I have a for loop set up and I want to extract data from three tiers. My first two tiers work beautifully but I'm having trouble with the third tier.
So in the third tier, at a given point in the loop, there could either be 1 or 2 elements, (My linguistics researcher is having me write this; I don't have a full understanding of what exactly I'm extracting) and I don't know how to check how many elements there are. Is there a function I can use that allows me to get the number of elements at a given interval? My line of thought at the moment is get the number of elements in the third tier at that point in the loop. If there is only one, get that one, assign it to the correct variable name, and move on. If there are two, grab both.
I can think of two ways to do this, "manually" and by extracting parts of the TextGrid.
Let's imagine (for clarity) that you want to count the number of points that fall within a given interval. There are some differences between this and counting intervals that fall within intervals, but baby steps.
Manually
What I mean by manually is that you can get the index of the "first" point within your interval (the first point after the beginning of the interval), and the index of the "last" point, and then just subtracting (beware of fencepost errors!). If the first is 3 and the last is 8, you know there are 6 points in your interval.
Let's assume we have this:
textgrid = selected("TextGrid")
main_tier = 1 ; The tier with the main interval
sub_tier = 2 ; The tier with the elements you want to count
interval = 3 ; The interval in the main tier
start = Get start point: main_tier, interval
end = Get end point: main_tier, interval
Then we can do this:
first = Get high index from time: sub_tier, start
last = Get low index from time: sub_tier, end
total = last - first + 1
appendInfoLine: "There are ", total, " points within interval ", interval
(Or you could use the "Count points in range..." command in the tgutils CPrAN plugin).
If you were counting intervals, you'd have to change that slightly:
first = Get high interval at time: sub_tier, start
last = Get low interval at time: sub_tier, end
Or, if you wanted to count only those intervals that fall entirely within your main interval
first = Get high interval at time: sub_tier, start
last_edge = Get interval edge from time: sub_tier, end
last = last_edge + 1
Extracting parts
An entirely different approach would be to use the "Extract part..."
command for TextGrids. You can extract the part of the TextGrid that
falls within your time window, and then work with that part only.
Counting the number of intervals in that part would then simply be a
matter of counting the total number of intervals in that new TextGrid.
Of course, this does not check whether your the intervals that are considered to be within are entirely within.
A simple example:
Extract part: start, end, "yes"
# And then you just count the intervals
intervals = Get number of intervals: sub_tier
# or points
points = Get number of points: sub_tier
If you want to do this repeatedly (eg. for each of the intervals in your main tier), the tgutils plugin mentioned above has a script to
"explode" TextGrids. Although the name might be a bit unnerving,
this just separates a TextGrid into interval-sized chunks using the
intervals in a given tier (by calling the same command mentioned above). As an example, if you "explode" a TextGrid
using an interval tier with 5 intervals, you'd get as a result 5
smaller TextGrids, corresponding to each of the original intervals.
The script can preserve the time stamps of the resulting TextGrids, to
make it easier to refer back to the original. And if run with a
TextGrid and a Sound selected, it will "explode" the Sound as well, so
you can work on the combination of both objects as well.
(Full disclosure: I wrote that plugin).

Is it possible to create a table made up of multiple what-if scenario results?

I'm going to describe my goal in steps because I think that might be the easiest way to explain it. This is what I'm trying to do:
1) Create a template that has various calculations on it. On this template, 1 specific cell is left blank. The calculations will change depending on what's in this cell (I'll refer to this as the special cell).
2) There's one final figure behind these calculations that's important. What I want to do is create a list with every possible final figure and in an adjacent cell, list the value of the special cell that gives this final figure.
The problem is Excel for Mac 2008 doesn't use macros or VBA. In my Windows version of Excel, this is just a simple function. But on Excel for Mac 2008, I'm not sure at all how to tackle this. The only solution I can think of is to create one sheet for every possible value of the special cell, with all the calculations done specifically for that value of the special cell. Then I could just link each final figure/special cell to a main page so all the information is together. However, there are roughly 400 values the special cell can take, and I really don't want to create 400 different sheets. Does anybody know how I can do this?
Also, just as a note in case this is easier to visualize what I mean, I'm basically trying to run multiple what-if scenarios and collect one specific number from each of these scenarios.
Here's an example of the processes involved. I should mention here that there are actual 2 different special cells, I wrote 1 in the original description because I'm assuming the idea would be the same to do 2:
1) The main template sheet is located on Sheet A
2) There are 10 slots for store names
3) Each store has a rate, the rate is found by applying a vlookup which looks up the special cell 1 and where the array table is located on Sheet B
4) Each store also has an index number (referred to as index)
5) Each store has a calculation which is index * special cell 2 (referred to as calc1)
6) Each store has another calculation which is rate * num1 (referred to as calc2)
7) Each store has another index number (referred to as index2)
8) Some of the index2 values have to be multiplied by calc2, the rest will stay the same (referred to as calc3)
9) A summation has to be done, summing all the calc2 values to result in sum1
10) A summation has to be done, summing all the calc3 values to result in sum2
11) The final figure is sum1 + sum2
It sounds like you could create 400 rows where each row is a what if scenario. Then next to each row you could take an input and an output, and graph accordingly.
Update
Per your description so far I've created the attached workbook with some formulas to put you in the right direction:
https://dl.dropbox.com/u/19599049/120813_2c.xlsx
It calculates the sum1 and sum2 For 10 stores based on the 2 inputs.
Note that I colored which cells were ending up in which final output.
yellow = original sum1/sum2
blue = array formula version of sum1/sum2
green = data used in both.
I did this to point out that while this example workbook seems to follow all 11 of your rules. the input 2 doesnt appear to be included in the final outputs of my mock-up version for some reason.
Either way this should serve as a good basis to get you started. And I can modify it if you continue to include more details.

Predator-prey simulation

I'm trying to implement a model of predator-prey.
It is agent-based model. Every few milliseconds is a new move. On the field there are two types of creatures: predator and prey. The behavior of each of them is given by the following rules:
Prey:
Just moved to an unoccupied cell
Every few steps creates offspring to his old cell
Life expectancy is limited by the number of moves
Predator:
Predator moves to the cell with prey. If such cells are not, in any
free neighboring cell
Same
Same
I have a problem with the choice of prey move.
For example, I have preys in cells 5 and 9.
Each of them can move to cell 6.
How can I resolve this conflict?
Thanks
Use asynchronous updating. Iterate through the prey in random order, having them decide in turn to which cell they should move.
This is a common approach in simulations. It has an additional benefit in that it eliminates limit cycles in the dynamics.
How long does 'moving' take? If you move one, then after the prey has moved, you move the next one, there is no conflict. The prey will simply see the space is already occupied and move elsewhere.
If moving takes time you might say the prey keep an eye on each other and see if some other prey is trying to move somewhere (like people watch cars in traffic). Then you would change the status of the target field to 'reserved for 5' when prey from 5 is trying to move there. Then prey from 9 can see this and decide if they want to collide with 5 (could be intresting :P) or avoid 5.
Depends on game logic. If preys can be on the same cell, so simply use indicator that show preys count. If you are using 2D array for representing current field state you can use such codes:
-1 - predator
n - preys
n >= 0, (n = 0 - cell is empty, n = 1 cell contains 1 prey and so on).
Otherwise (if preys can't appear on the same cell) use turn-based strategy. Save all your preys in array or give number to each prey. In that case preys' moves represents by simple loop (pseudocode):
for each prey in preys
move(prey)
end
where move logic describes algorithm how your prey moves.
Quite a few ways, depending on if you're deciding & moving as two steps or one, etc:
Keep track of each prey's intended moves, and prevent other prey from occupying those.
Check if another prey is already occupying the destination, and do nothing if so.
Remove one of the preys at random if they both try to occupy the same location.
Re-evaluate the move options if the destination is occupied.
There's not really a 'right' way to do it.
See this related question and my answer.
It describes a good collision detection mechanism.
Avoid O(n^2) complexity for collision detection

Resources