How to fix forecast looping push - javascript

How to fix the looping when clicking the nz-switch/switch button.
I'm create a switch . thank you
here's the code:
child.component.ts
#Input() toggleUnit: boolean = false;
ngOnChanges() {
switch(this.toggleUnit) {
case true: {
this.unit = 'imperial';
this.setWeatherForecast(this.unit)
break;
}case false: {
this.unit = 'metric';
this.setWeatherForecast(this.unit)
break;
}
}
}
setWeatherForecast(unit: any) {
this.weatherService.getLocation().subscribe(data => {
this.lat = JSON.parse(data['_body']).latitude;
this.lon = JSON.parse(data['_body']).longitude;
this.weatherService
.fiveDayForecast(this.lat, this.lon, unit)
.subscribe(data => {
for (let i = 0; i < data.list.length; i = i + 8) {
const forecastWeather = new Forecast(
data.city.name,
data.list[i].weather[0].description,
data.list[i].main.temp,
data.list[i].dt_txt,
data.list[i].weather[0].icon
);
this.forecast.push(forecastWeather);
}
return this.forecast;
});
});
}
parent.component.ts
toggleUnit: boolean = false;
onSwitchChange() {
let temperature: any = [];
switch (this.toggleUnit) {
case true: {
this.toggleUnit = true;
break;
}
case false: {
temperature = document.getElementById(`temperature-${i}`) as HTMLCanvasElement;
temperature.style.height =((this.tempThermometer[i].temperature - this.config.minTemp) / (this.config.maxTemp - this.config.minTemp)) * 100 + '%';
temperature.dataset.value = this.tempThermometer[i].temperature + this.units['Celcius'];
}
this.toggleUnit = false;
break;
}
}
****parent.component.html***
<app-forecast [toggleUnit]="toggleUnit"></app-forecast>
but when I try to login it instead it updates it push new row.
I use nz-swith and others.
the output will push another new array, same when it will switch it will add new array.

Related

Creating Coin Flip using Vanilla Javascript and decrement and this

I need to make a coin flip 20x and display the coin, and the results x times each. I am trying to use decrement to determine the coin flip. And then need to display the flip x number of times. I am running into an issue of how to write it using this. and decrement.
const coin = {
state: 0,
flip: function () {
this.state = Math.floor(Math.random() * 2) == 0 ? "tails" : "heads";
// 0 or 1: use "this.state" to access the "state" property on this object.
},
toString: function () {
if (this.state === 0) {
sides = "heads";
} else if (this.state === 1) {
sides = "tails";
}
return sides;
},
toHTML: function () {
const image = document.createElement("img");
let h1 = document.querySelector("h1");
h1.append(image);
if (this.state === 0) {
image.src = "images/tails.png";
} else if (this.state === 1) {
image.src = "image/heads.png";
}
return image;
},
};
function display20Flips() {
const results = [];
for (let i = 0; i < 20; i++) {
coin.flip();
h3.innerHTML += coin.state;
results.push(coin.state++);
}
You can also approach it functionally. This will help you focus on one problem at a time:
// Store the coin flip state as a boolean (true or false)
function randomBoolean () {
return Boolean(Math.floor(Math.random() * 2));
}
// Convert the boolean state to a "side" string
// heads is false, tails is true
function asCoinSide (bool) {
return bool ? 'tails' : 'heads';
}
function createCoinImage (bool) {
const side = asCoinSide(bool);
const image = document.createElement('img');
image.alt = side;
// StackOverflow doesn't have access to your local images,
// so this will show an error in the code snippet demo
// when the URL is loaded, but will work if the images exist:
image.src = `images/${side}.png`;
return image;
}
function displayCoinFlips (count = 20) {
const div = document.querySelector('div.coins');
const results = [];
for (let i = 0; i < count; i += 1) {
// Get a state
const state = randomBoolean();
results.push(state);
// Use the state to create the image
const image = createCoinImage(state);
// And append it to the container div
div.appendChild(image);
}
return results;
}
function displaySummary (states) {
const div = document.querySelector('div.summary');
let headsCount = 0;
let tailsCount = 0;
// Count the heads vs. tails results
// Remember: heads is false, tails is true
for (const state of states) {
if (state) tailsCount += 1;
else headsCount += 1;
}
div.textContent = `Heads: ${headsCount}, Tails: ${tailsCount}`;
}
const states = displayCoinFlips();
displaySummary(states);
<div class="coins"></div>
<div class="summary"></div>
You had some issues with your code. I fixed them. Still, the code needs to be a little redesigned to have a class Coin and then coin = new Coin().
const coin = {
state: 0,
flip: function() {
this.state = Math.floor(Math.random() * 2) == 0 ? "tails" : "heads";
},
toString: function() {
if (this.state === 0) {
sides = "heads";
} else if (this.state === 1) {
sides = "tails";
}
return sides;
},
toHTML: function() {
let h1 = document.querySelector(".container");
const div = document.createElement("div");
if (this.state === "tails") {
div.innerText = "images/tails.png";
} else {
div.innerText = "image/heads.png";
}
h1.append(div);
return div;
},
};
function displayFlips(n) {
const results = [];
for (let i = 0; i < n; i++) {
coin.flip();
coin.toHTML();
results.push(coin.state);
}
return results;
}
console.log(displayFlips(20));
<div class="container">
</div>

Why is my decryption function not working?

I created a function to encrypt and decrypt messages. the encrypting works fine. but when I try to log encrypted Hello World! it just logs H.
const chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".split("");
const numbs = "0123456789".split("");
const symbols = "!##$%^&*()_+-=[]{}|;':,./<>?\" ".split("");
function encrypt(message) {
message = message.split("")
var output = []
message.forEach(element => {
if (chars.includes(element)) {
output.push("c" + chars.indexOf(element))
} else if (numbs.includes(element)) {
output.push("n" + numbs.indexOf(element))
} else if (symbols.includes(element)) {
output.push("s" + symbols.indexOf(element))
} else {
console.log(element)
throw new Error(`Unknown character`)
}
});
return output.join("")
}
function decrypt(message) {
message = message.split("");
var output = [];
var prevDeter;
var prevNumbs = [];
message.forEach(element => {
if (element == "c") {
prevDeter = "c"
if (prevNumbs.length > 0) {
output.push(chars[parseInt(prevNumbs.join(""))])
}
} else if (element == "n") {
prevDeter = "n"
if (prevNumbs.length > 0) {
output.push(numbs[parseInt(prevNumbs.join(""))])
}
} else if (element == "s") {
prevDeter = "s"
if (prevNumbs.length > 0) {
output.push(symbols[parseInt(prevNumbs.join(""))])
}
} else {
prevNumbs.push(element)
}
});
return output.join("")
}
//expected to log Hello World! but logs H and when starting the message with a symbol or number it just logs nothing
console.log(decrypt(encrypt("Hello World!")))
Fixed it, i edited the encoding system to place a - between chars and the decoding system to just split the message at - and check if the element starts with c n or s. and then i just used substring to get the number and decrypt it
const chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".split("");
const numbs = "0123456789".split("");
const symbols = "!##$%^&*()_+-=[]{}|;':,./<>?\" ".split("");
function encrypt(message) {
message = message.split("");
var output = [];
message.forEach(element => {
if(chars.includes(element)) {
output.push("-c" + chars.indexOf(element));
}else if(numbs.includes(element)) {
output.push("-n" + numbs.indexOf(element));
}else if(symbols.includes(element)) {
output.push("-s" + symbols.indexOf(element));
}else{
console.log(element);
throw new Error(`Unknown character`);
};
});
return output.join("");
};
function decrypt(message) {
message = message.split("-");
console.log(message)
var output = [];
message.forEach(element => {
if(element.startsWith("c")) {
output.push(chars[element.substring(1)]);
}else if(element.startsWith("n")) {
output.push(numbs[element.substring(1)]);
}else if(element.startsWith("s")) {
output.push(symbols[element.substring(1)]);
}else if(element.length < 1){
}else{
throw new Error(`Invalid message`);
}
});
return output.join("");
};
console.log(decrypt(encrypt("Hello World!")));
You need to split the encoded string based on set/index pairs. This is easy enough to do with a look-ahead regular expression and splitting before a c, n or an s. /(?=[cns])/
const chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".split("");
const numbs = "0123456789".split("");
const symbols = "!##$%^&*()_+-=[]{}|;':,./<>?\" ".split("");
function encrypt(message) {
message = message.split("")
var output = []
message.forEach(element => {
if (chars.includes(element)) {
output.push("c" + chars.indexOf(element))
} else if (numbs.includes(element)) {
output.push("n" + numbs.indexOf(element))
} else if (symbols.includes(element)) {
output.push("s" + symbols.indexOf(element))
} else {
console.log(element)
throw new Error(`Unknown character`)
}
});
return output.join("")
}
function decrypt(message) {
message = message.split(/(?=[cns])/);
var output = [];
message.forEach(element => {
let set;
switch(element[0]){
case 'c':
set = chars;
break;
case 'n':
set = numbs;
break;
case 's':
set = symbols;
break;
}
const index = parseInt(element.substring(1));
output.push(set[index]);
});
return output.join('');
}
const encrypted = encrypt("Hello World!");
console.log(encrypted);
//expected to log Hello World! but logs H and when starting the message with a symbol or number it just logs nothing
console.log(decrypt(encrypted));

How to make a fully functional brainf*ck interpreter?

I have tried to implement a BF interpreter in Javascript. It works for many programs like printing Hello world, looping, etc.
Here is link to a sample interpreter that I use for comparing outputs: https://sange.fi/esoteric/brainfuck/impl/interp/i.html
But when I try to run a BF to C program, it gets stuck like it is in an infinite loop. It however does work in the sample interpreter above. What am I doing wrong?
Here is a BF code that converts an input BF code to C.
+++[>+++++<-]>>+<[>>++++>++>+++++>+++++>+>>+<++[++<]>---]
>++++.>>>.+++++.>------.<--.+++++++++.>+.+.<<<<---.[>]<<.<<<.-------.>++++.
<+++++.+.>-----.>+.<++++.>>++.>-----.
<<<-----.+++++.-------.<--.<<<.>>>.<<+.>------.-..--.+++.-----<++.<--[>+<-]
>>>>>--.--.<++++.>>-.<<<.>>>--.>.
<<<<-----.>----.++++++++.----<+.+++++++++>>--.+.++<<<<.[>]<.>>
,[>>+++[<+++++++>-]<[<[-[-<]]>>[>]<-]<[<+++++>-[<+++>-[<-->-[<+++>-
[<++++[>[->>]<[>>]<<-]>[<+++>-[<--->-[<++++>-[<+++[>[-[-[-[->>]]]]<[>>]<<-]
>[<+>-[<->-[<++>-[<[-]>-]]]]]]]]]]]]]
<[
-[-[>+<-]>]
<[<<<<.>+++.+.+++.-------.>---.++.<.>-.++<<<<.[>]>>>>>>>>>]
<[[<]>++.--[>]>>>>>>>>]
<[<<++..-->>>>>>]
<[<<..>>>>>]
<[<<..-.+>>>>]
<[<<++..---.+>>>]
<[<<<.>>.>>>>>]
<[<<<<-----.+++++>.----.+++.+>---.<<<-.[>]>]
<[<<<<.-----.>++++.<++.+++>----.>---.<<<.-[>]]
<[<<<<<----.>>.<<.+++++.>>>+.++>.>>]
<.>
]>
,]
<<<<<.<+.>++++.<----.>>---.<<<-.>>>+.>.>.[<]>++.[>]<.
Here is my implementation:
class Node {
constructor() {
this.value = 0;
this.next = null;
this.prev = null;
}
increment() {
this.value++;
}
decrement() {
this.value--;
}
}
class Memory {
constructor() {
this.current = new Node();
this.outputBuffer = [];
}
moveRight() {
if (this.current.next === null) {
const rightNode = new Node();
rightNode.prev = this.current
this.current.next = rightNode;
}
this.current = this.current.next;
}
moveLeft() {
if (this.current.prev === null) {
const leftNode = new Node()
leftNode.next = this.current;
this.current.prev = leftNode;
}
this.current = this.current.prev;
}
increment() {
this.current.increment();
}
decrement() {
this.current.decrement();
}
print() {
this.outputBuffer.push(String.fromCharCode(this.current.value));
}
input(ch) {
this.current.value = ch.charCodeAt(0);
}
}
class Interpreter {
reset() {
this.memory = new Memory();
this.instructionPointer = 0;
this.inputPointer = 0;
this.openingToClosingBrackets = new Map();
this.closingToOpeningBrackets = new Map();
}
interpret(code, input = "") {
this.reset();
this.code = code;
this.matchSquareBrackets();
this.input = input;
while (!this.reachedEOF()) {
const instruction = this.code[this.instructionPointer];
switch (instruction) {
case "+": this.memory.increment(); break;
case "-": this.memory.decrement(); break;
case ">": this.memory.moveRight(); break;
case "<": this.memory.moveLeft(); break;
case ".": this.memory.print(); break;
case ",": this.memory.input(this.getNextCharacter()); break;
case "[": this.loopStart(); break;
case "]": this.loopEnd(); break;
}
this.instructionPointer++;
}
return this.memory.outputBuffer.join("");
}
reachedEOF() {
return this.instructionPointer >= this.code.length;
}
getNextCharacter() {
if (this.inputPointer >= this.input.length) {
throw new Error("EOF. Expected more input characters.");
}
return this.input[this.inputPointer];
}
loopStart() {
if (this.memory.current.value !== 0) {
return;
}
this.instructionPointer = this.openingToClosingBrackets.get(
this.instructionPointer
);
}
loopEnd() {
if (this.memory.current.value === 0) {
return;
}
this.instructionPointer = this.closingToOpeningBrackets.get(
this.instructionPointer
);
}
matchSquareBrackets() {
const openingStack = [];
for (let i = 0; i < this.code.length; i++) {
const ch = this.code[i];
if (ch === "[") {
openingStack.push(i);
}
if (ch === "]") {
if (openingStack.length === 0) {
throw new Error("No matching '[' for ']' at index: " + i);
}
const openingMatch = openingStack.pop();
this.openingToClosingBrackets.set(openingMatch, i);
this.closingToOpeningBrackets.set(i, openingMatch);
}
}
if (openingStack.length > 0) {
throw new Error(
"No matching ']' for '[' at indices: " + openingStack.join(", ")
);
}
}
}
Your getNextCharacter doesn't work correctly: if there's at least one character of input, it will return that character each time it's called - it never increments the input index. Since the bf2c program keeps reading input until there is no more input, this causes your infinite loop.
Another problem with your code is that you throw an exception when , is used and there is no more input, causing the bf2c to abort with an exception when it reaches the end of the input. So you'll either need to explicitly terminate the input with a \0, so that the bf2c program knows when to stop reading or change getNextCharacter to return '\0' at the end of input instead of throwing an exception.

I cannot produce an error message with division when dividing by 0 (Javascript Calculator)

To preface this, I'm a beginner who's attempting to create a calculator in Javascript. I currently have a switch statement containing math operators. My issue is that in the switch statement, I want to include an error message (string) where division is concerned when trying to divide by 0; however, no matter what I do, I always get infinity up in the calculator's 'display.'
Any amount of help is greatly appreciated, even if it means me having to re-do this whole thing. Here is a snippet of the function(s) doing the actual calculation (though it is in a class, I will edit in the whole block of code if requested).
selectedOperation(operation) {
if (this.currentDisplay === '') return;
if (this.prevDisplay !== '') {
this.calculate();
}
this.operation = operation;
this.prevDisplay = this.currentDisplay;
this.currentDisplay = '';
}
calculate() {
let calculation;
const previousNum = parseFloat(this.prevDisplay);
const currentNum = parseFloat(this.currentDisplay);
if (isNaN(previousNum) || isNaN(currentNum)) return;
switch (this.operation) {
case '+' :
calculation = previousNum + currentNum
break;
case '-' :
calculation = previousNum - currentNum
break;
case 'x' :
calculation = previousNum * currentNum
break;
case '÷' :
calculation = previousNum / currentNum
if (currentNum === 0) return "error";
break;
default:
return;
}
this.currentDisplay = calculation;
this.operation = undefined;
this.prevDisplay = '';
}
**EDIT**:
getDisplayNumber(number) {
const stringNumber = number.toString();
const integerDigits = parseFloat(stringNumber.split('.')[0]);
const decimalDigits = stringNumber.split('.')[1];
let integerDisplay
if (isNaN(integerDigits)) {
integerDisplay = '';
} else {
integerDisplay = integerDigits.toLocaleString('en', {maximumFractionDigits: 0 });
}
if (decimalDigits != null) {
return `${integerDisplay}.${decimalDigits}`;
} return integerDisplay;
}
updateDisplay() {
this.cdisplay.innerText =
this.getDisplayNumber(this.currentDisplay);
if(this.operation != null) {
this.display.innerText =
`${this.prevDisplay} ${this.operation}`;
} else {
this.display.innerText = '';
}
}
Here is the updated solution. Check the explanation in the comments.
BTW the first argument passed to addEvenListener callback is an event, not the button itself but you can access the button using event.target.
class Calculator {
constructor(display, cdisplay) {
this.display = display;
this.cdisplay = cdisplay;
this.clear();
}
clear() {
this.currentDisplay = "";
this.prevDisplay = "";
// new property error
this.error = "";
this.operation = undefined;
}
del() {
this.currentDisplay = this.currentDisplay.toString().slice(0, -1);
}
appendNumber(number) {
// if an error exists and the user try to start a new operation
// clear everything
if (this.error) {
this.clear();
}
if (number === "." && this.currentDisplay.includes(".")) return;
this.currentDisplay = this.currentDisplay.toString() + number.toString();
}
selectedOperation(operation) {
if (this.currentDisplay === "") return;
if (this.prevDisplay !== "") {
this.calculate();
}
this.operation = operation;
this.prevDisplay = this.currentDisplay;
this.currentDisplay = "";
}
calculate() {
let calculation;
const previousNum = parseFloat(this.prevDisplay);
const currentNum = parseFloat(this.currentDisplay);
if (isNaN(previousNum) || isNaN(currentNum)) return;
switch (this.operation) {
case "+":
calculation = previousNum + currentNum;
break;
case "-":
calculation = previousNum - currentNum;
break;
case "x":
calculation = previousNum * currentNum;
break;
case "÷":
// if the user divide by 0 set this.error
if (currentNum === 0) this.error = "Can't divide by zero";
// else calculate normally
else calculation = previousNum / currentNum;
break;
default:
return;
}
this.currentDisplay = calculation;
this.operation = undefined;
this.prevDisplay = "";
}
getDisplayNumber(number) {
const stringNumber = number.toString();
const integerDigits = parseFloat(stringNumber.split(".")[0]);
const decimalDigits = stringNumber.split(".")[1];
let integerDisplay;
if (isNaN(integerDigits)) {
integerDisplay = "";
} else {
integerDisplay = integerDigits.toLocaleString("en", {
maximumFractionDigits: 0
});
}
if (decimalDigits != null) {
return `${integerDisplay}.${decimalDigits}`;
}
return integerDisplay;
}
updateDisplay() {
// if there is an error display the error and return
if (this.error) {
this.display.innerText = this.error;
return;
}
this.cdisplay.innerText = this.getDisplayNumber(this.currentDisplay);
if (this.operation != null) {
this.display.innerText = `${this.prevDisplay} ${this.operation}`;
} else {
this.display.innerText = "";
}
}
}
const cdisplay = document.querySelector("#cdisplay");
const display = document.querySelector("#display");
const numberButtons = document.querySelectorAll(".numbers");
const operationButtons = document.querySelectorAll(".operation");
const equalsButton = document.querySelector("#equals");
const delButton = document.querySelector("#del");
const clearButton = document.querySelector("#clear");
const negButton = document.querySelector("#neg");
const calculator = new Calculator(display, cdisplay);
numberButtons.forEach(button => {
button.addEventListener("click", () => {
calculator.appendNumber(button.innerText);
calculator.updateDisplay();
});
});
operationButtons.forEach(button => {
button.addEventListener("click", () => {
calculator.selectedOperation(button.innerText);
calculator.updateDisplay();
});
});
// this agrument passed to the callback function is an event not button
equalsButton.addEventListener("click", event => {
calculator.calculate();
calculator.updateDisplay();
});
// this agrument passed to the callback function is an event not button
clearButton.addEventListener("click", event => {
calculator.clear();
calculator.updateDisplay();
});
// this agrument passed to the callback function is an event not button
delButton.addEventListener("click", event => {
calculator.del();
calculator.updateDisplay();
});

Initializing a functions in javascript

I have created a function that creates some ammount of random cards, but my Init function returns undefined when I call it like init(1). Why doesn't it work? It should be like:
1. I'm calling a function for example init(1)
2. Init creates and shuffles cards and appends them to the body
// INIT
{
function init(difficulty) {
switch (difficulty) {
case 1:
createCards(4);
break;
case 2:
createCards(12);
break;
case 0:
createCards(24);
}
}
//FLIP CARD
function createCards(ammount) {
const gameCards = []
for (let i = 0; i < ammount; i++) {
const gameCard = document.createElement("div");
gameCard.className = "card card--click";
const gameCardFront = document.createElement("div");
const gameCardBack = document.createElement("div");
gameCard.appendChild(gameCardFront);
gameCard.appendChild(gameCardBack);
gameCardFront.className = "card__front card--reversed";
gameCardBack.className = "card__back";
const img = new Image();
function randImg() {
const uniqueSrc = {}
const imgArray = ["ball", "car", "fork", "spoon", "sun"];
const gameArray = [];
for (let i = 0; i < ammount * 2 + 1; i++) {
const randomSrc = Math.floor(Math.random() * (imgArray.length));
if (!uniqueSrc[randomSrc]) {
uniqueSrc[randomSrc] = randomSrc;
img.src = "img/" + imgArray[randomSrc] + ".png";
img.alt = imgArray[randomSrc];
gameArray.push(img);
} else {
i--;
}
}
return gameArray;
}
randImg();
gameCardBack.appendChild(img);
gameCards.push(gameCard)
}
return gameCards;
}
const cards = document.querySelectorAll(".card.card--click");
//FETCHING ALL CARDS
for (let i = 0; i < cards.length; i++) {
const card = cards[i];
//ADDING FLIP EFFECT TO EACH CARD
flipCard(card);
};
//FLIP EFFECT FUNCTION
function flipCard(card) {
card.addEventListener("click", function() {
const list = this.classList;
list.contains("card--flip") === true ? list.remove("card--flip") : list.add("card--flip");
});
};
function randomizer(array) {
for (let i = 0; i < array.length; i++) {
const j = Math.floor(Math.random() * (i + 1));
const tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
return array;
}
}
1) The thing is that youre not appending your cards to body. So you may want to return the cards in the init function:
function init(difficulty) {
switch (difficulty) {
case 1:
return createCards(4);
break;
case 2:
return createCards(12);
break;
case 0:
return createCards(24);
}
}
Then you can append the Array returned by init to body:
init(0).forEach(function(card){
document.body.appendChild(card);
});
2)Also this:
randImg();
doesnt make sense as randImg returns an array, you may wanna catch it:
arr=randImg();
3) Also the randImg will not work, you need to put the
const img=new Image();
into the loop.
4) And
const cards = document.querySelectorAll(".card.card--click");
Will be an empty collection unless you run the snippet above before...

Categories