What would be the best way to create a save select screen with more than 1 selectable save file, so far i have managed to get one save file working but i don't know how i would manage more than one of them, saving to it and loading that particular one when needed
here's the code for my saving and loading system
const FILE_NAME = "user://game-data1.json"
var player = {
"collected_level_one":false,
}
func save():
var file = File.new()
file.open(FILE_NAME, File.WRITE)
file.store_string(to_json(player))
file.close()
func load():
var file = File.new()
if file.file_exists(FILE_NAME):
file.open(FILE_NAME, File.READ)
var data = parse_json(file.get_as_text())
file.close()
if typeof(data) == TYPE_DICTIONARY:
player = data
else:
printerr("Corrupted data!")
else:
printerr("No saved data!")
If you want to have multiple save files. You would need use multiple selectable slots and a save and load button. That get your selected item and then either save or load, when they are clicked.
Calling save or load:
# Clicked save button.
func _on_Button_pressed_save() -> void:
# Get the selected save/load slot.
var index
# Save into the selected file.
SaveSystem.save(index)
# Clicked load button.
func _on_Button_pressed_save() -> void:
# Get the selected save/load slot.
var index
# Load the selected file.
SaveSystem.load(index)
You would also need to add your Savesystem script as a Singleton (Autoload). So that you can access it easily in other scripts.
After you've added the call to the functions you need to change them accordingly to be able to manage multiple save files.
Managing multiple save files:
# Clicked save button.
const FILE_NAME = "user://game-data"
const FILE_EXTENSION = ".json"
var player = {
"collected_level_one":false,
}
# Saves into the file with the given index.
func save(index : int) -> void:
var file := File.new()
var file_name := FILE_NAME + to_str(index) + FILE_EXTENSION
file.open(file_name, File.WRITE)
file.store_string(to_json(player))
file.close()
# Loads the file with the given index.
func load(index : int) -> void:
var file := File.new()
var file_name := FILE_NAME + to_str(index) + FILE_EXTENSION
if file.file_exists(file_name):
file.open(FILE_NAME, File.READ)
var data := parse_json(file.get_as_text())
file.close()
if typeof(data) == TYPE_DICTIONARY:
player = data
else:
printerr("Corrupted data!")
else:
printerr("No saved data!")
Related
Having a bit of trouble using importJSON for the first time in Google Sheets. My data is importing as truncated and I can't find any way to really filter things the way I'd like.
API source: https://prices.runescape.wiki/api/v1/osrs/1h
I'm using the following command: =IMPORTJSON(B1;B2)
where B1 is the source link, and B2 references any filters I've applied. So far I have no filters.
My result is a truncated list that displays as such:
data/2/avgHighPrice 166
data/2/highPriceVolume 798801
data/2/avgLowPrice 162
data/2/lowPriceVolume 561908
data/6/avgHighPrice 182132
data/6/highPriceVolume 7
data/6/avgLowPrice 180261
data/6/lowPriceVolume 37
data/8/avgHighPrice 195209
data/8/highPriceVolume 4
data/8/avgLowPrice 192880
data/8/lowPriceVolume 40
In the examples I've seen and worked with (primarily the example provided by the Addon), it will naturally pivot into a table. I can't even achieve that, which would be workable although I'm really only looking to ping the markers avgHighPrice and avgLowPrice.
EDIT:
I'm looking for results along the lines of this:
2
6
8
/avgLowPrice
162
180261
192880
/avgHighPrice
166
182132
195209
EDIT2:
So I have one more thing I was hoping to figure out. Using your script, I created another script to pull the names and item IDs
function naming(url){
//var url='https://prices.runescape.wiki/api/v1/osrs/mapping'
var data = JSON.parse(UrlFetchApp.fetch(url).getContentText())
var result = []
result.push(['#','id','name'])
for (let p in eval('data.data')) {
try{result.push([p,data.item(p).ID,data.item(p).Name])}catch(e){}
}
return result
}
Object.prototype.item=function(i){return this[i]};
I'm wondering if it is possible to correlate the item Name with the Item ID from the initial pricing script. To start, the 1st script only list items that are tradeable, while the 2nd list ALL item IDs in the game. I'd essentially like to correlate the 1st and 2nd script to show as such
ID
Name
avgHighPrice
avgLowPrice
2
Cannonball
180261
192880
6
Cannon Base
182132
195209
Try this script (without any addon)
function prices(url){
//var url='https://prices.runescape.wiki/api/v1/osrs/1h'
var data = JSON.parse(UrlFetchApp.fetch(url).getContentText())
var result = []
result.push(['#','avgHighPrice','avgLowPrice'])
for (let p in eval('data.data')) {
try{result.push([p,data.data.item(p).avgHighPrice,data.data.item(p).avgLowPrice])}catch(e){}
}
return result
}
Object.prototype.item=function(i){return this[i]};
You can retrieve informations for naming / from mapping as follows
function naming(url){
//var url='https://prices.runescape.wiki/api/v1/osrs/mapping'
var data = JSON.parse(UrlFetchApp.fetch(url).getContentText())
var result = []
result.push(["id","name","examine","members","lowalch","limit","value","highalch"])
json=eval('data')
json.forEach(function(elem){
result.push([elem.id.toString(),elem.name,elem.examine,elem.members,elem.lowalch,elem.limit,elem.value,elem.highalch])
})
return result
}
https://docs.google.com/spreadsheets/d/1HddcbLchYqwnsxKFT2tI4GFytL-LINA-3o9J3fvEPpE/copy
Integrated function
=pricesV2()
https://docs.google.com/spreadsheets/d/1HddcbLchYqwnsxKFT2tI4GFytL-LINA-3o9J3fvEPpE/copy
function pricesV2(){
var url='https://prices.runescape.wiki/api/v1/osrs/mapping'
var data = JSON.parse(UrlFetchApp.fetch(url).getContentText())
let myItems = new Map()
json=eval('data')
json.forEach(function(elem){myItems.set(elem.id.toString(),elem.name)})
var url='https://prices.runescape.wiki/api/v1/osrs/1h'
var data = JSON.parse(UrlFetchApp.fetch(url).getContentText())
var result = []
result.push(['#','name','avgHighPrice','avgLowPrice'])
for (let p in eval('data.data')) {
try{result.push([p,myItems.get(p),data.data.item(p).avgHighPrice,data.data.item(p).avgLowPrice])}catch(e){}
}
return result
}
Object.prototype.item=function(i){return this[i]};
I am trying to search-and-replace linked text from an old url to a new url.
It is not working and I have spent hours and hours. If I remove the "if (found)" it gives me "TypeError: Cannot read property 'getElement' of null" even though my files have text that is linked to this old_url.
Please, help me.
function myFunction() {
var old_url ="http://hurlx1.com";
var new_url ="http://urlxa.com";
var files = DriveApp.getFolderById("my folder id").getFilesByType(MimeType.GOOGLE_DOCS);
while (files.hasNext()) {
var file = files.next();
var doc = DocumentApp.openById(file.getId());
found=doc.getBody().findText(old_url);
if (found) {
var link_element = found.getElement().asText();
var start = found.getStartOffset();
var end = found.getEndOffsetInclusive();
var correct_link = link_element.getText().slice(start, end);
link_element.setLinkUrl(start, end, correct_link);
}
}
}
I believe your situation and goal as follows.
In your Google Document,
Text and hyperlink are the same with old_url.
Hyperlink is old_url. But the text is different from old_url.
You want to update old_url with new_url using Google Apps Script.
For this, how about this answer?
Modification points:
About your error message, when the text of old_url is not found in the Google Document with found=doc.getBody().findText(old_url);, found becomes null even when old_url is set as the hyperlink. Because findText searches the text on Document body, and that cannot search the hyperlinks set to the texts. I think that this is the reason of your issue.
In your script, var new_url ="http://urlxa.com"; is used. But when the link is set, correct_link is used like link_element.setLinkUrl(start, end, correct_link);. By this, new_url is not set.
When you want to update the text of http://hurlx1.com to new_url of var new_url ="http://urlxa.com";, it is required to also modify the text.
In your script, only the 1st old_url is updated. If there are several values of old_url in the Document, it is required to update them using the loop.
Specification of modified script:
This modified script can be used for the following patterns.
Text and hyperlink are the same with old_url.
In this case, the text value of old_url is also updated with old_url.
Hyperlink is old_url. But the text is different from old_url.
In this case, only the hyperlink of old_url is updated.
There are several texts with the hyperlink of old_url in the Google Document.
Modified script:
function myFunction() {
var old_url ="http://hurlx1.com";
var new_url ="http://urlxa.com";
var files = DriveApp.getFolderById("my folder id").getFilesByType(MimeType.GOOGLE_DOCS);
while (files.hasNext()) {
var file = files.next();
var doc = DocumentApp.openById(file.getId());
var body = doc.getBody();
// The following script is used for the situation that the text and hyperlink are the same with `old_url`.
var found = body.findText(old_url);
while (found) {
var link_element = found.getElement().asText();
var start = found.getStartOffset();
var end = found.getEndOffsetInclusive();
var correct_link = link_element.getText().slice(start, end);
link_element.setLinkUrl(start, end, new_url).replaceText(old_url, new_url);
found = body.findText(old_url, found);
}
// The following script is used for the situation that although the hyperlink is `old_url`, the text is different from `old_url`.
var text = body.editAsText();
for (var i = 0; i < text.getText().length; i++) {
if (text.getLinkUrl(i) == old_url) {
text.setLinkUrl(i, i + 1, new_url);
}
}
}
}
References:
replaceText(searchPattern, replacement)
findText(searchPattern, from)
editAsText()
After making a copy of my perfectly working google sheet, together with the script that comes with it; the script itself does not work anymore in the copy.
I go through the steps of authorizing it as an app but it seems to hang when i run it on the copy. It times out after 540 odd seconds. It seems to be having trouble with DriveApp.createFolder (exectution time 540 seconds). Yet i have not changed anything in the script, works fine on the original one.
Here is the script, im pretty sure everything is fine here, it just doesn't want to work as soon as you make a copy of it. I need to make copies of this sheet for each person in my team but i can't at the moment.
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var date = SpreadsheetApp.getActiveSheet().getRange(3,2).getValue();
var time = SpreadsheetApp.getActiveSheet().getRange(4,2).getValue();
var site = SpreadsheetApp.getActiveSheet().getRange(2,2).getValue();
// iterate through all sheets in the spreadsheet and rename them according to cell B2
for( var j = 0 ; j < sheets.length; j++) {
var sourceSheet = sheets[j];
// get contents of cell B2
var newSheetName = sourceSheet.getRange("B2").getValue();
// rename sheet
sourceSheet.setName(newSheetName);
}
// create a folder from the named SNOWSURVEYS with date
var folder = DriveApp.createFolder('SNOWSURVEYS' + '_' + date + '_'+ site);
// append ".csv" extension to the sheet name
fileName = SpreadsheetApp.getActiveSheet().getName() + ".csv";
// convert all available sheet data to csv format
var csvFile = convertRangeToCsvFile_(fileName);
// create a file in the Docs List with the given name and the csv data
folder.createFile(fileName, csvFile);
var folderID = folder.getId();
var folderName = folder.getName();
var ui = UiApp.createApplication().setTitle('Your files have are in your google drive in a folder called ' + folder);
var p = ui.createVerticalPanel();
ui.add(p);
p.add(ui.createAnchor('Click here to go straight to your files ',folder.getUrl()));
SpreadsheetApp.getActive().show(ui)
}
Execution transcript printscreen
While running this code, there is error while executing this line:
var invoiceSheet = newSSFile.getSheets()[0];'
"TypeError: Cannot find function getSheets in object Copy of Invoice Przykładowy. (line 69, file "Code")"
With this code I want:
Create a new spreadsheet and move it to proper folder [works]
Get a value from another spreadsheet and paste it in this new one [error]
Looked for answer for an hour without any result. Any idea what might cause this error?
function invoice() {
//Create copy SS + name
var ssTemp = SpreadsheetApp.openById("1Cr2W_4lNrHYRdXK-KDQ7UFJJ3Iagh-tGct8Ee5Y");
var newSS = ssTemp.copy("Copy of " + ssTemp.getName());
// Move to folder
var DestinyFolder = DriveApp.getFolderById("0B-y1OC8ChG2XRjRRbEJ");
var newSSFile = DriveApp.getFileById(newSS.getId());
DestinyFolder.addFile(newSSFile);
DriveApp.getRootFolder().removeFile(newSSFile);
// Modify details
// Invoice No
var klienciSS = SpreadsheetApp.openById("18B151VlJaVtDdQ9CcLrL3iwRAtWw2ZzZydproj");
var klienciSheet = klienciSS.getSheets()[0];
var klienciRange= klienciSheet.getRange('AB6');
var klienciValue = klienciRange.getValue();
var invoiceSheet = newSSFile.getSheets()[0];
var inboiceRange = invoiceSheet.getRange('F4');
newCellInvoice.setValue(klienciValue);
The problem is caused by the following line
var newSSFile = DriveApp.getFileById(newSS.getId());
It makes that newSSFile holds an instance of Class File instead of an instance of Class Spreadsheet
But the problematic line looks unnecessary. Replace the line that throws the error by
var invoiceSheet = newSS.getSheets()[0];
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.