Making LC wait until JS is done its thing

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

Post Reply
Opaquer
Posts: 247
Joined: Wed Aug 14, 2013 8:24 am

Making LC wait until JS is done its thing

Post by Opaquer » Wed Jun 24, 2020 3:50 pm

Hey guys!

So, I'm in the middle of making a (hopefully) pretty cool Sudoku app, and one of the things I want it to do is to be able to generate random sudokus. I have some very nice JS code that I've adapted to make do what I want, and am running it through a browser perfectly so far - what it does is tell me how many solutions a given sudoku has, and a list of all the solutions.

At the moment I'm using LC to generate random numbers in a sudoku grid, and make sure they're all valid. Then see if it can be solved - if so, to take the first solution it comes across, giving me a fully solved, randomly generated sudoku. This part is working 100% for me so far

The next part is meant to take out digits in the solved sudoku and try solving it again. If there's still only one solution, repeat the process, but if there's more than one solution, then I've gone too far, and it loads the previous step and tries again. It tries again a few times so that it doesn't remove 6 digits, find a non-unique solution and say "Ta da, I have a sudoku for you!", because that would then be a super easy sudoku!

Now, for some reason, the solving code (which is working perfectly everywhere else), doesn't seem to work properly when it comes to this bit. Instead of returning the right answer, sometimes it spits back that a non-unique sudoku has only 1 solution. Sometimes it spits back that it has 0 solutions (which doesn't even make sense, because I'm working backwards from a solved solution.... It makes my brain hurt, that's for sure!) My only guess I have at the moment is that since I'm asking it to solve the solution, it starts to solve it, but doesn't finish solving it before the next statement happens, and then things get iffy and it doesn't have the full amount of information available?

This is the general piece of code I have at the moment. SolvedGrid is the complete solved sudoku from the previous step

Code: Select all

on mouseUp
   put 1 into StillSolveable -- is the sudoku still solveable?
   put 0 into FailedAttempts -- number of 'failed' attempts at removing digits
   put 2 into MaxSolutions -- maximum number of solutions to show
   repeat while StillSolveable=1
      put SolvedGrid into SolvedSudoku -- make backup
      -- here I get 2 random numbers for the place in the grid to delete them from, and then delete them if there's a number there already
      if SolvedGrid[i_delete][j_delete]<>0 then
         put 0 into SolvedGrid[i_delete][j_delete]
         put SolveJS(SolvedGrid, MaxSolutions) into Answers -- here's the bit where it should try and solve the sudoku given
         -- I then do a bunch of stuff (like checking the failed attempts and a couple of other things like that that isn't important atm
      end if
   end repeat
   put SolvedSudoku into GeneratedSudoku -- i have this to load the last working sudoku because of how my code currently runs through the while loop
end mouseUp
My SolveJS code works 100% - I've tested it and know that it does in fact, work. Here's the code for it:

Code: Select all

function SolveJS SudokuToSolve, MaxSolutions
   put 0 into AnswerList[1]
   put 0 into AnswerList[2] -- see below about this
   local sudoku4JS, r
   -- this bit just converts SudokuToSolve into a JS friendly array (sudoku4JS) that I can put through the browser
   do "var g=" & sudoku4JS & ";var maxsols=" & MaxSolutions & ";solve(g,maxsols);" in widget "Browser"  -- solving out code
   return AnswerList
end SolveJS
The JSHandler calls for a function that spits out the number of solutions and the list of solutions as components 1 and 2 of global array AnswerList. I initially set both components to 0 as I had some issues when I was running the generating code above where it wouldn't solve for a sudoku properly and have the old values in there, which was a problem.

The code then runs the solve(g,maxsols) in the browser and will solve the sudoku 100% of the time with how many solutions there are (I have a solve button that does the SolveJS code separately, and have been using it without issue this whole time)

My guess is that in the mouseUp function, it tries to run SolveJS, but then continues while the browser is still in the middle of running the code, and that's causing issues for it? Given all that, is there a way to make my LC wait for it to have definitive answers from JS before continuing with the code? Or will it require a rewrite of how things are so far to get it to run in a different way rather than a mouseUp handler?

Hopefully all this made sense - I tried to take out all the unimportant bits and keep it short and informative, but it's also 1AM here and I stayed up way too late last night trying to fix this still, so apologies if I've rambled, included too much information or not enough information! If you have any questions, please don't hesitate to let me know and I can answer them!

Thanks in advanced guys!

Monox18
Posts: 118
Joined: Tue Nov 25, 2014 9:48 pm
Location: Deggendorf, Germany

Re: Making LC wait until JS is done its thing

Post by Monox18 » Fri Dec 11, 2020 1:14 am

Assuming that you have already communicated both ways with the browser (passing data from LC to JS & JS to LC) and that you are properly serializing arrays (Only strings, numbers and boolean are supported as passing data) I would guess that your problems relies on running a sequential code in an asynchronous operation. After the do command, JS runs async, and LC continues immediately. This explains why sometimes it returns 1 or none solutions because it barely had few microseconds to solve something before the next LC statement read the result data. You shouldn't make either LC or JS wait for the other. You can make LC wait after the do command but that's not efficient. I'd suggest you to break the sequential code into server-client kind of operation. Setting listeners and so on.
Monox
Developing a Cyber Physical System.
https://www.monoxware.com/

Post Reply

Return to “Getting Started with LiveCode - Complete Beginners”