Stunts Forum

Race for Kicks => General Chat - R4K => Topic started by: dreadnaut on August 20, 2021, 06:30:10 PM

Title: Track information
Post by: dreadnaut on August 20, 2021, 06:30:10 PM
Hello Cas and KyLiE,

I was considering re-adding the list of active races to the stunts.hu portal, at the very top. Would you be able to add something like the track.json (http://zak.stunts.hu/track.json) on ZakStunts? It can be a file or a script as you prefer, as long as it outputs the same format.

This is how ZakStunts generates it:
Code: (php) [Select]
    $current_track = Tracks::getCurrentTrack();

    $track_name = "{$current_track->name} - {$current_track->title}";
    $track_url  = "http://zak.stunts.hu/tracks/{$current_track->name}";
    $author     = $current_track->author;
    $deadline   = date('r', strtotime($current_track->end_date) + 86399);

    header('Content-Type: application/json');
    echo json_encode([
      'competition' => [
        'name'     => 'ZakStunts',
        'url'      => 'http://zak.stunts.hu',
      ],
      'track' => [
        'name'     => $track_name,
        'file'     => $track_url . '.trk',
        'url'      => $track_url,
        'deadline' => $deadline,
        'author'   => $author,
      ]
    ]);
Title: Re: Track information
Post by: KyLiE on August 21, 2021, 11:05:13 AM
I can't see why not.  I'll check with Cas as he is the one responsible for all the PHP code on Race For Kicks.
Title: Re: Track information
Post by: Cas on August 21, 2021, 11:13:06 PM
Hi!  Yes, that would be a very good thing to do. However, there's a catch. Even though so far Race For Kicks has been featuring only one active race all the time, it actually does not have a "current race", but an arbitrary number of "active races". It could theoretically feature more than one race at the same time with different starting and finishing dates. How would you like that to be represented?  In the future, at some point, it will happen that more than one race are running together. Additionally, while normally, a race name is the same as the track title, there is the ability for R4K to have an "event name", so that two different races on a same track have different names or a special event can be called for what it is, even if the track has another name (for example, "Race for Immortality" was an event raced on the track called "Bliss"). This is even more likely to happen in the future. What would you suggest us to do about that?  Cheers!
Title: Re: Track information
Post by: dreadnaut on August 23, 2021, 11:21:12 PM
Those are very good points you make Cas, the format should be flexible enough to cater for multiple races and tracks. What about this:

Code: [Select]
{
  "website": {
    "name": "ZakStunts",
    "url": "http://zak.stunts.hu"
  },
  "races": [
    {
      "name": "ZCT242 - Full Fontal",
      "url": "http://zak.stunts.hu/tracks/ZCT242",
      "deadline": "Sat, 18 Sep 2021 23:59:59 +0200",
      "track": {
        "title": "Full Fontal",
        "author": "Overdrijf",
        "file": "http://zak.stunts.hu/tracks/ZCT242.trk"
      }
    },
    {
      ...
    }
  ]
}

races would be an array with all the active races. Name is the name of the race, and there's a separate track record for the track details, which could be optional.
Title: Re: Track information
Post by: Cas on August 24, 2021, 03:54:03 AM
That looks good!  I'll make sure to add that to the code. It will take me a little bit because there's one thing it's currently doing in an untidy way that I've been wanting to change and I need to get that fixed before, but... maybe that's easier to fix than I expected and I could get all this working tonight.

Right now, I'm already working on R4K, adding a few security patches. The most important one is that R4K was storing passwords complete and as plain text. Unforgivable, I know!  But now that's fixed and passwords are going to be hashed. Of course, the directory was protected and inaccessible from outside the server anyway. So, now that I'm at it, I think I can add this in the same run :)

EDIT: OK... I *think* I did it. Please test it. Only thing I didn't know how to do was creating a nameless array that can be differentiated, so the race ID is used as an axis. You'll see what I mean when you parse the file. I'm sure it'll be no problem for you, but you'll certainly know the right way. Oops!  I'm unable to access the FTP, so I can't upload it. It looks like my IP changed again. I'll soon be uploading the changes!

ANOTHER EDIT: I forgot to mention that, once it's working, this information is saved to a file at http://www.raceforkicks.com/stunts-hu.api
Title: Re: Track information
Post by: dreadnaut on August 24, 2021, 07:16:23 PM
Only thing I didn't know how to do was creating a nameless array that can be differentiated, so the race ID is used as an axis. You'll see what I mean when you parse the file.

You can add elements without an index by... not using an index ;D

Code: [Select]
~$ php -a
php > $a = array();
php > $a[] = 77;
php > $a[] = 123;
php > echo json_encode($a);
[77,123]

Otherwise, you can remove the keys and keep only the values with array_values() (http://php.net/array_values).


Regarding the name, maybe we can go for something generic like races.json ?
Title: Re: Track information
Post by: Cas on August 25, 2021, 02:30:34 PM
Oh!  It never occurred to me that it could be so simple!

The code is uploaded already and you can test the file, although I have not changed the name or the index yet

I would need to update the interface used for non-web integration (such as Bliss) via the tour.cfg file, as this one still can only show the last race and no event information. I haven't touched this file because I don't want to break compatibility with older versions of Bliss, so I'll have to think carefully of a way to do it. I don't want to use the json format for exchange outside the web, since it's very complex to parse and bugs become more likely. Within the web, you just use a pre-made function, so no problem.
Title: Re: Track information
Post by: dreadnaut on August 25, 2021, 08:38:53 PM
The code is uploaded already and you can test the file, although I have not changed the name or the index yet

Thank you! A couple of small things to fix:

Title: Re: Track information
Post by: Cas on August 26, 2021, 04:42:06 AM
Alright... This is what happened:
Attached is is what I got when I removed the indices. You surely can hint me on what I could be doing wrong. Each line, as displayed by the browser when the file is open directly, would get its own "index number" and all would be separated. This is a code snippet from the part that generates this:

Code: [Select]
$j["races"][$raceid]["url"] = "http://www.raceforkicks.com/index.php?page=race&race=" . $raceid;
$j["races"][$raceid]["deadline"] = $dl;

$j["races"][$raceid]["track"]["title"] = $md["Titl"];
$j["races"][$raceid]["track"]["author"] = $md["Autr"];
$j["races"][$raceid]["track"]["file"] = "http://www.raceforkicks.com/" . TRACKS . $race["track"] . ".trk";

For the version I attached, I had simply removed the "$raceid" from every line.
The file currently shows the version with the indices and the changes I described, if you want to test it!
Title: Re: Track information
Post by: dreadnaut on August 26, 2021, 07:17:02 PM
The tricky bit is that every time you assign $a[] = ..., you add a new element to the array. So you need to prepare the record for the race, and add it in one operation. For example:

Code: [Select]
$record = [
  "url" => "http://www.raceforkicks.com/index.php?page=race&race={$raceid}",
  "deadline" => $dl,
  "track" => [
    "title" => $md["Titl"],
    "author" => $md["Autr"],
    "file" => "http://www.raceforkicks.com/" . TRACKS . $race["track"] . ".trk",
  ],
];

$j["races"][] = $record;

Regarding the timezone, maybe there's a different default timezone set? Try resetting it (http://php.net/date_default_timezone_set) at the start of your PHP script:
Code: [Select]
date_default_timezone_set("UTC");

Note that you can also get more readable output with this option:
Code: [Select]
$text = json_encode($j, JSON_PRETTY_PRINT);
Title: Re: Track information
Post by: Cas on August 26, 2021, 09:15:49 PM
Ah!  Now I got you about the "un-indices" :D  I didn't know about the default time zone. I've been forcing it with gmdate(). And I'll have to try that JSON_PRETTY_PRINT to know what it is about. I suppose that won't change how the parser interprets the contents, right?
Title: Re: Track information
Post by: dreadnaut on August 27, 2021, 12:31:40 AM
I suppose that won't change how the parser interprets the contents, right?
It just adds whitespace to create indentation. It's good for reading and debugging, or if you don't care about how many characters you are using.
Title: Re: Track information
Post by: Cas on August 31, 2021, 01:23:24 AM
Alright!  I changed the code so now the index is undefined and it seems to work well!
Title: Re: Track information
Post by: dreadnaut on August 31, 2021, 07:13:25 PM
Alright!  I changed the code so now the index is undefined and it seems to work well!

Thanks Cas, I'll use it in the next days :)
Title: Re: Track information
Post by: dreadnaut on September 24, 2021, 10:12:20 PM
I've got this working and I can load the races, no issues there. However, there was a flaw in my plan: retrieving the data can take some time, making the portal 3-4× slower to load. What if, instead of ZakStunts asking RaceForKicks about the current race, it worked the other way around?

Instead of calling to see what's the current race, I would add a script at, for example, stunts.hu/register-race, waiting for incoming requests. When you create a new race on RaceForKicks, you could send a POST request to that address, with the same data we have discussed above.

When the request arrives, I can verify that it comes from you, and store the information about the race in the database, and the will appear in the portal at the right time 8)   Bonus: we get a second archive of races: title, URL, dates, etc.

How does it sound? I can define this better if it seems doable to you.
Title: Re: Track information
Post by: Cas on September 24, 2021, 11:57:18 PM
That sounds very reasonable. With the current method, an inter-site read has to be made every time somebody loads stunts.hu, while with what you suggest, the slowdown would only occur twice a month, when a race is started or ends in Race For Kicks.

I have thoughts of ideas similar to this before, but I haven't yet done it. So far, I'm familiar with sending a POST when the user presses a Submit button, but I don't know how to trigger a POST with a PHP function. I would have to read more about that. Then, I suppose I'd be creating an HTTP form with the necessary information to be sent via POST, only instead of it being triggered by a button, it would be unconditionally sent somehow.

Another thing I don't know is how to have website A send a POST to website B without it resulting in website B being loaded on the browser, instead keeping the same page being browsed.

If you can more or less hint me on these things, I can start to make a picture of what it would be like and I'm sure I can do it.
Title: Re: Track information
Post by: dreadnaut on September 25, 2021, 12:52:22 AM
[...] the slowdown would only occur twice a month, when a race is started or ends in Race For Kicks.

If we add the start date of the race next to the end date, then it should be enough to only send information once, when you add the race to your website.

If you can more or less hint me on these things, I can start to make a picture of what it would be like and I'm sure I can do it.

There's a few ways in PHP. One is with the "curl" functions, but they are quite complex and have tons of options to keep track of. An easier one is to use file_get_contents().

A non-obvious feature of file_get_contents is that is can do HTTP calls, for example to retrieve the content of a page:
Code: [Select]
$page = file_get_contents('http://raceforkicks.com');

That would be a GET request, but with some options you can convince it to do a POST as well:

Code: [Select]
$race_for_kicks_data = [
  'website' => ...
  'races' => ...
];

$context = stream_context_create([ 'http' => [
  'method' => 'POST',
  'header' => 'Content-Type: application/x-www-form-urlencoded',
  'content' => http_build_query($race_for_kicks_data),
]]);

$response = file_get_contents('http://stunts.hu/register-race', false, $context);

The above would send a POST request to the stunts.hu address, with the form data in $race_for_kicks_data. The receiving script could reply OK!, and that would end up in $response.
Title: Re: Track information
Post by: Cas on September 26, 2021, 03:54:50 AM
Wow!  That looks a lot simpler than I expected!
I don't have much time today, but I'll certainly be updating that soon
Title: Re: Track information
Post by: dreadnaut on September 26, 2021, 09:32:40 AM
I don't have much time today, but I'll certainly be updating that soon

No rush! I can prepare things on the ZakStunts side, so you have something to test against.
Title: Re: Track information
Post by: dreadnaut on September 27, 2021, 05:05:15 PM
Here I am! The ZakStunts side is ready: you can now register "events" that will eventually appear on the portal, be they races or competitions, etc.

I've attached a minimal client for the API, so you don't have to write much code. It works like this:
Code: [Select]
require 'ZakStuntsApi.php';

$api = new ZakStuntsApi('<your API client id>', '<your API client secret>');

$response = $api->updateEvent([
  "id"           => "r4k-2021-09",
  "name"         => "2021-09 - Tropical Springs Stunt Park",
  "url"          => "http://www.raceforkicks.com/index.php?page=race&race=2021-09",
  "opens_on"     => "2021-09-01T15:59:00+02:00",
  "closes_on"    => "2021-09-27T01:59:00+02:00",
// these fields are optional, all three or none
  "track_title"  => "Tropical Springs Stunt Park",
  "track_author" => "KyLiE",
  "track_url"    => "http://www.raceforkicks.com/tracks/r4k14.trk"
]);

echo var_export($response, true);

The id is whatever you want to use to identify the race. As long as you use the same one, you can update the event information as many times as you want.

If the update goes well, it will return "status" => 200. Otherwise, you should get a useful error message.

I'll send you credentials through a different channel ;)
Title: Re: Track information
Post by: Cas on September 28, 2021, 01:16:04 AM
Uhm... now I'm a little lost. I had understood the previous post, but now I downloaded the API php file and I'm not sure how the thing works. My confusion may have to do with the OOP structure, as I always write procedure oriented code, but I think there's probably something more I haven't understood.

Anyway, is stunts.hu already waiting for a message?  If I get this working, will it reflect the changes?  This is, I would like to begin testing and want to make sure when the thing starts working. I already got the information you sent me via e-mail.