Action Script 3.0 from 2.0 Falling Randomly Placed Objects and a countdown timer - actionscript

Looking for some help on a lesson I teach to my pupils in Flash Animation.
Not overly familiar with the code, I can essentially do this one thing
I have four layers on my animation. Background, snow, timer and action script.
I have the following code on my snow layer (which has a simple oval in white on it)
onClipEvent (load) {
movieWidth=550;
movieHeight=400;
i=1+Math.random()*2;
k = -Math.PI+Math.random()*Math.PI;
this._xscale = this._yscale=50+Math.random()*100;
this._alpha = 60+Math.random()*100;
this._x = -10+Math.random()*movieWidth;
this._y = -10+Math.random()*movieHeight;
}
onClipEvent (enterFrame){
rad += (k/180)*Math.PI;
this._x -= Math.cos(rad);
this._y += i;
if(this._y>=movieHeight){
this._y = -5;
}
if((this._x>=movieWidth) || (this._x<=0)){
this._x = -10+Math.random()*movieWidth;
this._y = -5;
}
}
and this on my action script layer
this.onEnterFrame = function()
{
var today:Date = new Date();
var currentYear = today.getFullYear();
var currentTime = today.getTime();
var targetDate:Date = new Date(currentYear, 11, 25);
var targetTime = targetDate.getTime();
var timeLeft = targetTime - currentTime();
var sec = Math.floor(timeLeft/1000);
var min = Math.floor(sec/60);
var hours = Math.floor(min/60);
var days = Math.floor(hours/24);
sec = String(sec % 60);
if(sec.length < 2){
sec = "0" + sec;
}
min = String(min % 60);
if(min.length < 2){
min = "0" + min;
}
hours = String(hours % 24);
if(hours.length < 2){
hours = "0" + hours;
}
days = String(days)
var counter:String = days + " Days\n" + hours + ":" + min + ":" + sec;
time_txt.text = counter;
}
for (k=0; k<100; k++){
duplicateMovieClip(this.snow, "snow"+k, k);
}
I know this worked previously in AS2, but I have trouble getting it to work.
Currently getting a syntax error which wasn't there when I used an older version
Any help is much appreciated
Thanks

You are using flash player 6 syntax with flash player 5 elements (onClipEvent() handlers assignable to movieclips on the timeline). I don't think one could possibly expect to see something like that now... As it started getting outdated by late 2001, when FP 6 with (almost) fully ECMA262-compliant ActionScript 1.0 emerged.
Anyway, you can compile it after setting File -> Publish Settings... -> Script option to ActionScript 1.0 or ActionScript 2.0. Your code does work this way, I copied and pasted it to make sure. Be carefull to place the onClipEvent() code on the snow clip and not on the timeline frame. This is the FP5 way of handling events. And the rest of the code goes to timeline frame (I guess this is what you did).
You may also need to change target Flash Player version in case your IDE doesn't allow you to set script version to 1.0 without that (with Flash Pro CS6 this is not the case).
Working example (open in CS5 or newer): snowCS5.fla

Related

Formula To Aggregate Totals for Year

I have a spreadsheet that I use to keep track of climbing progress (snippet shown below). I have formulas and graphs that keep track of counts of specific grades over time, but I am having trouble with a formula to keep a running total (by year) of feet climbed. I intent to put this in another sheet.
Basically I would like a single cell that does something like ... if Sheet1!A:A begins with "21." and if Sheet1!E:E,"<>*%" (which means I actually completed the climb) then add the rows total climb length (Sheet1!J:J * Sheet1!I:I) to the running total for that year.
What is the best way to do this?
You can try using Apps Script and creating a script in order to manage your task.
So for example, you might want to take a look at the snippet below:
Code
function calculateTotal() {
let ss = SpreadsheetApp.getActive().getSheetByName('Sheet1');
let date = ss.getRange('A2:A').getDisplayValues();
let tries = ss.getRange('E2:E').getDisplayValues();
let lengths = ss.getRange('I2:I').getDisplayValues();
let total = 0;
for (let i =0; i<date.length; i++) {
if (date[i][0].toString().startsWith('21') != false && tries[i][0].toString().includes('%') == false) {
total = total+lengths[i][0];
}
}
ss.getRange('M2').setValue(total);
}
Explanation
The script above gathers all the values from the Sheet1 and loops through them. If the conditions check (the date should start with 21 and the E column does not contain %) then the corresponding length is added to the total; the total is then saved in the M2 cell in this case.
Further improvement
The advantage of using a script is that it is versatile and easier to manage. In this situation, you can make use of Apps Script's time-driven triggers; so assuming you plan on updating your spreadsheet every day at a specific time, you can create a trigger which will run right after it.
For example, the below function creates a trigger for the function above which will run every day at ~9.
function createTrigger() {
ScriptApp.newTrigger("calculateTotal")
.timeBased()
.atHour(9)
.everyDays(1)
.create();
}
Reference
Google Apps Script;
Apps Script Installable Triggers.
Thanks Ale13 ... using your example and adding a couple of things (also needed to parseInt totals) ...
function calculateTotal() {
let ss = SpreadsheetApp.getActive().getSheetByName('Sheet1');
let s7 = SpreadsheetApp.getActive().getSheetByName('Sheet7');
let date = ss.getRange('A2:A').getDisplayValues();
let type = ss.getRange('F2:F').getDisplayValues();
let tries = ss.getRange('E2:E').getDisplayValues();
let lengths = ss.getRange('I2:I').getDisplayValues();
let laps = ss.getRange('J2:J').getDisplayValues();
let btotal = 0;
let rtotal = 0;
for (let i =0; i<date.length; i++) {
if (date[i][0].toString().startsWith('21') != false && tries[i][0].toString().includes('%') == false) {
// Totals for Bouldering
if (type[i][0] == "B") {
btotal = btotal + parseInt(lengths[i][0]*laps[i][0]);
}
// Totals for Top Rope or Sport
else {
rtotal = rtotal + parseInt(lengths[i][0]*laps[i][0])
}
}
}
console.log("Roped total = " + rtotal)
console.log("Bouldering total = " + btotal)
s7.getRange('B2').setValue(rtotal);
s7.getRange('B3').setValue(btotal);
}

Rounding a Duration to the nearest second based on desired precision

I recently started working with Dart, and was trying to format a countdown clock with numbers in a per-second precision.
When counting down time, there's often a precise-yet-imperfect way of representing the time - so if I started a Duration at 2 minutes, and asked to show the current time after one second has elapsed, it is almost guaranteed that the precision of the timer will report at 1:58:999999 (example), and if use Duration.inSeconds() to emit the value, it will be 118 (seconds) which is due to how the ~/ operator works, since it's rounding down to integers based on the Duration's microseconds.
If I render the value as a clock, I'll see the clock go from "2:00" to "1:58" after one second, and will end up displaying "0:00" twice, until the countdown is truly at 0:00:00.
As a human, this appears like the clock is skipping, so I figured since the delta is so small, I should round up to the nearest second, and that would be accurate enough for a countdown timer, and handle the slight imprecision measured in micro/milli-seconds to better serve the viewer.
I came up with this secondRounder approach:
Duration secondRounder(Duration duration) {
int roundedDuration;
if (duration.inMilliseconds > (duration.inSeconds * 1000)) {
roundedDuration = duration.inSeconds + 1;
} else {
roundedDuration = duration.inSeconds;
}
return new Duration(seconds: roundedDuration);
}
This can also be run in this DartPad: https://dartpad.dartlang.org/2a08161c5f889e018938316237c0e810
As I'm yet unfamiliar with all of the methods, I've read through a lot of the docs, and this is the best I've come up with so far. I think I was looking for a method that might looks like:
roundedDuration = duration.ceil(nearest: millisecond)
Is there a better way to go about solving this that I haven't figured out yet?
You can "add" your own method to Duration as an extension method:
extension RoundDurationExtension on Duration {
/// Rounds the time of this duration up to the nearest multiple of [to].
Duration ceil(Duration to) {
int us = this.inMicroseconds;
int toUs = to.inMicroseconds.abs(); // Ignore if [to] is negative.
int mod = us % toUs;
if (mod != 0) {
return Duration(microseconds: us - mod + toUs);
}
return this;
}
}
That should allow you to write myDuration = myDuration.ceil(Duration(seconds: 1)); and round the myDuration up to the nearest second.
The best solution according to the documentation is to use .toStringAsFixed() function
https://api.dart.dev/stable/2.4.0/dart-core/num/toStringAsFixed.html
Examples from the Documentation
1.toStringAsFixed(3); // 1.000
(4321.12345678).toStringAsFixed(3); // 4321.123
(4321.12345678).toStringAsFixed(5); // 4321.12346
123456789012345678901.toStringAsFixed(3); // 123456789012345683968.000
1000000000000000000000.toStringAsFixed(3); // 1e+21
5.25.toStringAsFixed(0); // 5
Another more flexible option can be...
You can use this function to roundup the time.
DateTime alignDateTime(DateTime dt, Duration alignment,
[bool roundUp = false]) {
assert(alignment >= Duration.zero);
if (alignment == Duration.zero) return dt;
final correction = Duration(
days: 0,
hours: alignment.inDays > 0
? dt.hour
: alignment.inHours > 0
? dt.hour % alignment.inHours
: 0,
minutes: alignment.inHours > 0
? dt.minute
: alignment.inMinutes > 0
? dt.minute % alignment.inMinutes
: 0,
seconds: alignment.inMinutes > 0
? dt.second
: alignment.inSeconds > 0
? dt.second % alignment.inSeconds
: 0,
milliseconds: alignment.inSeconds > 0
? dt.millisecond
: alignment.inMilliseconds > 0
? dt.millisecond % alignment.inMilliseconds
: 0,
microseconds: alignment.inMilliseconds > 0 ? dt.microsecond : 0);
if (correction == Duration.zero) return dt;
final corrected = dt.subtract(correction);
final result = roundUp ? corrected.add(alignment) : corrected;
return result;
}
and then use it the following way
void main() {
DateTime dt = DateTime.now();
var newDate = alignDateTime(dt,Duration(minutes:30));
print(dt); // prints 2022-01-07 15:35:56.288
print(newDate); // prints 2022-01-07 15:30:00.000
}

Why wont my MQL4 EA code change my open positions to breakeven?

Trying to add a StopLoss to my open market positions which also takes into account my brokers stoplevel. I have set this to add a breakeven stop loss when my trade gets to 100 points in profit.
This is the code - but its completely ignoring any order modification during my back testing.
OK this is now what I have so far, one for loop for the buy, one for the sell. I;ve also declared the "BuyMod" & "SellMod" to true as was suggested in pervious answers, as well as Normalzing prices in the OrderModify signature.
/*Breakeven Order Modification*/
bool BuyMod = true;
bool SellMod = true;
for(int b = OrdersTotal()-1;b>=0;b--)
{
if(OrderSelect(b,SELECT_BY_POS,MODE_TRADES))
{
double aBidPrice = MarketInfo(Symbol(),MODE_BID);
double anOpenPrice = OrderOpenPrice();
double aNewTpPrice = OrderTakeProfit();
double aCurrentSL = OrderStopLoss();
double aNewSLPrice = anOpenPrice;
double pnlPoints = (aBidPrice - anOpenPrice)/_Point;
double stopPoints = (aBidPrice - aNewSLPrice)/_Point;
int stopLevel = int(MarketInfo(Symbol(),MODE_STOPLEVEL));
int aTicket = OrderTicket();
if(OrderType() == OP_BUY)
if(stopPoints >= stopLevel)
if(aTicket > 0)
if(pnlPoints >= breakeven)
if(aNewSLPrice != aCurrentSL)
{
BuyMod = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(aNewSLPrice,Digits),NormalizeDouble(aNewTpPrice,Digits),0,buycolor);
SendMail("Notification of Order Modification for Ticket#"+IntegerToString(OrderTicket(),10),"Good news! Order Ticket#"+IntegerToString(OrderTicket(),10)+"has been changed to breakeven");
}
}
}
for(int s = OrdersTotal()-1; s>=0; s--)
{
if(OrderSelect(s,SELECT_BY_POS,MODE_TRADES))
{
double anAskPrice = MarketInfo(Symbol(),MODE_ASK);
double anOpenPrice = OrderOpenPrice();
double aNewTpPrice = OrderTakeProfit();
double aCurrentSL = OrderStopLoss();
double aNewSLPrice = anOpenPrice;
double pnlPoints = (anOpenPrice - anAskPrice)/_Point;
double stopPoints = (aNewSLPrice - anAskPrice)/_Point;
int stopLevel = int(MarketInfo(Symbol(),MODE_STOPLEVEL));
int aTicket = OrderTicket();
if(OrderType()== OP_SELL)
if(stopPoints >= stopLevel)
if(pnlPoints >= breakeven)
if(aNewSLPrice != aCurrentSL)
if(aTicket > 0)
{
SellMod = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(aNewSLPrice,Digits),NormalizeDouble(aNewTpPrice,Digits),0,sellcolor);
SendMail("Notification of Order Modification for Ticket#"+IntegerToString(OrderTicket(),10),"Good news! Order Ticket#"+IntegerToString(OrderTicket(),10)+"has been changed to breakeven");
}
}
}
This code will not work due to several reasons:
First:The function-call signature of OrderModify() is wrong.
You might want to know, that OrderModify() call-signature requires as per MQL4 documentation to include also an OrderExpiration value in the call, even though the Order is currently not a pending order any more.
Check the documentation and the IDE tooltip, which helps one remind the order of the function call parameters.
Second:The other, less-visible reasons could be reported by GetLastError() after the OrderModify() function call returns a False as an indication of failure.

Multiple criteria timestamp

I am using...
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
var r = s.getActiveCell();
var time = new Date(+new Date + (1000 * 60 * 60 * 24 * 7));
time = Utilities.formatDate(time, "GMT-08:00", "MM/dd/yyyy");
if( r.getColumn() == 2 ) { //checks the column
var nextCell = r.offset(0, 6);
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(time);
}
}
...to add a timestamp+7 days to column H.
In addition to this timestamp feature... (could be another script)
When column D value = "Questions/Waiting for Info" and then changes to anything else.
and
When column E value = "Preliminary, Less than 25kW" or "Preliminary, Less than 25kW" and then changes to anything except for "Preliminary, Less than 25kW" or "Preliminary, Less than 25kW".
we want to start the timestamp+7 days over again.
It appears that this might not work with onEdit as there are some values that must be read prior to the edit. Not sure how to do this. Thanks
Correct, this is impossible using onEdit without copying the original data somewhere else first. A complicated solution out of my expertise at the moment.
Maybe try something like this
function onEdit(e) {
var d = new Date(new Date() + (1000 * 60 * 60 * 24 * 7));
var time = Utilities.formatDate(d, "GMT-08:00", "MM/dd/yyyy"),
ind = [2, 4].indexOf(e.range.columnStart),
off;
if (ind == 0) {
off = 6;
} else if (ind == 1 && e.value !== "Questions/Waiting for Info") {
off = 4;
}
e.range.offset(0, off).setValue(time)
}

Swarming in AS2

Hi I keep getting the error: expecting identifier before greater than.
on line 13.
Any help would be nice please and Thank you.
fly = function () {
this.animate = function() {
// Capture mouse positions and distance from mouse
this.targetX = _root._xmouse;
this.targetY = _root._ymouse;
this.distX = this.targetX-this.meX+this.flockX;
this.distY = this.targetY-this.meY+this.flockY;
//
if ((this.targetX == this.oldTargetX) && Math.random()>0.9) {
// add small scale random darting if mouse is still
this.flockX = (Math.random()*100)-50;
this.flockY = (Math.random()*100)-50;
} else if ((this.targetX<>this.oldTargetX) && Math.random()>0.8) {
// add large scale random darting if mouse is moving
this.flockX = (Math.random()*400)-200;
this.flockY = (Math.random()*400)-200;
}
// Apply inertia equation
this.meX = Math.round(this.meX+(this.distX)/20);
this.meY = Math.round(this.meY+(this.distY)/20);
// perform animation
this._x = this.meX;
this._y = this.meY;
// remember the current mouse pos so we can tell if
// it has moved next time around
this.oldTargetX = this.targetX;
};
this.initialize = function() {
this.targetX = 0;
this.targetY = 0;
this.distX = 0;
this.distY = 0;
this.meX = this._x;
this.meY = this._y;
this.oldTargetX = 0;
this.flockX = (Math.random()*200)-100;
this.flockY = (Math.random()*200)-100;
};
// set up onEnterFrame script to animate _parent...
this.initialize();
this.onEnterFrame = this.animate;
};
//
//
var i:Number = 0;
var bugClip:MovieClip;
for (i=0; i<30; i++) {
bugClip = this.attachMovie("bug", "bug"+i, i);
fly.apply(bugClip);
}
I don't know about Actionscript, but by looking at your code I would recomend doing like this:
randomValue = Math.random()
if ((this.targetX == this.oldTargetX) && randomValue>0.9) {
The <> operator for not equals has been deprecated since Flash Player 5 Doc reference here
You should use != for the same functionality.
Although i tested this on Flash Player 10.2 and it will still compile and run with no errors. I guess you are compiling to a later version.

Resources