 I'm Calvin. I wrote the work library I was talking about back a long time ago before, but it's kind of pointless if you don't have access to the, if you can actually work in, you know, explore. So, if you want to follow on at home, this is the URL. There's quite a few links in here that on that page to help you follow along. I make web maps primarily. I mainly do backend stuff and node. So, I think my talk title ended up just being Chris Helm looking at my GitHub like history and like picking two things that I'd recently done. So, it's called pouchTV and SQL down. I understand the TV and the SQL. Yeah. So, or when Postgres is too much. So, Postgres is hands down the best database. It's the best SQL one and it's the best JSON database if you have to do queries. Like, it is head and shoulders faster, better in every possible way than Mongo and, you know, pouch is good for, I mean, pouchTV is good for some very specific stuff but Postgres, if you have to do complex queries, don't bother. Just use Postgres. But sometimes Postgres is, you know, a little much. If you just want to do, you know, store stuff locally, you know, do something you can use in the browser. And something that I really, really helpful is level up which is a wrapper around, I think called levelTV which is a simple key value database with just lexically, alphabetically ordered strings for the keys and it's just super simple. But you can build something. So, indexTV and Chrome is built with levelTV. PouchTV which is a JavaScript port of pouchTV is built in on node with levelTV. So it's dat which Max Ogden who's done a lot of good stuff. It's his get for data thing which is pretty exciting. That's all at levelTV. And you can have backends besides level, the default level down which is just the C levelTV library. You can sub in other backends like everyone called SQL down which you can use Postgres or SQL Play or MySQL or WebSQL in the browser at the back end. And somebody wrote, Max Ogden actually, not just somebody, wrote one for indexTV which means that you can browser find code with levelTV and use it in the browser. And use it in node and use it both places with the exact same code if you need to store data locally which is just really helpful when you have, you know, large amounts of data. You know, I know somebody is doing tiles and you can do tiles when, you know, the download to cache and you can do a lot of really cool stuff in the browser. So this is just Geo. So we've got some Geo stuff with it. So the first thing people did to try and store, do Geo stuff with levelTV is Geohashes. If anybody doesn't know what Geohashes is, it sort of divides up the world into quadrants. So basically it says A, B, C, D inside of them. A, B, C, D. And just so that you have followed AA and that's A, B. So that sort of turning your tile URLs into just a string of letters. If people are giving me blank stares, I cannot actually read anything on either screen. So we'll just pretend that you understood what I was saying. And just, so it's basically, it really works well with levelTV because it basically means that adjacent tiles are alphabetically next to each other. So you could just do ranges of them. So, but one of the big things about them is what's called a Hilbert Curve, which is fancy talk for this one. I do have a link somewhere. So it's basically saying, making sure that all adjacent things are next to each other. So in a Geohash basically, A, B, C, D, AA, A, B, C, A, D. But with a Hilbert Curve you basically go, instead of over here you go, you know, like that. So they're all next to each other. So the tile that is adjacent in the naming scheme is always adjacent in real life. And it means that you can just do queries on the ranges really easily. So that was the first way people were going to do it. There are like several plugins for levelTV that people have written with quantities, though without Hilbert Curves. And then I decided to talk about doing a ternary one with a Hilbertish Curve. That one actually, called MelEntree, I just published it. I just pulled it out and published it about a couple weeks ago. But that one, if you want for some reason to do that kind of thing, that one's pretty good. The main problem with Geohashes of any sort is that a Geohash is really good for finding things that are smaller. So if you have a bounding box, you can find things that are totally inside the bounding box. So finding points. If you're doing a big box and finding the points inside, a very small polygons or stuff. It does not work at all if you need to find, you know, if you have a point and you want to find what the state is, it does not work. Well, you can make it work, but it is not actually efficient in any way, and you should not do that. So if you do something like that, you need an R-tree of some sort. So Watterer has one called Rbush. There's one that somebody else wrote called Rtree that I now maintain. Don't use Rtree. I started maintaining it before Rbush, and if you need to serialize and deserialize your tree, that's the only time Rtree is so much better than Rbush, because Rbush just does values by reference. But unless you have that very specific thing, so I wrote a... But they're all synchronous, so they're great if you're just in memory, but if you need to serialize its of it and don't want it entirely in memory, they're not going to work. So I wrote an async R-tree. It is pretty much just a port of Rbush, but async, which actually makes it somewhat easier to write because when things are asynchronous in JavaScript, you don't have to care about recursion or anything because the only thing that's wrong with recursion in JavaScript is that the stack can get so big you'll run out of memory. But if things are async, they do not capture their stack, so you can be totally just recursive. So yeah, so I wrote an async R-tree documentation. The other thing was that you have to optimize it somewhat differently because... Well, optimizing it somewhat different because the thing that actually takes a lot of time is all the data lookups. So you end up wanting very broad shallow trees instead of deep trees that are in memory ones. But yeah, I wrote that and then went to do stuff with it. So other than this, I went to use my address. I was definitely operating and I got false as well because all our trees care about is bounding boxes. And you know what I'm excited? The Boston bounding box, because it's a giant convex polygon. So that's all the way up to there. So that is like, God damn it. So I had to write a library for bbox testing. It's basically the, because it turns out there is not really any good libraries for, does this bbox intercept this georgiasm and do it well. And I have another slide here. Did I forget to polish? So, and also the weird corner case you have to hit. So like this one is not actually hitting any of the points and that was inside of the ring and that, you know... Oh yeah, and all this stuff is dimensionally agnostic. So it'll work in my 40. I haven't really tested that as much as I'd like, but... Yeah, what's going on down here? It's just redoing it. It's retiling it. You should have gotten used to this. I'm the eighth person that used this presentation library today. Yeah, so, and then I wrapped it all together with Level Up to make Level Tree, which is just an R tree in Level where you can do, you know, the sort of geo queries. And then also PowerCBC can do syncing. So that's sort of it. I can... Is there like a trick for getting it to not look like weirdness? Anybody know? This is Steve's Linux laptop. Was it not stretch-up? Is it like the stretching thingy that people were doing with? What? On your keyboard command minus. So we can... What kind of scenarios are you kind of chaining towards with this kind of disconnected scenario? Yeah, so if Steve was still here asking me about what's the next big thing, it could be offline. Offline first. So saving data and then querying the VBOX of what large amounts of data that when you don't have connection to some big fancy server. That's like the Google presentation. Give me a web map, even when the web's not on. Yeah, so I mentioned pouch earlier. I'm going to talk much more about that in my presentation tomorrow that you're all invited to. There's no GIS and no JS. But that's about syncing and then using it offline and then syncing when you get it data again. And so that's going to be something that we're probably going to do a lot more of where people are like, oh, but I want this to work on my phone when I'm in the subway. Or, you know, I don't want to use it on my laptop but I don't actually have, you know, to buy at the construction woods or whatever. So that's going to be the thing that your clients are going to be bothering you about going forward. They already are. Yeah. By short ends, who's doing kind of home cooked, home brewed by offline data collection with some sort of synchronization once the connection is. Yeah, so it's out there. I get the request all the time and it's a difficult knot to figure out. I know somebody is doing storing tiles in pouch so they can sync it over. He's also doing that in like IE 10. So binary data in IE 10 in index TV, like the offline storage and web browsers are terrible. Like you have two databases and they're both sort of competing with each other which can have the weirdest API and like the worst documentation. So you have... So it is not a very fun thing to have to deal with of like I need index TV except when I'm on Safari or old Android. We're going to use a weird port of web SQL that has really nothing documented about how to deal with JavaScript objects. So, because who would want to know about that in JavaScript? You guys, run out of time? Yeah, so that's the state of that. There's an index TV 2 coming out soon. I suppose it's going to be even more complex and less usable if trends hold. Okay, if you're employed. Questions? Yeah. Questions for the audience? Anyone? Yes? Yeah, so I'm really intrigued by Couch. I've played with Couch a lot. I've always wanted to build off one of my big geodesic applications. It sounds like... I mean, Couch certainly has a very specific scenario where you want to use it. Have you experimented with using Couch on the client and then being able to somehow synchronize with those threads? Or is that just way too much work? So... It seems like the synchronization to get from Couch and how to appropriate the hardware you're with, right? Yeah. So, Postgres, no. I mean, it's got its... You could write some sort of client that would do that, but you sort of store your data in a very specific way in Couch so that you can do... Because Couch and Patch can deal with, you know, multiple people editing the document when they're offline or when they're both online, instead of dealing with that. So you end up having to sort of store revisions. So it's... You're not syncing up with Postgres, but what you could do is there's a... You can run... You can sync up with this PatchDB in Node and PatchDB in the browser and use that to then update a Postgres database if you wanted. You know, if I'm using Postgres, there's often, like... Yeah, that's not something we do, but it's something that... So when we have the time to actually bother to do it, it might be possible. Right? Yeah. The... Watch it now. Yeah, actually, not a question, but just a comment. If anybody's looking just to steal a bunch of code, we've got a project on Azure that they have called Offline Editor. JS was looking at it here, and it just uses local browser cache, but it has the whole model of being able to go offline. And it also does tile fetching, too. So if it basically cookie-cuts your vectors and your tiles, puts them in your browser store, then you go offline, make some edits, and then go back online. So you may not be interested in all the code, but it may be something there that's... It's easy to reuse. Yeah, I use it on projects, like for building a trail out. So if you want to go hiking and take some pictures and stuff like that, you might cookie-cuts stuff out, and then go up and pick pictures, get back online and it goes to the data store, and then it goes... Just something to keep up. Right? Yeah, one of the... It turns out one thing that's really hard to do in a browser is to figure out if you're online or not. There's no... There's online and offline events, and they just... they do nothing. It's... you have to... It's far harder than it should be. So any code that... I feel it's already written that, just take it, like, and run with it. Care for it? Yeah. And you're going to find yourself doing that a lot more. Other handover? Yeah? This is another one of these I could use if not really a comment, comments, questions. For browsers, storage stuff. Riley Ru wrote Lawn Share. Yes. Which does a amazing job of abstracting away all the weird, like, is it Web SQL? Is it indexed to be easy? Yeah. And that's Lawn Share? Yeah, Lawn Share. Yeah. So if you just, like, say, I have this wall of data I want to store it somewhere. So there has actually been some talk about using that in Pouch. The problem with that about really any abstraction is that when you have... when you then need to, like, do... ask questions and do queries on it, you end up having a giant form of it. So that... So PouchCV has built-in adapters for indexed CV Web SQL and level... level up. Each of them has totally different ways of, like, iterating totally different ways of, you know, getting glimpsed stuff. And you just end up, you know, it was just too slow because... and see, it sort of had to work with the, uh, the sort of bare stuff. Database. There was a guy in Nolan who did all this work on Web SQL and indexed CV. I honestly, if my life depended on having to put some data in indexed CV, I might not be able to do it because I just, like, focused on all the other parts. But, yeah, if you have to do something less complex and just storing key value stuff, Lawn chair is a great one. There's also one called local forage. It's sort of like local storage, but it's not as bad as local storage because, you know, it's async. Well, local storage is really slow. So indexed CV and Web SQL are much faster. Ironically, even though Web SQL is depreciated and probably going to be taken out of Chrome at some point, in a really, probably distant future, is a lot faster than indexed CV because it's just S2 Lite 3 with a small, tiny little wrapper around it. So you can get some pretty fast stuff there, but only as far in Chrome. We have time for one more question slash comment, masquerading question. Observation. Yeah, I have a really good question about workers. So what's the deal with transferable objects on IE? I learned that there are many sources that say that you can transfer one object at a time if you use this. So transferable objects refers to, you can do, there's a thing in workers where you can just sort of like copy in a ray buffer over and then you are not able to use it. So you basically send it from one side to the other and after you send it, you then can't touch it. It's gone from the side that sent it. The thing that's never really documented anywhere is that it's not just ray buffers that you can do that with. It's also port objects. So that you can actually send a message port over to a worker. So a message port is basically like a telephone in that you put stuff into one end and it comes out of the events come out in the other end. So you can send that to a worker. And that's the thing that, so that IE, you can have a message port in the second position to transfer over. But if you give it an array, which is what everything else takes, they take an array of array buffers, it will just explode and throw an error. Why would they be helpful or anything? So that's what you can do in IE, is just transfer a port, a message port. It means that you, it's not very useful. Because the main way that that is useful is in places that don't have sub-workers. You could, you can take, since you can't basically create a worker from inside another worker, you could sort of simulate that by creating a second worker and then just transferring a port object to both of them so that you can sort of pretend that this worker created this one, even though it's just in a different one. I have no idea why you'd want to use that otherwise. It just seems not very helpful. What's one array buffer and it will transfer it? No, it doesn't work. No. It's not, it's not, so IE, it doesn't work. Everything else that does work. But it does have to be an array. When is this in the end of the course? So no, you can pass an array first and you can transfer them and then it works just like it says in the end. I think this is what you said earlier. But yeah, it works just like it says in the end and then on the main thread or whatever, transfer that object, that object is no longer useful at all. So instead of having to copy or use structured cloning, it just takes it and takes the pointer and gives it to the other thread. The one on the thread that passed it, that pointer system should, it's pointing to null. It's pointing to nothing. So they didn't have to, the message just passed the pointer. But that doesn't work in IE. You can do, you can put a different thing there because you can also transfer that port, so that's where it's often very confusing. If anybody wants to just edit that MDN article like right now and make that more clear, that would be cool. It's also where it's targeted to transfer it off. Those are, structured clone is, is the one where you don't transfer it. Operation, but no, if you clone a transferable object which includes message port, find in the, well that you don't clone it, right? Structured clone, yeah. Structured clone is the technical term for the way you pass JSON because JSON likes things because you can't actually stringify with JSON something that's got circular references or anything. So they use something called structured clone, which it turned out, recently, that they're, that's a recursive algorithm, both of them, both JSON and stringify and structured clone are both recursive in most browsers and will throw a call stack seeded error if you have something that's too deeply nested. Let's clap it up a thousand times.