Google sheet cell is only writen once instead of multiple times - javascript

I would like to make a visual random number genarator. That means in Cell F4 should random numbers shuffle trough until it stops with a random number.
My Problem is now, that i can only see the last number generated and not the shuffeling.
function Wuerfeln() {
var Upperbound = 60;
var Lowerbound = 1;
var i = Math.floor(Math.random() * (50 - 10 + 1) + 10);
var RandomNummber = 0;
var range = SpreadsheetApp.getActiveSpreadsheet().getRange("F4");
while(i>0)
{
RandomNummber = Math.floor(Math.random() * (Upperbound - Lowerbound + 1) + Lowerbound);
range.setValue(RandomNummber);
i--;
Utilities.sleep(200);
};
};

Google Sheets has a minimum refresh time, you're not going to make it change super fast by design.
Many requests from a script get batched together and run at the same time, so when the edits are all in the same cell you do not see them change and only the last one is displayed.
The only way to force a cell to change is using SpreadsheetApp.flush() as suggested by Sergey. This forces all pending sheet changes to be pushed. As you have noted however, this is slow.
To do this at all you would need to have an HTML dialog or sidebar which can run JavaScript that directly changes the HTML elements rather than a cell in the spreadsheet.

I would suggest you define a few things and then try it out until it looks like you want, or what you could do is create a pop up which shows a .gif of a dice.
The first approach would look like this
function wurfel(){
const timeDelay = 200
const numbersToShowUntilFinal = 20 // or do a random num
// then your code here,
// but using the variables above to test around until you found a cool
}

Related

How to auto refresh these randomly generated colors

I've tried many solutions off my head like using setInterval in various ways but I can't seem to get it working.
Currently on every refresh, the patterns will all be random. The closest thing to what I wanted was that I made a setInterval and code but it only made 1 square continuously change its color. I deleted it by the way.
I just want after the page loads, it will continue to flip through random colors and not just be stuck on what was already generated.
var rndTile = Math.floor((Math.random() * 40) + 1);
var base = 2 / 2;
var colChoices = ["#81A594","#79BEDB","#6B78B4", "#593E1A", "#99CCCC"];
var fadeTime = Math.floor((Math.random * 6000));
Code: https://jsfiddle.net/nL56woyy/8/
Since i can't understand your fiddle properly i am presenting my own solution here. Your first problem is that the random number is only generated once on site load. Second thing: your var base is always 1 and gets reseted to 0 in the each call. Thats why your output is always the same.
Since the code is to long to put it on stackoverflow here is the fiddle: https://jsfiddle.net/0ajg01y1/1/

Continuously loop colors on div using javascript on mouseenter

I have a div on a page and I would like to continuously cycle through a set of colors using javascript.
I've seen a number of articles on Stack Overflow about continuous loops to show information using arrays and javascript yet I have had trouble trying to implement it into my own project.
My HTML:
<div id="box" style="background:grey;" onmouseenter="change()"></div>
and the closest JS solution I can find:
var change = function() {
colors = ['#00b0e2', '#e3144e', '#15e39b'];
count = -1;
return function() {
return colors[++count % colors.length];
}
document.getElementById('box').style.background = colors; // or should this be **colors[]**?
}
I understand what is happening up until the return function but then I am having trouble understanding how to inject the color into the html?
Any help or tips would be appreciated thanks.
I think you are really close, but are missing a couple of key things.
Firstly, when you say onmouseover="change()" that means that it will run change() every time the mouseover runs unlike using addEventListener(change()) which would run the function returned by change as the event handler.
Secondly to change the element, all you need to do is get a handle on the element and set the background.
The code below does what I think you were trying to do but more simply. I hope it helps.
// setup our colors and state once
colors = ['#00b0e2', '#e3144e', '#15e39b'];
count = -1;
var change = function(element) {
element.style.background = colors[++count % colors.length];
}
<!-- Pass in the element when creating the change listener -->
<div id="box" style="background:grey;" onmouseenter="change(this)">
Give our box some contents so we can see it.
</div>
Explanation:
the basic concept behind the loop is that we have a count that tells us colors[count] is currently active.
When a mouseover happens, three things happen in the one line.
++count: this adds 1 to count, but unlike count++, it does so before the value is used. Meaning that the first time a mouseover occurs, the value of count is 0
count % colors.length: This just lets us wrap around to the first color once it has hit the last color. The % (modulus) operator gives the remainder. a % b will return the remainder after dividing a / b. If count = 0, count % 3 yields 0, but if count = 4, count % 3 yields 1. You can read more about this and other Arithmetic operators on MDN
element.style.background = colors[...]: This sets the background css attribute to the color we selected in the last step.
so to put it all together, here is the change function broken out into 3 lines.
var change = function(element){
count++; //increment count before using it.
var our_color = count % colors.length; // wrap properly
element.style.background = colors[our_color];
}

Better random function in JavaScript

I'm currently making a Conway's Game of Life reproduction in JavaScript and I've noticed that the function Math.random() is always returning a certain pattern. Here's a sample of a randomized result in a 100x100 grid:
Does anyone knows how to get better randomized numbers?
ApplyRandom: function() {
var $this = Evolution;
var total = $this.Settings.grid_x * $this.Settings.grid_y;
var range = parseInt(total * ($this.Settings.randomPercentage / 100));
for(var i = 0; i < total; i++) {
$this.Infos.grid[i] = false;
}
for(var i = 0; i < range; i++) {
var random = Math.floor((Math.random() * total) + 1);
$this.Infos.grid[random] = true;
}
$this.PrintGrid();
},
[UPDATE]
I've created a jsFiddle here: http://jsfiddle.net/5Xrs7/1/
[UPDATE]
It seems that Math.random() was OK after all (thanks raina77ow). Sorry folks! :(. If you are interested by the result, here's an updated version of the game: http://jsfiddle.net/sAKFQ/
(But I think there's some bugs left...)
This line in your code...
var position = (y * 10) + x;
... is what's causing this 'non-randomness'. It really should be...
var position = (y * $this.Settings.grid_x) + x;
I suppose 10 was the original size of this grid, that's why it's here. But that's clearly wrong: you should choose your position based on the current size of the grid.
As a sidenote, no offence, but I still consider the algorithm given in #JayC answer to be superior to yours. And it's quite easy to implement, just change two loops in ApplyRandom function to a single one:
var bias = $this.Settings.randomPercentage / 100;
for (var i = 0; i < total; i++) {
$this.Infos.grid[i] = Math.random() < bias;
}
With this change, you will no longer suffer from the side effect of reusing the same numbers in var random = Math.floor((Math.random() * total) + 1); line, which lowered the actual cell fillrate in your original code.
Math.random is a pseudo random method, that's why you're getting those results. A by pass i often use is to catch the mouse cursor position in order to add some salt to the Math.random results :
Math.random=(function(rand) {
var salt=0;
document.addEventListener('mousemove',function(event) {
salt=event.pageX*event.pageY;
});
return function() { return (rand()+(1/(1+salt)))%1; };
})(Math.random);
It's not completly random, but a bit more ;)
A better solution is probably not to randomly pick points and paint them black, but to go through each and every point, decide what the odds are that it should be filled, and then fill accordingly. (That is, if you want it on average %20 percent chance of it being filled, generate your random number r and fill when r < 0.2 I've seen a Life simulator in WebGL and that's kinda what it does to initialize...IIRC.
Edit: Here's another reason to consider alternate methods of painting. While randomly selecting pixels might end up in less work and less invocation of your random number generator, which might be a good thing, depending upon what you want. As it is, you seem to have selected a way that, at most some percentage of your pixels will be filled. IF you had kept track of the pixels being filled, and chose to fill another pixel if one was already filled, essentially all your doing is shuffling an exact percentage of black pixels among your white pixels. Do it my way, and the percentage of pixels selected will follow a binomial distribution. Sometimes the percentage filled will be a little more, sometimes a little less. The set of all shufflings is a strict subset of the possibilities generated this kind of picking (which, also strictly speaking, contains all possibilities for painting the board, just with astronomically low odds of getting most of them). Simply put, randomly choosing for every pixel would allow more variance.
Then again, I could modify the shuffle algorithm to pick a percentage of pixels based upon numbers generated from a binomial probability distribution function with a defined expected/mean value instead of the expected/mean value itself, and I honestly don't know that it'd be any different--at least theoretically--than running the odds for every pixel with the expected/mean value itself. There's a lot that could be done.
console.log(window.crypto.getRandomValues(new Uint8Array(32))); //return 32 random bytes
This return a random bytes with crypto-strength: https://developer.mozilla.org/en/docs/Web/API/Crypto/getRandomValues
You can try
JavaScript Crypto Library (BSD license). It is supposed to have a good random number generator. See here an example of usage.
Stanford JavaScript Crypto Library (BSD or GPL license). See documentation for random numbers.
For a discussion of strength of Math.random(), see this question.
The implementation of Math.random probably is based on a linear congruential generator, one weakness of which is that a random number depends on the earlier value, producing predictable patterns like this, depending on the choice of the constants in the algorithm. A famous example of the effect of poor choice of constants can be seen in RANDU.
The Mersenne Twister random number generator does not have this weakness. You can find an implementation of MT in JavaScript for example here: https://gist.github.com/banksean/300494
Update: Seeing your code, you have a problem in the code that renders the grid. This line:
var position = (y * 10) + x;
Should be:
var position = (y * grid_x) + x;
With this fix there is no discernible pattern.
You can using the part of sha256 hash from timestamp including nanoseconds:
console.log(window.performance.now()); //return nanoseconds inside
This can be encoded as string,
then you can get hash, using this: http://geraintluff.github.io/sha256/
salt = parseInt(sha256(previous_salt_string).substring(0, 12), 16);
//48 bits number < 2^53-1
then, using function from #nfroidure,
write gen_salt function before, use sha256 hash there,
and write gen_salt call to eventListener.
You can use sha256(previous_salt) + mouse coordinate, as string to get randomized hash.

How to write javascript to reorder pages of a pdf document?

I have a double-sided document as two separate pdf files — front-facing pages in one document and rear-facing pages in the second.
front.pdf
rear.pdf
I have also combined them into a single document with all the pages but with all the front-facing pages before the rear-facing pages. The page ordering is of the form, {1,3,5,7,...,[n],2,4,6,8,...,[n-1 OR n+1]}
all.pdf
I wish to write a simple javascript that can be run from inside Adobe Abrobat X Pro. Ideally, it would count the pages of the document all.pdf, handle both occasion when there are either an odd or even number of total pages and then reorder them such that they are in their original order:
page [1>3>4>2] => page [1>2>3>4]
The tiny leading code snippet above is from the answer by user171577 on SuperUser in this question: https://superuser.com/questions/181596/software-that-merges-pdf-every-other-page
I was able to accomplish this following advice from NullUserException :
This script requires a document composed of all the odd pages followed by all the even pages. It will cope with cases where there are n even pages and n+1 odd pages.
I entered a 'Document JavaScript' called InterleavePages, with the following code:
function InterleavePages() {
var n = this.numPages;
var nOdd = Math.floor(n / 2);
var nEven = n - nOdd;
var x;
var y;
var i;
for(i = 0; i < nEven; i++) {
// movePage x, toAfterPage y
// note page numbers are 0-indexed
x = nOdd + (i); //
y = i * 2 ; //
this.movePage(x,y);
}
}
InterleavePages();
Thanks, this was a great help. Just wanted to point out the limitation I found is it only works as written with an even number of pages. Although it's probably possible to write a more sophisticated calculation script, I took the easy way out and just added a blank page to the end of my 17-page test document. I did, however, add an alert so I wouldn't forget to add an extra page when necessary...
function InterleavePages() {
var n = this.numPages;
var nOdd = Math.floor(n / 2);
var nEven = n - nOdd;
var x;
var y;
var i;
app.alert({
cMsg: "Total pages must be an even number",
cTitle: "Even Number of Pages Required!",
nIcon: 1, nType: 1
});
this.pageNum = 0;
for(i = 0; i < nEven; i++) {
// movePage x, toAfterPage y
// note page numbers are 0-indexed
x = nOdd + (i); //
y = i * 2 ; //
this.movePage(x,y);
}
}
InterleavePages();
As mentioned in some other exchanges, to interweave the pages two pdfs, you can use the Java console.
The first step is to combine the pdfs into a single document. I would do this by highlighting both files, and then right-clicking on one of them. There should be an option to "Combine supported files in Acrobat".
Then, once they are combined, open the combined file, where you want to run the code
for (i = 0; i <= this.numPages/2-1; i++) this.movePage(this.numPages-1,this.numPages/2-i-1);
The step-by-step details for running such code are:
1) Open the pdf.
2) Go to the second page. Doing this way will allow you to notice whether the change has taken place. You don't have to do this step, but it helps.
2) Press Control + J
3) In the window that pops up, I always go to the "View" Dropdown menu, and set it to "Script and Console".
4) In the bottom window, replace the text that should read something like
"Acrobat EScript Built-in Functions Version 10.0
Acrobat SOAP 10.0"
with
for (i = 0; i <= this.numPages/2-1; i++) this.movePage(this.numPages-1,this.numPages/2-i-1);
5) Press enter once. Pressing twice might run the code again (which you do not want).
6) Check you pdf to see if the pages have been interlaced. If not, try step 5 again.
7) You are now a Java wizard. Congratulations.
I had the same issue, my scanner was single sided only, and the scanner software, after being done with the auto-feeder, asked if there's more to scan. If you grab the stack, turn it over and feed it again, you'll end up with a single PDF where the n-page document is arranged as 1f, 2f, 3f ... nb, (n-1)b, (n-2)b ... 1b (f=front, b=back, 1-based page numbers). By definition you'd have an even number of scanned pages, the javascript for re-arranging the whole thing (careful, only works with even number of pages in this context!) is:
// rearrange the pages from single-side scanner, 0-based page# where
// pages 0 .. n/2-1 are front, pages n/2 .. n-1 are back
function Rearrange() {
var tpn=0; // target page number
for (count = 0; count < this.numPages/2; count++) {
this.movePage(this.numPages-1,tpn);
tpn=tpn+2;
}
}
Rearrange();

Using .blur(function() to update live calculation

I'm trying to use .blur to update a calculation function based off of a select box. It works when the user first changes the box from 0 to 1 for example, but when it's changed after that it won't reverse the previous calculation. #to_condition is the id that is displayed in text, originally 10. After I change #is_bent_num from 0 to 1, #to_condition is correctly decreasing by 0.5 to 9.5, but if I change it again, say to 3, instead of adding 0.5 back and then subtracting 1.5 (making #to_condition 8.5) it subtracts 1.5 from the 9.5, making #to_condition = 8.
var bent_num = 0.5;
var bent_orig = $("#is_bent_num").val();
$("#is_bent_num").blur(function(){
var bent_new = $("#is_bent_num").val();
updatecondition(bent_num * bent_orig * -1);
updatecondition(bent_num * bent_new);
bent_orig = bent_times;
});
function updatecondition(newcondition){
var changecondition = $("#condition_exact").val() - newcondition;
$("#condition_exact").val(changecondition);
if (changecondition < 0){
changecondition = 0;
}
changecondition = changecondition.toFixed(1);
$("#to_condition").text(changecondition);
}
James, I think you didn't paste you whole code, e.g. definition of bent_times is missing. However it clearly seems for me that the first two lines of updatecondition are the cause of your problem. You should always substract from $("#is_bent_num").val() isntead of $("#condition_exact").val()
The result put into #to_condition when the function updatecondition is called depends on both the newcondition parameter sent to the function and the #condition_exact value, and the latter is updated every time the updateconditino is called. Perhaps that update of the #condition_exact value is what is causing your problem?
$("#condition_exact").val(changecondition);
I think your problem is here:
updatecondition(bent_num * bent_orig * -1);
updatecondition(bent_num * bent_new);
You basically update the #condition_exact field twice; once with a value based on bent_num, and once with a value based on the user's input (bent_new). The second update is (of course) the one you will see. I think what you meant to do was this:
updatecondition(bent_orig - (bent_num * bent_new));
Now the field will be updated only once. The new value will be the original value, minus the user's input times bent_num.
By the way, your variable names are a bit confusing. For example, what does bent_num mean? Is it the step size? Would someone else who looks at this code know what it means? (I certainly don't.) Will you, if you look at the code again in 6 months' time? So if bent_num is the step size, why not call it step_size (or stepSize)?

Categories

Resources