NATION

PASSWORD

Wolfram and Hart - Sleeping Beauty

Talk about regional management and politics, raider/defender gameplay, and other game-related matters.
Not a roleplaying forum.

Advertisement

Remove ads

User avatar
Wolfram and Hart
Secretary
 
Posts: 37
Founded: Jul 06, 2017
Father Knows Best State

Postby Wolfram and Hart » Wed Dec 06, 2017 5:50 am

Thanks for your support!

We're allowed 50 'hits' on the server every 30 seconds. Each nation counts as two hits in my code (don't know why yet), so that's a max of 25 nations in 30 seconds. If you put in more than 25, you get blocked from doing more hits for 15 minutes.

It would be good to add a timer. The code could split the list into chunks of 25 nations, then send them out every 30 seconds. That would comply with site rules.

I'll work on that at some point. Though anyone else is welcome to post how they would do that!

User avatar
Roavin
Ambassador
 
Posts: 1056
Founded: Apr 07, 2016
Scandinavian Liberal Paradise

Postby Roavin » Wed Dec 06, 2017 6:21 am

Wolfram and Hart wrote:We're allowed 50 'hits' on the server every 30 seconds. Each nation counts as two hits in my code (don't know why yet), so that's a max of 25 nations in 30 seconds.


That might be because Chrome is sending an additional OPTIONS request. Auralia had a similar problem. In most cases, it can be worked around by just halving the rate limit; unless you have that many, it won't make it unbearably slow (auto-logon scripts used to do one login every 10 seconds to stay compliant).

Wolfram and Hart wrote:It would be good to add a timer. The code could split the list into chunks of 25 nations, then send them out every 30 seconds. That would comply with site rules.

I'll work on that at some point. Though anyone else is welcome to post how they would do that!


(at risk of veering into Technical-territory)

[v] has stated that she prefers spaced out request rather than bunched up requests. You could have fLogin() place the nation/password tuples into a queue, then a function processNextNation() picks up the frontmost nation from the queue, does the thing, and then at the end of the onreadystatechange a setTimeout() call with an appropriate delay calls processNextNation() again. Note that if you detect HTTP 429, it includes a X-Retry-After header that you can parse to know when to try again (so your setTimeout() call would then use that time instead of the rate limit).
RoavinA Francoist-Defenderist Subversive from the South Pacific

"Not to mention TSP are some democracy wankers
and democracy wanking is peak defender
" — Tim

NS Coders Discord | I am a LOLcat | Former First Warden of TGW

User avatar
Wolfram and Hart
Secretary
 
Posts: 37
Founded: Jul 06, 2017
Father Knows Best State

Postby Wolfram and Hart » Wed Dec 06, 2017 12:15 pm

Nice! Great advice. Much appreciated.

User avatar
Honeydewistania
Ambassador
 
Posts: 1237
Founded: Jun 09, 2017
Capitalist Paradise

Wolfram and Hart Special Operations Update

Postby Honeydewistania » Tue Dec 12, 2017 8:34 am

Wolfram and Hart have been working on some Special Operations defending the defenceless and the occasional tag.
Regions Defended:
Sikh Empire with help from South Asians
Pacific Islands
Eurasian Socialist Union helping The Union of Democratic States
Giveran Empire
Regions Tagged:
Sontami

Special Operatives Present:
Port Honeydew
Wolfram and Hart
Attorneys Office

Excited? Are you thrilled just by looking at this posts? Do you want to be like us, super cool? Contact Wolfram and Hart.
Honeydewistania

Regional Military Director of Lazarus
Posts OOC unless marked otherwise.
Ambassador to the WA: Benji Hepperle

The MT Army Warrior
Biggest acheivement: Spelling
GA#494 "Regulating Desalination"
GA#498 "Ban on Forced Blood Sports"
GA#502 Repeal "Freedom to Seek Medical Care II"

SC#315 "Commend Vippertooth33"

User avatar
The Noble Thatcherites
Diplomat
 
Posts: 513
Founded: Dec 03, 2015
New York Times Democracy

Postby The Noble Thatcherites » Tue Dec 12, 2017 9:01 am

Honeydewistania wrote:
Wolfram and Hart have been working on some Special Operations defending the defenceless and the occasional tag.
Regions Defended:
Sikh Empire with help from South Asians
Pacific Islands
Eurasian Socialist Union helping The Union of Democratic States
Giveran Empire
Regions Tagged:
Sontami

Special Operatives Present:
Port Honeydew
Wolfram and Hart
Attorneys Office

Excited? Are you thrilled just by looking at this posts? Do you want to be like us, super cool? Contact Wolfram and Hart.
I didn’t realize that we where working together. That’s awesome. I look forward to working together more often.
—Thatcher Whitehall
Kanglia wrote:Thatcher. Wants. As. Little. To. Do. With. You. All. As. Possible.
Résumé
The Union of Democratic States
Citizen and Founder
Prime Minister (x1)
Motion(s) Passed (x15)
Ambassador (x21)
Publisher for The Union Post (x5)
Constitutional Framer (x4)
The Free Nations Region
Citizen and Legislator
Justice (x1)
Motion(s) Passed (1x)
The Allied States
Citizen
Senator (x1)
FORGE
Representative (x4)
Chancellor (x1)
ITDA
Founder
Representative (x1)
Secretary General (x1)
Charter Author (x2)
Court of International Law and Justice
Foreign Affairs Justice (x1)
Europeia
Citizen and Assemblyman (x1)
The South Pacific
Citizen
SPSF Recruit (x1)


The Union of Democratic States

User avatar
Wolfram and Hart
Secretary
 
Posts: 37
Founded: Jul 06, 2017
Father Knows Best State

Postby Wolfram and Hart » Sun Dec 17, 2017 2:47 pm

I've updated the Puppet Login code.
I took some of Roavin's advice, and spaced the login requests apart. I think the way I've done it should avoid the "429 - Too many logins" error.
And Queen Yuno, this version should be able to handle your 1000 puppets!

User avatar
Wolfram and Hart
Secretary
 
Posts: 37
Founded: Jul 06, 2017
Father Knows Best State

Postby Wolfram and Hart » Sat Dec 30, 2017 6:11 pm

Telegram Script

I've been playing around with code again, and came up with this script to telegram new nations. It's very basic. There are far better apps out there (and I'd strongly recommend you use them rather than this), so I'm sharing this mostly for novelty value.

Check out these threads if you're looking for a proper app.
viewtopic.php?f=15&t=432124
viewtopic.php?f=15&t=388960
viewtopic.php?f=15&t=350586

Edit: I've updated to version 1.2. This version should keep trying to TG new nations until your PC goes to sleep.

What

Use this code to send recruitment telegrams to 49 of the 50 most recently created nations (yeah, there's a bug!)
Use this code (v1.2) to send recruitment telegrams to new nations.

How

You need a Client Key, and the telegram ID and Secret Key for your recruitment telegram. I'm not going to explain how to get them here. If you really want to send out recruitment TGs, you'll easily find out for yourself, and you'll also likely want to use better software!

On your PC or laptop, open a text editor, like Notepad. Copy the code (below) into the editor.

Put your own Client Key, telegram ID and Secret Key in the code (place indicated by all the asterisks).

Save the file as “TelegraphMachine.html”

Check the filename. If it saved as “TelegraphMachine.html.txt” or similar, rename it to “TelegraphMachine.html”.

When you open the file again, it should get opened in your browser by default. You should see a black page with “Wolfram & Hart” written across the top.

When you click the button, the code asks NS for a list of the 50 most recently created nations.
It then attempts to send a telegram to the first nation on the list.
At this point, I always seem to get an "Error 0" message.
Three minutes later, the next telegram gets sent out.(This one should be OK)
Then three minutes later, the next, and so on until the list of 50 nations is finished.
The code then gets a fresh list of the 50 most recently created nations, and repeats.

Possible Improvements

Add text boxes so users can input Client Key etc on the screen.
Add a text box so users can supply their own list of nations.
Add a radio button to control telegram speed. The default would be 3 minutes (the fastest rate currently allowed for recruitment TGs). The alternative would be 30 seconds (permitted for non-recruitment TGs).
Check that the nation accepts recruitment telegrams before sending them one.
Create a loop, so that when all 50 new nations have been telegrammed, the next 50 are chosen. Without sending duplicate TGs to the same nations!


Feedback
If you use this script, please drop [nation]Wolfram & Hart[/nation] a telegram. It would be interesting to know how widely this was used (if at all!). Any suggestions for improvements and enhancements are welcome.
Code: Select all
<!DOCTYPE html>

<!-- Wolfram & Hart Telegraph Machine\ Script v1.0

     Version | Date        | Name           | Comment
     1.0     | 23 Dec 2017 | Wolfram & Hart | Created

     This code is not warranted in any way.  Use at your own risk.

     Use and modify this code as suits.
     Make sure you comply with the NationStates API rules.
     See:  https://www.nationstates.net/pages/api.html 

     Feedback: If you use this script, please drop [nation]Wolfram & Hart[/nation] a telegram. 
     It would be interesting to know how widely this was used (if at all!)
     Any suggestions for improvements and enhancements are welcome.
-->

<head>
  <!-- Set the title, visible in the browser tab -->
  <title>W&H Telegraph Machine</title>

  <!-- Set the colour scheme and format for the page -->
  <style>
    body {background-color: black;}
    div {
      text-align:center;
      color: white;
      font-family: times;
    }
  </style>
</head>

<body>
  <div>
    <!-- Display headers.  Use <span> tags to format the "W", "&", and "H" in "Wolfram & Hart". -->
    <h1><span style="font-size:120%;">W</span>OLFRAM <span style="color:red; font-size:120%;">&</span> <span style="font-size:120%;">H</span>ART</h1>
    <h3>Telegraph Machine</h3>

    <!-- Add a blank line -->
    <br>

    <!-- Add a button.  When clicked, this will run the JavaScript function, "fMain" -->
    <button type="button" onclick="fMain()">Telegram New Nations</button>

    <!-- Add an empty paragraph, ready to display results -->
    <p id="result"></p>
  </div>

  <!-- This is the JavaScript that will be run when the button is pressed -->
  <script>

    /* ***********INSERT YOUR OWN CLIENT KEY, TG ID, AND SECRET KEY IN THIS SECTION******** */
    /* Need client key, telegram ID, and the secret key. 
       See https://www.nationstates.net/pages/api.html#telegrams for more info.
    */
    var strClientKey = "abcd1234"
    var strTgId = "12345678"
    var strSecretKey = "12345678abcd"
    /* ************************************************************************************* */

    /* Set TG speed (recruitment = 180s, non recruitment = 30s) */
    var intSpeed = 180000

    /* Set an array variable to store the list of nations */
    var astrNations = [];

    /* Set a variable to record the nations processed.  This will update the html paragraph. */
    var strMessage = "";

    /* The fMain function resets the 'result' paragraph to being blank.
       It then gets a list of new nations from NS (should be 50 most recently created)
       It waits until after the list of nations is received before trying to send a TG
    */
    function fMain() {
      strMessage = "";
      document.getElementById("result").innerHTML = "";
      fGetNewNations();
    }

    /* The fGetNewNations function requests the list of new nations from NS
       When the list is in, it calls the fTelegram function, to send the first TG.
    */
    function fGetNewNations() {
      /* Create an object to send the details to NS */
      var objXhttp = new XMLHttpRequest();
      objXhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          astrNations = this.responseText.split(",");
          fTelegram(0);
        }
      };
      objXhttp.open("GET", "https://www.nationstates.net/cgi-bin/api.cgi?q=newnations", true);
      objXhttp.send();
    }

    /* the fTelegram function sends out the TG, logs a response, then sets a timer to send the next one */
    function fTelegram(intNation) {

      /* If there are still nations to be processed, then process them */
      if (intNation < astrNations.length) {

        /* get the nation name from the list */
        var strNation = astrNations[intNation];

        /* Create an object to send the details to NS */
        var objXhttp = new XMLHttpRequest();

        /* Set the object to update the html paragraph when it gets a response from NS
           When a response is received, update the paragraph.  Then wait before telegramming the next nation.
        */
        objXhttp.onreadystatechange = function() {
          if (objXhttp.readyState == 4) {
            if (objXhttp.status == 200) {
              strMessage = strMessage + "<br>" + strNation + ": OK";
              setTimeout(function(){ fTelegram(intNation + 1) }, intSpeed);
            } else {
              strMessage = strNation + ": Error " + objXhttp.status + ": " + objXhttp.responseText + "<br>" + strMessage;
              setTimeout(function(){ fTelegram(intNation + 1) }, intSpeed);
            }
            document.getElementById("result").innerHTML = strMessage;
          }
        };

        objXhttp.open("GET",
          "https://www.nationstates.net/cgi-bin/api.cgi?a=sendTG&client=" + strClientKey
          + "&tgid=" + strTgId + "&key=" + strSecretKey + "&to=" + strNation.replace(" ", "_"), true);
        objXhttp.send();
      } else {
        strMessage = "Processing Complete<br>" + strMessage;
      }
    }
  </script>
</body>
</html>


Code: Select all
<!DOCTYPE html>

<!-- Wolfram & Hart Telegraph Machine Script v1.2

     Version | Date        | Name           | Comment
     1.0     | 23 Dec 2017 | Wolfram & Hart | Created
     1.2     | 03 Feb 2018 | Wolfram & Hart | Restructured to use Callback function with AJAX request.
             |             |                | Loop added to keep looking for new nations.
             |             |                | Bug fix for 1st and last nation name processing.

     This code is not warranted in any way.  Use at your own risk.

     Use and modify this code as suits.
     Make sure you comply with the NationStates API rules.
     See:  https://www.nationstates.net/pages/api.html 
-->

<head>
  <title>W&H Telegraph Machine</title>
  <style>
    body {background-color: black;}
    div {
      text-align:center;
      color: white;
      font-family: times;
    }
  </style>
</head>

<body>
  <div>
    <h1><span style="font-size:120%;">W</span>OLFRAM <span style="color:red; font-size:120%;">&</span> <span style="font-size:120%;">H</span>ART</h1>
    <h3>Telegraph Machine</h3>
    <br>
    <button type="button" onclick="fMain()">Telegram New Nations</button>
    <p id="err"></p>
    <p id="msg"></p>
  </div>

  <!-- This is the JavaScript that will be run when the button is pressed -->
  <script>

    /* Get a list of the 50 most recently created nations.
       For each nation:
       If the nation accepts recruitment TGs, send one.
       Move on to the next nation.
       When all 50 nations are done, start again.
    */

    /* *******INSERT YOUR OWN CLIENT KEY, TG ID, SECRET KEY AND REGION IN THIS SECTION****** */
    var strClientKey = "abcd1234";
    var strTgId = "12345678";
    var strSecretKey = "123456abcdef";
    var strRegion = "MyRegion";
    /* ************************************************************************************* */

    var intSpdTG = 180000;  // Recruitment TGs can be sent every 180 seconds (note non-recruitment TGs can be sent every 30 seconds)
    var intSpdAPI = 1200;   // Regular API calls to NS can be sent every 1.2 seconds (actually 50 "hits" in 30 seconds, but this seems to work)
    var astrNtns = [];      // An array variable to store the list of new nations
    var intNtn = 0;         // Keep a note of which nation is being processed
    var strErr = "";        // Keep a record of any HTTP errors
    var strMsg = "";        // Keep a record of nations successfully processed

    /* The fMain function is called when the button is pressed.
       Reset displayed paragraphs to be blank, then request a list of new NS nations
    */
    function fMain() {
      strRegion = strRegion.replace(" ", "_");
      strErr = "";
      strMsg = "";
      document.getElementById("err").innerHTML = strErr;
      document.getElementById("msg").innerHTML = strMsg;
      fGetNewNations();
    }

    /* The fGetNewNations function requests the list of new nations from NS */
    function fGetNewNations() {
      fGetXml("https://www.nationstates.net/cgi-bin/api.cgi?q=newnations", fProcessNewNations);
    }

    /* The fProcessNewNations function parses the list of new nations into an array
       It then tries to recruit the first nation (0) on the list
    */
    function fProcessNewNations(objXml) {
      if (objXml.status == 200) {
        astrNtns = objXml.responseXML.getElementsByTagName("NEWNATIONS")[0].childNodes[0].nodeValue.split(",");
        intNtn = 0;
        setTimeout(function(){ fGetCanRecruit() }, intSpdAPI);
      } else {
        strErr = "fGetNewNations Error " + objXml.status + ": " + objXml.responseText + "<br>" + strErr;
        document.getElementById("err").innerHTML = strErr;
      }
    }

    /* The fGetCanRecruit function checks if the nation accepts recruitment TGs
       Sending the optional "from=(region_name)" parameter checks that you didn't send them a TG too recently.
    */
    function fGetCanRecruit() {
      /* First check that there are still nations to process */
      if (intNtn >= astrNtns.length) {
        fGetNewNations();
      } else {
        /* get the nation name from the list */
        var strNtn = astrNtns[intNtn].replace(" ", "_");
        var strUrl = "https://www.nationstates.net/cgi-bin/api.cgi?nation=" + strNtn + "&q=tgcanrecruit&from=" + strRegion
        fGetXml(strUrl, fProcessCanRecruit);
      }
    }
       
    /* The fProcessCanRecruit function:
       If the response is "1", (Nation accepts recruitment TGs), send a TG
       Else, try the next nation
    */
    function fProcessCanRecruit(objXml) {
      if (objXml.status == 200) {
        var strMrkr = objXml.responseXML.getElementsByTagName("TGCANRECRUIT")[0].childNodes[0].nodeValue;
        if (strMrkr == "1") {
          setTimeout(function(){ fTelegram() }, intSpdAPI);
        } else {
          strMsg = intNtn + ": " + astrNtns[intNtn] + ": TG Blocked" + "<br>" + strMsg;
          document.getElementById("msg").innerHTML = strMsg;
          intNtn = intNtn + 1;
          setTimeout(function(){ fGetCanRecruit() }, intSpdAPI);
        }
      } else {
        strErr = "fGetCanRecruit Error " + objXml.status + ": " + objXml.responseText + "<br>" + strErr;
        document.getElementById("err").innerHTML = strErr;
        intNtn = intNtn + 1;
        setTimeout(function(){ fGetCanRecruit() }, intSpdAPI);
      }
    }

    /* The fTelegram function sends out the TG */
    function fTelegram() {
      var strNtn = astrNtns[intNtn].replace(" ", "_");
      var strUrl = "https://www.nationstates.net/cgi-bin/api.cgi?a=sendTG&client="
        + strClientKey + "&tgid=" + strTgId + "&key=" + strSecretKey + "&to=" + strNtn;
      fGetXml(strUrl, fProcessTelegram);
    }

    /* Log the response, then check the next nation */
    function fProcessTelegram(objXml) {
      if (objXml.status == 200) {
        strMsg = intNtn + ": " + astrNtns[intNtn] + ": TG Sent" + "<br>" + strMsg;
        document.getElementById("msg").innerHTML = strMsg;
      } else {
        strErr = "fTelegram Error " + objXml.status + ": " + objXml.responseText + "<br>" + strErr;
        document.getElementById("err").innerHTML = strErr;
      }
      intNtn = intNtn + 1;
      setTimeout(function(){ fGetCanRecruit() }, intSpdTG - intSpdAPI);
    }

    /* fGetXml needs to know the URL to get data from, and the function to run when the data is retrieved. */
    function fGetXml(strUrl, objFn) {
      var objXhttp = new XMLHttpRequest();        // Create an object to send the details to NS
      objXhttp.onreadystatechange = function() {
        if (this.readyState == 4) {
            objFn(this);
        }
      };
      objXhttp.open("GET", strUrl, true);
      objXhttp.send();
    }

  </script>
</body>
</html>
Last edited by Wolfram and Hart on Thu Oct 25, 2018 2:58 pm, edited 4 times in total.

User avatar
Wolfram and Hart
Secretary
 
Posts: 37
Founded: Jul 06, 2017
Father Knows Best State

Postby Wolfram and Hart » Tue Feb 13, 2018 3:12 pm

I've updated the Puppet Login Script. Now on version 1.4. This one displays the region your puppet is in, and a count of any unread notices, TGs, RMB posts, and unanswered issues. It also puts your WA nation at the top of the screen (handy if you forgot where you left your WA!), followed by nations in the Rejected Realms (handy to see if your puppets got booted out of a region).

User avatar
Wolfram and Hart
Secretary
 
Posts: 37
Founded: Jul 06, 2017
Father Knows Best State

Postby Wolfram and Hart » Thu Oct 25, 2018 2:53 pm

Sleeping Beauty

What
This code logs in your puppets, and answers their issues according to pre-defined rules.

When setting up the code, the user gives it a target completion time. This is initially set to 60 minutes, though is easily changed. The code will try to answer issues for all your puppets within this time frame. It may finish sooner. Depending on the number of puppets, it may take longer. Your PC must be switched on the entire time the code is running, else some puppets may not get processed.

The code randomly chooses a time to log in each puppet, subject to the target completion time you give.

The code logs into a puppet, records which region the puppet is in, how many unread notifications, telegrams, RMB posts, and issues there are. If the nation is your WA nation, it will be displayed in red. The code then starts answering issues according to pre-defined rules. The code tries to leave gaps of 20 to 80 seconds between answering issues. The purpose of this delay is to try and make it look like a real player is making considered decisions.

If your target completion time is short, then a keen observer may notice that your puppets log in and answer issues at similar times. If your target completion time is longer, then it is harder for an observer to associate your puppets with each other.

The code allows for puppets to be processed concurrently - so Puppet1 can answer issues inbetween Puppet2's answers to their own issues. This behaviour aims to make it look more like the puppets are controlled by different players.

At the end of processing, the code should display a pop-up stating "Done".

The available pre-defined rules are:
1st: The code will always select the first issue answer that is available to the puppet.
2nd: The code will always select the second issue answer that is available to the puppet.
2nd last: The code will always select the second last issue answer that is available to the puppet.
last: The code will always select the last issue answer that is available to the puppet.
random: The code will always select a random issue answer that is available to the puppet.
If you give the code an unrecognised value for the rule (eg you tell the code to use "first" instead of "1st"), the code will not answer issues for that puppet.

These rules will not allow your puppets to follow a consistent political ideology, or to maximise a particular census score. To do so would require rules that can identify which issue answer was appropriate for your objective, for each of the 1000+ issues.


How
On your PC or laptop, open a text editor, like Notepad. Copy the code (below) into the editor.

Put your own email address in the code (place indicated by all the asterisks).

Put your own Nation names, passwords, and issue-answering styles (pre-defined rules) in the code (place indicated by all the asterisks).

Set your own target completion time (in minutes) in the code (place indicated by all the asterisks).

REMEMBER: If you share your computer, then potentially someone else will have access to your passwords.

Save the file as “SleepingBeauty.html”

Check the filename. If it saved as “SleepingBeauty.html.txt” or similar, rename it to “SleepingBeauty.html”.

When you open the file again, it should get opened in your browser by default. You should see a black page with “Wolfram & Hart” written across the top.

When you click the button, the code should send login requests to NS. NS then sends a response back, which will be displayed on your webpage.


Why
If you don't know why, this code probably isn't for you!


Feedback
If you use this, the Telegram script, or the PuppetMaster Login script, please drop me a telegram. It would be interesting to know how widely these were used.
Any suggestions for improvements and enhancements are welcome.

Code: Select all
<!DOCTYPE html>

<!-- Wolfram & Hart Sleeping Beauty v1.0

     Version | Date        | Name           | Comment
     1.0     | 25 Oct 2018 | Wolfram & Hart | Created

     This code is not warranted in any way.  Use at your own risk.

     Use and modify this code as suits.
     Make sure you comply with the NationStates API rules.
     See:  https://www.nationstates.net/pages/api.html

     Feedback: If you use this script, please drop [nation]Wolfram & Hart[/nation] a telegram. 
     It would be interesting to know how widely this was used (if at all!)
     Any suggestions for improvements and enhancements are welcome.
-->

<head>
  <title>W&H Sleeping Beauty</title>
  <style>
    body {background-color: black;}
    div {
      text-align: center;
      color: white;
      font-family: times;
    }
    table,th,td {
      border : 1px solid white;
      border-collapse: collapse;
    }
    th,td {
      padding: 5px;
    }
  </style>
</head>

<body>
  <div>
    <h1><span style="font-size:120%;">W</span>OLFRAM <span style="color:red; font-size:120%;">&</span> <span style="font-size:120%;">H</span>ART</h1>
    <h3>Sleeping Beauty</h3>
    <br>
    <button type="button" onclick="fMain()">Process Puppets</button>
    <p><i>(Click table header to sort data)</i></p>
    <p id="log"></p>
    <p id="err"></p>
    <table id="msg" align=center><tr>
      <th onclick="fSortNtns('ntn')">Nation</th>
      <th onclick="fSortNtns('rgn')">Region</th>
      <th onclick="fSortNtns('ntc')">Notices</th>
      <th onclick="fSortNtns('tgs')">Telegrams</th>
      <th onclick="fSortNtns('rmb')">RMB</th>
      <th onclick="fSortNtns('iss')">Issues</th>
    </tr></table>
  </div>

  <!-- This is the JavaScript that will be run when the button is pressed -->
  <script>


    /* **********************CHANGE THIS TO USE YOUR OWN EMAIL ADDRESS********************** */
    /* NationStates require a 'UserAgent', so you can be contacted if something goes wrong   */
    var strUserAgent = "myname@email.com";
    /* ************************************************************************************* */


    /* ***********CHANGE THIS ARRAY TO INCLUDE YOUR NATIONS, PASSWORDS, AND STYLES********** */
    var aobjNtns = [
      {nation:"Nation 1", password:"Password1", style:"1st"},
      {nation:"Nation 2", password:"Password2", style:"2nd"},
      {nation:"Nation 3", password:"Password3", style:"2nd last"},
      {nation:"Nation 4", password:"Password4", style:"last"},
      {nation:"Last Nation", password:"LastPassword", style:"random"}
    ];
    /*
    var aobjNtns = [
    ];
    */
    /* ************************************************************************************* */


    /* *****************SET THE TIME (IN MINUTES) TO TRY AND FINISH BY********************** */
    var intEnd = 60;
    /* ************************************************************************************* */


    var strPasswordType = "X-Password";   // Tell NS the format of the above passwords.  This info is needed by NS
    var dteNow;            // Used at various points to record the current time
    var strNtnLast = "";      // Record the last nation processed to determine whether Pin or Password is used for next login.

    var strErr;            // Set variables to record the nations processed.  These are used to update the html.
    var strMsg;
    var strHdr = document.getElementById("msg").innerHTML;
    var strSort = "";

    /* The fMain function:
       Convert the target end time, intEnd, to millisecconds, and subtract estimated required processing times.
       After this convertion, intEnd represents the latest time that the code should start handling a nation.
       Reset the 'msg' table to being blank.
       Put the list of nations into a random order, then adds them to the request queue.
       Tell the code to login the first nation in the queue.
    */
    function fMain() {
      dteNow = new Date().getTime();               // Note the time.  Used when adding nations to the request queue
      intEnd = (intEnd * 60000) - (aobjNtns.length * 1200) - 400000;   // Convert target end time to ms and adjust
      if (intEnd < 0) { intEnd = 1000; };            // Make sure the new end time is at least one second long!
      strErr = "";                     // Reset the message strings and blank out the html
      strMsg = strHdr;
      document.getElementById("err").innerHTML = strErr;
      document.getElementById("msg").innerHTML = strMsg;
      aobjNtns = aobjNtns.map(fRemapNtns);            // Add some extra detail to the nation records
      aobjRqst = aobjNtns.map(fAddNtnsToRqstQueue);         // Add the nations to the request queue
      aobjRqst.sort(fSortWhen);                  // Sort requests into the order in which they'll be made
      fGetXml();                     // Request the first item in the request queue
    }

    /* fRemapNtns expands each Nation object to hold the data that will be returned from NS */
    function fRemapNtns(value, index, array) {
      return {
        name: value.nation,
        ntn: value.nation.toLowerCase().replace(/ /g, "_"),
        styl: value.style.toLowerCase(),
        pwrdtyp: strPasswordType,
        pwrd: value.password,
        pin: "",
        wa: "",
        rgn: "?",
        ntc: -1,
        tgs: -1,
        rmb: -1,
        iss: -1
      };
    }

    /* fAddNtnsToRqstQueue takes the list of nations and passwords, and adds them to a queue of requests to be sent to NS
       Set a random time, based on intEnd, to start handling the nation.
    */
    function fAddNtnsToRqstQueue(value, index, array) {
      return {
        ntn: value.ntn,
        rqst: "&q=wa+name+region+unread+issues",
        pwrdtyp: value.pwrdtyp,
        pwrd: value.pwrd,
        when: dteNow + intEnd * Math.random()
      };
    }

    /* function to sort array by scheduled request time */
    function fSortWhen(a,b) {
      return a.when - b.when;
    }

    /* fGetXml takes the first request to be processed, then requests the XML from NS
       When the result is back, call fProcessXml.
    */
    function fGetXml() {
      if (aobjRqst.length > 0) {
        var objRqst = aobjRqst.shift();            // Take the first item in the queue
        var objXhttp = new XMLHttpRequest();                    // Create an object to send the details to NS
        objXhttp.onreadystatechange = function() {
          if (objXhttp.readyState == 4) {
            if (objXhttp.status == 200) {
              fProcessXml(this);            // When a response is received from NS, process it
            } else {
              if (objXhttp.status == 403) {
                strErr = objRqst.ntn + ": Forbidden (incorrect password?)<br>" + strErr;
              } else if (objXhttp.status == 404) {
                strErr = objRqst.ntn + ": Not Found (nation CTEd / misspelled / doesn't exist?)<br>" + strErr;
              } else if (objXhttp.status == 429) {
                strErr = objRqst.ntn + ": Too Many Requests.  Processing stopped<br>" + strErr;
              } else {
                strErr = objRqst.ntn + ": Error " + objXhttp.status + "<br>" + strErr;
              };
              document.getElementById("err").innerHTML = strErr;
            };
          };
        };
        // Set the details of the request:
        objXhttp.open("GET", "https://www.nationstates.net/cgi-bin/api.cgi?nation=" + objRqst.ntn + objRqst.rqst, true);
        if (objRqst.ntn == strNtnLast) {
          var i = 0;
          while (aobjNtns[i].ntn != strNtnLast) { i++; };         // Find the matching nation in aobjNtns
          objXhttp.setRequestHeader("X-Pin", aobjNtns[i].pin);         // If this request is for the same nation as the last,
          objXhttp.setRequestHeader(objRqst.pwrdtyp, objRqst.pwrd);      // use the Pin.  Send password as well, just in case
        } else {
          objXhttp.setRequestHeader(objRqst.pwrdtyp, objRqst.pwrd);      // Else set to use the password, and
          strNtnLast = objRqst.ntn;                  // record that this nation is now the latest nation
        };
        objXhttp.setRequestHeader("User-Agent", strUserAgent);         // Set to send the User-Agent too
        objXhttp.send();                     // Send the request to NS
      };
    }

    /* fProcess:
       Reads in the XML data.
       Updates the nation with the new Pin
       Works out when to call the routine that sends the next request
    */
    function fProcessXml(objXhttp) {
      dteNow = new Date().getTime();
      var objXML = objXhttp.responseXML;               // Read in the body of the returned data
      var strNtn = objXML.getElementsByTagName("NATION")[0].getAttribute("id");   // Read the nation ID
      var i = 0;
      while (aobjNtns[i].ntn != strNtn) { i++; };            // Find the matching nation in aobjNtns
      var strPin = objXhttp.getResponseHeader("X-Pin");            // Read in the pin from returned data header
      if (strPin != null) { aobjNtns[i].pin = strPin; };         // Assign the pin to the nation
      if (objXML.getElementsByTagName("UNREAD").length > 0) {
        fProcessFirst(objXhttp, strNtn, i);         // If this was the first request for the nation, process accordingly
      } else {
        fProcessIssue(objXML, i);            // If this was the result of answering an issue, process accordingly
      };
      if (aobjRqst.length > 0) {
        var intWhen = aobjRqst[0].when - dteNow;      // If there are more requests in the queue, work out when to send the next
        if (intWhen < 1200) { intWhen = 1200; };
        setTimeout(function(){ fGetXml() }, intWhen);
      } else {
        window.alert("Done");               // Else notify the user that the job is complete
      };
    }

    /* fProcess reads in the XML data.
    */
    function fProcessFirst(objXhttp, strNtn, i) {
      var dteWhen = dteNow;
      var strTmp
      var objXML = objXhttp.responseXML;                     // Read in the body of the returned data
      aobjNtns[i].pwrdtyp = "X-Autologin";
      var strPwrd = objXhttp.getResponseHeader("X-Autologin");               // Read in the password from returned data header
      aobjNtns[i].pwrd = strPwrd;                        // Update the nation with the returned data
      aobjNtns[i].wa = objXML.getElementsByTagName("UNSTATUS")[0].childNodes[0].nodeValue;
      aobjNtns[i].rgn = objXML.getElementsByTagName("REGION")[0].childNodes[0].nodeValue;
      aobjNtns[i].ntc = objXML.getElementsByTagName("NOTICES")[0].childNodes[0].nodeValue;
      aobjNtns[i].tgs = objXML.getElementsByTagName("TELEGRAMS")[0].childNodes[0].nodeValue;
      aobjNtns[i].rmb = objXML.getElementsByTagName("RMB")[0].childNodes[0].nodeValue;
      aobjNtns[i].iss = objXML.getElementsByTagName("ISSUES")[0].childNodes[0].nodeValue;
      var aobjIss = objXML.getElementsByTagName("ISSUE");               // Create an array of the issues data
      var strOpt = "ignore";
      for (var j = 0; j < aobjIss.length; j++) {
        var aobjOpts = aobjIss[j].getElementsByTagName('OPTION');            // For each issue, find the options & choose response
        switch (aobjNtns[i].styl) {
          case "random":
            strOpt = aobjOpts[Math.floor(Math.random() * aobjOpts.length)].getAttribute('id');   // Choose a random answer
            break;
          case "1st":
            strOpt = aobjOpts[0].getAttribute('id');                  // Choose the first available answer
            break;
          case "2nd":
            strOpt = aobjOpts[1].getAttribute('id');                  // Choose the second available answer
            break;
          case "2nd last":
            strOpt = aobjOpts[aobjOpts.length - 2].getAttribute('id');            // Choose the second last answer
            break;
          case "last":
            strOpt = aobjOpts[aobjOpts.length - 1].getAttribute('id');            // Choose the last answer
            break;
        };                                 // Else the default treatment is to ignore issues
        if (strOpt != "ignore") {
          dteWhen = dteWhen + 20000 + 60000 * Math.random();               // Set the gap between issue answers to 20 to 80 seconds
          var objRqst = {
            ntn: strNtn,
            rqst: "&c=issue&issue=" + aobjIss[j].getAttribute("id") + "&option=" + strOpt,
            pwrdtyp: "X-Autologin",
            pwrd: strPwrd,
            when: dteWhen
          };
          aobjRqst.push(objRqst);                        // Add the nation, issue, and answer to the request queue
        };   
      };
      aobjRqst.sort(fSortWhen);                           // Make sure the request queue is in the right order     
      fSortNtns(strSort);                           // Update the visible HTML table
    }   

    /* fProcessIssue:
       Reduces the nation's issue count by one, if an issue was successfully answered
    */
    function fProcessIssue(objXML, i) {
      if (objXML.getElementsByTagName("OK").length > 0) {
        aobjNtns[i].iss = aobjNtns[i].iss - 1;            // If the issue was successfully answered, reduce the number of outstanding issues
        fSortNtns(strSort);                  // Update the visible HTML table
      };
    }

    function fSortNtns(strBy) {
      strSort = strBy; 
      switch (strBy) {
        case "ntn":
          aobjNtns.sort(fSortNtn);
          break;
        case "rgn":
          aobjNtns.sort(fSortRgn);
          break;
        case "ntc":
          aobjNtns.sort(fSortNtc);
          break;
        case "tgs":
          aobjNtns.sort(fSortTgs);
          break;
        case "rmb":
          aobjNtns.sort(fSortRmb);
          break;
        case "iss":
          aobjNtns.sort(fSortIss);
          break;
      };
      fUpdateTable();
    }

    /* function to sort array by nation */
    function fSortNtn(a,b) {
      var x = a.ntn.toLowerCase();
      var y = b.ntn.toLowerCase();
      if (x < y) { return -1; };
      if (x > y) { return 1; };
      return 0;
    }

    /* function to sort array by region */
    function fSortRgn(a,b) {
      var x = a.rgn.toLowerCase();
      var y = b.rgn.toLowerCase();
      if (x < y) { return -1; };
      if (x > y) { return 1; };
      return 0;
    }

    /* function to sort array by nation sort order */
    function fSortNtc(a,b) {
      return b.ntc - a.ntc;
    }

    /* function to sort array by nation sort order */
    function fSortTgs(a,b) {
      return b.tgs - a.tgs;
    }

    /* function to sort array by nation sort order */
    function fSortRmb(a,b) {
      return b.rmb - a.rmb;
    }

    /* function to sort array by nation sort order */
    function fSortIss(a,b) {
      return b.iss - a.iss;
    }

    /*
    */
    function fUpdateTable() {
      var i;
      var strMsg = strHdr;                     // Set the table header
      var strNtc;
      var strTgs;
      var strRmb;
      var strIss;
      for (i = 0; i < aobjNtns.length; i++) {
        if (aobjNtns[i].wa == "WA Member") {
          strMsg = strMsg + "<tr style='color:red;'>";            // Set to display any WA nation in red
        } else {
          strMsg = strMsg + "<tr>";
        };
        strNtc = aobjNtns[i].ntc;                  // If 'unread' counts are unknown, display them as "?"
        if (strNtc < 0) { strNtc = "?" };
        strTgs= aobjNtns[i].tgs;
        if (strTgs < 0) { strTgs = "?" };
        strRmb = aobjNtns[i].rmb;
        if (strRmb < 0) { strRmb = "?" };
        strIss = aobjNtns[i].iss;
        if (strIss < 0) { strIss = "?" };
        strMsg = strMsg + "<td>"
          + aobjNtns[i].name + "</td><td>" + aobjNtns[i].rgn + "</td><td>"
          + strNtc + "</td><td>" + strTgs + "</td><td>"
          + strRmb + "</td><td>" + strIss + "</td></tr>";         // Add details of each nation
      };
      document.getElementById("msg").innerHTML = strMsg;         // Output the complete data to the HTML table
    }
  </script>
</body>
</html>


Edit: Version 1.2. Returns SPDR for each nation. Code skips over unrecognised / CTEd nations instead of stopping.

Code: Select all
<!DOCTYPE html>

<!-- Wolfram & Hart Sleeping Beauty v1.2

     Version | Date        | Name           | Comment
     1.0     | 25 Oct 2018 | Wolfram & Hart | Created
     1.2     | 19 Nov 2018 | Wolfram & Hart | Included SPDR. Continues processing if nation or password invalid.

     This code is not warranted in any way.  Use at your own risk.

     Use and modify this code as suits.
     Make sure you comply with the NationStates API rules.
     See:  https://www.nationstates.net/pages/api.html
-->

<head>
  <title>W&H Sleeping Beauty</title>
  <style>
    body {background-color: black;}
    div {
      text-align: center;
      color: white;
      font-family: times;
    }
    table,th,td {
      border : 1px solid white;
      border-collapse: collapse;
    }
    th,td {
      padding: 5px;
    }
  </style>
</head>

<body>
  <div>
    <h1><span style="font-size:120%;">W</span>OLFRAM <span style="color:red; font-size:120%;">&</span> <span style="font-size:120%;">H</span>ART</h1>
    <h3>Sleeping Beauty</h3>
    <br>
    <button type="button" onclick="fMain()">Process Puppets</button>
    <p><i>(Click table header to sort data)</i></p>
    <p id="log"></p>
    <p id="err"></p>
    <table id="msg" align=center><tr>
      <th onclick="fSortNtns('ntn')">Nation</th>
      <th onclick="fSortNtns('rgn')">Region</th>
      <th onclick="fSortNtns('ntc')">Notices</th>
      <th onclick="fSortNtns('tgs')">Telegrams</th>
      <th onclick="fSortNtns('rmb')">RMB</th>
      <th onclick="fSortNtns('iss')">Issues</th>
      <th onclick="fSortNtns('spdr')">Influence</th>
    </tr></table>
  </div>

  <!-- This is the JavaScript that will be run when the button is pressed -->
  <script>


    /* **********************CHANGE THIS TO USE YOUR OWN EMAIL ADDRESS********************** */
    /* NationStates require a 'UserAgent', so you can be contacted if something goes wrong   */
    var strUserAgent = "myname@email.com";
    /* ************************************************************************************* */


    /* ***********CHANGE THIS ARRAY TO INCLUDE YOUR NATIONS, PASSWORDS, AND STYLES********** */
    var aobjNtns = [
      {nation:"Nation 1", password:"Password1", style:"1st"},
      {nation:"Nation 2", password:"Password2", style:"2nd"},
      {nation:"Nation 3", password:"Password3", style:"2nd last"},
      {nation:"Nation 4", password:"Password4", style:"last"},
      {nation:"Last Nation", password:"LastPassword", style:"random"}
    ];
    /* ************************************************************************************* */


    /* *****************SET THE TIME (IN MINUTES) TO TRY AND FINISH BY********************** */
    var intEnd = 60;
    /* ************************************************************************************* */


    var strPasswordType = "X-Password";   // Tell NS the format of the above passwords.  This info is needed by NS
    var dteNow;            // Used at various points to record the current time
    var strNtnLast = "";      // Record the last nation processed to determine whether Pin or Password is used for next login.

    var strErr;            // Set variables to record the nations processed.  These are used to update the html.
    var strMsg;
    var strHdr = document.getElementById("msg").innerHTML;
    var strSort = "";

    /* The fMain function:
       Convert the target end time, intEnd, to millisecconds, and subtract estimated required processing times.
       After this convertion, intEnd represents the latest time that the code should start handling a nation.
       Reset the 'msg' table to being blank.
       Put the list of nations into a random order, then adds them to the request queue.
       Tell the code to login the first nation in the queue.
    */
    function fMain() {
      dteNow = new Date().getTime();               // Note the time.  Used when adding nations to the request queue
      intEnd = (intEnd * 60000) - (aobjNtns.length * 1200) - 400000;   // Convert target end time to ms and adjust
      if (intEnd < 0) { intEnd = 1000; };            // Make sure the new end time is at least one second long!
      strErr = "";                     // Reset the message strings and blank out the html
      strMsg = strHdr;
      document.getElementById("err").innerHTML = strErr;
      document.getElementById("msg").innerHTML = strMsg;
      aobjNtns = aobjNtns.map(fRemapNtns);            // Add some extra detail to the nation records
      aobjRqst = aobjNtns.map(fAddNtnsToRqstQueue);         // Add the nations to the request queue
      aobjRqst.sort(fSortWhen);                  // Sort requests into the order in which they'll be made
      fGetXml();                     // Request the first item in the request queue
    }

    /* fRemapNtns expands each Nation object to hold the data that will be returned from NS */
    function fRemapNtns(value, index, array) {
      return {
        name: value.nation,
        ntn: value.nation.toLowerCase().replace(/ /g, "_"),
        styl: value.style.toLowerCase(),
        pwrdtyp: strPasswordType,
        pwrd: value.password,
        pin: "",
        wa: "",
        rgn: "?",
        ntc: -1,
        tgs: -1,
        rmb: -1,
        iss: -1,
        spdr: -1
      };
    }

    /* fAddNtnsToRqstQueue takes the list of nations and passwords, and adds them to a queue of requests to be sent to NS
       Set a random time, based on intEnd, to start handling the nation.
    */
    function fAddNtnsToRqstQueue(value, index, array) {
      return {
        ntn: value.ntn,
        rqst: "&q=wa+name+region+unread+issues+census;scale=65;mode=score",
        pwrdtyp: value.pwrdtyp,
        pwrd: value.pwrd,
        when: dteNow + intEnd * Math.random()
      };
    }

    /* function to sort array by scheduled request time */
    function fSortWhen(a,b) {
      return a.when - b.when;
    }

    /* fGetXml takes the first request to be processed, then requests the XML from NS
       When the result is back, call fProcessXml.
    */
    function fGetXml() {
      if (aobjRqst.length > 0) {
        var objRqst = aobjRqst.shift();            // Take the first item in the queue
        var objXhttp = new XMLHttpRequest();                    // Create an object to send the details to NS
        objXhttp.onreadystatechange = function() {
          if (objXhttp.readyState == 4) {
            if (objXhttp.status == 200) {
              fProcessXml(this);            // When a response is received from NS, process it
            } else {
              if (objXhttp.status == 403) {
                strErr = objRqst.ntn + ": Forbidden (incorrect password?)<br>" + strErr;
                fGetNext();
              } else if (objXhttp.status == 404) {
                strErr = objRqst.ntn + ": Not Found (nation CTEd / misspelled / doesn't exist?)<br>" + strErr;
                fGetNext();
              } else if (objXhttp.status == 429) {
                strErr = objRqst.ntn + ": Too Many Requests.  Processing stopped<br>" + strErr;
              } else {
                strErr = objRqst.ntn + ": Error " + objXhttp.status + "<br>" + strErr;
              };
              document.getElementById("err").innerHTML = strErr;
            };
          };
        };
        // Set the details of the request:
        objXhttp.open("GET", "https://www.nationstates.net/cgi-bin/api.cgi?nation=" + objRqst.ntn + objRqst.rqst, true);
        if (objRqst.ntn == strNtnLast) {
          var i = 0;
          while (aobjNtns[i].ntn != strNtnLast) { i++; };         // Find the matching nation in aobjNtns
          objXhttp.setRequestHeader("X-Pin", aobjNtns[i].pin);         // If this request is for the same nation as the last,
          objXhttp.setRequestHeader(objRqst.pwrdtyp, objRqst.pwrd);      // use the Pin.  Send password as well, just in case
        } else {
          objXhttp.setRequestHeader(objRqst.pwrdtyp, objRqst.pwrd);      // Else set to use the password, and
          strNtnLast = objRqst.ntn;                  // record that this nation is now the latest nation
        };
        objXhttp.setRequestHeader("User-Agent", strUserAgent);         // Set to send the User-Agent too
        objXhttp.send();                     // Send the request to NS
      };
    }

    /* fGetNext sets up when to call fGetXML again */
    function fGetNext() {
      dteNow = new Date().getTime();
      if (aobjRqst.length > 0) {
        var intWhen = aobjRqst[0].when - dteNow;      // If there are more requests in the queue, work out when to send the next
        if (intWhen < 1200) { intWhen = 1200; };
        setTimeout(function(){ fGetXml() }, intWhen);
      } else {
        window.alert("Done");               // Else notify the user that the job is complete
      };
    }

    /* fProcess:
       Reads in the XML data.
       Updates the nation with the new Pin
       Works out when to call the routine that sends the next request
    */
    function fProcessXml(objXhttp) {
      // dteNow = new Date().getTime();
      var objXML = objXhttp.responseXML;               // Read in the body of the returned data
      var strNtn = objXML.getElementsByTagName("NATION")[0].getAttribute("id");   // Read the nation ID
      var i = 0;
      while (aobjNtns[i].ntn != strNtn) { i++; };            // Find the matching nation in aobjNtns
      var strPin = objXhttp.getResponseHeader("X-Pin");            // Read in the pin from returned data header
      if (strPin != null) { aobjNtns[i].pin = strPin; };         // Assign the pin to the nation
      if (objXML.getElementsByTagName("UNREAD").length > 0) {
        fProcessFirst(objXhttp, strNtn, i);         // If this was the first request for the nation, process accordingly
      } else {
        fProcessIssue(objXML, i);            // If this was the result of answering an issue, process accordingly
      };
      fGetNext();
    }

    /* fProcess reads in the XML data.
    */
    function fProcessFirst(objXhttp, strNtn, i) {
      var dteWhen = dteNow;
      var strTmp
      var objXML = objXhttp.responseXML;                     // Read in the body of the returned data
      aobjNtns[i].pwrdtyp = "X-Autologin";
      var strPwrd = objXhttp.getResponseHeader("X-Autologin");               // Read in the password from returned data header
      aobjNtns[i].pwrd = strPwrd;                        // Update the nation with the returned data
      aobjNtns[i].wa = objXML.getElementsByTagName("UNSTATUS")[0].childNodes[0].nodeValue;
      aobjNtns[i].rgn = objXML.getElementsByTagName("REGION")[0].childNodes[0].nodeValue;
      aobjNtns[i].ntc = objXML.getElementsByTagName("NOTICES")[0].childNodes[0].nodeValue;
      aobjNtns[i].tgs = objXML.getElementsByTagName("TELEGRAMS")[0].childNodes[0].nodeValue;
      aobjNtns[i].rmb = objXML.getElementsByTagName("RMB")[0].childNodes[0].nodeValue;
      aobjNtns[i].iss = objXML.getElementsByTagName("ISSUES")[0].childNodes[0].nodeValue;
      aobjNtns[i].spdr = Number(objXML.getElementsByTagName("SCORE")[0].childNodes[0].nodeValue);
      var aobjIss = objXML.getElementsByTagName("ISSUE");               // Create an array of the issues data
      var strOpt = "ignore";
      for (var j = 0; j < aobjIss.length; j++) {
        var aobjOpts = aobjIss[j].getElementsByTagName('OPTION');            // For each issue, find the options & choose response
        switch (aobjNtns[i].styl) {
          case "random":
            strOpt = aobjOpts[Math.floor(Math.random() * aobjOpts.length)].getAttribute('id');   // Choose a random answer
            break;
          case "1st":
            strOpt = aobjOpts[0].getAttribute('id');                  // Choose the first available answer
            break;
          case "2nd":
            strOpt = aobjOpts[1].getAttribute('id');                  // Choose the second available answer
            break;
          case "2nd last":
            strOpt = aobjOpts[aobjOpts.length - 2].getAttribute('id');            // Choose the second last answer
            break;
          case "last":
            strOpt = aobjOpts[aobjOpts.length - 1].getAttribute('id');            // Choose the last answer
            break;
        };                                 // Else the default treatment is to ignore issues
        if (strOpt != "ignore") {
          dteWhen = dteWhen + 20000 + 60000 * Math.random();               // Set the gap between issue answers to 20 to 80 seconds
          var objRqst = {
            ntn: strNtn,
            rqst: "&c=issue&issue=" + aobjIss[j].getAttribute("id") + "&option=" + strOpt,
            pwrdtyp: "X-Autologin",
            pwrd: strPwrd,
            when: dteWhen
          };
          aobjRqst.push(objRqst);                        // Add the nation, issue, and answer to the request queue
        };   
      };
      aobjRqst.sort(fSortWhen);                           // Make sure the request queue is in the right order     
      fSortNtns(strSort);                           // Update the visible HTML table
    }   

    /* fProcessIssue:
       Reduces the nation's issue count by one, if an issue was successfully answered
    */
    function fProcessIssue(objXML, i) {
      if (objXML.getElementsByTagName("OK").length > 0) {
        aobjNtns[i].iss = aobjNtns[i].iss - 1;            // If the issue was successfully answered, reduce the number of outstanding issues
        fSortNtns(strSort);                  // Update the visible HTML table
      };
    }

    function fSortNtns(strBy) {
      strSort = strBy; 
      switch (strBy) {
        case "ntn":
          aobjNtns.sort(fSortNtn);
          break;
        case "rgn":
          aobjNtns.sort(fSortRgn);
          break;
        case "ntc":
          aobjNtns.sort(fSortNtc);
          break;
        case "tgs":
          aobjNtns.sort(fSortTgs);
          break;
        case "rmb":
          aobjNtns.sort(fSortRmb);
          break;
        case "iss":
          aobjNtns.sort(fSortIss);
          break;
        case "spdr":
          aobjNtns.sort(fSortSpdr);
          break;
      };
      fUpdateTable();
    }

    /* function to sort array by nation */
    function fSortNtn(a,b) {
      var x = a.ntn.toLowerCase();
      var y = b.ntn.toLowerCase();
      if (x < y) { return -1; };
      if (x > y) { return 1; };
      return 0;
    }

    /* function to sort array by region */
    function fSortRgn(a,b) {
      var x = a.rgn.toLowerCase();
      var y = b.rgn.toLowerCase();
      if (x < y) { return -1; };
      if (x > y) { return 1; };
      return 0;
    }

    /* function to sort array by notices */
    function fSortNtc(a,b) {
      return b.ntc - a.ntc;
    }

    /* function to sort array by telegrams */
    function fSortTgs(a,b) {
      return b.tgs - a.tgs;
    }

    /* function to sort array by RMB posts */
    function fSortRmb(a,b) {
      return b.rmb - a.rmb;
    }

    /* function to sort array by Issues */
    function fSortIss(a,b) {
      return b.iss - a.iss;
    }

    /* function to sort array by SPDR */
    function fSortSpdr(a,b) {
      return b.spdr - a.spdr;
    }

    /*
    */
    function fUpdateTable() {
      var i;
      var strMsg = strHdr;                     // Set the table header
      var strNtc;
      var strTgs;
      var strRmb;
      var strIss;
      var strSpdr;
      for (i = 0; i < aobjNtns.length; i++) {
        if (aobjNtns[i].wa == "WA Member") {
          strMsg = strMsg + "<tr style='color:red;'>";            // Set to display any WA nation in red
        } else {
          strMsg = strMsg + "<tr>";
        };
        strNtc = aobjNtns[i].ntc;                  // If 'unread' counts are unknown, display them as "?"
        if (strNtc < 0) { strNtc = "?" };
        strTgs= aobjNtns[i].tgs;
        if (strTgs < 0) { strTgs = "?" };
        strRmb = aobjNtns[i].rmb;
        if (strRmb < 0) { strRmb = "?" };
        strIss = aobjNtns[i].iss;
        if (strIss < 0) { strIss = "?" };
        strSpdr = aobjNtns[i].spdr;
        if (strSpdr < 0) { strSpdr = "?" };
        strMsg = strMsg + "<td>"
          + aobjNtns[i].name + "</td><td>" + aobjNtns[i].rgn + "</td><td>"
          + strNtc + "</td><td>" + strTgs + "</td><td>"
          + strRmb + "</td><td>" + strIss + "</td><td>"
          + strSpdr + "</td></tr>";                  // Add details of each nation
      };
      document.getElementById("msg").innerHTML = strMsg;         // Output the complete data to the HTML table
    }
  </script>
</body>
</html>
Last edited by Wolfram and Hart on Mon Nov 19, 2018 2:48 pm, edited 2 times in total.

User avatar
Wolfram and Hart
Secretary
 
Posts: 37
Founded: Jul 06, 2017
Father Knows Best State

Postby Wolfram and Hart » Mon Nov 19, 2018 2:50 pm

Sleeping Beauty updated following feedback. Thanks for the new ideas!

User avatar
Augustus Rex
Lobbyist
 
Posts: 23
Founded: Feb 11, 2018
Ex-Nation

Postby Augustus Rex » Mon Nov 19, 2018 5:28 pm

As an ex-raider, thank you for this tool! Keeps the raiding fun w/o needing to answer drab issues
Formerly known as Gibraltarica

Previous

Advertisement

Remove ads

Return to Gameplay

Who is online

Users browsing this forum: Fereiland, Todd McCloud

Advertisement

Remove ads