Acces Array of object and accesing or checking ut - javascript

So i tried to make the program that formattting the input to be array and object, but i struggle to acces, check, and add an object to an array, here's the code, input and output
The program will ask for input from the user, the request will be formatted as:
{
name : (inputName),
location : (inputlocation),
request : [
{(productName ) : (totalRequest)}
e.g : {meatball : 1},
],
}
The program will check whether the same item has been previously ordered by the same user
If it is, then the totalRequest of the same item will be increased, if not, an object will be created with the format {productName : totalRequest }
let user = {
name : readLine.question("Name : "),
location : readLine.question('Location : '),
request : []
}
while(true){
var product = readLine.question('input your request : ').toLowerCase();
var total = readLine.question("total request : ");
var requestProduct = {}
//this is the part of the problem, the data is checked in here
for(let i of user.request){
for(let j in i){
if(j == product){
i[product] += total;
} else {
requestProduct[product] = total;
user.request.push(requestProduct);
}
}
}
var isEnough = readLine.question('Enough ?(yes/no)');
if(isEnough == 'yes'){
console.log(user);
break;
} else {
continue;
}
}
/**
* expected output :
* {
* name : Budi,
* Location : Supeno Street, number 150,
* request : [
* {meatball : 12},
* {"ice tea" : 12},
* ]
* }
* output on reality:
* {
* name : Budi,
* Location : Supeno Street, number 150,
* request : []
* }
* */
i've commented the problem part on the code review, i hope someone can help me solve the problem

You shouldn't loop through the object. Use Object.keys() to get the key of the object. Then you can check if this key matches what the user entered.
let found = false;
for (let i of user.request) {
let key = Object.keys(i)[0];
if (key == product) {
found = true;
i[key] += total;
break;
}
}
if (!found) {
user.request.push({[product]: total});
}

Related

When run the code on trigger change I get an error "Auto Move Rows Cannot read property 'getLastRow' of undefined Code line: 559" [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I have an issue with trying to run a script named 'moveRowsFromSpreadsheetToSpreadsheet_ version 2.7' the script will run perfect when he on_edit trigger is installed however when I try to run the script using the on_change trigger it returns an error the sheet "Auto Move Rows Cannot read property 'getlastRow' of undefined code line:267.
Any suggestions will be greatly appreciated on how to get the script to run on_change trigger.
Thanks in advance
/**
* Global variables.
*/
try {
////////////////////////////////
// [START modifiable parameters]
var sheetsToWatch = ['QUOTATIONS'];
var columnsToWatch = ['STATUS', 'STATUS'];
var valuesToWatch = [/^(CONFIRMED)$/i, /^(PENDING)$/i];
var targetSheets = ['DELIVERIES', 'PENDING'];
var targetSpreadheets = ['165PYmS-NkEqM7kSBhZ7EjMF4CIhxvdaIQJB6meJd-DE',
'165PYmS-NkEqM7kSBhZ7EjMF4CIhxvdaIQJB6meJd-DE'];
var targetIdColumn = [];
var targetValues = [];
var transferTypes = ['PASTE_NORMAL'];
var allowArrayFormulas = [true, true];
var copyInsteadOfMove = [true, true];
var numColumnsToMove = [];
var changeColumnOrderTo = [];
var sheetsToSort = ['Target'];
var columnToSortBy = [3];
var sortAscending = [true];
// [END modifiable parameters]
////////////////////////////////
} catch (error) {
showAndThrow_(error);
}
/**
* Moves rows from sheet to sheet, and sorts the source and target sheets after the move.
*
* #param {Object} e The onEdit event object.
*/
function moveRowsAndSortSheet_(e) {
// version 1.1, written by --Hyde, 27 June 2020
// - use LockService
// - sort all targetSheets instead of sorting just one targetSheet
// version 1.0, written by --Hyde, 9 January 2020
// - initial version
try {
var lock = LockService.getDocumentLock();
lock.waitLock(30 * 1000);
var modifiedSheets = moveRowsFromSpreadsheetToSpreadsheet_(e);
if (modifiedSheets) {
[modifiedSheets.sourceSheet].concat(modifiedSheets.targetSheets).forEach(function (sheet) {
sortSheet_(sheet);
});
}
} catch (error) {
showAndThrow_(error);
} finally {
lock.releaseLock();
}
}
/**
* Moves a row from a spreadsheet to another spreadsheet file when a magic value is entered in a column.
*
* The name of the sheet to move the row to is derived from the position of the magic value on the valuesToWatch list.
* The targetSpreadheets list uses spreadsheet IDs that can be obtained from the address bar of the browser.
* Use a spreadsheet ID of '' to indicate that the row is to be moved to another tab in the same spreadsheet file.
*
* Globals: see the Global variables section.
* Displays pop-up messages through Spreadsheet.toast().
* Throws errors.
*
* #param {Object} e The 'on edit', 'on form submit' or 'on change' event object.
* #return {Object} An object that lists the sheets that were modified with this structure, or a falsy value if no rows were moved:
* {Sheet} sourceSheet The sheet from where a row was moved.
* {Sheet[]} targetSheets The sheets to where rows were moved.
* {Number} numRowsMoved The number of rows that were moved to another sheet.
*/
function moveRowsFromSpreadsheetToSpreadsheet_(e) {
var event = getEventObject_(e);
if (!event || sheetsToWatch.indexOf(event.sheetName) === -1) {
return;
}
if (targetIdColumn.length) {
var targetIdColumnNumber = event.columnLabels.indexOf(targetIdColumn[0]) + 1;
if (!targetIdColumnNumber || !targetValues.length) {
throw new Error('Could not find target values in target column "' + String(targetIdColumn[0]) + '".');
}
var valuesInTargetIdColumn = event.sheet.getRange(event.rowStart, targetIdColumnNumber, event.numRows, 1).getDisplayValues();
}
var numRowsMoved = 0;
var messageOnDisplay = false;
var sourceSheetNames = [];
var targetSheetNames = [];
var targets = [];
for (var row = event.numRows - 1; row >= 0; row--) {
for (var column = 0; column < event.numColumns; column++) {
if (event.rowStart + row <= event.columnLabelRow || columnsToWatch.indexOf(event.columnLabels[event.columnStart - 1 + column]) === -1) {
continue;
}
var valuesToWatchIndex = -1;
for (var i = 0, numRegexes = valuesToWatch.length; i < numRegexes; i++) {
if (event.displayValues[row][column].match(valuesToWatch[i])) {
valuesToWatchIndex = i;
break;
}
}
if (valuesToWatchIndex === -1) {
continue;
}
var targetIndex = -1;
if (targetIdColumn.length) {
for (var i = 0, numRegexes = targetValues.length; i < numRegexes; i++) {
if (valuesInTargetIdColumn[row][0].match(targetValues[i])) {
targetIndex = i;
break;
}
}
} else {
targetIndex = valuesToWatchIndex;
}
if (targetIndex === -1) {
continue;
}
if (!messageOnDisplay) {
showMessage_('Moving rows...', 30);
messageOnDisplay = true;
}
var targetSheet = getTargetSheet_(event, targetIndex);
if (!targetSheet) {
continue; // skip moving the row if it would end up on the same sheet
}
var sourceRange = event.sheet.getRange(event.rowStart + row, 1, 1, event.numSheetColumns);
var transferType = transferTypes[targetIndex];
var firstFreeTargetRow = targetSheet.getLastRow() + 1;
if (firstFreeTargetRow > targetSheet.getMaxRows()) {
targetSheet.insertRowAfter(targetSheet.getLastRow());
}
var targetRange = targetSheet.getRange(firstFreeTargetRow, 1);
switch (transferType) {
case 'PASTE_VALUES':
case undefined:
var rowValues = rearrangeRowValues_(sourceRange, targetIndex);
targetSheet.appendRow(rowValues);
break;
case 'PASTE_FORMAT':
// #see https://developers.google.com/apps-script/reference/spreadsheet/copy-paste-type
sourceRange.copyTo(targetRange, SpreadsheetApp.CopyPasteType[transferType], false);
sourceRange.copyTo(targetRange, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
break;
case 'PASTE_FORMULA':
case 'PASTE_NORMAL':
case 'PASTE_NO_BORDERS':
sourceRange.copyTo(targetRange, SpreadsheetApp.CopyPasteType[transferType], false);
break;
default:
throw new Error('Unknown transferType "' + transferType + '".');
}
// clear cells in targetRange where column label row contains an array formula
if (allowArrayFormulas[targetIndex]) {
var numColumns = sourceRange.getWidth();
var formulas = targetSheet.getRange(targetSheet.getFrozenRows() || 1, 1, 1, numColumns).getFormulas()[0];
formulas.forEach(function (formula, index) {
if (formula.match(/^=.*arrayformula/i)) {
targetRange.offset(0, index, 1, 1).clearContent();
}
});
}
numRowsMoved += 1;
if (!copyInsteadOfMove[targetIndex]) {
if (event.sheet.getMaxRows() <= event.columnLabelRow + 1) { // avoid deleting the last unfrozen row
event.sheet.appendRow([null]);
}
event.sheet.deleteRow(event.rowStart + row);
}
sourceSheetNames = sourceSheetNames.concat(event.sheetName).filter(filterUniques_);
targetSheetNames = targetSheetNames.concat(targetSheet.getName()).filter(filterUniques_);
targets = targets.concat(targetSheet).filter(filterUniques_);
} // column
} // row
if (messageOnDisplay) {
var message = 'Moved ' + numRowsMoved + (numRowsMoved === 1 ? ' row ' : ' rows ') + "from '" + sourceSheetNames.join(', ') + "' to '" + targetSheetNames.join(', ') + "'.";
showMessage_('Moving rows... done. ' + message);
}
return numRowsMoved ? { sourceSheet: event.sheet, targetSheets: targets, numRowsMoved: numRowsMoved } : null;
}
/**
* Sorts a sheet.
*
* Globals: sheetsToSort, columnToSortBy, sortAscending.
*
* #param {Sheet} sheet The sheet to sort.
*/
function sortSheet_(sheet) {
// version 1.0, written by --Hyde, 19 March 2020
// - initial version
var sheetIndex = sheetsToSort.indexOf(sheet.getName());
if (sheetIndex === -1) {
return;
}
sheet.sort(columnToSortBy[sheetIndex], sortAscending[sheetIndex]);
}
/**
* Determines the type of a spreadsheet event and populates an event object.
*
* Globals: valuesToWatch.
*
* [NOTE] Could add these fields: value, oldValue, values.
*
* #param {Object} e The original event object.
* #return {Object} An event object with the following fields, or null if the event type is unknown.
* {Spreadsheet} spreadsheet The spreadsheet that was edited.
* {Sheet} sheet The sheet that was edited in spreadsheet.
* {Range} range The cell or range that was edited in sheet.
* {String} sheetName The name of the sheet that was edited.
* {Number} rowStart The ordinal number of the first row in range.
* {Number} rowEnd The ordinal number of the last row in range.
* {Number} columnStart The ordinal number of the first column in range.
* {Number} columnEnd The ordinal number of the last column in range.
* {Number} numRows The number of rows in range.
* {Number} numColumns The number of columns in range.
* {String} changeType Always EDIT, and never INSERT_ROW, INSERT_COLUMN, REMOVE_ROW, REMOVE_COLUMN, INSERT_GRID, REMOVE_GRID, FORMAT, or OTHER.
* {String} authMode One of ScriptApp.AuthMode.NONE, .LIMITED, .FULL or .CUSTOM_FUNCTION.
* {String[][]} displayValues The values in range as shown in the spreadsheet as text strings.
* {Number} numSheetColumns The number of columns in sheet.
* {Number} columnLabelRow The 1-based row number where column labels are found.
* {String[]} columnLabels The values in row event.columnLabelRow as shown in the spreadsheet as text strings.
*/
function getEventObject_(e) {
// version 1.1, written by --Hyde, 29 July 2020
// - use Number()
// version 1.0, written by --Hyde, 27 July 2020
// - initial version
if (!e || !valueIsPlainObject_(e)) {
return null;
}
var event = {};
if (e.range && JSON.stringify(e.range) !== '{}') { // triggered by ScriptApp.EventType.ON_EDIT or .ON_FORM_SUBMIT
if (e.value === '') { // optimization for single-cell edits
return null;
}
if (e.value !== undefined) { // optimization for single-cell edits
var valuesToWatchIndex = -1;
for (var i = 0, numRegexes = valuesToWatch.length; i < numRegexes; i++) {
if (e.value.match(valuesToWatch[i])) {
valuesToWatchIndex = i;
break;
}
}
if (valuesToWatchIndex === -1) {
return null;
}
}
event.range = e.range;
event.rowStart = Number(e.range.rowStart);
event.rowEnd = Number(e.range.rowEnd);
event.columnStart = Number(e.range.columnStart);
event.columnEnd = Number(e.range.columnEnd);
event.changeType = 'EDIT';
event.eventType = e.namedValues ? 'ON_FORM_SUBMIT' : 'ON_EDIT';'ON_CHANGE';
} else if (e.changeType === 'EDIT') { // triggered by ScriptApp.EventType.ON_CHANGE
var ss = SpreadsheetApp.getActive();
event.range = ss.getActiveRange();
event.rowStart = event.range.getRow();
event.rowEnd = e.range.getLastRow(1);
event.columnStart = event.range.getColumn();
event.columnEnd = e.range.getLastRow();
event.changeType = e.changeType;
event.eventType = 'ON_CHANGE';
} else { // triggered by some other change type
return null;
}
event.authMode = e.authMode; //
event.displayValues = event.range.getDisplayValues();
event.sheet = event.range.getSheet();
event.sheetName = event.sheet.getName();
event.spreadsheet = event.sheet.getParent();
event.numRows = event.rowEnd - event.rowStart + 1;
event.numColumns = event.columnEnd - event.columnStart + 1;
event.columnLabelRow = event.sheet.getFrozenRows() || 1;
event.numSheetColumns = event.sheet.getLastColumn();
event.columnLabels = event.sheet.getRange(event.columnLabelRow, 1, 1, event.numSheetColumns).getDisplayValues()[0];
return event;
}
function valueIsPlainObject_(value) {
// version 1.0, written by --Hyde, 26 June 2020
// - initial version
var type = typeof value;
if (type === 'function' || Array.isArray(value)) {
return false;
}
return type === 'object' && !!value;
}
function filterUniques_(element, index, array) {
// version 1.0, written by --Hyde, 30 May 2019
// - initial version
return array.indexOf(element) === index;
}
function rearrangeRowValues_(range, targetIndex) {
// version 1.0, written by --Hyde, 27 June 2020
// - initial version, based on inline code in moveRowsFromSpreadsheetToSpreadsheet_
var rowValuesInOriginalOrder = range.getValues()[0];
if (numColumnsToMove[targetIndex] !== undefined) {
var rowValues = rowValuesInOriginalOrder.slice(0, numColumnsToMove[targetIndex]);
} else {
rowValues = rowValuesInOriginalOrder.slice();
}
for (var changeIndex = 0; changeIndex < changeColumnOrderTo.length; changeIndex++) {
if (changeColumnOrderTo[changeIndex] !== undefined) {
rowValues[changeIndex] = rowValuesInOriginalOrder[changeColumnOrderTo[changeIndex]];
} else if (rowValues[changeIndex] === undefined) {
rowValues[changeIndex] = null;
}
}
return rowValues;
}
function getTargetSheet_(event, targetIndex) {
// version 1.0, written by --Hyde, 27 June 2020
// - initial version, based on inline code in moveRowsFromSpreadsheetToSpreadsheet_
var targetSheetName = targetSheets[targetIndex];
var targetSpreadsheetId = String(targetSpreadheets[targetIndex] || '');
if (targetSpreadsheetId) {
try {
var targetSpreadsheet = SpreadsheetApp.openById(targetSpreadsheetId);
} catch (error) {
var ssIdShortened
= targetSpreadsheetId.length > 13
? targetSpreadsheetId.slice(0, 5) + '...' + targetSpreadsheetId.slice(-5)
: targetSpreadsheetId;
throw new Error('Could not open a target spreadsheet with ID "' + ssIdShortened + '".');
}
} else {
targetSpreadsheet = event.spreadsheet;
if (targetSheetName === event.sheetName) {
return null; // skip moving the row if it would end up in the same sheet
}
}
var targetSheet = targetSpreadsheet.getSheetByName(targetSheetName);
if (!targetSheet) {
throw new Error("Could not find the target sheet '" + targetSheetName + "'"
+ targetSpreadsheet === event.spreadsheet
? '.'
: ' in spreadsheet "' + targetSpreadsheet.getName() + '".');
}
return targetSheet;
}
/**
* Installs a trigger that runs each time the user hand edits the spreadsheet.
* Deletes any previous instances of ON_EDIT and ON_CHANGE triggers.
*
* To permanently install the trigger, choose Run > Run function > installOnEditTrigger.
* You only need to install the trigger once per spreadsheet.
* To review the installed triggers, choose Edit > Current project's triggers.
*/
function installOnEditTrigger() {
// version 1.0, written by --Hyde, 7 May 2020
// - initial version
deleteTriggers_(ScriptApp.EventType.ON_EDIT);
deleteTriggers_(ScriptApp.EventType.ON_CHANGE);
ScriptApp.newTrigger('moveRowsAndSortSheet_')
.forSpreadsheet(SpreadsheetApp.getActive())
.onEdit()
.create();
}
/**
* Installs a trigger that runs each time a change is done by Glide, IFTTT, Zapier or other such tools.
* Deletes any previous instances of ON_EDIT and ON_CHANGE triggers.
* [NOTE] This trigger will also move rows when you hand edit the spreadsheet.
* [NOTE] Tested with Glide, but untested with IFTTT, Zapier.
*
* To permanently install the trigger, choose Run > Run function > installOnChangeTrigger.
* You only need to install the trigger once per spreadsheet.
* To review the installed triggers, choose Edit > Current project's triggers.
*/
function installOnChangeTrigger() {
// version 1.0, written by --Hyde, 7 May 2020
// - initial version
deleteTriggers_(ScriptApp.EventType.ON_EDIT);
deleteTriggers_(ScriptApp.EventType.ON_CHANGE);
ScriptApp.newTrigger('moveRowsAndSortSheet_')
.forSpreadsheet(SpreadsheetApp.getActive())
.onChange()
.create();
}
/**
* Deletes all installable triggers of the type triggerType associated with the current
* script project that are owned by the current user in the current spreadsheet.
*
* #param {EventType} triggerType One of ScriptApp.EventType.ON_EDIT, .ON_FORM_SUBMIT, .ON_OPEN, .ON_CHANGE, .CLOCK (time-driven triggers) or .ON_EVENT_UPDATED (Calendar events).
*/
function deleteTriggers_(triggerType) {
// version 1.1, written by --Hyde, 27 June 2020
// - use getUserTriggers(ss) instead of getProjectTriggers()
// version 1.0, written by --Hyde, 7 May 2020
// - initial version
var triggers = ScriptApp.getUserTriggers(SpreadsheetApp.getActive());
for (var i = 0, numTriggers = triggers.length; i < numTriggers; i++) {
if (triggers[i].getEventType() === triggerType) {
ScriptApp.deleteTrigger(triggers[i]);
}
}
}
/**
* Shows error.message in a pop-up and throws the error.
*
* #param {Error} error The error to show and throw.
*/
function showAndThrow_(error) {
// version 1.0, written by --Hyde, 16 April 2020
// - initial version
var stackCodeLines = String(error.stack).match(/\d+:/);
if (stackCodeLines) {
var codeLine = stackCodeLines.join(', ').slice(0, -1);
} else {
codeLine = error.stack;
}
showMessage_(error.message + ' Code line: ' + codeLine, 30);
throw error;
}
/**
* Shows a message in a pop-up.
*
* #param {String} message The message to show.
* #param {Number} timeoutSeconds Optional. The number of seconds before the message goes away. Defaults to 5.
*/
function showMessage_(message, timeoutSeconds) {
// version 1.0, written by --Hyde, 16 April 2020
// - initial version
SpreadsheetApp.getActive().toast(message, 'Auto Move Rows', timeoutSeconds || 5);
}
event.rowEnd = e.range.getLastRow(1); event.columnStart = event.range.getColumn(); event.columnEnd = e.range.getLastRow();
There is no range listed here for an onChange Event.
Also the first getLastRow() has a parameter which is wrong.

localstorage variable only writes 0 to index.html

Hi when I run this block of code, the result of "clickamt" is 0 and it does not increment:
switch (isNaN(incremental) || isNaN(clickamt) || isnull(incremental) || isnull(clickamt) || isnull(curfloat) || isNaN(curfloat)) {
case true:
storage.setItem("clickamt", "0");
clickamt = (parseFloat(storage.getItem("clickamt")).toFixed(1));
storage.setItem("incremental", "1");
incremental = (parseInt(storage.getItem("incremental")));
storage.setItem("curfloat", "0");
curfloat = (parseFloat(storage.getItem("curfloat")).toFixed(1));
break;
case false:
if (clickamt % 1000 === curfloat) {
curfloat = (moneylevels()).toFixed(1);
}
clickamt = ((clickamt + incremental) + curfloat).toFixed(1);
incremental++;
storage.setItem("clickamt", (clickamt));
storage.setItem("incremental", (incremental).toString());
storage.setItem("curfloat", (curfloat).toString());
break;
}
The innerHTML of "clickamt" writes 0 and only 0 to "index.html".
I want "clickamt" of type float to increment by using incremental of type int plus curfloat which is of type float. "curfloat" is incremented by 0.1 per 1000 of "clickamt".
I don't think it's a parsing issue or anything of the sort. When I recoded it once it would just append the float it would increment by to the end of clickamt. This made me think there may be a parsing issue somewhere.
Some outputs I've seen are (0, 0.101011,00.010101,1,11,1111111,1111111111,etc.)
You can check on page load if the value for necessary key exists in localStorage. If the value is missing, then compute and save the new value. You can also have an extra event on which you can override the value of this key, but this will be a user action.
function computeRandomValue() {
var data = ["test", "test1", "test2", "test3", "test4"];
var index = Math.floor(Math.random() * 10) % data.length;
return data[index];
}
function setToLocalStorage(newVal) {
var lsKey = "_lsTest";
localStorage.setItem(lsKey, newVal);
}
function getFromLocalStorage() {
var lsKey = "_lsTest";
return localStorage.getItem(lsKey);
}
function initializePage() {
var _val = getFromLocalStorage();
if (!(_val && _val.trim().length > 0)) {
_val = computeAndSaveNewValue();
}
printValue(_val, "lblResult");
}
function computeAndSaveNewValue() {
var newVal = computeRandomValue();
setToLocalStorage(newVal);
printValue(newVal);
return newVal;
}
function printValue(value) {
var id = "lblResult";
document.getElementById(id).innerHTML = value;
}
(function() {
window.onload = initializePage;
})()

Translate aggregation operation in MongoDB to MapReduce

I've been trying to translate this query into MapReduce for a few days. Specifically, I need to figure out how many different cars have driven "N" kilometers.
Query:
db.adsb.group({
"key": {
"KM": true
},
"initial": {
"countCar": 0
},
"reduce": function(obj, prev) {
if (obj.Matricula != null) if (obj.Matricula instanceof Array) prev.countCar += obj.Matricula.length;
else prev.countCar++;
},
"cond": {
"KM": {
"$gt": 10000,
"$lt": 45000
}
}
});
Each document in Mongo has this form:
{
"_id" : ObjectId("5a8843e7d79a740f272ccc0a"),
"KM" : 45782,
"Matricula" : "3687KTS",
}
I'm trying to get something like:
/* 0 */
{
“KM” : 45000,
“total” : 634
}
/* 1 */
{
“KM” : 46000,
“total” : 784
}
My code is below, and it compiles but does not give me the expected results.
In particular, every time I enter 'reduce' it seems to reset all the values to 0, which prevents me from accumulating the registrations.
One of my problems is that when handling large amounts of information, the function must iterate several times ' reduce'.
I also don't know if it could be done that way, or I would need to return a list of car plates and their counter together in 'reduce'; and then in finalize add it all up.
// Map function
var m = function() {
if (this.KM > 10000 && this.KM < 45000) { // So that i can get KM grouped together by thousands (10000, 20000, 30000...)
var fl = Math.round(this.KM / 1000) * 1000;
var car = this.Matricula
emit (fl, car);
//print("map KM=" + fl + " Matricula= " + car);
}
};
// Reduce function
var r = function(key, values) {
var ya_incluido = false;
var cars_totales = 0;
var lista_car = new Array();
//print( key + " ---- " + values);
for (var i=0; i < values.length;i++)
{
for (var j=0; j < lista_car.length;j++)
{
if(values[i] == lista_car[j]) { //If it is already included, don't aggregate it
ya_incluido = true;
}
} if (ya_incluido != true) { //If it is not included, add it to lista_av list.
lista_car.push(values[i]);
} ya_incluido = false;
}
cars_totales = lista_av.length; //The number of distinct cars is equal to the lenght of the list we created
return cars_totales;
};
// Finalize function
var f = function(key,value) {
// Sum up the results?
}
db.runCommand( {
mapReduce: "dealer",
map: m,
reduce: r,
finalize: f,
out: {replace : "result"}
} );
I found the answer and a really good explanation here: https://stackoverflow.com/a/27532153/13474284
I found the answer and a really good explanation here: https://stackoverflow.com/a/27532153/13474284
I couldn't find a way to return in 'reduce' the same thing that came from ' map' . And since it was run several times, it only got the results of the last iteration. The way it appears in the link, the problem is solved without any difficulty.

Discord RPG Bot display ids for each player in array

I'm trying to learn javascript and how to use the developer api provided by discord.
I do believe everything I want so far is working except I wanted to create a system like how a database works. Where each player in the table has a unique id key. I'm not sure if this is possible without using a db.
[Index.js]
/* Discord API Information */
const Discord = require('discord.js');
const token = '';
const Game = require('./game.js');
const client = new Discord.Client();
let playersName = []; // tracks each player that joins
let currPlayers = 0; //tracker for total players online
let INIT_GAME;
let userJoined = false;
let inBattle = false;
client.on('message', (msg) => {
if(msg.content === '!join'){
// Prevents multiple instances of the same person from joining
for(var x = 0; x < playersName.length; x++){
if(playersName[x]===msg.author.username){
return playersName[x];
}
}
currPlayers++;
userJoined = true;
playersName.push(msg.author.username);
//My attempt at having the question im asking
function convertToID(arr, width) {
return arr.reduce(function (rows, key, index) {
return (index % width == 0 ? rows.push([key])
: rows[rows.length-1].push(key)) && rows;
}, []);
}
console.log(convertToID(playersName,1)); /* Tracks players by ID in developer tools */
INIT_GAME = new Game(playersName, client, 'bot-testing', currPlayers);
let myRet = INIT_GAME.startGame();
const embed = new Discord.RichEmbed()
.setTitle("Welcome To Era Online")
.setColor(0xFF0000)
.addField(`${msg.author.username} has Joined`, myRet);
msg.channel.send(embed);
msg.channel.send(`${msg.author} has joined the game.`);
return;
}
if(userJoined == true){
if(msg.content === '!fight' && (!inBattle)){
let grabCurrPlayer = msg.author.username;
msg.channel.send(`${INIT_GAME.initBattle(grabCurrPlayer)}`);
}
else if(msg.content === '!leave'){
let tempLeave = msg.author.username;
for(var y = 0; y < playersName.length; y++){
if(playersName[y] == msg.author.username){
playersName[y] = [`${playersName[y]} was previously ID: ` + [y]];
currPlayers--;
}
}
msg.channel.send([`${tempLeave} has left the server.`]);
userJoined = false;
}
else if(msg.content === '!newgame'){
msg.channel.send(INIT_GAME.newGame());
}
/* Simply checks the bonus damage. command for developer*/
else if(msg.content === '!bonus'){
msg.channel.send(INIT_GAME.bonusAttack());
}
}
/* checks whose currently online. command for developer*/
if(msg.content === '!online'){
msg.channel.send(INIT_GAME.getOnline());
}
});
client.on('ready', () => {
console.log('Bot is now connected');
});
client.login(token);
[game.js]
class Game {
constructor(player, client, channelName='bot-testing', playersOnline){
this.client = client;
this.channelName = channelName;
this.currentPlayer = player;
this.playersOnline = [];
this.hitpoints = 120;
this.damage = '';
this.chance = 3;
this.inBattle = false;
this.online = playersOnline;
this.monster = [{
hp: Math.floor(Math.random() * 200),
temphp: 0,
damage: 10
}];
};
/* main menu information, players online */
startGame(){
for(var x = 0; x < this.currentPlayer.length; x++){
this.playersOnline.push(this.currentPlayer[x]);
if(this.playersOnline[x] === this.currentPlayer[x]){
return [`Players Online: ${this.online}\n`];
}
}
}
/* Battle system */
initBattle(currPlayer){
this.inBattle = true;
let npcHP = this.monster[0].hp;
let numberOfAttacks = 0;
let totalDamage=0, totalBonusDamage=0;
while( this.monster[0].hp > 0 ){
let playerDamage = Math.floor(Math.random() * (npcHP / 4));
if(this.bonusAttack() === 2){
console.log(`Bonus Attack: ${this.bonusAttack()}`);
console.log(`Regular damage without bonus attack: ${playerDamage}`);
playerDamage = playerDamage + 2;
}
this.monster[0].hp -= playerDamage;
this.hitpoints -= this.monster[0].damage;
console.log('Monster: ' + this.monster[0].hp);
console.log('Player: ' + this.hitpoints);
console.log(`${currPlayer} has attacked for ${playerDamage}`);
console.log(`NPC health: ${this.monster[0].hp}`);
if(this.hitpoints <= 0){
return [`You lost the battle.`];
}
this.inBattle = false;
numberOfAttacks++;
totalDamage += playerDamage;
totalBonusDamage = playerDamage + this.bonusAttack();
}
if(this.monster[0].hp <= 0 && this.inBattle !== true){
let maxDamage = totalDamage + totalBonusDamage;
return [`${currPlayer} has attacked ${numberOfAttacks} times dealing ${totalDamage} + (${totalBonusDamage}) bonus damage for a total of ${maxDamage} damage. The monster is dead.\n
Your Health: ${this.hitpoints}`];
}
else{
this.newGame();
return [`You rejuvenated your hitpoints and are ready for battle. \nType !fight again to start a new battle!`];
}
}
/* bonus attack damage [ 1 in 3 chance ] */
bonusAttack(bonusDamage){
let chance = Math.floor(Math.random() * 3);
return chance === 2 ? bonusDamage = 2 : false;
}
/* displays players currently online */
getOnline(){
console.log(this.currentPlayer);
return this.currentPlayer;
}
/* refresh stats */
newGame(){
this.monster[0].hp = Math.floor(Math.random() * 50);
this.hitpoints = 150;
}
}
module.exports = Game;
[My Question]
The only real important part within those 2 files is in index.js at the line that speaks about when a player leaves. So !leave.
I had a problem where one player typed !leave, both people would leave. That is the solution I used to fix it.
I could not get it to empty the array for ONLY the person who typed the command.
Example:
Person A types !join
Players online = [PlayerA]
Person B types !join
Players online = [PlayerA, PlayerB]
Player A types !leave
Players online = [[], PlayerB]]
It would always insert a empty array in the spot. So what I did was just fill that spot with the users previous name and their array id.
What I want is so that it completely deletes the person from the array AND removes that empty spot.
I would also like to know if it's possible that every time someone types !join, I would be able to insert them into an new array that is multidimensional and has the id for each player so that when I type !online, it would display
[[0, PlayerA], [1, PlayerB]] . Like a database where I can always see their index if needed.
What I have so far:
https://i.imgur.com/lWrtEtB.png
It only tracks the last index after they leave. How do I make it display the current index of the players online?
Use findIndex() to find the position of the name in your array. Then use the splice() method to remove a value from your array. You don't need to use that for loop, as findIndex will run a similar loop.
var playerIndex = playersName.findIndex(function(index) {
return index === tempLeave
})
playersName.splice(playerIndex, 1)
After reading the second part of your question though, I think you should be creating objects inside of your array. An example would be:
[
{
playerName: "Foo",
id: indexNumber,
isOnline: true
},
{
playerName: "Bar",
id: indexNumber,
isOnline: true
}
]
When someone joins, you check if their name is already assigned to an object (you can use findIndex again here). If not you create a new player, else you will change the players isOnline attribute to true. I'm sure this is the best way to go about storing user info, but it might work for you.

How to use random string as JSON object name

I am trying to create a JSON object, with a random string as the name, just like how Firebase does it.
Goal: replace child name with random string.
For example:
"Users" : {
"mGKgNDOw0qd77m6tmdDh76zOQOm2" : {
"email" : "someuser#gmail.com",
"firstName" : "some",
"lastName" : "user",
"username" : "someuser"
},
"vyMiCS7olNPh9bCXoKWqcIFNWVy2" : {
"email" : "someuser2#gmail.com",
"firstName" : "some",
"lastName" : "user2",
"username" : "someuser2"
}
}
This is what I got so far, I manage to get my head around with a string randomise function.
randomString(length) {
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
}
And I would like to push my data into the object with random string as the name.
I tried string interpolation but it does not work.
var expensesObject = {
uid: {
amount: spentAmount,
category: selectedCategory,
date: formattedDate,
time: formattedTime,
note: note
}
}
Consider this code
var users = {}
users[ randomString(20) ] = {
amount : spentAmount,
category : selectedCategory,
date : formattedDate,
time : formattedTime,
note : note
}
You can do this by setting directly the object's key using []:
var expensesObject = {}
expensesObject[uid] = {
amount: spentAmount,
category: selectedCategory,
date: formattedDate,
time: formattedTime,
note: note
}
You could use a single random number for a distinct place. The check if lower or upper case.
Then assign to the new key the property of uid and delete the property.
function replaceUID(object) {
object[random(28)] = object.uid;
delete object.uid;
}
function random(size) {
var r, s = '';
while (s.length < size) {
r = Math.floor(Math.random() * 62);
s += r >= 36 ? (r - 26).toString(36).toUpperCase() : r.toString(36);
}
return s;
}
var expensesObject = { uid: { amount: 'spentAmount', category: 'selectedCategory',
date: 'formattedDate', time: 'formattedTime', note: 'note' } };
replaceUID(expensesObject);
console.log(expensesObject);
Copy the object uid to a new object containing the random string
var expensesObject = {
uid: {
amount: 5,
category: "catA",
date: "02-03-2017",
time: "14:00:00",
note: "Notes"
}
};
var finalobject = {};
let propertyName = randomString(10); //get the random string
finalobject[propertyName] = expensesObject.uid; //copy uid object
console.log(finalobject);
function randomString(length) {
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
}
You could do something like this:
function randomString(length) {
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
}
var keylength = 16; // <-- change as needed
var myObject = {
amount: spentAmount,
category: selectedCategory,
date: formattedDate,
time: formattedTime,
note: note
}
var expensesObject = {};
var uuid = randomString(keylength);
expensesObject[uuid]=myObject; // <-- use [ var_name ]
You also can create string and convert it to JSON object like this:
var expensesObjectStr = "{"+ '"'+ uid+'"'+": {"+
'"amount"'+":"+ spentAmount+","+
'"category"'+":"+'"'+ selectedCategory+'"'+","+
'"date"'+": "+'"'+ formattedDate+'"'+","+
'"time"'+": "+'"'+ formattedTime+'"'+","+
'"note"'+": "+'"'+ note+'"'+
"} }";
var obj = jQuery.parseJSON(expensesObjectStr);
Here small fiddle - https://jsfiddle.net/skyr9999/2dvffaty/
var temp = expensesObject[uid];
expensesObject[randomString(<length>)] = temp;

Categories

Resources