These forums have been archived and are now read-only.

The new forums are live and can be found at https://forums.eveonline.com/

EVE Technology Lab

 
  • Topic is locked indefinitely.
 

Google Apps Script Discussion

First post
Author
Reservist Ringgton
Sebiestor Tribe
Minmatar Republic
#1 - 2014-10-29 11:12:20 UTC  |  Edited by: Reservist Ringgton
Hello everyone!

I don't know if this quite belongs up here or if it is welcome but I have found next to zero threads on this topic and it is something I have really found to be a fun part of the meta-game. That thing is, of course, Google Apps Script (GAS); specifically in Google Docs. I know most of the people here are probably seasoned computer programmers and web designers and some might even scoff at the idea of using it in any real sense.

However, despite it not being the most professional or technically challenging platform, I would still like to see if there is any other hobbyists out there who are interested in discussing it. I would even love to start a mailing list of people in EVE who use GAS in EVE as a hobby and are willing to share ideas and creations on the platform with each other.

If you are interested or even have questions as to what GAS is and what can be created on it in respect to EVE dont be afraid to post. This is a ball I want to get rolling. Lol

Thank you very much, Reservist Ringgton.
Steve Ronuken
Fuzzwork Enterprises
Vote Steve Ronuken for CSM
#2 - 2014-10-29 12:28:00 UTC
Reservist Ringgton
Sebiestor Tribe
Minmatar Republic
#3 - 2014-10-29 12:39:31 UTC
Steve Ronuken wrote:
https://github.com/fuzzysteve/eve-googledocs-script may be of interest Smile

Brilliant! I do use a lot of your stuff and went through heaps of your documentation when teaching myself the language. Fun fact: never knew you could use the "if" statement like you did in line 90 of MarketOrders.gs. Smile
Wafflehead
Garoun Investment Bank
Gallente Federation
#4 - 2014-10-29 22:39:46 UTC  |  Edited by: Wafflehead
Reservist Ringgton wrote:
Steve Ronuken wrote:
https://github.com/fuzzysteve/eve-googledocs-script may be of interest Smile

Brilliant! I do use a lot of your stuff and went through heaps of your documentation when teaching myself the language. Fun fact: never knew you could use the "if" statement like you did in line 90 of MarketOrders.gs. Smile


Also: http://eve-prosper.blogspot.co.uk/2014/07/building-better-spreadsheets-crius.html (googledocs aswell)
Reservist Ringgton
Sebiestor Tribe
Minmatar Republic
#5 - 2014-11-10 12:12:31 UTC
To get the ball rolling again I want to share a little snippet of what I have done. These two little recursive programs should be able to read most of EVE's APIs and spit out an array into Google Sheets ( Yes this includes the dreaded asset list Smile ).

//Converts the EVE api XML to a useable array format.



function eveXMLToArray(url) {
  var xml = UrlFetchApp.fetch(url).getContentText();
  var document = XmlService.parse(xml);
  var rowset = document.getRootElement().getChild('result').getChild('rowset');
  var attributes = rowset.getAttribute('columns').getValue().split(',');
  var children = rowset.getChildren();
  var prefill = [];
  var res = [[]]
  while ( res.length < attributes.length + 1 ) {
    res.push([]);
  };
  while ( prefill.length < attributes.length ) {
    prefill.push('#NULL')
  };
  prefill.push(-1);
  res = eveAPICrawler(children,attributes,prefill,res);
  return res
};



//Subfunction of eveXMLToArray().  Converts the raw data to a readable array format.



function eveAPICrawler(children,attributes,prefill,res) {
  prefill[attributes.length] += 1;
  var subchildren = [];
  var subprefill = [];
  var i = 0;
  var value = '';
  while ( i < children.length ) {
    while ( subprefill.length < attributes.length ) {
      try {
        value = children[i].getAttribute(attributes[subprefill.length]).getValue();
        res[subprefill.length].push(value);
        subprefill.push(value)
      } catch (e) {
        res[subprefill.length].push(prefill[subprefill.length]);
        subprefill.push(prefill[subprefill.length])
      }
    };
    res[subprefill.length].push(prefill[attributes.length]);
    subprefill.push(prefill[attributes.length])
    try {
      subchildren = children[i].getChildren()[0].getChildren();
      res = eveAPICrawler(subchildren,attributes,subprefill,res)
    } catch (e) {};
    subchildren = [];
    subprefill = [];
    i += 1
  };
  return res
};


Here is a link to a GAS file too if you prefer to view it that way and just make a copy.
Thank you guys and keep the ball rolling!
Ugurtan
Republic Military School
Minmatar Republic
#6 - 2014-11-11 12:13:06 UTC  |  Edited by: Ugurtan
What would I have to change in order to get a transposed output? Currently you write a new column for every rowset, but I would like to have a new row every rowset (if that makes any sense). The new googlespreadsheats seem todo this differently now (no more continue function it seems and I am getting errors that I have to manually add rows so your function can work. I have a feeling that will not happen if it expands "downwards" instead of "sideways".

edit: yeah as expected, if I wrap your function inside a transpose() the output gets done automatically and how i like it (rows, instead of columns), but I consider that ugly, so please get me a pointer how to change your function in the first place :-)
Ugurtan
Republic Military School
Minmatar Republic
#7 - 2014-11-11 14:01:54 UTC
another questions (yeah before you get the chance to answer the first, nasty I know!):

how do I get one of the columns to be of type number instead of text? Currently everything you import is text and it would be nice if I could get the runs column from /char/blueprints as numbers.
Steve Ronuken
Fuzzwork Enterprises
Vote Steve Ronuken for CSM
#8 - 2014-11-11 14:09:12 UTC
hrm. might be able to do something like

value = children[i].getAttribute(attributes[subprefill.length]).getValue();
value = isNumeric(value)?parseFloat(value):value;


So just add the second line, after the first one. You'll also need to add the function below. It's not ideal, as it doesn't check to make sure that it's a float or an integer, but it should do the job.

function IsNumeric(input)
{
   return (input - 0) == input && input.length > 0;
}

Woo! CSM XI!

Fuzzwork Enterprises

Twitter: @fuzzysteve on Twitter

Ugurtan
Republic Military School
Minmatar Republic
#9 - 2014-11-11 14:42:01 UTC
Steve Ronuken wrote:
hrm. might be able to do something like

value = children[i].getAttribute(attributes[subprefill.length]).getValue();
value = isNumeric(value)?parseFloat(value):value;


So just add the second line, after the first one. You'll also need to add the function below. It's not ideal, as it doesn't check to make sure that it's a float or an integer, but it should do the job.

function IsNumeric(input)
{
   return (input - 0) == input && input.length > 0;
}


thanks Steve, but I already figured it out, using your blueprints.gs examples from github. I just added a
before blueprints = I added

runs = +rows[i].getAttribute("runs").getValue();

and exchanged the last row[i] with runs

so the whole for block looks like this now:


    for(var i = 0; i < rows.length; i++) {
      runs = +rows[i].getAttribute("runs").getValue();
      blueprint=[rows[i].getAttribute("itemID").getValue(),
                 rows[i].getAttribute("locationID").getValue(),
                 rows[i].getAttribute("typeID").getValue(),
                 rows[i].getAttribute("typeName").getValue(),
                 rows[i].getAttribute("flagID").getValue(),
                 rows[i].getAttribute("quantity").getValue(),
                 rows[i].getAttribute("timeEfficiency").getValue(),
                 rows[i].getAttribute("materialEfficiency").getValue(),
                 runs]
      blueprints.push(blueprint);
    }

Ugurtan
Republic Military School
Minmatar Republic
#10 - 2014-11-11 14:44:34 UTC
thanks for the help in general guys! Now I only need to poke the API guy to "fix" /char/blueprints for me and I am set.
Reservist Ringgton
Sebiestor Tribe
Minmatar Republic
#11 - 2014-11-11 14:50:26 UTC
Steve Ronuken wrote:
hrm. might be able to do something like

value = children[i].getAttribute(attributes[subprefill.length]).getValue();
value = isNumeric(value)?parseFloat(value):value;


So just add the second line, after the first one. You'll also need to add the function below. It's not ideal, as it doesn't check to make sure that it's a float or an integer, but it should do the job.

function IsNumeric(input)
{
   return (input - 0) == input && input.length > 0;
}


Quick question:
I am not too familiar with how the '?' operator is used in GAS/JavaScript and what exactly is happening on your second line of code. Could you shed some light on what it is and how it works? Correct me if I am wrong but it seems a bit like the left-hand operand is an 'if' statement while the right is what it should do when it is 'true:false'.
Steve Ronuken
Fuzzwork Enterprises
Vote Steve Ronuken for CSM
#12 - 2014-11-11 14:53:49 UTC
It's a ternary operator Smile

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator

it does the test before the ?, then returns the first expression afterwards if it's true, or the second if it's false, with the : splitting the expressions.

Just me being lazy Smile

Woo! CSM XI!

Fuzzwork Enterprises

Twitter: @fuzzysteve on Twitter

Reservist Ringgton
Sebiestor Tribe
Minmatar Republic
#13 - 2014-11-11 14:59:03 UTC
Steve Ronuken wrote:
It's a ternary operator Smile

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator

it does the test before the ?, then returns the first expression afterwards if it's true, or the second if it's false, with the : splitting the expressions.

Just me being lazy Smile

No no no! That is amazing there are so many places that I can use this it isn't funny. Thank you so much. Oh and a tip back at you. There is actually already a function to test if something is a number. It is:
isNaN(Value)

Which will return 'false' if it is a number and 'true' if it is. So all you need to do is:
value = isNaN(value)?value:parseFloat(value);

Again, thank you very much!
Ugurtan
Republic Military School
Minmatar Republic
#14 - 2014-11-11 15:58:43 UTC
speaking of being lazy (big fan here as well :-)), do you think it really necessary to test on the runs column? In that special case it should always return either -1 for a BPO or the actuall number of runs left for the BPC, so just hardconverting it to a number seems only fair. I surfed around and found that putting + infront of your expression does the trick.
Reservist Ringgton
Sebiestor Tribe
Minmatar Republic
#15 - 2014-11-12 01:03:55 UTC
Ugurtan wrote:
speaking of being lazy (big fan here as well :-)), do you think it really necessary to test on the runs column? In that special case it should always return either -1 for a BPO or the actuall number of runs left for the BPC, so just hardconverting it to a number seems only fair. I surfed around and found that putting + infront of your expression does the trick.

He was just applying it to my code because my code doesn't distinguish between the columns. It just take an API and spits out an array without needing the specific code for the API's XML layout. Your code can be hard coded however because you have specific requests for each one. Smile
salacious necrosis
Garoun Investment Bank
Gallente Federation
#16 - 2014-11-12 03:54:04 UTC
I started working on something in this space which is probably slightly crazed. It's basically a port of EveApi to javascript. The result of each API call is a javascript object with appropriately named fields, etc. In other words, an xml to json converter.

You can check out the .gs here.

This code is designed to be used as a Google App Script Library. You can, of course, just copy the script and use it directly. But if you want to try it as a library the project key is (you can also get this from the app script editor at File -> Project properties):

MbLq1kJQ6_7pLvBd9dKPO2TA3Wcg5FMSu

With the key you can pull the script into your .gs project as a library, so no need to cut and paste the script.

I'll try to post a vid this weekend showing how to set everything up.

I'm working on the same thing for EveKit (i.e. app script library for pulling EveKit data into sheets), but the link above will give you a start on a library for directly hitting the EVE XML API.

Use EveKit ! - Tools for EVE Online 3rd party development

Reservist Ringgton
Sebiestor Tribe
Minmatar Republic
#17 - 2014-11-12 11:19:04 UTC
I have a strange problem if anybody wants to see if they can help me solve it. I thought I would develop a small web app to help me add and materials to my ore buyback system for corp. Unfortunately there has been a problem with the HTML code that has stopped it form operating. The link to my code is here.
The problem is not with the JavaScript it is with the HTML. Specifically the "onClick" attribute which now only works with one variable or the other. This is odd because not 10 minutes earlier when I was trying out a more basic code it was working fine. I can solve this right now by just doing the code within the HTML file but I would love to see where the problem in this code lies first.
Thanks for any help.
salacious necrosis
Garoun Investment Bank
Gallente Federation
#18 - 2014-11-17 05:38:52 UTC
We released the first version of our Google App Script library for EVE XML API calls today. Posted on the thread here.

Use EveKit ! - Tools for EVE Online 3rd party development

salacious necrosis
Garoun Investment Bank
Gallente Federation
#19 - 2014-11-18 00:53:55 UTC
Reservist Ringgton wrote:
I have a strange problem if anybody wants to see if they can help me solve it. I thought I would develop a small web app to help me add and materials to my ore buyback system for corp. Unfortunately there has been a problem with the HTML code that has stopped it form operating. The link to my code is here.
The problem is not with the JavaScript it is with the HTML. Specifically the "onClick" attribute which now only works with one variable or the other. This is odd because not 10 minutes earlier when I was trying out a more basic code it was working fine. I can solve this right now by just doing the code within the HTML file but I would love to see where the problem in this code lies first.
Thanks for any help.


In case you didn't figure this out yet , the problem with your script is that server side calls with a form argument can only take a single argument. Check out this link.

So to make your example work you have to do something like use hidden form arguments. E.g. change your form to be something like:


(form id="frm1" name = "mat_add")
(input width="1000" type="text" name="mat" value="Enter Item Here")(br /)
(input type="hidden" id="tab_array" name="tab_array")
(input type="button" value="Submit" name="mat_sub" onclick="document.getElementById('tab_array').value=document.getElementById('spn1').innerHTML; google.script.run.withSuccessHandler(onSuccess).shortlist(this.parentNode)")
(/form)


Then change your "shortlist" function to start with something like:


function shortlist(form) {
  var table = form.tab_array;
  ...


Use EveKit ! - Tools for EVE Online 3rd party development