No output using a node delta calculator - node.js

I found this package and I tried to use it because I would like to see differences in JSON: https://www.npmjs.com/package/json-multilevel-delta
This is what I tried:
// row.old = "{\"current_page\":1,\"data\":[{\"id\":6430,\"name\":\"A random name\",\"code\":\"rname13\",\"description\":\"rname13test ...
// row.new = "{\"current_page\":1,\"data\":[{\"id\":6430,\"name\":\"A random name 2\",\"code\":\"rname13\",\"description\":\"rname13test ...
const oldData = JSON.parse(row.old);
const newData = JSON.parse(row.new);
const difference = jsonMultilevelDelta.json(oldData, newData);
console.log(difference);
However for some reason I am not getting any result, am I using it wrong?

From looking at it, it is only finding the difference by looking for missing properties, not by looking at the difference in values. I don't know if it was designed to meet your requirements.
It also has low weekly downloads and little activity so probably not the best thing you want in a project, imo.

Related

Creating Node.js enum in code to match list of values in database

I have a list of valid values that I am storing in a data store. This list is about 20 items long now and will likely grow to around 100, maybe more.
I feel there are a variety of reasons it makes sense to store this in a data store rather than just storing in code. I want to be able to maintain the list and its metadata and make it accessible to other services, so it seems like a micro-service data store.
But in code, we want to make sure only values from the list are passed, and they can typically be hardcoded. So we would like to create an enum that can be used in code to ensure that valid values are passed.
I have created a simple node.js that can generate a JS file with the enum right from the data store. This could be regenerated anytime the file changes or maybe on a schedule. But sharing the enum file with any node.js applications that use it would not be trivial.
Has anyone done anything like this? Any reason why this would be a bad approach? Any feedback is welcome.
Piggy-backing off of this answer, which describes a way of creating an "enum" in JavaScript: you can grab the list of constants from your server (via an HTTP call) and then generate the enum in code, without the need for creating and loading a JavaScript source file.
Given that you have loaded your enumConstants from the back-end (here I hard-coded them):
const enumConstants = [
'FIRST',
'SECOND',
'THIRD'
];
const temp = {};
for (const constant of enumConstants) {
temp[constant] = constant;
}
const PlaceEnum = Object.freeze(temp);
console.log(PlaceEnum.FIRST);
// Or, in one line
const PlaceEnum2 = Object.freeze(enumConstants.reduce((o, c) => { o[c] = c; return o; }, {}));
console.log(PlaceEnum2.FIRST);
It is not ideal for code analysis or when using a smart editor, because the object is not explicitly defined and the editor will complain, but it will work.
Another approach is just to use an array and look for its members.
const members = ['first', 'second', 'third'...]
// then test for the members
members.indexOf('first') // 0
members.indexOf('third') // 2
members.indexOf('zero') // -1
members.indexOf('your_variable_to_test') // does it exist in the "enum"?
Any value that is >=0 will be a member of the list. -1 will not be a member. This doesn't "lock" the object like freeze (above) but I find it suffices for most of my similar scenarios.

Get the label of a MathJax equation

How can I get the label of an equation? I'm attempting to reprocess an equation with a label, but I have to delete the label from MathJax.Extension["TeX/AMSmath"].labels first, for which the label must be known...
I know I can scan through the source text for the label MathJax.Hub.getAllJax("mathDiv")[0}.SourceElement().find("\label(") (...), but this seems needlessly complicated. Is there a better way?
There's no built-in API for this.
If you don't need to keep labels, then the reset in the comment above is probably the best way to go about it:
MathJax.Extension["TeX/AMSmath"].labels = {}
A quick and dirty way to get the IDs is to leverage the fact that they end up in the output. So you can just get all the IDs in the output, e.g.,
const math = MathJax.Hub.getAllJax()[0];
const nodesWithIds = document.getElementById(math.root.inputID).previousSibling.querySelectorAll('[id]');
const ids = [];
for (node of nodesWithIds) ids.push(node.id);
A cleaner and perhaps conceptually easier way would be to leverage MathML (which is essentially the internal format): the \label{} always ends up on an mlabeledtr. The trouble is that you'd have to re-parse that, e.g.,
const temp = document.createElement('span');
temp.innerHTML = math.root.toMathML();
const nodesWithIds = temp.querySelectorAll('mlabeledtr [id]');
const ids = [];
for (node of nodesWithIds) ids.push(node.id);
This will make sure the array only has relevant IDs in them (and the contents of the nodes should correspond to \label{}.
I suppose with helper libraries it might be easier to dive into the math.root object directly and look for IDs recursively (in its data key).

How to extract raw values for comparison or manipulation from Gremlin (Tinkerpop)

I know I'm missing something obvious here. I'm trying to extract values from TitanDB using Gremlin in order to compare them within Groovy.
graph = TinkerFactory.createModern()
g = graph.traversal(standard())
markoCount = g.V().has('name','marko').outE('knows').count()
lopCount = g.V().has('name','lop').outE('knows').count()
if(markoCount > lopCount){
// Do something
}
But apparently what I'm actually (incorrectly) doing here is comparing traversal steps which obviously won't work:
Cannot compare org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal with value '[TinkerGraphStep(vertex,[name.eq(marko)]), VertexStep(OUT,[knows],edge), CountGlobalStep]' and org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal with value '[TinkerGraphStep(vertex,[name.eq(lop)]), VertexStep(OUT,[knows],edge), CountGlobalStep]'
I'm having the same issue extracting values from properties for use in Groovy as well. I didn't see anything in the docs indicating how to set raw values like this.
What is needed to return actual values from Gremlin that I can use later in my Groovy code?
Figured it out, I needed next():
graph = TinkerFactory.createModern()
g = graph.traversal(standard())
markoCount = g.V().has('name','marko').outE('knows').count().next()
lopCount = g.V().has('name','lop').outE('knows').count().next()
if(markoCount > lopCount){
// Do something
}

Converting a PGN to a list of FEN strings in nodejs (chess notations)

I'm building a chess-related application using nodejs. I've been trying to use chess.js as much as I can but I think I've hit a roadblock in terms of functionality. Before extending that functionality, I wanted to make sure that there wasn't another tool that can do what I need.
I'm looking for a way to convert a PGN string into a list of FEN moves. I was hoping to use load_pgn() in chess.js to load the moves into the object and then loop over each move and invoke the fen() function to output the current FEN. However, chess.js doesn't seem to have a way to walk through the moves in a game. Unless I'm missing something.
I'd rather not have to get into parsing strings, but will if I have to. Any suggestions?
Solution:
also see efirvida's answer below for a solution
Something like this (untested) seems to work. The function accepts a Chess object created with chess.js that already has a PGN loaded into it.
function getMovesAsFENs(chessObj) {
var moves = chessObj.history();
var newGame = new Chess();
var fens = [];
for (var i = 0; i < moves.length; i++) {
newGame.move(moves[i]);
fens.push(newGame.fen());
}
return fens;
}
Take a look to the github page .load_pgn link
var chess = new Chess();
pgn = ['[Event "Casual Game"]',
'[Site "Berlin GER"]',
'[Date "1852.??.??"]',
'[EventDate "?"]',
'[Round "?"]',
'[Result "1-0"]',
'[White "Adolf Anderssen"]',
'[Black "Jean Dufresne"]',
'[ECO "C52"]',
'[WhiteElo "?"]',
'[BlackElo "?"]',
'[PlyCount "47"]',
'',
'1.e4 e5 2.Nf3 Nc6 3.Bc4 Bc5 4.b4 Bxb4 5.c3 Ba5 6.d4 exd4 7.O-O',
'd3 8.Qb3 Qf6 9.e5 Qg6 10.Re1 Nge7 11.Ba3 b5 12.Qxb5 Rb8 13.Qa4',
'Bb6 14.Nbd2 Bb7 15.Ne4 Qf5 16.Bxd3 Qh5 17.Nf6+ gxf6 18.exf6',
'Rg8 19.Rad1 Qxf3 20.Rxe7+ Nxe7 21.Qxd7+ Kxd7 22.Bf5+ Ke8',
'23.Bd7+ Kf8 24.Bxe7# 1-0'];
chess.load_pgn(pgn.join('\n'));
// -> true
chess.fen()
// -> 1r3kr1/pbpBBp1p/1b3P2/8/8/2P2q2/P4PPP/3R2K1 b - - 0 24
something like
moves = chess.history();
var chess1 = new Chess();
for (move in moves){
chess1.move(move);
fen = chess1.fen()
}
(Not really an answer; just a comment that needs extra formatting.)
Your getMovesAsFENs function might also be written as:
function getMovesAsFENs(chessObj) {
return chessObj.history().map(function(move) {
chessObj.move(move);
return chessObj.fen();
});
}
Perhaps it doesn't matter to you, but this appeals to my sense of neatness.
Here is an end to end answer with some ES6 sugar added in:
const Chess = require('chess.js').Chess;
const chess1 = new Chess();
const chess2 = new Chess();
const startPos = chess2.fen();
const pgn = `1.e4 c5 0-1`;
chess1.load_pgn(pgn);
let fens = chess1.history().map(move => {
chess2.move(move);
return chess2.fen();
});
//the above technique will not capture the fen of the starting position. therefore:
fens = [startPos, ...fens];
//double checking everything
fens.forEach(fen => console.log(fen));
"However, chess.js doesn't seem to have a way to walk through the
moves in a game. Unless I'm missing something.".
You are right (as I have read the entire library multiple times by now). And everything that needs to see back into the history is basically undoing and then redoing the moves, without some sort of real navigation integrated (it is an interesting choice to have it solved this way, with the pros of it being lighting fast for some tasks, but with the cons of being a real pain for other seemingly easier tasks like the one you need).
Disclaimer (I wrote the following tool), I have been creating a tool (isepic-chess.js) for the past 5+ years, something similar to chess.js and I think it's slowly getting there... The library stores the moves history in an object with information like (fen, from_square, to_square, san, etc.), and also have some kind of "cursor" with the move index and some move-navigation helpers.
So with isepic-chess.js you can just call the board method board.fenHistoryExport() to get the FEN list after you parse the PGN game:
var example_pgn = `[Event "m1 London"]
[Site "?"]
[Date "1861.07.??"]
[Round "9"]
[White "Kolisch, Ignatz"]
[Black "Anderssen, Adolf"]
[Result "0-1"]
[Annotator "JvR"]
[SetUp "1"]
[FEN "5r1k/pp4pp/3r3q/8/3PpP1P/1P2NbP1/PB1Q3K/R7 b - - 0 30"]
[PlyCount "13"]
[EventDate "1861.??.??"]
30... Rxf4 $1 {Anderssen starts fireworks.} 31. Qe1 (31.gxf4 $2 Qxh4+ 32.Kg1
Rg6+) 31... Rg6 (31...Rxh4+ $1 32.gxh4 Rg6 $1) 32. Bc1 (32.Ng2 $1) 32... Rxh4+
$1 33. gxh4 Qf4+ 34. Kh3 Bg2+ $1 35. Nxg2 Qf3+ 36. Kh2 Qxg2# { Anderssen won
the match by this mate (+4, =2, -3).} 0-1`;
var board = Ic.initBoard({
pgn : example_pgn
});
console.log(board.fenHistoryExport());
There is a more complete node.js example in the README.md with the const {Ic} = require("isepic-chess"); import thingy to have it running in node.js.

How to generate short unique names for uploaded files in nodejs

I need to name uploaded files by short unique identifier like nYrnfYEv a4vhAoFG hwX6aOr7. How could I ensure uniqueness of files?
Update: shortid is deprecated. Use Nano ID instead. The answer below applies to Nano ID as well.
(Posting my comments as answer, with responses to your concerns)
You may want to check out the shortid NPM module, which generates short ids (shockingly, I know :) ) similar to the ones you were posting as example. The result is configurable, but by default it's a string between 7 and 14 characters (length is random too), all URL-friendly (A-Za-z0-9\_\- in a regex).
To answer your (and other posters') concerns:
Unless your server has a true random number generator (highly unlikely), every solution will use a PRNG (Pseudo-Random Number Generator). shortid uses Node.js crypto module to generate PRNG numbers, however, which is a much better generator than Math.random()
shortid's are not sequential, which makes it even harder to guess them
While shortid's are not guaranteed to be unique, the likelihood of a collision is extremely small. Unless you generate billions of entries per year, you could safely assume that a collision will never happen.
For most cases, relying on probability to trust that collisions won't happen is enough. If your data is too important to risk even that tiny amount, you could make the shortid basically 100% unique by just prepending a timestamp to it. As an additional benefit, the file names will be harder to guess too. (Note: I wrote "basically 100% unique" because you could still, in theory, have a collision if two items are generated in the same timestamp, i.e. the same second. However, I would never be concerned of this. To have a real 100% certainty your only option is to run a check against a database or the filesystem, but that requires more resources.)
The reason why shortid doesn't do that by itself is because for most applications the likelihood of a collision is too small to be a concern, and it's more important to have the shortest possible ids.
One option could be to generate unique identifiers (UUID) and rename the file(s) accordingly.
Have a look at the kelektiv/node-uuid npm module.
EXAMPLE:
$ npm install uuid
...then in your JavaScript file:
const uuidv4 = require('uuid/v4'); // I chose v4 ‒ you can select others
var filename = uuidv4(); // '110ec58a-a0f2-4ac4-8393-c866d813b8d1'
Any time you execute uuidv4() you'll get a very-fresh-new-one.
NOTICE: There are other choices/types of UUIDs. Read the module's documentation to familiarize with those.
Very simple code. produce a filename almost unique
or if that's not enough you check if the file exists
function getRandomFileName() {
var timestamp = new Date().toISOString().replace(/[-:.]/g,"");
var random = ("" + Math.random()).substring(2, 8);
var random_number = timestamp+random;
return random_number;
}
export default generateRandom = () => Math.random().toString(36).substring(2, 15) + Math.random().toString(23).substring(2, 5);
As simple as that!
function uniqueFileName( filePath, stub)
{
let id = 0;
let test = path.join(filePath, stub + id++);
while (fs.existsSync(test))
{
test = path.join(filePath, stub + id++);
}
return test;
}
I think you might be confused about true-random and pseudo-random.
Pseudo-random strings 'typically exhibit stastical randomness while being generated by an entirely deterministic casual process'. What this means is, if you are using these random values as entropy in a cryptographic application, you do not want to use a pseudo-random generator.
For your use, however, I believe it will be fine - just check for potential (highly unlikely) clashes.
All you are wanting to do is create a random string - not ensure it is 100% secure and completely random.
Try following snippet:-
function getRandomSalt() {
var milliseconds = new Date().getTime();
var timestamp = (milliseconds.toString()).substring(9, 13)
var random = ("" + Math.random()).substring(2, 8);
var random_number = timestamp+random; // string will be unique because timestamp never repeat itself
var random_string = base64_encode(random_number).substring(2, 8); // you can set size here of return string
var return_string = '';
var Exp = /((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+[0-9a-z]+$/i;
if (random_string.match(Exp)) { //check here whether string is alphanumeric or not
return_string = random_string;
} else {
return getRandomSalt(); // call recursivley again
}
return return_string;
}
File name might have an alphanumeric name with uniqueness according to your requirement. Unique name based on the concept of timestamp of current time because current time never repeat itself in future and to make it strong i have applied a base64encode which will be convert it into alphanumeric.
var file = req.files.profile_image;
var tmp_path = file.path;
var fileName = file.name;
var file_ext = fileName.substr((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1);
var newFileName = getRandomSalt() + '.' + file_ext;
Thanks

Resources