I need help with seeding data in a league with 12 teams, each team has a TeamId key value of 1 to 12 respectively
I have pre-populated and seeded the ScheduledFixtures table with 22 rows. In my attempt below I do a take 11 while i try to set up the first half of season, i.e. everyone plays everyone once. Each week for each team has to be home game, then away game
My code is at a point where it works in that it seeds the right number of rows but the wrong teamId's are set in fixture game. This is the bit I cannot figure out. So ScheduleFixture 1 loops once and I need each team to play each other, then next loop same again but who was at home is now away etc etc
var sheduledFixtures = db.ScheduledFixtures.Take(22);
var teams = db.Teams;
foreach (var x in sheduledFixtures)
{
var i = 1;
for (int t = 1; t < 8; t++)
{
if (t != i)
{
var fixtureGame = new FixtureGame();
fixtureGame.AwayTeamId = i;
fixtureGame.HomeTeamId = t;
db.FixtureGames.Add(fixtureGame);
db.SaveChanges();
// Add Fixture Record
var fixture = new Fixture();
fixture.FixtureGameId = fixtureGame.FixtureGameId;
fixture.SeasonId = 1;
fixture.ScheduledFixtureId = x.ScheduledFixtureId;
db.Fixtures.Add(fixture);
i++;
}
}
}
db.SaveChanges();
Related
I have a spreadsheet that I use to keep track of climbing progress (snippet shown below). I have formulas and graphs that keep track of counts of specific grades over time, but I am having trouble with a formula to keep a running total (by year) of feet climbed. I intent to put this in another sheet.
Basically I would like a single cell that does something like ... if Sheet1!A:A begins with "21." and if Sheet1!E:E,"<>*%" (which means I actually completed the climb) then add the rows total climb length (Sheet1!J:J * Sheet1!I:I) to the running total for that year.
What is the best way to do this?
You can try using Apps Script and creating a script in order to manage your task.
So for example, you might want to take a look at the snippet below:
Code
function calculateTotal() {
let ss = SpreadsheetApp.getActive().getSheetByName('Sheet1');
let date = ss.getRange('A2:A').getDisplayValues();
let tries = ss.getRange('E2:E').getDisplayValues();
let lengths = ss.getRange('I2:I').getDisplayValues();
let total = 0;
for (let i =0; i<date.length; i++) {
if (date[i][0].toString().startsWith('21') != false && tries[i][0].toString().includes('%') == false) {
total = total+lengths[i][0];
}
}
ss.getRange('M2').setValue(total);
}
Explanation
The script above gathers all the values from the Sheet1 and loops through them. If the conditions check (the date should start with 21 and the E column does not contain %) then the corresponding length is added to the total; the total is then saved in the M2 cell in this case.
Further improvement
The advantage of using a script is that it is versatile and easier to manage. In this situation, you can make use of Apps Script's time-driven triggers; so assuming you plan on updating your spreadsheet every day at a specific time, you can create a trigger which will run right after it.
For example, the below function creates a trigger for the function above which will run every day at ~9.
function createTrigger() {
ScriptApp.newTrigger("calculateTotal")
.timeBased()
.atHour(9)
.everyDays(1)
.create();
}
Reference
Google Apps Script;
Apps Script Installable Triggers.
Thanks Ale13 ... using your example and adding a couple of things (also needed to parseInt totals) ...
function calculateTotal() {
let ss = SpreadsheetApp.getActive().getSheetByName('Sheet1');
let s7 = SpreadsheetApp.getActive().getSheetByName('Sheet7');
let date = ss.getRange('A2:A').getDisplayValues();
let type = ss.getRange('F2:F').getDisplayValues();
let tries = ss.getRange('E2:E').getDisplayValues();
let lengths = ss.getRange('I2:I').getDisplayValues();
let laps = ss.getRange('J2:J').getDisplayValues();
let btotal = 0;
let rtotal = 0;
for (let i =0; i<date.length; i++) {
if (date[i][0].toString().startsWith('21') != false && tries[i][0].toString().includes('%') == false) {
// Totals for Bouldering
if (type[i][0] == "B") {
btotal = btotal + parseInt(lengths[i][0]*laps[i][0]);
}
// Totals for Top Rope or Sport
else {
rtotal = rtotal + parseInt(lengths[i][0]*laps[i][0])
}
}
}
console.log("Roped total = " + rtotal)
console.log("Bouldering total = " + btotal)
s7.getRange('B2').setValue(rtotal);
s7.getRange('B3').setValue(btotal);
}
I'm using a turn-based match for a board game, and when a turn is complete I call GKTurnBasedMatch.EndTurn and pass the match participants and the new match data as the arguments. I need the game to advance to the unmatched players, but it only does so after some indeterminate time related to the timeout value. Setting the timeout value 0 only prevents the game from ever progressing past player 1. The match data is being updated, so the app is definitely communicating with Game Center servers. What am I missing here?
private void endTurn(double timeout)
{
// Copies list of participants to a mutable array
GKTurnBasedParticipant[] Participants = new GKTurnBasedParticipant[match.Participants.Length];
match.Participants.CopyTo(Participants, 0);
// Advances to the next player
match.EndTurn(Participants, timeout, matchData, (e) =>
{
// If there is an error message, print it to the console
if (e != null)
{
Console.WriteLine(e.LocalizedDescription);
Console.WriteLine(e.LocalizedFailureReason);
}
// Otherwise proceed normally
else
turnOverUpdate();
});
}
Apple's documentation is quite poor for the EndTurn method, but I figured it out. The NextParticipants field should be treated like EndTurnWithNextParticipant, so you have to copy GKTurnBasedMatch.Participants and reorder it so the next player is first and so fourth. The match only gives you the participants in order of joining, not relative to the local player, so you have to sort it. Below is the code I used to accomplish this.
List<GKTurnBasedParticipant> participants = new List<GKTurnBasedParticipant>();
// Gets the index of the local player
int index = 0;
for (int i = 0; i < match.Participants.Length; i++)
{
if (match.Participants[i].Player != null)
{
if (match.Participants[i].Player.PlayerID == GKLocalPlayer.LocalPlayer.PlayerID)
{
index = i;
break;
}
}
}
int offset = match.Participants.Length - index;
for (int i = 1; i < offset; i++)
participants.Add(match.Participants[i + index]);
for (int i = 0; i <= index; i++)
participants.Add(match.Participants[i]);
GKTurnBasedParticipant[] nextParticipants = participants.ToArray();
I have successfully linked my BigCommerce account to my Google Sheets (Drive) account so every time I receive a new order in my store the order is automatically exported into a Google Sheet. Unfortunately, an entire order is listed on one row with multiple items added into one cell. What I need is to have each product on its own row; for example, if someone orders three different products Zapier would create three new rows. This functionality exists when directly exporting orders from BigCommerce, but the "Zap" does not use the BigCommerce export function when pulling order information from my store to the Google Sheet.
I know this is a shot in the dark, but I am hoping someone might have a solution that I can implement. Thank you for your help!
I have created a script that perhaps could be used or modified, at least until you find if the process can be done within Zapier.
You can try the script in the following ss: https://docs.google.com/spreadsheets/d/1ggNYlLEeN3UYtZC_KlOGwpyII9CzOLKMnIOKIDrPJPM/edit?usp=sharing
The script assumes that orders arrive in the tab named Zapier. As things are set up, you would run the script through the Custom Menu.
If there are 2 orders or more, click the menu for each order.
The complete rows appear in the sheet FullList.
(if you want to play/try again, you will have to manually delete the rows in FullList once they are showing).
function processForNewOrders() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName('Zapier');
var destinationSheet = ss.getSheetByName('FullList');
var sourceValues = sourceSheet.getDataRange().getValues();
var destinationValues = destinationSheet.getDataRange().getValues();
var index = [];
destinationValues.forEach( function (x) {
index.push(x[0]);
})
var newOrders = [];
for (var y = sourceValues.length -1 ; y > 0 ; y --){
if(sourceValues[y][0].toString().indexOf('po_number') != -1 ) continue;
var i = index.indexOf(sourceValues[y][0]);
if(i != -1) break; // This readies only the fresh orders for processing
newOrders.push(sourceValues[y]);
}
Logger.log(newOrders)
for (var j = 0 ; j < newOrders.length ; j++){
var output = [];
var orderLine = newOrders[j];
Logger.log('orderLine = ' + orderLine);
var circuit = 0;
var items = 1
while (circuit < items){
var row = [];
for (var z = 0 ; z < orderLine.length; z++){
var cell = orderLine[z];
// Logger.log(cell);
var lines = cell.toString().split(',');
if(lines.length > 1) items = lines.length;
row.push(lines[circuit] ? lines[circuit] : lines[0]);
// Logger.log('row =' + row);
}
circuit ++;
Logger.log('circuit circuit circuit =' + circuit)
output.push(row);
}
}
Logger.log(output);
if(output != undefined)
destinationSheet.getRange(index.length+1,1,output.length,output[0].length).setValues(output);
}
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('Custom Menu')
.addItem('Process new order', 'processForNewOrders')
.addToUi();
}
I'm looking to clone a row 3x, but only keeping data from one column.
So essentially I have the following [Name / Time / Booking], and each row is populated with all 3 properties, I'm trying to create 3 blank rows underneath each current row which is populated with only the persons name.
Can't work how to do it in scripting and can't find a plugin to do this. My data set is over 10,000 big so doing it manually isn't an option.
What I have:
What I want:
UPDATED code:
function duplicateRows() {
var sh, v, arr, c, b;
sh = SpreadsheetApp.getActive()
.getSheetByName('Blad1')
v = sh.getRange(1, 1, sh.getLastRow(), 40)
.getValues();
arr = [v[0]];
v.splice(1)
.forEach(function (r, i) {
arr.push(r)
c = 0
while (c < 3) {
dup = makeEmptyArrayXEl(40)
dup[0] = r[0];
arr.push(dup)
c += 1;
}
})
sh.getRange(1, 1, arr.length, arr[0].length)
.setValues(arr);
}
function makeEmptyArrayXEl(num) {
var arr = [];
for (var i = 0; i < num; i++) {
arr.push("")
}
return arr;
}
Would this work for you? It requires a free column to the left of Booking in the original data set. The formula below is a new sheet.
=ArrayFormula(sort({A2:A4,B2:B4,C2:C4;A2:A4,D2:D4,D2:D4;A2:A4,D2:D4,D2:D4;A2:A4,D2:D4,D2:D4},1,FALSE))
I have a Ruby on Rails project where I use a DHTMLX Grid.
Is there a way of showing, using the event handler "onFullSync" provided by the grid API, to show updated data?
Let me explain a little better... I know I can do something like:
dp.attachEvent("onFullSync", function(){
alert("update complete");
})
But what I want is something more complex. I want to, after each completed update, alter a div adding the information like this:
Field 2 was updated to XYZ and field 3 was updated to XER on line X
Field 1 was updated to 123 and field 3 was updated to XSD on line Y
Is this possible?
Thanks
There is a onAfterUpdate event that can be used similar to onFullSync
http://docs.dhtmlx.com/api__dataprocessor_onafterupdate_event.html
It will fire after each data saving operation ( if you are saving 5 rows - it will fire 5 times )
Still, info about updated columns will not be available here.
Also, you can try onEditCell event of grid. It fires after changing data in db, but before real saving in database. Here you can get all necessary info - row, column, old value and new value.
http://docs.dhtmlx.com/api__link__dhtmlxtreegrid_oneditcell_event.html
So, what I end up doing was:
After creating the grid I created an array:
var samples = [];
Then, as per #Aquatic suggestion, I added to "onEditCell" event the following line:
samples[samples.length] = grid.cells(rId, 5).getValue();
This allowed me to add to the array the value present on column 5 of the row changed. Then, on "onFullSync" event I hide or show the div created on the view with the messages (I distinguish if it's on row or more changed on the grid).
//Deals with messages after update
dp.attachEvent("onFullSync", function(){
unique_samples = uniq_fast(samples.sort());
if (unique_samples.length == 1){
$('#updated-samples').text("");
$(".messages").show();
$('#updated-samples').text("A seguinte amostra foi actualizada: " + unique_samples[0]);
//to clear the array
samples = [];
} else if (unique_samples.length > 1){
$('#updated-samples').text("");
$(".messages").show();
$('#updated-samples').text("As seguintes amostras foram actualizadas: " + unique_samples.sort().join(", "));
//to clear the array
samples = [];
} else {
$('#updated-samples').text("");
$(".messages").hide();
//to clear the array
samples = [];
}
})
The problem with using "onEditCell" is that everytime a field is changed on that row I get a repeated value on my "samples" array, I I had to remove duplicate from that array. For that I used one of the suggestions at this answer
// remove duplicates in array
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i];
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
Then I have on the beginning of the view, to show the messages:
<div class="alert alert-success messages" id="updated-samples">
And that's it. I could be not the most efficient way but it works for what I wanted. I will leave the question open a few more days to see if any other option appears.