After Effects: Stop/Start at Markers and Loop - after-effects

I have a looping composition with Time Remapping and the following snippet in the Expression language menu:
loopOut(type = "cycle", numKeyframes = 0);
I would like to build a script, which stops and starts the composition at specific markers (i.e. at Odd Markers = Stop, and at Even = Play). This should keep the little snippet below into consideration.
I managed to do it for two markers but not for an infinite number...
m = thisLayer.marker;
if (m.numKeys > 1){
if (time < m.key(1).time)
time
else if (time < m.key(2).time)
m.key(1).time
else
m.key(1).time + (time - m.key(2).time);
}else{
value
}
Do you have any ideas on how to expand its functionality?
Many thanks!

Related

What am I misunderstanding when determining if a value is between two numbers?

I have a PDF form that adds up several different answers and displays the sum of these answer at the bottom of the page. I want to take that number, and have a sentence underneath it display three different options depending on the sum.
Greater than 60: Proceed
between 45 & 60: Consult Sales Lead
Less than 45: Decline
I am attempting to run a custom calculation script that takes the sum (which is named "total") and writes the above options, but I'm running into a myriad of errors.
My code I've written is below
var A = this.getField("total").value;
if (A >= 60){
event.value = "Proceed";
} else {
if (A <= 45){
event.value = "Decline";}
} else {
if (A < 60 && A > 45){
event.value = "Proceed, decision made with sales leader";}
}
If I were to only write the below block, I do not get any errors.
var A = this.getField("total").value;
if (A >= 60){
event.value = "Proceed";
}
I'm a newbie when it comes to most JavaScript, so any help is greatly appreciated! Thanks in advance!
I have based most of my code off of different search results from google. My main source
example 1
Below are a few other links I've referenced
example 2
example 3
You can leave away the
if (A < 60 && A > 45) {
line, because that condition is always true after the two previous conditions.
And then, it should work properly.
Just if you want to stay with that last condition, you would have to close it with a curly brace.
I think I managed to figure it out! For some reason, the addition of the "else" factor was causing syntax errors, so I tried it without and it seems to work as intended!
My code, for anyone that happens to find this, is the following:
var A = this.getField("total").value;
if (A >= 60) {event.value = "Proceed";}
if (A <= 59 && A >= 46) {event.value = "Proceed, decision made with sales leader";}
if (A <= 45) {event.value = "Decline";}
if (A == 0) {event.value = " ";}
Thanks to everyone that took a look at this, even if you didn't get to comment before I figured it out!

Can't understand how it works (ThinkScript code)

I'm currently converting a ThinkScript indicator to python, however, I've run into this piece of code and I'm kinda confused on how it works:
input rollingPeriodMinutes = 60;
def factor = (SecondsFromTime(Market_Open_Time) / (60 * rollingPeriodMinutes) / 100);
def rolloverTime = if factor == Round(factor) then 1 else 0;
rec H1 = compoundValue(1, if !rolloverTime then if high > H1[1] then high else H1[1] else high, high);
rec H = compoundValue(1, if rolloverTime then H1[1] else H[1], high);
I can't really understand what is stored at the end in the variable "H". Can you help me understand?
Any help is really appraciated!! Thanks
input rollingPeriodMinutes = 60;
declares (defines) and sets a variable, rollingPeriodMinutes, to a default value of 60. The input declaration indicates that the user will be able to alter this value in the thinkorswim settings for this script.
def factor = (SecondsFromTime(Market_Open_Time) / (60 * rollingPeriodMinutes) / 100);
declares and sets a variable, factor to a calculated value. This uses the rollingPeriodMinutes value, above, as well as the SecondsFromTime function and a Market_Open_Time variable that must have been set elsewhere in the script.
def rolloverTime = if factor == Round(factor) then 1 else 0;
declares and sets a variable, rolloverTime to a boolean based on the if statement. This uses the factor variable above (1 is true and 0 is false in thinkscript).
rec H1 = compoundValue(1, if !rolloverTime then if high > H1[1] then high else H1[1] else high, high);
rec H = compoundValue(1, if rolloverTime then H1[1] else H[1], high);
rec is actually the same as def and has been obsoleted. Previously, it specifically declared a recursive variable; now one would just use def regardless. See the notes below for more information.
CompoundValue is an easy statement in thinkscript, but complicated to understand from the Learning Center reference.
In short, the declarations for H and H1 are saying 'going back 1 bar: if no data is present, then use the if statement to determine a value; else if data is present, then use the high value.
Broken out, the algorithm for H1 (where high is a reserved word for the high price for a given bar) could look like:
let numBarsBack = 1
if (data is present for the bar at numBarsBack) then
if (!rolloverTime == true) then
if high > (H1 value one bar previous) then H1 = high
else H1 = (H1 value one bar previous)
else H1 = high // thinkscript sometimes requires a "default" in `if` statements, even if there's no 3rd possible value
else (if rolloverTime == true) then H1 = high
else (if data is not present for the bar at numBarsBack) then H1 = high
*** See my complete description of how CompoundValue works in thinkscript at the SO question "Understanding & Converting ThinkScripts CompoundValue Function".***
Notes:
SecondsFromTime, according to the current thinkscript Learning Center reference looks like:
SecondsFromTime ( int fromTime);
Description
Returns the number of seconds from the specified time (24-hour clock notation) in the EST timezone. Note that this function always returns zero when chart's aggregation period is greater than or equal to 1 day.
Input parameters
Parameter Default value Description
fromTime - Defines time from which seconds are counted, in the HHMM format, 24-hour clock notation.
The Learning Center reference for rec says this:
rec
Notice: this is an article about an obsolete thinkScript® notation. Although rec variables are still supported by thinkScript®, they can be completely replaced by def.
Syntax
rec
Description
Enables you to reference a historical value of a variable that you are calculating in the study or strategy itself. Rec is short for "recursion".
Example
rec C = C[1] + volume;
plot CumulativeVolume = C;
This example plots the cumulative volume starting from the beginning of the time period.
and, finally:
Remember that thinkscript code is executed for every bar in a selected period. Ie, if you're looking at 10 days with a daily period, there will be a bar for each of the 10 days; and the script will run a loop, repeating the code for each of those 10 bars. As a result, the variables will have appropriate values for each bar.
Although the OP is wanting to convert a script to Python, if someone comes here interested in how thinkscript works, there are tricks to keep a value constant for an entire script (though this section of code does not include examples for that). For information on how to do this in thinkscript, see my answer to SO question "thinkscript - How to create a variable that retains its value".

Can I use return to return to the start of an if statement?

I'm currently programming some homework, and we have to make a program that turns a hindu-arabic numeral into a roman numeral. I've already made the first part, where my teacher said we had to make sure the number is in between 1 and 3999. My algorithm so far is like this:
if (num-1000) > 0 {
add M to output
num -= 1000
return if
}
else {
(repeat for other digits, aka 500, 100, 50, and so on)
}
The problem is, I don't know if it's even possible. All the Stack Overflow pages I've seen say that I should use while statements for this, but since we haven't tackled while statements yet (even though I've self-learned it) we can't use while loops. So, can I use return to return to the start of an if statement?
What you are describing is a while. You can also achieve that with a go to but using that at this stage of learning would inspire some very very bad habits so I wholeheartedly discourage it. Another way you could do this is with recursion but that is an even more advance topic.
Given your restrictions (no loops, a number between 1 and 3999) I think you are supposed to use a bunch of ifs. Something like this pseudocode:
if (n >= 3000)
add 'M'
else if (n >= 2000)
add 'MM'
else if (n >= 1000)
add 'MMM'
n = n % 1000;
if (n >= 900)
add 'CM'
// and so on

range function in sml with a step parameter

I am very new to SML and functional programming.
I have searched the site but was unable to find an answer to my question.
I am trying to write a basic range function with a start, stop, and step parameter.
For example, range(2, 12, 3) should return the list [2,5,8,11].
I don't get any errors, but when I try running range(2,12,3); the cursor advances to the next line and nothing happens, I can't even type anything into the smlnj app.
Here is my code:
fun range(start, stop, step) =
if start = stop then nil
else start::range(start+step, stop, step);
Which outputs this:
val range = fn : int * int * int -> int list
What changes do I need to make to my code so that when I run range(2,12,3) I get [2,5,8,11] ?
Thank you
Your condition (start = stop) to break the recursion is wrong. In your example you'll perform recursive calls with start=2, start=5, start=8, start=11, start=14, ... leading to an infinite loop. It's not that nothing happens, it's just that smnlj keeps computing...
You have an infinite recursion whenever stop - start is not a multiple of the step size (or zero).
Look at range(11,12,3), which should generate your last number:
if 11 = 12 then nil
else 11::range(11+3, 12, 3)
This will calculate range(14,12,3):
if 14 = 12 then nil
else 14::range(14+3, 12, 3)
and then range(17,12,3), and so on, ad infinitum.
You need to replace = with either > or >=, depending on whether stop should be included or not.

Traveling a Grid for a Palindrome

I have been trying to solve this problem for quite a bit now and have not been able to come up with anything other than a naive solution. Basically, I am given a character grid of size N in which I have to find the number of distinct paths from the upper-left to the top-right when only traveling down and to the right that give a palindrome.
Here is an example of a grid:
ABCD
BXZX
CDXB
WCBA
There are 12 palindromes in this grid such as "ABXZXBA". My solution was to walk through all paths in the grid and check if that string was a palindrome by keeping a character stack for the first N characters and popping each character for the next N characters and checking if they were the same. This solution times out when N gets too big and I am not sure how to proceed. Any psuedocode or suggestions would be much appreciated.
Just a theory - I haven't tried to work out the code yet:
You could start at the top left and bottom right and keep the paths in sync. As it is a palindrome there would need to be the same letters in the path from the bottom as from the top.
Each time you look for the next step in a path, check to see that there is a matching letter in the reverse step.
The reverse step's available path can be further constrained in that it can't get to the left or above the forward step.
Stop when the paths meet, which is complicated by the fact that they might end up on the same grid location (odd number of rows), or they might just meet up (even number of rows).
The back tracking and stack keeping may be a bit more complicated, as you have to account for (possibly) several choices of reverse step, but it should cut down the number of possibilities. It might be better to think of it as each step in the forward and reverse paths gives you a new (smaller) grid to check for palindromes.
Something like this?
(At least it stops if the path is not forming a palindrome or is out of bounds/sync.)
JavaScript code:
function f(m){
var stack = [[0,0,m.length - 1,m.length - 1,""]],
count = 0;
while(stack.length > 0){
var next = stack.pop(),
y = next[0],
x = next[1],
yr = next[2]
xr = next[3];
if (y - yr > 0 || x - xr > 0){
continue;
} else if (m[y][x] != m[yr][xr]){
continue;
} else if (y == yr && x == xr){
count++;
} else {
stack.push([y + 1,x,yr - 1,xr]);
stack.push([y + 1,x,yr,xr - 1]);
stack.push([y,x + 1,yr - 1,xr]);
stack.push([y,x + 1,yr,xr - 1]);
}
}
return count;
}
Output:
var t = [["A","B","C","D"]
,["B","X","Z","X"]
,["C","D","X","B"]
,["W","C","B","A"]];
console.log(f(t));
12