i have a JSON file and it has mutes for a specific staff member
and i want to decrement it until 0
how can i do that?
also i want a code to decrement all staff members mutes
client.on('message', message => {
if(!staffstats[message.author.id]) staffstats[message.author.id] = {
mutes: 0,
bans: 0,
warns: 0,
tickets: 0,
appeals: 0,
vips: 0,
WarnedTimes: 0
}
if(message.content === prefix + "mutes-reset"){
user = message.mentions.users.first();
staffstats[user.id].mutes--;
}
})
You were close! You are able to do staffstats[user.id].mutes = staffstats[user.id].mutes - 1;, however, you do ask for until 0, so a simple check before changing the value will suffice:
if (!staffstats[user.id].mutes <= 0) //if mutes value is NOT lower or equal to 0, do:
staffstats[user.id].mutes = staffstats[user.id].mutes - 1; //reduces current value of mutes by 1
To decrement all staff members mutes, you will need to know who the staff are, and their IDs. Assuming you know this, you can loop through an array of the user ids for instance.
If you are solely storing all the values of all staff members in objects ({}), then you can do Object.keys(staffstats); for all the keys (those are the user ids) because it's conveniently in an array that you can loop through.
var staffId = ['12345', '23456', '34567']; //this is just an example array
staffId.forEach(id => { //loop through array of staffId, storing value in id variable
//same method as above
if (!staffstats[id].mutes <= 0)
staffstats[id].mutes = staffstats[id].mutes - 1;
};
Related
I am new to coding.
I am trying to edit and set values from an entire row but want to skip certain columns, because there are formulas in it.
In short: I want to / have to keep track of sing-in and sign-out times, which then will be calculated in the spreadsheet but shouldn't be overwritten by the array. Is there a way to skip every 3rd "value"/index (as these are the columns which have the formulas)?
In fact I want to skip the columns: TOTAL, day1tot, day2tot, day3tot .... day14tot.
function editCustomerByID(id,customerInfo){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("DATA");
const custIds = ws.getRange(2, 1, ws.getLastRow()-1, 1).getDisplayValues().map(r => r[0].toString().toLowerCase());
const posIndex = custIds.indexOf(id.toString().toLowerCase());
const rowNumber = posIndex === -1 ? 0 : posIndex +2;
Logger.log(customerInfo);
ws.getRange(rowNumber, 2, 1, 8).setValues([[
customerInfo.name,
customerInfo.total,
customerInfo.day1in,
customerInfo.day1out,
customerInfo.day1tot,
customerInfo.day2in,
customerInfo.day2out,
customerInfo.day2tot
// UNTIL DAY 14
]]);
return true;
To skip columns, you can subdivide your range into individual ranges and implement conditional statements
Sample:
function editCustomerByID(id,customerInfo){
...
var valueArray = [
customerInfo.name,
customerInfo.total,
customerInfo.day1in,
customerInfo.day1out,
customerInfo.day1tot,
customerInfo.day2in,
customerInfo.day2out,
customerInfo.day2tot
// UNTIL DAY 14
]
var startColumn = 2;
//loop through all values
for (var i = 0; i < valueArray; i++){
// filter out every 3rd value
if((i+1) % 3 != 0){
ws.getRange(rowNumber, (startColumn + i)).setValue(valueArray[i]);
}
}
return true;
Note that the sample code above uses the method setValue() instead of setValues()
Performing multiple requests to set values to individual ranges is less efficient that setting all values at once within a single request, however in your case it is necessary since your desired value range is not continuos
I have a set of documents in Firestore in this format. Questions array will 10 questions.
I want to get the data of questions field: one row for one question
I do I code in the appscript to perform this
This is my code so far (for one document only)
function test(){
const firestore = getFirestore();
var query = firestore.getDocument("QuestionCollection/test").fields;
var data = {};
data.subject = query.subject;
data.questions= query.questions;
const sheet = SpreadsheetApp.getActiveSheet();
for(i = 0 ; i < 10 (no. of question); i++){
const row = [data.questions[i].answer, data.questions[i].difficulty];
sheet.appendRow(row);
}
}
Error:
TypeError: Cannot read property 'answer' of undefined
Modification points:
When I saw your sample data in the image, it seems that the array length of questions is 2. But at the for loop, the end index of loop is 9. I think that by them, such error occurs.
When you want to put the value of "Serial", it is required to add the value for putting to Spreadsheet.
In your script, appendRow is used in a loop. In this case, the process cost becomes high.
When above points are reflected to your script, it becomes as follows.
Modified script:
Your for loop is modified as follows.
From:
for(i = 0 ; i < 10 (no. of question); i++){
const row = [data.questions[i].answer, data.questions[i].difficulty];
sheet.appendRow(row);
}
To:
var values = [];
for (var i = 0; i < data.questions.length; i++) {
const row = [i + 1, data.questions[i].answer, data.questions[i].difficulty];
values.push(row);
}
sheet.getRange(sheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
For the end index of loop, the array length is used.
Reference:
setValues(values)
You shouldn't query the .fields property directly (because your data isn't converted properly). Assuming you're using v28+ of the library, your code should look something like this:
function test(){
const firestore = getFirestore();
const query = firestore.getDocument("QuestionCollection/test").obj; // Don't use .fields here
const sheet = SpreadsheetApp.getActiveSheet();
const values = [["Serial", "Answer", "Difficulty"]]; // Init 2D array with Header row
// Loop through each question in the array and extract necessary values to construct Data rows
for (const question of query.questions){
values.push([query.questions.indexOf(question) + 1, question.answer, question.difficulty]);
}
// Replace 1, 1 below with coords of "Serial" header cell
const range = sheet.getRange(1, 1, values.length, values[0].length);
range.setValues(values);
// sheet.getRange(subjRow, subjCol).setValue(query.subject); // Add location for Subject data
}
I saw that you wanted "Serial" to represent "Question number", so I added that column to the header and data rows.
As Tanaike mentioned, there's a huge performance hit for writing to the spreadsheet in a loop, so it's better if you set up a 2D array of values to write all at once using range.setValues(array2D). Ideally, you'll want to minimize the calls to the Spreadsheet API.
Disclaimer: I'm an active contributor to the FirestoreGoogleAppsScript library.
All, I am attempting to calculate the winning percentage of each user in a group, sort the users by winning percentage, and return the user's rank -- that is, the position where the user's winning percentage is set within the group.
So, the function should return "1" for the user with the highest winning percentage.
So far my code is:
def rank (user, group)
users = UserGroup.select(:user_id).where(group_id => group)
user = user.id
rank = Hash.new
users.each do |user|
total = Game.where("group_id = ? AND (user1 = ? OR user2 = ?"), group user_id, user_id).count
win = Game.where(:group_id => group, :winner => user).count
win_percentage = win/total.to_f
ranks[:user] = win_percentage
end
ranks.sort_by{|key, value|, value}.to_h
return ranks.each_with_index.detect{|(key, value), index| key == user).last +1
end
I think everything should be fine, but I can't figure out how to return the index of a the hash based on the key. I think that I might need to convert into an array of arrays and use Array#index; but I am also unclear on how to find an index of an array of arrays.
how to return the index of a the hash based on the key
You can use each_with_index. A quick example:
hash = {:h=>1, :k=>2, :v=>3}
hash.each_with_index.detect { |(key,value),index| key == :k }
# => [[:k, 2], 1]
hash.each_with_index.detect { |(key,value),index| key == :k }.last
# => 1
I have been trying to iterate through an array to check how many times two particular values occur. I came up with this code:
var paymentNum = 0
var creditNum = 0
for index in images {
if images.objectAtIndex(index) == 0 {
paymentNum = paymentNum + 1
} else {
creditNum = creditNum + 1
}
}
This doesn't seem to work though. I just get the error 'AnyObject' is not convertible to 'Int'.
Where am I going wrong?
I'm making some pretty huge assumptions because you don't have much detail about what's going on.
I'm assuming that images is an NSArray. NSArray in Objective-C translates into an [AnyObject] in swift.
When you have a for-each style loop like this
for value in array
{}
the loop will iterate through each value in the array. Value is the actual object in the array, not a counter as in a for(int i = 0; i < 10; i++) style loop
So what you're probably really expecting to do is
for item in images {
if item == 0 {
paymentNum++
} else {
creditNum++
}
}
you also might need to cast the loop from an [AnyObject] to an [Int] like this
let tmp = images as [Int]
for item in tmp
{...}
or, cast the value pulled out of the array like this
for item in images {
if (item as Int) == 0 {
paymentNum++
} else {
creditNum++
}
}
But the former is probably preferable
paste ina playground:
import Foundation
let images = [1, 0, 1, 1, 0, 0, 1, 0, 1, 1]
var paymentNum = 0
var creditNum = 0
for item in images {
println(item)
if item == 0 {
paymentNum = paymentNum + 1
} else {
creditNum = creditNum + 1
}
}
println(paymentNum) //4
println(creditNum) //6
There's a more compact way of achieving that, in just 2 lines of code.
It makes the assumption that an array element it's a credit if its value is 1, otherwise is 0.
That said, if you sum up all elements of array, you obtain the number of credits - the number of payments is the array size minus the number of credits.
To sum all elements of the array, the simplest way is using the reduce method (more info here)
var creditNum = images.reduce(0, combine: { $0 + $1 } )
var paymentNum = images.count - creditNum
If using values different than 0 or 1 to identify credits and payments, then the calculation can be modified to check for explicit values as follows:
var creditNum = images.reduce(0, combine: { $0 + ($1 == 1 ? 1 : 0) } )
Here it takes the previous count ($0) and add either 1 or 0, depending whether the element array ($1) is equal to 1 or not.
players={}
players["foo"] =
{
wins = 0, deaths = 0, draws = 0, rounds = 0, bet = "None", rank = 0
}
modify = function (stat, set, target)
local player = players[target]
local dictionary =
{
["wins"] = player.wins, ["deaths"] = player.deaths,
["draws"] = player.draws, ["rounds"] = player.rounds,
["bet"] = player.bet, ["rank"] = player.rank,
}
if dictionary[stat] then
dictionary[stat] = set
print(dictionary[stat])
print(player.wins)
end
end
modify("wins", 1, "foo")
The code mentioned above doesn't really function as it's supposed to. It modifies the key "wins" but the value it's self (player[target].wins) isn't modified.
Numeric values aren't references. You get copies when you copy them not references back to their original locations.
So when you assign ["wins"] = player.wins you aren't getting a reference to the wins field in the player table. You are copying the value into the dictionary table.
If you want to modify the player table you need to modify the player table.
Also the indirection in that function is entirely unnecessary. You can reference player[stat] just the same as you can reference dictionary[stat].
tbl.stat is syntactic sugar[1] for tbl["stat"].
Additionally, as seen in ยง2.5.7 of the lua manual:
tbl = {
stat = 0,
}
is the same as
tbl = {
["stat"] = 0,
}
when the name is a string, does not start with a number, and is not a reserved token.
[1] See the The type table paragraph.