Gridhaul: Difference between revisions

From GridPlay
No edit summary
 
(27 intermediate revisions by the same user not shown)
Line 14: Line 14:
|image = GridHaul.png
|image = GridHaul.png
|leader = [[venkellie]]
|leader = [[venkellie]]
|members = 10
|members = 27
}}
}}
===HUD===
===HUD===
Line 24: Line 24:
Updating your hub is easy, right click the old one, select Delete, rez out the new one<br>
Updating your hub is easy, right click the old one, select Delete, rez out the new one<br>
Minimum parcel size is 256 sqm
Minimum parcel size is 256 sqm
===Hub Webconfig===
First off the web config is version 1 so the code is kinda dated.<br>
From the web config you can edit your hub name, add a texture UUID (in world texture) and info about your hub to show on the website and what types of vehicles your hub can accept.<br>
Below that is a list of all items you can buy for your hub, this uses gridhaul G$ dollars to buy items so please try the game first before buying stuff for your hub.<br>
You can also sell items that is in your hub for G$.<br>
With 2.0 on the way upgrading your terminal is as easy as rezzing out the new one, yes thats it.<br>
Our system goes by your parcel's UUID key, not a stored key in the terminal prim.


==API==
==API==
Line 42: Line 49:
     "fee":50,
     "fee":50,
     "tohub":"SLDA North Complex",
     "tohub":"SLDA North Complex",
     "tohubuuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f"
     "tohubuuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f",
    "tohubname":"SLDA North Complex"
     },
     },
"parcel_uuid":"638f361e-7eea-3b5a-b253-1ef41c9034ba"
"parcel_uuid":"638f361e-7eea-3b5a-b253-1ef41c9034ba"
Line 61: Line 69:
     "fee":50,
     "fee":50,
     "tohub":"SLDA North Complex",
     "tohub":"SLDA North Complex",
     "tohubuuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f"
     "tohubuuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f",
    "tohubname":"SLDA North Complex",
    "fromhubuuid": "the uuid of the hub the cargo came from",
    "fromhubname": "SLDA South Complex"
     },
     },
"parcel_uuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f"
"parcel_uuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f"
Line 69: Line 80:
===RESTful===
===RESTful===
We have two types of info which are '''hubs''' and '''items''' which both will return a json<br>
We have two types of info which are '''hubs''' and '''items''' which both will return a json<br>
<code>GET https://api.gridplay.net/gridhaul/hubs</code><br>
<code>GET https://sl.gridplay.net/api/gridhaul/hubs</code><br>
<syntaxhighlight lang="json">
<syntaxhighlight lang="json">
{
{
Line 135: Line 146:
}
}
</syntaxhighlight>
</syntaxhighlight>
<code>GET https://api.gridplay.net/gridhaul/items</code><br>
<code>GET https://sl.gridplay.net/api/gridhaul/items</code><br>
<syntaxhighlight lang="json">
<syntaxhighlight lang="json">
{
{
Line 154: Line 165:
}
}
</syntaxhighlight>
</syntaxhighlight>
<code>GET https://api.gridplay.net/gridhaul/jobs</code><br>
<code>GET https://sl.gridplay.net/api/gridhaul/jobs</code><br>
<syntaxhighlight lang="json">
<syntaxhighlight lang="json">
{
{
Line 192: Line 203:
*/
*/
integer OPENAPI = 47434285;
integer OPENAPI = 47434285;
string wcurl = "https://api.gridplay.net/gridhaul";
string wcurl = "https://sl.gridplay.net/api/gridhaul";
list httplist = [HTTP_METHOD, "GET", HTTP_VERIFY_CERT, TRUE,
list httplist = [HTTP_METHOD, "GET", HTTP_VERIFY_CERT, TRUE,
HTTP_VERBOSE_THROTTLE, FALSE, HTTP_MIMETYPE,"application/json"];
HTTP_VERBOSE_THROTTLE, FALSE, HTTP_MIMETYPE,"application/json"];
Line 266: Line 277:
}
}
</syntaxhighlight>
</syntaxhighlight>
===PHP Example Code===
===PHP Example Code===
Comes with Bootstrap 5.1.3
Comes with Bootstrap 5.1.3
Line 272: Line 284:
function GET($uri, $search = "") {
function GET($uri, $search = "") {
$ch = curl_init();
$ch = curl_init();
$url = "https://api.gridplay.net/gridhaul/".$uri."?search=".$search;
$url = "https://sl.gridplay.net/api/gridhaul/".$uri."?search=".$search;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
Line 315: Line 327:


==UPDATES==
==UPDATES==
''' 2.0.2 Aug 18 2023 '''
* URL update, switch from gridplay.net to sl.gridplay.net
* Removed getting the hud directly from our own dropbox. Link to MP is still available
''' HUB 2.0.1 - May 24 2023 '''
* Removed the issue where the hub could NOT be installed on non-deeded land
''' 2.0.0a - March 6 2023 '''
* Fix to the API in the HUD, sorry about that
''' 2.0 March 2 2023 '''
* Ranged Delivery. Be within 96 meters of the terminal to deliver. Handy for rail hubs that dont have a switch to the SLRR.
* Ended support for VenLife(discontinued) and Vittles. Sorry all.
* Now when not on a run the hud will say if at a hub and the hub's name
* Position of the HUD is down abit to make room for Vista AO's and GridPhone
* Hub terminal has some code clean up, bug fixes and added a link to this wiki
* Server side has some changes, some are already in use like a update to managing inventory from the web config
* Hopefully fix the paging issue in the HUD
* Starting balance is set to G$1,000, same with GridPay
* Vehicle API has some wording fixed along with some code fixes
* Vehicle API now adds the number of prims (divided by 2) in the vehicle's linkset to the max grid grams if maxgg is set to -1
* Hub list in the HUD now sorts by distance. Example: If picking up from SLDA south complex, SLDA north complex will be first in the hub list.
* When cancelling a run the product you were carrying now goes back to the hub you picked it up from, HOWEVER you do not get your G$ back.
* Pickup list now can be reset on touch by the owner of the sign
* Pickup list script is now mod so you all can see and learn how to script
* Now in the edit hub page (web config) items to buy for your hub has been squished over to make room for a new list. This new list shows who picked up or dropped off a item to the hub. ONLY the hub owner can see this list for now
''' Server side update - Dec 1 2022 '''
* Reset all player delivery count to zero
* Dropped player pickup count
* Starting from now at the end of every month the top delivery player wins 1,000 GridHaul dollars
''' HUD 1.2.2 - Aug 11 2022 '''
* Update to how VenLife stats are sent to the hud on delivery. Now the player gets 25 fun but takes 5 energy from the VenLife HUD. This of course is a option to play. Wont affect GridHaul at all if you dont play VenLife.
''' HUD 1.2.1 - August 9 2022 '''
* This update just adds support for VenLife. Now if you wear the VenLife HUD you get 25 fun points for every GridHaul delivery.
''' Hub 1.2.0 - June 30 2022 '''
''' Hub 1.2.0 - June 30 2022 '''
Happy Canada / USA Day eh
Happy Canada / USA Day eh
Line 389: Line 439:
* More minor fixes to the php code
* More minor fixes to the php code


==Video==
==Videos==
<youtube>https://www.youtube.com/watch?v=Bbd1UYkb2FA</youtube>
<youtube>https://www.youtube.com/watch?v=Bbd1UYkb2FA</youtube>
<youtube>https://www.youtube.com/watch?v=zav5Pio3wxQ</youtube>
<youtube>https://www.youtube.com/watch?v=zav5Pio3wxQ</youtube>

Latest revision as of 21:33, 18 August 2023

Info

GridHaul is a parcel based frieght hauling game.
Similar to the popular GTFO but parcel based meaning there can be more then one hub per sim.
Can exchange GridHaul dollars (G$) to Gridpay dollars (P$) and spend anywhere.

How To

GridHaul Group
Leader venkellie
Members 27

HUD

Wear the FREE hud, be in a GridHaul parcel, touch it and select pickup, select what item then your destination.
Travel to the destination, when you are in the parcel the text on the hud will turn green, touch and select Deliver

HUB Terminal

Rez it, click it, type in a name and submit.
Can then edit your hub using the GridPlay webconfig system
Updating your hub is easy, right click the old one, select Delete, rez out the new one
Minimum parcel size is 256 sqm

Hub Webconfig

First off the web config is version 1 so the code is kinda dated.
From the web config you can edit your hub name, add a texture UUID (in world texture) and info about your hub to show on the website and what types of vehicles your hub can accept.
Below that is a list of all items you can buy for your hub, this uses gridhaul G$ dollars to buy items so please try the game first before buying stuff for your hub.
You can also sell items that is in your hub for G$.
With 2.0 on the way upgrading your terminal is as easy as rezzing out the new one, yes thats it.
Our system goes by your parcel's UUID key, not a stored key in the terminal prim.

API

LSL

The HUD broadcasts loading and unloading commands on channel 47434285 with a json message
LOADING

{
"uri":"loading",
"cargo":
    {
    "id":3,
    "name":"Tree Logs",
    "des":"Rolls down stairs, alone or in pairs.",
    "p_per_gg":25,
    "slurl":"http:\/\/maps.secondlife.com\/secondlife\/Cavanaugh\/192\/154\/100",
    "gg":2,
    "fee":50,
    "tohub":"SLDA North Complex",
    "tohubuuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f",
    "tohubname":"SLDA North Complex"
    },
"parcel_uuid":"638f361e-7eea-3b5a-b253-1ef41c9034ba"
}

UNLOADING

{
"uri":"unloading",
"cargo":
    {
    "id":3,
    "name":"Tree Logs",
    "des":"Rolls down stairs, alone or in pairs.",
    "p_per_gg":25,
    "slurl":"http:\/\/maps.secondlife.com\/secondlife\/Cavanaugh\/192\/154\/100",
    "gg":2,
    "fee":50,
    "tohub":"SLDA North Complex",
    "tohubuuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f",
    "tohubname":"SLDA North Complex",
    "fromhubuuid": "the uuid of the hub the cargo came from",
    "fromhubname": "SLDA South Complex"
    },
"parcel_uuid":"4ab1c442-4c0e-0bb5-9959-f51a0337ad3f"
}

RESTful

We have two types of info which are hubs and items which both will return a json
GET https://sl.gridplay.net/api/gridhaul/hubs

{
  "uri": "hubs",
  "hubs": [
    {
      "name": "Australian Locomotive Shed",
      "sim": "Tuliptree",
      "ifo": null,
      "owner": "Hrdtop75 Deluxe",
      "Vehicle_Types": "Foot,Road,RailRoad",
      "map": {
        "uuid": "960987dd-4673-08d2-f526-dc10c9f67954",
        "name": "Australian Locomotive Shed",
        "pos": "1007.7265625,1014.34765625",
        "lpos": "186,89,30",
        "icon": "https://gridplay.net/slmap/GHLogoNoAlpha.png",
        "sim": "Tuliptree"
      },
      "items": [
        {
          "id": 5,
          "name": "Lag test dummies",
          "onHand": 2
        },
        {
          "id": 8,
          "name": "Max8 airplane reckage",
          "onHand": 36
        },
      ]
    },
    {
      "name": "AXON Airport",
      "sim": "Lesters Best",
      "ifo": null,
      "owner": "Nikoli Nicholls",
      "Vehicle_Types": "Foot,Airport,Helipad",
      "map": {
        "uuid": "d355ece5-aacf-0be9-5e5e-d6858de51700",
        "name": "AXON Airport",
        "pos": "1130.55859375,1058.21484375",
        "lpos": "143,55,131",
        "icon": "https://gridplay.net/slmap/GHLogoNoAlpha.png",
        "sim": "Lesters Best"
      },
      "items": [
        {
          "id": 2,
          "name": "Barrel of Debiven Red Wine",
          "onHand": 0
        },
        {
          "id": 8,
          "name": "Max8 airplane reckage",
          "onHand": 0
        },
        {
          "id": 3,
          "name": "Tree Logs",
          "onHand": 2
        }
      ]
    },
}

GET https://sl.gridplay.net/api/gridhaul/items

{
  "uri": "items",
  "items": [
    {
      "id": 1,
      "name": "Arabica Coffee beans",
      "des": "Beans for making coffee",
      "p_per_gg": 2
    },
    {
      "id": 2,
      "name": "Barrel of Debiven Red Wine",
      "des": "Not only good tasting wine but healthy too. Grown, aged and produced in Plusia",
      "p_per_gg": 10
    },
}

GET https://sl.gridplay.net/api/gridhaul/jobs

{
  "uri": "jobs",
  "jobs": [
    {
      "from_hub": "Brandi's  Depo",
      "to_hub": "SLDA North Complex",
      "item": "Arabica Coffee beans",
      "gg": "2",
      "time": "Aug 03 2022 2:11.44PM"
    },
    {
      "from_hub": "Brandi's  Depo",
      "to_hub": "SLDA South Complex",
      "item": "Arabica Coffee beans",
      "gg": "2",
      "time": "Aug 03 2022 6:18.24AM"
    },
    {
      "from_hub": "SLDA South Complex",
      "to_hub": "Paradise Marina",
      "item": "Hemp",
      "gg": "2",
      "time": "Aug 02 2022 6:20.47PM"
    }
  ]
}

LSL Example Code

/*
Wiki at https://wiki.gridplay.net/w/Gridhaul#API
THIS IS JUST A EXAMPLE OF HOW TO USE THE GRIDHAUL API WITHIN LSL
Please feel free to add to it to make your own products to sell
*/
integer OPENAPI = 47434285;
string wcurl = "https://sl.gridplay.net/api/gridhaul";
list httplist = [HTTP_METHOD, "GET", HTTP_VERIFY_CERT, TRUE,
HTTP_VERBOSE_THROTTLE, FALSE, HTTP_MIMETYPE,"application/json"];
key http_q;
string pid;
sendmsg(string uri, string search) {
    http_q = llHTTPRequest(url+"/"+uri+"?search="+search, httplist, "");
}
default {
	state_entry() {
		llListen(OPENAPI, "", "", "");
    	list pdetails = llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_ID]);
    	pid = llList2String(pdetails,0)];
		sendmsg("hubs", pid);
	}
	listen(integer channel, string name, key id, string msg) {
		if (channel == OPENAPI) {
			// Lets make sure its for this parcel since the hud sends as llRegionSay
			if (llJsonGetValue(msg, ["parcel_uuid"]) == pid) {
				string uri = llJsonGetValue(msg, ["uri"]);
				string cargo = llJsonGetValue(msg, ["cargo"]);
				string itemName = llJsonGetValue(cargo, ["name"]);
				integer gg = (integer)llJsonGetValue(cargo, ["gg"]);
				if (uri == "loading") {
					// add to item
				}
				if (uri == "unloading") {
					// remove from item
				}
			}
		}
	}
	http_response(key request_id, integer status, list metadata, string body) {
        if (request_id == http_q) {
            string json = llUnescapeURL(body);
            string uri = llJsonGetValue(json, ["uri"]);
            if (uri == "hubs") {
            	string hubs = llJsonGetValue(json, ["hubs"]);
            	list hublist = llJson2List(hubs);
            	integer i = 0;
            	for(i; i < llGetListLength(hublist); i++) {
            		string hub = llList2String(hublist, i);
            		string hubName = llJsonGetValue(hub, ["name"]);
            		string hubOwner = llJsonGetValue(hub, ["owner"]);
            		string items = llJsonGetValue(hub, ["items"]);
            		list itemlist = llJson2List(items);
            		integer ii = 0;
            		for (ii; ii < llGetListLength(itemlist); ii++) {
            			string item = llList2String(itemlist, ii);
            			string itemID = llJsonGetValue(item, ["id"]);
            			string itemName = llJsonGetValue(item, ["name"]);
            			integer onHand = (integer)llJsonGetValue(item, ["onHand"]);
            			// handle item data here
            			sendmsg("items", itemID);
            		}
            		string ifo = llJsonGetValue(hub, ["ifo"]);
            		string Vehicle_Types = llJsonGetValue(hub, ["Vehicle_Types"]);
            		// handle hub data here
            	}
            }
            if (uri == "items") {
            	string items = llJsonGetValue(json, ["items"]);
            	list itemlist = llJson2List(items);
            	integer i = 0;
            	for(i; i < llGetListLength(itemlist); i++) {
            		string des = llJsonGetValue(item, ["des"]);
            		string p_per_gg = llJsonGetValue(item, ["p_per_gg"]);
            		// handle item data here
            	}
            }
        }
    }
}

PHP Example Code

Comes with Bootstrap 5.1.3

<?php
function GET($uri, $search = "") {
	$ch = curl_init();
	$url = "https://sl.gridplay.net/api/gridhaul/".$uri."?search=".$search;
	curl_setopt($ch, CURLOPT_URL, $url);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$output = curl_exec($ch);
	curl_close($ch);
	return json_decode($output, true);
}
$search = "Calleta";
if (!empty($_GET['search'])) {
	$search = $_GET['search'];
}
echo '<html><head>';
echo '<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">';
echo '</head><body><B>Showing results for '.$search.'</B>';
echo '<table class="table">';
echo '<thead><tr>';
echo '<th>Image</th>';
echo '<th>Name</th>';
echo '<th>Sim</th>';
echo '<th>Item Name - Quantities - Description</th>';
echo '</tr></thead>';
echo '<tbody>';
$hubs = GET("hubs", $search);
foreach($hubs['hubs'] as $hub) {
	echo '<tr>';
	echo '<td><img src="'.$hub['map']['icon'].'" style="max-height: 50px;"></td>';
	echo '<th>'.$hub["name"].'</th>';
	echo '<td>'.$hub["sim"].'</td>';
	$items = [];
	foreach($hub['items'] as $item) {
		$itemGET = GET("items", $item['id']);
		$items[] = $item['name'].' - '.$item['onHand'].' - '.$itemGET['items'][0]['des'];
	}
	echo '<td>'.implode("<br>", $items).'</td>';
	echo '</tr>';
}
echo '</tbody></table>';
echo '<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>';
echo '</body></html>';
?>

UPDATES

2.0.2 Aug 18 2023

  • URL update, switch from gridplay.net to sl.gridplay.net
  • Removed getting the hud directly from our own dropbox. Link to MP is still available

HUB 2.0.1 - May 24 2023

  • Removed the issue where the hub could NOT be installed on non-deeded land

2.0.0a - March 6 2023

  • Fix to the API in the HUD, sorry about that

2.0 March 2 2023

  • Ranged Delivery. Be within 96 meters of the terminal to deliver. Handy for rail hubs that dont have a switch to the SLRR.
  • Ended support for VenLife(discontinued) and Vittles. Sorry all.
  • Now when not on a run the hud will say if at a hub and the hub's name
  • Position of the HUD is down abit to make room for Vista AO's and GridPhone
  • Hub terminal has some code clean up, bug fixes and added a link to this wiki
  • Server side has some changes, some are already in use like a update to managing inventory from the web config
  • Hopefully fix the paging issue in the HUD
  • Starting balance is set to G$1,000, same with GridPay
  • Vehicle API has some wording fixed along with some code fixes
  • Vehicle API now adds the number of prims (divided by 2) in the vehicle's linkset to the max grid grams if maxgg is set to -1
  • Hub list in the HUD now sorts by distance. Example: If picking up from SLDA south complex, SLDA north complex will be first in the hub list.
  • When cancelling a run the product you were carrying now goes back to the hub you picked it up from, HOWEVER you do not get your G$ back.
  • Pickup list now can be reset on touch by the owner of the sign
  • Pickup list script is now mod so you all can see and learn how to script
  • Now in the edit hub page (web config) items to buy for your hub has been squished over to make room for a new list. This new list shows who picked up or dropped off a item to the hub. ONLY the hub owner can see this list for now

Server side update - Dec 1 2022

  • Reset all player delivery count to zero
  • Dropped player pickup count
  • Starting from now at the end of every month the top delivery player wins 1,000 GridHaul dollars

HUD 1.2.2 - Aug 11 2022

  • Update to how VenLife stats are sent to the hud on delivery. Now the player gets 25 fun but takes 5 energy from the VenLife HUD. This of course is a option to play. Wont affect GridHaul at all if you dont play VenLife.

HUD 1.2.1 - August 9 2022

  • This update just adds support for VenLife. Now if you wear the VenLife HUD you get 25 fun points for every GridHaul delivery.

Hub 1.2.0 - June 30 2022 Happy Canada / USA Day eh

  • Fixed a bug where the terminal wouldnt do a full reset on rezzing
  • Added a confirm dialog when deleting the hub through the dialog
  • Some code clean up, mostly useless if statements
  • Website button now directs the person to the hub's website listing

HUD 1.2.0 - June 28 2022

  • Added distance to drop off location
  • Fixed some spelling issues
  • Hubs in the HUD now sort by sim name in ascending order (A-Z)
  • Some bug fixes
  • Text update timer changed from 5 seconds to 1 second

Hub 1.1.1 - Oct. 7 2021

  • Issue installing fixed. Seems to be a problem with a OR in a IF statement

Vehicle API 1.1.0a - Sept 17 2021

  • Same reason as with HUB and HUD, want to move all products to match
  • Fix Amphibian so that they now are supported by airports, marinas and road hubs
  • Fix OPENAPI data handling by Venkellie. OPENAPI is only triggered now if the sender is NOT owned by the owner of this script

HUD 1.1.0 - Sept 17 2021

  • Moving all GridHaul products to 1.1.0 so they all on the same version number going forward.
  • Cancel Run option
  • Fix page issue i hope (could still be buggy for some weird reason)

HUB 1.1.0 - Sept 17 2021

  • Code fixes and clean up
  • More info when installing a hub such as minimum parcel size
  • Moving all GridHaul products to 1.1.0 so they all on the same version number going forward.

SERVER SIDE AGAIN - Sept 14 2021

  • Amphibians can now see airports, marinas and road hubs
  • More fixes to picking hubs and dropping off

SERVER SIDE - Sept 13 2021

  • Added more info of the API to the wiki
  • Can now search by parcel uuid in the RESTful API
  • Deduction of quantity from a pickup hub should calculate correctly
  • Added a cancel run option to the server for a future HUD update
  • Fixed drop off issue
  • Fixed pagination issue with items and hubs, HUD fix coming soon
  • Amphibians can now see boat and airport hubs when picking up

HUD 1.0.7a - Sept 10 2021

  • HUD is now modifiable so you can resize it

Vehicle Script 1.1.0 - Sept 10 2021

  • FindSitTarget() fix by CarlaWetter
  • Sit attachment fix by CarlaWetter, enhanced by Venkellie
  • Max GridGram calculations by Venkellie
  • amphibian added by Venkellie
  • API cleanup by Venkellie
  • Szym Paladin compatibility by Venkellie
  • Max GG message by CarlaWetter

Server Side - Sept 10 2021

  • Added Amphibian to the hub and vehicle API options, this gives 19 GridGrams
  • More fixes for gg calculations
  • Fix for the search option, still needs testing
  • Distance check now in play when selecting a hub from the hud

HUD 1.0.7 - Sept 1 2021

  • Region say for API
  • Help button link fixed
  • Hub search option

July 25 2021 - Server side update

  • Picking up through the HUD will show items that hub has for pickup
  • Hub owners can now buy items for their hub using Haul dollars
  • Fixed a issue with vehicle types saving to the database
  • More minor fixes to the php code

Videos

<youtube>https://www.youtube.com/watch?v=Bbd1UYkb2FA</youtube> <youtube>https://www.youtube.com/watch?v=zav5Pio3wxQ</youtube>