Kirchoff Current Law using JavaScript - javascript

I am wondering how should I implement KCL using JavaScript. I have several current meter that to detect the value of current along a line.
I came out with a simple program but was unable to think about how to implement KCL efficiently.
var currentPointsDBA = new Array(); // Data from electricity meter will be captured and store in this array
var totalCurrentMDB = new Array(); // Total current from adding will be stored in array. Each index represents 1 distribution board.
const totalBusBar = 5;
for (z=0; z<currentPointsDBA.length(); z++){
totalCurrent += currentPoints[z];
}
totalCurrentMDB[0] = totalCurrent;
var currentCheck = [
{
name: DBA, number: 0, threshold: 0
}];
for(i=0; i<totalBusBar; i++){
var totalCurrentCheck = currentCheck[i];
if(totalCurrentMDB[totalCurrentCheck.number] != 0){
//DO SOMETHING
}
}
I realized with this, the condition will never be met as I am adding the current without using the concept of current entering the node is equals to current exiting a node.
Another difficulty that I was facing was to have an algorithm that can be used to calculate positively and negatively for KCL.
Inputs would be a power line that will be connected to a transducer(meter to measure current). Output is also current that is connected to a meter.
For the Point 1,2,3,4,5 it will be replaced with the meters. Basically, I would want an algorithm to have Sum of DBA = Point 1+2+3+4+5. However, point 1 is bi-directional. It can act as input or output. The issue will be to figure out how the current direction is and use that to determine as input or output.

Related

How do I implement minimax with the chess.js node module

I'm currently working on creating a chess engine using chess.js, chessboard.js, and the minimax algorithm. I eventually want to implement alpha-beta, but for right now, I just want to get minimax to work. It seems like the computer is thinking, but it usually just does Nc6. If I move the pawn to d4, it usually takes with the knight, but sometimes it just moves the rook back and forth in the spot that was opened up by the knight. If there is nothing for the knight to take, the computer moves the Rook or some other pointless move. My best guess is that all of the moves are returning the same valuation, and so it just makes the first move in the array of possible moves, hence the top left rook being a prime target. I should note that part of my confusion is around the way a recursive function works, and most of the stuff I've found online about recursive functions leaves me more confused than when I started.
I'm using Express.js with the chessboard.js config in public/javascripts as a boardInit.js that's included in the index.ejs folder, and when the user makes a move, a Post request is sent to /moveVsComp. It sends it to the server, where the app.post function for /moveVsComp tells chess.js to make the move that the player made.
After the player move is recorded, the computer calls the computerMoveBlack function.
Function call in the post request:
let compMove = computerMoveBlack(3);
game.load(currentFen)
game.move(compMove)
res.status(200).send({snapback: false, fen: game.fen()})
computerMoveBlack Function:
function computerMoveBlack(depth) {
let bestMove = ['', 105];
for (let move of game.moves()) {
game.move(move)
let value = minimax(move, depth-1, false)
if (value < bestMove[1]) {
bestMove = [move, value]
}
game.undo()
}
console.log(bestMove[0])
return bestMove[0]
}
This function loops through all of the moves, and I was using this because it seemed like this was the best way to keep the best move instead of just returning a valuation of the current position.
Minimax Function:
function minimax(node, depth, maximizingPlayer) {
let value = maximizingPlayer ? -105 : 105
if (depth === 0 || game.game_over()) return getValuation()
if (maximizingPlayer) {
for (let move of game.moves()) {
game.move(move)
value = Math.max(value, minimax(move, depth-1, false))
game.undo()
}
return value
} else {
for (let move of game.moves()) {
game.move(move)
value = Math.min(value, minimax(move, depth-1, true))
game.undo()
}
return value
}
}
getValuation Function:
function getValuation() {
let evalString = game.fen().split(' ')[0];
let score = 0;
score += (evalString.split('r').length -1) * -5 || 0;
score += (evalString.split('b').length -1) * -3 || 0;
score += (evalString.split('n').length -1) * -3 || 0;
score += (evalString.split('q').length -1) * -9 || 0;
score += (evalString.split('p').length -1) * -1 || 0;
score += (evalString.split('R').length -1) * 5 || 0;
score += (evalString.split('N').length -1) * 3 || 0;
score += (evalString.split('B').length -1) * 3 || 0;
score += (evalString.split('Q').length -1) * 9 || 0;
score += (evalString.split('P').length -1) || 0;
return score;
}
I should note that I understand using a FEN in the valuation is very slow for this use case, but I'm not really sure what a better alternative would be.
Just as kind of a recap of the questions, I'm trying to figure out why it just makes the first move in the array every time, what is wrong with the format of my functions, and what a better way to get the valuation of a position is as opposed to string manipulation of the FEN.
I will point out a few suggestions below to help you on the way if you are just getting started. First I just want to say that you are probably right that all moves get the same score and therefore it picks the first possible move. Try to add some Piece Square Tables (PST) to your Evaluation function and see if it puts pieces on appropriate squares.
I would implement a Negamax function instead of Minimax. It is way easier to debug and you won't have to duplicate a lot of code when you later make more optimizations. Negamax is one of the standard chess algorithms.
It seems like you don't do the legal move generation yourself, do you know how the board is represented in the library that you use? Instead of using the FEN for evaluation you want to use the board (or bitboards) to be able to do more advanced evaluation (more on it further down).
The min/max value of -105/105 is not a good way to go. Use -inf and inf instead to not get into troubles later on.
Regarding the evaluation you normally use the board representation to figure out how pieces are placed and how they are working together. Chessprogramming.org is a great resource to read up on different evaluation concepts.
For your simple starting evaluation you could just start with counting up all the material score at the beginning of the game. Then you subtract corresponding piece value when a piece is captured since that is the only case where the score is changing. Now you are recalculating lots of things over and over which will be very slow.
If you want to add PST to the evaluation then you also want to add the piece value change for the moving piece depending on the old and new square. To try and sum up the evaluation:
Sum up all piece values at start-up of a game (with PST scores if you use them) and save it as e.g. whiteScore and blackScore
In your evaluation you subtract the piece value from the opponent if you capture a piece. Otherwise you keep score as is and return it as usual.
If using PST you change the own score based on the new location for the moved piece.
I hope it makes sense, let me know if you need any further help.

assigning varying inputs to varying positions in a 4 by 4 array

I am writing a JavaScript program that is supposed to generate a number (2 90% of the time, 4 for the other 10%). This works fine, however the number is then supposed to randomly replace one of the spots in the array that had previously had a value of zero. As far as I can tell, my code that should work but it does not and I get this error message:
Cannot read property '0' of undefined
I've included my code below but it may look weird because I am using Khan Academy's JavaScript teaching tool which might not be the same as normal JavaScript (I am not sure about this since I am new to the language).
var M=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
var NewTile=function(M){
var open=0; // checks all tiles to see whitch ones are 0's
var available=[]; // while recorfing the number of zeros and
for (var p=0; p<=3; p+=1){ // thier positions
for (var q=0; q<=3; q+=1){
var i=M[p][q];
if (i===0){
open=open+1;
available.push([p,q]);
}
}
}
var TwoOrFour=random(1,10);
var NewValue;
if (TwoOrFour===10){ // generates the new value
NewValue=4;
}else{
NewValue=2;
}
var NewPos;
if (open===0){ // decides whether the game is lost
var over=true;
return over;
}else{ // replaces the correct spot in the array
var GetPos=random(0,open);
var NewPos=available[GetPos];
M[NewPos[0]][NewPos[1]]=NewValue; // THIS IS WHERE THE ERROR SEEMS TO CAUSE AN ISSUE
}
return M;
};
var M=NewTile(M);
println(M[0]);
println(M[1]);
println(M[2]);
println(M[3]);
Can anyone tell me what I am doing wrong and why I am getting this error?

Get visible points for a series in LightningChartJs

Exists a function in LightningChartJs to get all visible points from a line or point series in a chart?
If I zoom the chart I want to show something if no visible points available. In some cases I have breaks in my data.
For now I have to check the range and filter all points within this range, but that seems not to be very performant. I guess LC is aware of all the visible points and can give me that.
I would very much welcome any thoughts on the subject or other solutions. Thanks.
LightningChart JS doesn't track the data points that are visible at any time. So the method that you have used to solve the issue is the best way currently.
Something like this seems to be reasonably performant.
function getDataInRange(data, rangeStart, rangeEnd){
const inRangeData = []
const dataLength = data.length
let curPoint
for(let i = 0; i < dataLength; i += 1){
curPoint = data[i]
if(curPoint.x >= rangeStart && curPoint.x <= rangeEnd){
inRangeData.push(curPoint)
}
}
return inRangeData
}
On my personal machine it can process 1 million points in ~10ms ± 2ms. If you only want to know that a point is visible in the range then you could just break the loop as soon as a single point is in the visible range.
Late to the game but for anybody googling:
If you already have a chart defined and it happens to be named 'chart' (otherwise change chart to your chart's object name), you can track the visible start and end data points like this:
axisX = chart.getDefaultAxisX()
window.axisXScaleChangeToken = axisX.onScaleChange((s, e) => {
window.axisXVisibleDataRangeStart = s
window.axisXVisibleDataRangeEnd = e
})
let visiblePoints = [];
for(let i of cur.data){
if(i[0] > window.axisXVisibleDataRangeStart && i[0] < window.axisXVisibleDataRangeEnd) visiblePoints.push(i)
}
Every time the X axis is scaled/zoomed/moved, axisXVisibleDataRangeStart and axisXVisibleDataRangeEnd will change. You're then iterating over where your data points are stored (cur.data in my case and the example) and comparing: If timestamp is within range, push to visiblePoints.
(I am using OHLC where data[0] is the timestamp. Your comparison might be to an object array where {x:} is the value youre looking to compare. You get the idea.)
To remove the listener and stop the logging:
axisX.offScaleChange(window.axisXScaleChangeToken)

Detecting a Fist with Leap Motion SDK V2

I want to check if a Hand in a Leap Motion Frame is currently a Fist.
The usually suggested method is to look for hand.grabStrength with a value of 1. The problem is that the value jumps to 1 even with a "Claw-Like" Hand, or anything else with very slightly curled fingers.
Another approach would be to check on each finger if it is extended. But this has a similiar issue, Fingers only count as extended if they are completely straight. So even if i check for all fingers to be not extended, the same issue as above occurs (claw-like hands get recognized as grabbed).
Combining these two methods also does not solve the issue, which is not surprising given that they both suffer from the same problems.
Now, we do have all the bones of each finger available, with positions and everything. But I have no idea where to start with the math to detect if a finger is curled.
Basically I have this setup for now:
var controller = Leap.loop(function(frame){
if(frame.hands.length>0){
//we only look at the first available hand
var hand = frame.hands[0];
//we get the index finger only, but later on we should look at all 5 fingers.
var index = hands.fingers[1];
//after that we get the positions of the joints between the bones in a hand
//the position of the metacarpal bone (i.e. the base of your hand)
var carp = index.carpPosition;
//the position of the joint on the knuckle of your hand
var mcp = index.mcpPosition;
//the position of the following joint, between the proximal and the intermediate bones
var pip = index.pipPosition;
//the position of the distal bone (the very tip of your finger)
var dip = index.dipPosition;
//and now we need the angle between each of those positions, which is where i'm stuck
}
});
So, how do I get the angle between two of those positions (carp to mcp, mcp to pip, pip to dip)? Any ideas?
Alright, I think I found a sort of working approach to detect an actual fist, and not a claw.
First off, instead of the positions of the joints, we need the distance Vectors for each Bone.
Then we calculate the Dot product between the Metacarpal and the Proximal bone, as well as the dot Product between the Proximal and the Intermediate Bone. We can ignore the Distal bone, it doesn't change the result too much.
We sum all the calculated dot products (10 in total) and calculate the average out (we divide by 10). This will give us a value between 0 and 1. A Fist is beneath 0.5 and everything above that is basically not a fist.
Additionally you might also want to check for the amount of extended fingers on a Hand and check if it is 0. This will ensure that a "Thumbs-up" and similiar 1-digit poses do not get recognized as a Fist.
Here is my implementation:
const minValue = 0.5;
var controller = Leap.loop(function(frame){
if(frame.hands.length>0)
{
var hand = frame.hands[0];
var isFist = checkFist(hand);
}
});
function getExtendedFingers(hand){
var f = 0;
for(var i=0;i<hand.fingers.length;i++){
if(hand.fingers[i].extended){
f++;
}
}
return f;
}
function checkFist(hand){
var sum = 0;
for(var i=0;i<hand.fingers.length;i++){
var finger = hand.fingers[i];
var meta = finger.bones[0].direction();
var proxi = finger.bones[1].direction();
var inter = finger.bones[2].direction();
var dMetaProxi = Leap.vec3.dot(meta,proxi);
var dProxiInter = Leap.vec3.dot(proxi,inter);
sum += dMetaProxi;
sum += dProxiInter
}
sum = sum/10;
if(sum<=minValue && getExtendedFingers(hand)==0){
return true;
}else{
return false;
}
}
While this works like it should, I doubt that this is the correct and best approach to detect a Fist. So please, if you know of a better way, post it.
Solution works perfect, any chance you could explain why you divide by 10 and why the minValue is 0.5? Thanks!
Well, it doesn't work that good, to be honest. I'll soon start to work on a little project that has the goal to improve the detection of fists with Leap Motion.
Regarding your questions, We divide the sum by 10 because we have 2 Bone Joints per finger, with 5 fingers. We want the average value from the sum of all those calculations, because not all fingers will be angled in the same way. So we want some value that encompasses all of these values into a single one: the average value. Given that we have 10 calculations in total (2 per each finger, 5 fingers), we divide the sum of those calculations and there we go. We will get a value between 0 and 1.
Regarding the minValue: Trial&Error. In a project of mine, I used a value of 0.6 instead.
This is another problem of this approach: ideally a flat hand should be a value of nearly 0, while a fist should be 1.
I know it is an old topic but if you guys still around the answer could be simpler just by using sphereRadius() ;
I found "grabStrength" is good

Creating a random number generator in jscript and prevent duplicates

We are trying to create a random number generator to create serial numbers for products on a virtual assembly line.
We got the random numbers to generate, however since they are serial numbers we don't want it to create duplicates.
Is there a way that it can go back and check to see if the number generated has already been generated, and then to tell it that if it is a duplicate to generate a new number, and to repeat this process until it has a "unique" number.
The point of a serial number is that they're NOT random. Serial, by definition, means that something is arranged in a series. Why not just use an incrementing number?
The easiest way to fix this problem is to avoid it. Use something that is monotonically increasing (like time) to form part of your serial number. To that you can prepend some fixed value that identifies the line or something.
So your serial number format could be NNNNYYYYMMDDHHMMSS, where NNNN is a 4-digit line number and YYYY is the 4 digit year, MM is a 2 digit month, ...
If you can produce multiple things per second per line, then add date components until you get to the point where only one per unit time is possible -- or simply add the count of items produced this day to the YYYYMMDD component (e.g., NNNNYYYYMMDDCCCCCC).
With a truly random number you would have to store the entire collection and review it for each number. Obviously this would mean that your generation would become slower and slower the larger the number of keys you generate (since it would have to retry more and more often and compare to a larger dataset).
This is entirely why truly random numbers just are never used for this purpose. For serial numbers the standard is always to just do a sequential number - is there any real real for them to be random?
Unique IDs are NEVER random - GUIDs and the like are based on the system time and (most often) MAC address. They're globally unique because of the algorithm used and the machine specifics - not because of the size of the value or any level of randomness.
Personally I would do everything I could to either use a sequential value (perhaps with a unique prefix if you have multiple channels) or, better, use a real GUID for your purpose.
is this what you are looking for?
var rArray;
function fillArray (range)
{
rArray = new Array ();
for(var x = 0; x < range; x++)
rArray [x] = x;
}
function randomND (range)
{
if (rArray == null || rArray.length < 1)
fillArray (range);
var pos = Math.floor(Math.random()*rArray.length);
var ran = rArray [pos];
for(var x = pos; x < rArray.length; x++)
rArray [x] = rArray [x+1];
var tempArray = new Array (rArray.length-1)
for(var x = 0; x < tempArray.length; x++)
tempArray [x] = rArray [x];
rArray = tempArray;
return ran;
}

Categories