I want to make a chess puzzle on my website for my student.
I use stockfish.js to play with the engine.
How to change the start position on the board?
I try to change all FEN string but did not work.
Where to look for the function or something?
Anybody can help me, please?
Interacting with the javascript port of Stockfish is (at time of writing) still like communicating with a chess engine that uses/supports UCI (Universal Chess Interface).
The UCI position command should suffice:
var fenString = "rnbqkbnr/ppppp1pp/8/5p2/3P4/8/PPP1PPPP/RNBQKBNR w KQkq - 0 2"
// start UCI
stockfish.postMessage("uci");
// start new game
stockfish.postMessage("ucinewgame");
// set new game position
stockfish.postMessage("position fen " + fenString);
// start search
stockfish.postMessage("go depth 10");
Edited: Updated case for postMessage() function.
I was working on the same thing and figured it out -- it's by no means obvious and within the stockfish example there are lots of little trips and pitfalls. I found a couple questions online and thought I'd give them some answers.
So -- this answer assumes working with the example code found here: https://github.com/nmrugg/stockfish.js/tree/Stockfish11/example.
There are two major modifications that need to happen - first in the index.html file and second in enginegame.js.
First we'll define a helper function which will make it easy to work with the url "search" as it's called:
function searchToObject() {
var pairs = window.location.search.substring(1).split("&"),
obj = {},
pair,
i;
for ( i in pairs ) {
if ( pairs[i] === "" ) continue;
pair = pairs[i].split("=");
obj[ decodeURIComponent( pair[0] ) ] = decodeURIComponent( pair[1] );
}
return obj;
}
For ease I just placed that function in both files, within index.html it's at the beginning of the script tag, in enginegame.js it's the very first line. Also btw, I certainly pilfered that from stackoverflow, but I can't seem to find that answer any more, rats.
In index.html the newGame function wants to look like this:
newGame = function newGame() {
var baseTime = parseFloat($('#timeBase').val()) * 60;
var inc = parseFloat($('#timeInc').val());
var skill = parseInt($('#skillLevel').val());
game.reset();
let search = searchToObject();
if (search.player) {
game.setPlayerColor(search.player)
} else {
game.setPlayerColor($('#color-white').hasClass('active') ? 'white' : 'black');
}
if (search.fen) {
game.game.load(search.fen);
game.board.position(game.game.fen());
}
game.setTime(baseTime, inc);
game.setSkillLevel(skill);
game.setDisplayScore($('#showScore').is(':checked'));
game.start();
}
Note the game.game and game.board -- those need to be added in enginegame.js where it's returning an object. If I were writing this I would have done it differently, but I didn't have the patience to rename things.
Next up in enginegame.js we need to adjust prepareMove.
function prepareMove() {
stopClock();
$('#pgn').text(game.pgn());
board.position(game.fen());
updateClock();
var turn = game.turn() == 'w' ? 'white' : 'black';
if (!game.game_over()) {
if (turn != playerColor) {
let search = searchToObject();
if (search.fen) {
uciCmd('position fen ' + search.fen + ' moves ' + get_moves());
} else {
uciCmd('position startpos moves' + get_moves());
uciCmd('position startpos moves' + get_moves(), evaler);
}
evaluation_el.textContent = "";
uciCmd("eval", evaler);
if (time && time.wtime) {
uciCmd("go " + (time.depth ? "depth " + time.depth : "") + " wtime " + time.wtime + " winc " + time.winc + " btime " + time.btime + " binc " + time.binc);
} else {
uciCmd("go " + (time.depth ? "depth " + time.depth : ""));
}
isEngineRunning = true;
}
if (game.history().length >= 2 && !time.depth && !time.nodes) {
startClock();
}
}
}
See, the trick is that if ever there was a fen string to start the game, every subsequent position call needs to be different. I think that's probably what's tripping most people up - that's definitely what got me.
What helped things click for me was reading through the UCI documentation. Before that my board was in some crazy infinite loop.
Also one weird but critical bit I stumbled onto was the game.game.load(<fen string>) function call in the index.html file. I can't find any documentation for that. I don't even remember how I found it. But there it is!
Related
I am trying to create questionnaire (15 questions)in my Messenger with the two possible answers Yes and No. Each answer has value (Yes..3) and (No..1). I create Zap where I calculate number like result. I create Java script code by Zapier like next step and here my knowledge is finished. I code to calculate number and like next step sending the message back with answer like number.
What I want from javascript code by Zapier is to calculate answers and based on the results send the answer to Subscriber who answer the Questionnaire.
The answer message according to the scoring answers should be following:
<26
"messege"
26-35
"messege"
>35
"messege"
Here it is how I made until now (sorry but answers are in Slovene language...not important):
return {
calculatednumber: Number(inputData.q1) + Number(inputData.q2) + Number(inputData.q3) + Number(inputData.q4) + Number(inputData.q5) + Number(inputData.q6) + Number(inputData.q7) + Number(inputData.q8) + Number(inputData.q9) + Number(inputData.q10) + Number(inputData.q11) + Number(inputData.q12) + Number(inputData.q13) + Number(inputData.q14) + Number(inputData.q15)
}
if (calculatednumber ==='<25') {
return []; //"Videti je, da so vaše prehranske navade ustrezne. Za izboljšanje priporočamo jemanje multivitaminskih/mineralnih tablet!"
}
if (calculatednumber ==='26,27,28,29,30,31,32,33,34,35') {
return []; //"Multivitaminski/mineralni dodatek k prehrani bo vašemu telesu pomagal ohraniti esencialna hranila, ki jih potrebuje, skupaj z drugimi označenimi dodatki!"
}
if (calculatednumber ==='>36') {
return []; //"Vnos multivitaminov/mineralov bi vam zagotovo koristil. Z bolj uravnoteženo prehrano in dodatkom multivitaminov/mineralov pa bi potrebovali še vnos drugih vitaminov/mineralov!"
};
Thank you for helping me.
You're on the right track! Some pointers:
You'll only ever call one return function, so you don't want to use it for the variable at the top.
You don't need to nest the variable inside an object; it can just be a number
the calculatedNumber variable will never be equal to "<25" because that's a string with a character in it, so your logic branches don't work.
Try this instead:
let calculatedNumber = Number(inputData.q1) + Number(inputData.q2) // + ...
if (calculatedNumber < 25) {
return {message: 'Small Message'} // it's important to return an object
} else if (calculatedNumber > 36) {
return {message: 'Large Message'}
} else {
// everything inbetween 25 and 36
return {message: 'Medium Message'}
}
Anyway, I'd recommend reading through https://learnxinyminutes.com/docs/javascript/ to get a better handle on some of the syntax fundamentals.
I was just going through the code of timer.js HERE. and came across the following lines of code:
var paramList = ['autostart', 'time'];
for (var arg in paramList) {
if (func[paramList[arg]] != undefined) {
eval(paramList[arg] + " = func[paramList[arg]]");
}
};
In the source code its all on one line, but i've made it more readable above , my difficulty is with the usage of eval, I.E. the below line of code:
eval(paramList[arg] + " = func[paramList[arg]]");
now if i add a breakpoint in chrome to the above line and go to the console and paste the line of code i get the following:
true
How come ? lets have a close look at the statement again:
eval(paramList[arg] + " = func[paramList[arg]]");
what is the + doing here ? converting paramList[arg] to a string , in which case eval is being used as follows:
eval("paramList[arg] = func[paramList[arg]]");
?
or is the plus sign being used for concatenation purpose ? (which i think is very unlikely !)
I have read MDN eval(), but still had doubts.
can anybody explain the breakdown of that statement please ?
Thank you.
eval takes a string. What you have:
eval(paramList[arg] + " = func[paramList[arg]]");
The + is just string concatenation.
Is equivalent to:
var code = paramList[arg] + " = func[paramList[arg]]"
eval(code);
So I'd say it should be equivalent to:
global[paramList[arg]] = func[paramList[arg]];
Or, in this particular example (with var paramList = ['autostart', 'time'];)):
if (func['autostart'] != undefined)
autostart = func['autostart'];
if (func['time'] != undefined)
time = func['autostart'];
I want to be able to link any word of my choice to a specific URL for example:
I want the word "goat" to link to "http://goat.com" across the entire website. So all "goat"/s will link to that URL right across the website.
I am using wordpress and I have not yet found a plugin to do this. If I can get a solution to this I would most likely create a plugin for this functionality.
I know how to target one word on a single page. But I would like it to be across all the pages and all the words in those pages( I used JavaScript for this).
Something like this may work for you.
function replaceWithUri(textToReplace, element){
element.innerHTML = element.innerHTML.replace(textToReplace, '<a href="http://www.' + textToReplace + '.com" >' + textToReplace + '</a>');
}
replaceWithUri('goat', document.getElementsByTagName('body')[0]);
Here's a crappy solution but it's better than nothing:
I found some code here which searches for a world across the whole page so I copy pasted that and modified it.
The replaceWord variable cannot contain the same string as word, otherwise it'll loop infinitely.
var word = " goat",
replaceWord = " <a href = 'http://goat.com'>goat</a>",
queue = [document.body],
curr
;
while (curr = queue.pop()) {
if (!curr.textContent.match(word)) continue;
for (var i = 0; i < curr.childNodes.length; ++i) {
switch (curr.childNodes[i].nodeType) {
case Node.TEXT_NODE : // 3
if (curr.childNodes[i].textContent.match(word)) {
curr.innerHTML = curr.innerHTML.replace(word,replaceWord);
}
break;
case Node.ELEMENT_NODE : // 1
queue.push(curr.childNodes[i]);
break;
}
}
}
Hello goat
<div>Look a goat</div>
This might be a bit resource intensive and replaceWord cannot contain the same string as word, otherwise it'll loop forever.
document.onload = function() {
var word = " goat",
replaceWord = " <a href = 'http://goat.com'>goat</a>";
while(document.body.innerHTML.indexOf(word) !== -1) {
document.body.innerHTML = document.body.innerHTML.replace(word,replaceWord);
}
}
Hello goat
<div>Look a goat</div>
I was interested in writing a twitter bot to help out some friends at a local ski resort. I found this tutorial from Amit Agarwal which gave me enough to get started (it did take me more than 5 minutes since I did a lot of modifying). I host the script on google docs.
FIRST I think this is javascript (my understanding is that google apps script uses javascript...) and when I have had problems with the code so far, google searches for javascript-such-and-such have been helpful, but if this is not actually javascript, please let me know so I can update the tag accordingly!
I have no prior experience with javascript, so I am pretty happy that it's actually working. But I want to see if I'm doing this right.
The start function initiates the trigger, which kicks off the fetchTweets() function every interval (30 minutes). In order to avoid duplicates (the first errors I encountered) & potentially being flagged as spam, I needed a way to ensure that I was not posting the same tweets over and over again. Within the start() function, the initial since_id value is assigned:
ScriptProperties.setProperty("SINCE_TWITTER_ID", "404251049889759234");
Within the fetchTweet() function, I think I am updating this property with the statement:
ScriptProperties.setProperty("SINCE_TWITTER_ID", lastID + '\n');
Is this a good way to do this? Or is there a better/more reliable way? And if so, how can I be sure it's updating the property? (I can check the log file and it seems to be doing it, so I probably just need to create a permanent text file for the logger).
Any help is greatly appreciated!!
/** A S I M P L E T W I T T E R B O T **/
/** ======================================= **/
/** Written by Amit Agarwal #labnol on 03/08/2013 **/
/** Modified by David Zemens #agnarchy on 11/21/2013 **/
/** Tutorial link: http://www.labnol.org/?p=27902 **/
/** Live demo at http://twitter.com/DearAssistant **/
/** Last updated on 09/07/2013 - Twitter API Fix **/
function start() {
Logger.log("start!" + '\n')
// REPLACE THESE DUMMY VALUES
// https://script.google.com/macros/d/18DGYaa-jbaAK9rEv0HZ2cMcWjFGgkvVcvr6TfksMNbbu2Brk3gZeZ46R/edit
var TWITTER_CONSUMER_KEY = "___REDACTED___";
var TWITTER_CONSUMER_SECRET = "___REDACTED___";
var TWITTER_HANDLE = "___REDACTED___";
var SEARCH_QUERY = "___REDACTED___" + TWITTER_HANDLE;
// Store variables
ScriptProperties.setProperty("TWITTER_CONSUMER_KEY", TWITTER_CONSUMER_KEY);
ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", TWITTER_CONSUMER_SECRET);
ScriptProperties.setProperty("TWITTER_HANDLE", TWITTER_HANDLE);
ScriptProperties.setProperty("SEARCH_QUERY", SEARCH_QUERY);
ScriptProperties.setProperty("SINCE_TWITTER_ID", "404251049889759234");
// Delete exiting triggers, if any
var triggers = ScriptApp.getScriptTriggers();
for(var i=0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
// Setup trigger to read Tweets every 2 hours
ScriptApp.newTrigger("fetchTweets")
.timeBased()
.everyMinutes(30)
//.everyHours(2)
.create();
}
function oAuth() {
//Authentication
var oauthConfig = UrlFetchApp.addOAuthService("twitter");
oauthConfig.setAccessTokenUrl("https://api.twitter.com/oauth/access_token");
oauthConfig.setRequestTokenUrl("https://api.twitter.com/oauth/request_token");
oauthConfig.setAuthorizationUrl("https://api.twitter.com/oauth/authorize");
oauthConfig.setConsumerKey(ScriptProperties.getProperty("TWITTER_CONSUMER_KEY"));
oauthConfig.setConsumerSecret(ScriptProperties.getProperty("TWITTER_CONSUMER_SECRET"));
}
function fetchTweets() {
oAuth();
// I put this line in to monitor whether the property is getting "stored" so as to avoid
// reading in duplicate tweets.
Logger.log("Getting tweets since " + ScriptProperties.getProperty("SINCE_TWITTER_ID"))
var twitter_handle = ScriptProperties.getProperty("TWITTER_HANDLE");
var search_query = ScriptProperties.getProperty("SEARCH_QUERY")
Logger.log("searching tweets to " + search_query + '\n');
// form the base URL
// restrict to a certain radius ---:
//var search = "https://api.twitter.com/1.1/search/tweets.json?count=5&geocode=42.827934,-83.564306,75mi&include_entities=false&result_type=recent&q=";
// unrestricted radius:
var search = "https://api.twitter.com/1.1/search/tweets.json?count=5&include_entities=false&result_type=recent&q=";
search = search + encodeString(search_query) + "&since_id=" + ScriptProperties.getProperty("SINCE_TWITTER_ID");
var options =
{
"method": "get",
"oAuthServiceName":"twitter",
"oAuthUseToken":"always"
};
try {
var result = UrlFetchApp.fetch(search, options);
var lastID = ScriptProperties.getProperty("SINCE_TWITTER_ID");
if (result.getResponseCode() === 200) {
var data = Utilities.jsonParse(result.getContentText());
if (data) {
var tweets = data.statuses;
//Logger.log(data.statuses);
for (var i=tweets.length-1; i>=0; i--) {
// Make sure this is a NEW tweet
if (tweets[i].id > ScriptProperties.getProperty("SINCE_TWITTER_ID")) {
lastID = (tweets[i].id_str);
var answer = tweets[i].text.replace(new RegExp("\#" + twitter_handle, "ig"), "").replace(twitter_handle, "");
// I find this TRY block may be necessary since a failure to send one of the tweets
// may abort the rest of the loop.
try {
Logger.log("found >> " + tweets[i].text)
Logger.log("converted >> " + answer + '\n');
sendTweet(tweets[i].user.screen_name, tweets[i].id_str, answer.substring(0,140));
// Update the script property to avoid duplicates.
ScriptProperties.setProperty("SINCE_TWITTER_ID", lastID);
Logger.log("sent to #" + tweets[i].user.screen_name + '\n');
} catch (e) {
Logger.log(e.toString() + '\n');
}
}
}
}
}
} catch (e) {
Logger.log(e.toString() + '\n');
}
Logger.log("Last used tweet.id: " + lastID + + "\n")
}
function sendTweet(user, reply_id, tweet) {
var options =
{
"method": "POST",
"oAuthServiceName":"twitter",
"oAuthUseToken":"always"
};
var status = "https://api.twitter.com/1.1/statuses/update.json";
status = status + "?status=" + encodeString("RT #" + user + " " + tweet + " - Thanks\!");
status = status + "&in_reply_to_status_id=" + reply_id;
try {
var result = UrlFetchApp.fetch(status, options);
Logger.log("JSON result = " + result.getContentText() + '\n');
}
catch (e) {
Logger.log(e.toString() + '\n');
}
}
// Thank you +Martin Hawksey - you are awesome
function encodeString (q) {
// Update: 09/06/2013
// Google Apps Script is having issues storing oAuth tokens with the Twitter API 1.1 due to some encoding issues.
// Henc this workaround to remove all the problematic characters from the status message.
var str = q.replace(/\(/g,'{').replace(/\)/g,'}').replace(/\[/g,'{').replace(/\]/g,'}').replace(/\!/g, '|').replace(/\*/g, 'x').replace(/\'/g, '');
return encodeURIComponent(str);
// var str = encodeURIComponent(q);
// str = str.replace(/!/g,'%21');
// str = str.replace(/\*/g,'%2A');
// str = str.replace(/\(/g,'%28');
// str = str.replace(/\)/g,'%29');
// str = str.replace(/'/g,'%27');
// return str;
}
When you use ScriptProperties.setProperty("KEY", "VALUE");, internally Script Properties will overwrite a duplicate key (i.e., if an old Property has the same key, your new one will replace it). So in your case, since you are using the same identifier for the key (SINCE_TWITTER_ID), it will replace any previous Script Property that is that key.
Furthermore, you can view Script Properties via File -> Project properties -> Project properties (tab). Imo Google didn't name that very well. User properties as specific to Google users. Script properties as specific to the Script Project you are working under.
Also, it probably isn't a good idea to include \n in your value when you set the property. That will lead to all sorts of bugs down the road, because you'll have to compare with something like the following:
var valToCompare = "My value\n";
instead of:
var valToCompare = "My value";
because the value in SINCE_TWITTER_ID will actually be "some value\n" after you call your fetchTweet() function.
Of course, one seems more logical I think, unless you really need the line breaks (in which case you should be using them somewhere else, for this application).
Its ok like that thou I dont know why you are adding \n at fhe end. Might confuse other code. You can see script properties in the script's file menu+ properties
I'm trying to build a POC to migrate a heavy JSF application to a stateless ajax/restful application .
In the proccess i can't decide what is the best way of presenting the JSON data returned to the screen , i can see 2 major approaches one is to have templates and use something like prototype's toHTML() with them and the other is to build the objects in javascript and then use appendchild .
the first one is much more easy to understand for a new person who has to maintain the code as the templates are very clear and easier to maintain (allso the skills needed to change the html in templates are lower) but from what i understand the appendchild method is better in regards to browser speed .
what is the preferable way to handle this and am i missing other points of comparison between the two ?
append child is this a good compromise between the two ?
are there any other ways to do this ?
P.S : to be clear i'm talking about client side manipulations only
Setting html directly with innerHTML is the fastest way cross-browser. It has some bugs, however, that you should keep in mind (tables, forms, etc.).
var html = [];
for (...) {
html.push( PARTIAL_HTML );
}
element.innerHTML = html.join("");
UPDATE: The best way may be to test it for yourself:
function test( name, fn, n, next ) {
var n = n || 100; // default number of runs
var start, end, elapsed;
setTimeout(function() {
start = Number(new Date());
for ( ; n--; ) {
fn()
}
end = Number(new Date());
elapsed = end - start;
// LOG THE RESULT
// can be: $("#debug").html(name + ": " + elapsed + " ms");
console.log(name + ": " + elapsed + " ms"));
next && next();
}, 0);
}
test("dom", function() {
// ...
});
test("innerHTML", function() {
// ...
});