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:
$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,
]
]);
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.
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!
Those are very good points you make Cas, the format should be flexible enough to cater for multiple races and tracks. What about this:
{
"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.
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
Quote from: Cas on August 24, 2021, 03:54:03 AM
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
~$ 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 ?
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.
Quote from: Cas on August 25, 2021, 02:30:34 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:
- Instead of website and url at top level, could you have title and url inside a website record? (see example above)
- could you format deadline to include time and timezone? You can get a standard format with date('r', ...), which I can then parse using strtotime() (http://php.net/strtotime)
- you have already mentioned the indexes :)
Alright... This is what happened:
- I noticed what you pointed out about the website and URL, so I corrected it and now it's good
- I changed the deadline format at first copying from your code, but that resulted in a -0300 timezone, which is strangely local in Argentina, yet the server is in Australia. Anyway, Race For Kicks turns the clock at midnight UTC, so I changed it to display "UTC". It's not exactly the same format you use, but you can easily convert it into what you need. Besides, I like it more this way, ha, ha. Just let me know
- I thought I had understood the issue with the indices, but when I tried removing them, I didn't get what I expected, so I reverted to using indices again. I'll need a deeper explanation on the matter :P
- I renamed the file to webapi-races.json. Now the extension agrees with the format. I wouldn't want to just use "races.json", as its simplicity suggests it's the standard way of retrieving race information from R4K while this is done through tour.cfg.
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:
$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!
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:
$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:
date_default_timezone_set("UTC");
Note that you can also get more readable output with this option:
$text = json_encode($j, JSON_PRETTY_PRINT);
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?
Quote from: Cas on August 26, 2021, 09:15:49 PM
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.
Alright! I changed the code so now the index is undefined and it seems to work well!
Quote from: 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!
Thanks Cas, I'll use it in the next days :)
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.
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.
Quote from: Cas on September 24, 2021, 11:57:18 PM
[...] 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.
Quote from: Cas on September 24, 2021, 11:57:18 PM
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:
$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:
$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.
Wow! That looks a lot simpler than I expected!
I don't have much time today, but I'll certainly be updating that soon
Quote from: Cas on September 26, 2021, 03:54:50 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.
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:
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 ;)
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.
Alright... I've been analysing the code carefully. It seems that what gets me confused is mostly the OOP structure, but also, the fact that I'm unable to see the information I'm passing or receiving. If I can somehow test this, I'll be able to understand it better.
So, what I see is I need to have this client ID and client secret to be able to send the message. I think you had sent me this via e-mail at some point, but I'm not finding it. If you can please do it again, I'll be able to send a test. Is stunts.hu ready to respond and will it update visibly if I send it a message now?
Another thing I'd like to know is a detail about IDs and updating races. Suppose a race called "race1" is running now and is due to end on day 25. I understand that, if I want to change the deadline live, I can use the "race1" ID and pass a new deadline and it'll be updated in the portal. Now, say this race hasn't ended, but now a new race is scheduled for day 31... can I use the ID "race2" for this new race to set it as "scheduled"? Or will this cause the portal now to only show the scheduled race and no longer the ongoing one? This is a question mostly to understand what to expect. We don't normally schedule races until a few days after a race is over, but R4K allows it.
The portal has now gained some new API features: https://github.com/dreadnaut/stunts-portal-api
The webpage changes will follow soon :)
That looks really nice!
Alright, I've been able to adapt the code in R4K to communicate with the API and it's working fine. The API response is good. If there's anything to fine tune later, just let me know :)
Far too late at night :o But the portal now shows timely events, in some draft arrangement.
It looks great! Thank you!
Nice work! :) Thanks!
That's really cool! Thanks for your work!
Seeing the races together feels very comfortable because you naturally know where you are in each, what's in more hurry, when a new race has started, etc :)
When our race ends and we schedule the next one, we'll have a chance to test how that part works and fix whatever might be buggy on our end.
I'll see about incorporating these changes to EasyTour so that they can be applied on the other two tournaments as well
A couple of things to mention:
- I can see that the general tournament details are no longer shown and I realise that it's not easy to decide on where to put them or how to organise them. Putting them all there like before would push the current race information down and make it less immediate and that's more important information. If I can help with anything there, just let me know
- I see that all tournaments show their dates in CEST. While it makes things clearer to use a single time zone for all dates instead of mixing, I think ZakStunts uses CEST because of its Hungarian origins and currently we have very few Hungarian members. I think most people in the community now are under UTC+1. Race For Kicks, although its origins are Argentine and is now run from Australia, has always used UTC(+0) because it's a global tournament. I think if we have to settle for one time zone, it'd make more sense to use either UTC or UTC+1. My personal opinion.
Quote from: Cas on June 16, 2023, 07:42:41 PMI think ZakStunts uses CEST because of its Hungarian origins and currently we have very few Hungarian members. I think most people in the community now are under UTC+1
Hungary is in Central Europe, and uses the same timezone: CET in winter (UTC+1), and CEST in summer (UTC+2).
A more precise approach would be the "Continent/Capital" method, which takes into account daylight saving time schedules. ZakStunts thinks in
Europe/Budapest terms, and since the original data did not include timezone information it'll take a bit of work to make customisable.
The portal inherited the timezone, living on stunts.hu, but it could gain a "set your timezone option" 👍
Yeah, this is just a suggestion and it's not very important really. I just thought it'd be more balanced that way. It already looks great
I love the look as well.
Two things I am missing in the competition's (not relevant to ZakStunts) is, the car(s) allowed and the description text (or part of it).
Now we have the description :) It looks good. I think that cars allowed could be placed to the right of the track title, below the description and on top of the race time bar. Instead of placing it as text, the cars could be displayed by icon. We could send the car ID(s) for current race in the form. Hovering over the car icon could show the car name. Of course, in this case, ZakStunts would have 16 car icons, which is a lot, but could fit a 4x4 grid.
Alternatively, there could be a "See available cars" thingy that you hover on and pulls down a dialog with the current available car list (which could be text or icons). Or a mix: show up to say, four cars, and if there are more, add a plus sign that you hover and reads "see all available cars"; you click on it and it shows you. Just throwing out ideas :)