Episode: 2723 Title: HPR2723: Using Elm in context of 4X game client Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2723/hpr2723.mp3 Transcribed: 2025-10-19 15:40:34 --- This is HPR Episode 2007-123 entitled, using L-min context on Forex Game Client. It is hosted by Tuku Toroto and is about 45 minutes long and Karima Clean Flag. The summary is Tuku Toroto's new decision-on-structuring L-application. This episode of HPR is brought to you by an honesthost.com. Get 15% discount on all shared hosting with the offer code HPR 15. That's HPR 15. Better web hosting that's honest and fair at An Honesthost.com. Hello listeners, I'm Tuku and you're listening to the Hacker Pocket Radio. The trick of today is riding L-client for the Forex Game that I'm working on. Initially when I started working on the game, I had an idea of riding it mostly with the HTML-client set that is and only had a little bit of scripting here and there. But as the work-progressor soon realized that it wouldn't work very well. And there was some things that I perceived that might cause performance problems. For example, if you are in the old way that I wrote when you opened a display or the page that was used to design the spaceships, it always called to the... It first loaded the L-program and then the L-program called to the server to load some data that was needed for the seed construction or seed designing. And if the user later on came back to that site, that back to that page, it did that again. But that led me into thinking that maybe I should ride the whole client in an L-m innovative. It loads the code only once and as the user navigates around the program, it doesn't have to load the code over and over and over again. And it also could cache some data that difficult doesn't change. It wouldn't have to retrieve it from the server site. For example, the technology, technology 3 that tells what the player has researched and what they are able to build doesn't change that often. So it wouldn't have to download that from the server all the time. So all this led me into scrapping pretty much everything I wrote with the method using Hamlet template and look into writing the client site with the L. So as I said, back end of the server site is in the method. It's called Haskell's framework for web platforms and the client site is written in the L. So they need to communicate and for that I choose pretty standard rest interface, rest place interface. So there's plenty of JSON data flowing to back and forth. The back end and front end are printed in the languages that are static typing, which made it all at least in this current project, I really like it, like it. The transfer of data in between is of course in strings. So you need to have a you need to pay or I need to pay attention how the how those strings handled so that the data sent from the server does not change to something completely different on the client site. But luckily the LM and Jesuit has a pretty cool good tools for this. So my goal for this was to keep things as easy as possible, keep them type safe and extensible because I don't have that clear idea of what I will be. Writing in a couple of months for example. And then this of course the things like user authentication, authorization that I wanted to print to the client site to work some of you have to be able to tell the difference between regular player and administrator because administrators have their own set of views on the client site that they can use to examine the state of the system and do maintenance and such things. So there are typical architecture for the LM has four major parts, these are the model, U, messages and update function. Model is a single type that catches the state of the program, view is a function that when given a model will render HTML and that HTML may contain things that produce events for example on click, handler on some link or button and those are used to create messages or are instructed, the instruct LM that when you click this thing you should create this kind of message. And the message is a single type again that catches all all the interactions that the programs can have. For example, you should click in on some button or program receiving a update from the server or program sending update to the server. And the final final part is the update function that when given our model current state of the program and a message will produce a new model and a possibly new message to. So because of this I didn't have to really think how what the overall architecture of the program that was already given to me but I had to figure out how to make this thing a sort of extensible. There are multiple pages for example one page to view all the star systems that the player has found and on nodes of another page to to look into details of one of those far systems and then get another page to look into details of a planet and to the two things that you usually do in a 4x game on planets constructing things, changing policies, things like that. And I decided to split this thing into pages like there's a one function to render each of these pages. Well I mean one function to render one page and then another function to render another page and one function the page to handle the messages that it made create and then one function to initialize the model when the page page is open. I put in our links into the follow nodes into these examples of these functions and then there's a one function to yeah the one function to initialize the model when the page is open. This is basically the two when when user opens for example a planet view for for first time for a certain planet and the client doesn't yet have a data that is needed for the explain that information. This function will create a bunch of requests to the server that by the way I need the population information for the earth and I need all the buildings allocated on the earth and I need things that are being constructed on the earth and those are sent to the server and when the response comes back that here's the data we store them into the model. There's a for the for example for the buildings there's a dictionary for that is the key to buy the planet ID actually it's key to buy the integrals because you cannot exactly you cannot put self-defined pipes into the key to the dictionary you have to cast cast them to integrals or strings for example there's only very few data pipes that you can use as a key in the dictionary but in any case those are stored in the dictionary and you can find them if you if you know the ID of the planet you can find buildings that are being constructed on it and the view function that renders the planet we look into that dictionary find that check if the if there's a buildings present present it will render them name and level and damage I think info information when it was last observed and if the information is in present it will just leave that part of the UMD a property should put out some sort of indicator that will tell the user that the data is in present and as soon as the update comes from the server it will it will change that part of the UI it will Elm does it in a way that as whenever a model changes it will change the respective parts of the UI on the on the on the on the browser these are called reactive programming and Elm is even functional reactive programming really it's really nice I am very I'm very happy for work with Elm because you can always at least I have the feeling that you can pretty much always indicate things like for example if I have something that may or may not be present then the data that the type of that is maybe that thing X maybe buildings if the building system type of that tells me what kind of buildings are on the planet and then on the when I'm rendering on the screen there's the Elm made sure that I don't just really really start rendering them it forces me to check that hey this is this thing might or might might not be present the compiler will tell me that you did not do that you have to do that it doesn't it doesn't type check so on the rendering part I have to account both cases the information is present or information is not present and that's that's that's captured on the type level in the model it actually it really says that this might or might not be here and as soon as I soon as the thing changes the UI changes okay so the model is split into couple parts you know in my system there's the general path that holds all the common data like planets that have been the information on the planets that have been retrieved from the service parts, how much resources the player has what time is it in the game things like that that that can be used pretty much everywhere and then there's a single type for each of the pages for example for the planets the I'm for the view that is used to render or the page that is so shows the planet information there's a type called planet r r has also copied the naming convention from the yes or and that pipe holds the data that is needed for specifically for that page like if there's a info panel that player can open or close or if they're the search fields that they can do to use. That kind of information is used in that model. I mean, so in that, that is a particular model pattern. Those two together are actually the latter one is part of the first one. The view function that is used to render this planet information has, that that function has all the information it needs to put rendering. Each page has their own. I guess one could call it view model. I couldn't think that of the name, that holds that data that is specific to that particular view. And this is the one that is inutilized by e-function when a page is open first time. Okay, the message is there's a type that has inventively named as a MSG, so opened of as a message that holds all the messages that the program needs to react or send access to react to. And again, it has a separate message for each of those different views. For planet, there's a planet message is for the stars and these stars and messages. And that message contains usually the stuff that only that page needs, needs users click the open this info panel that sends a specific planet message. And then there's an app message that is used to deal with responses for queries to the server. If my system has queried, has asked the server to send information about the population on the planet, it will arrive back as an app message population received and then the population received contains all the relevant information. And this is a 100-part update function in the element. All the messages are handled by the single update function. They come to the single single function that is in charge of taking care of everything. And if you have a big program, it can get really, really big. And that's not fun. So again, I split this into the smaller parts. It's, I eat, subtab message, have their own handler. So when the, there's still one update function that is in charge of dealing with the messages, but that can delegate the handling to the other other other functions, depending on the type of the message that actually arrived. I think that's all about messages. So where do these messages are sent to this or rather way to this queries request sent to the LMSA type URL or that is, that is, that is, that's it for the address to send data. And all the end functions that deal with the networking use, use that one. I didn't want to use that because that would mean that I would have to write the strings quite many places. And I have, I have noticed that I tend to do typos in those and that will lead into hard to debug problems because, because that will lead into the incorrect behavior that is noticed only when the program is running. I rather have the typos code in advance when you are, when you are compiling the program. One way would, would be to define constants for this, but I thought that again, borrowing something from the result, I made our own type called end point. And this end point is used to capture, it has, it has all the end points or addresses that you can call on the server side. For example, and that type even captures the parameters that you need to send to the, you need to give to that type. For example, if I wanted to request information about population on the planet, that type, that constructor I would call is an API population, inventively named and that takes a single parameter of the planet ID. So whenever I want to call to the server and I want the API population, I can give this specific constructor data constructor and the compiler will make sure that I have typed it correctly and I have given it to a correct amount of parameters and those parameters of correct byte. But of, and then on the behind the scenes, I have a function that will turn this, because the, Elm of course does not understand these pipes. I had to, first of all, I had to define my own versions of, of get, post, put and delete, that not to the rest behavior. And these take these end points as one of the parameters and then they understand how to get from the end point into the correct URL byte. So mapping is in one place. And they also, that, for example, get has information of what kind of event will be, what kind of message will be created and what kind of decode or JSON files will be used to process this data. So when the response comes back from the server into the update function of ours, it, it has already been passed the JSON data has been mapped into the Elm object. So it's very nice, it's pleasant to use. You don't have to, there's a one place where you have to worry about transform taking JSON data apart and constructing a Elm object and that places somewhere behind the scenes that you don't have to worry about when you are doing these calls. Same, same system is done with the pages instead of end point, this type is called root. The idea is the same though, the root captures the different pages and parameters that you are required to give when you want to move to that page. For example, if you go to the home page, it's just a home or you don't need to give any parameters to that. But if you are, you, if you want to send user to a specific page about specific planet, it takes two parameters. Planet R takes two parameters, star system ID and planet ID. And based on those two parameters, there's a root to string function that understands that planet R actually maps into the string that is slash star system, slash and then star system ID, slash planet ID. So again, the Elm, of course, the HTML function of the Elm don't understand a path of roots. So I actually define my own version of HRED that works identically to the Elm's HRED, but instead of taking a URL, it takes my root parameter and then behind of the, when it's rendering the stuff on the screen, it will actually use the correct Elm's HRED to output the data to output the HTML that the browser understands. So this is a little bit of good. And there's the whole Elm HTML library that is really good and couple of little additions that are specific to the system data. And here are the, since 0.19 version of the Elm, the Elm program can be made aware of on what URL, URL is it is being run. So this allowed me to wrote the system in a way that the server, the ESRD, will serve the same Elm program from multiple locations. For example, if you go into the homepage, it will serve the same Elm program as if you went to the, for example, planet page or star system page or page about messages. The all will serve the exact same Elm program. And the Elm program itself is aware of URL where it was started, which allows it to, in the start app, to move to that correct view, it will render. For the user, it will look like they are, they are starting from different, different pages within the program, as they actually are starting from the, from the different pages within the program, but it's still the same Elm program in every, in each and every of these cases. I made this because it allowed me to, for example, this allows players to keep links to other players, if they, if they have opened a specific, a planet, for example, they can set copy the URL, mail that URL to another player and say that, hey, have a look at this planet. And if that another player has sufficient information, they have, they have observed that planet at some, at some point, opening, opening that a URL will give them the correct, correct view, they can see the same plant. And if they are, members of the same faction, they are getting the exact same information even, because I, I, I had a feeling that it's important to, even, even when the program, even when the client site is a single program, it is important to give the user's ability to send links to another user and have those links work in the way that they would work in a normal, normal that, not, not, not in a case, not in a, because in some cases, they are those single page applications where you cannot link into a sub-view. And I don't like those. I think that, I think that the ability to link to a specific point in a system is a very crucial integral part of the web. Okay. Yeah. And now I lost my door. Okay. There's a part of this, that was required for this is the, the, we have the function root to string that when given a root will give you the correct string that you can use in the URLs part to facilitate the mapping from the another, another direction we have, we had to create a mapping that tries when given a any kind of string as a URL will try to figure out what root that this would be and part of that mapping for this is defined in the function root that I have the definition of that in the show notes, that only, that basically maps that if there's a, for example, if there's a string profile, nothing else, it will map to the profile page within the program, if there's a string star system slash star system ID slash planet ID, it will not do the planet hard resource or root, sorry, root. And then the top root home is used when passing fails. So whenever you say, for example, if you use types that you have a hello world, it will take them to the home root. And what else? Predecramps, yeah, there's a part of the, the really, this one is actually pretty proud of, I lifted the basic idea from the yesterday again, but in top of the top of the page, there's a Predecramps, this is just a hierarchical navigational age, it displays names of the pages that are earlier and not early on the history, but sort of an above of this specific page that users currently, when they are the very beginning it shows just a home as a text, but if they click to the better star systems, the Predecramps will read home slash star systems. And now home is suddenly a link that you can click and get back to the whole page. And on the star system page users have a little list of star systems that they are aware of, all these all these data that the client is showing is based on the, on the reports that have been generated during the gameplay. I talked about those earlier. And those, those, those reports are just telling the user that this is how you observe the, how you observe the world, this is the information you have, and the client is dealing only on those reports, the client never ever sees the actual data about what's the real state of the world. But I got lost, so when they click a, for example, a solve system, now the Predecramps will read home slash star systems slash solve, not star system, not general name, but solve because that's the current system they are viewing. And home and star system text are links to those respective pages. And now the user are showing the details of the solve system. They are a list of the planets that they are aware of if they click the Earth, they are taken to the page that shows the details of the Earth. And now the Predecramps will read home star system, so home slash star system slash solve slash Earth. And all about the Earth are links to the door to the rest of the pages. This, the idea behind here is that the users are, they are aware of where they have navigated, they have some sort of contextual information of the location in the system, and they are also given a tool to quickly jump back to somewhere. They can use browser type button. Elm program will detect that now they have requested moving to a different URL, and we will serve the correct page, meeting the Elm program. You don't actually exit the Elm program when you hit back or forward in the browser. Until you go all the way to the back and you go back from where you started from the Elm program, then you of course are, the new, of course, leave the Elm program. How, how, how game client and pretend to, was it proved the start page of your browser, for example. So the Predecramps are offered another way you don't have to use the back button that you can directly, even if you are viewing the third you can directly jump to the home page of the game client. I'm just clicking that home link. And these, these, these are defined. Well, there's a little bit of functions that are not interesting, but the Predecramps, I'm calling Predecramps past the whole thing, is made in a, there's a function, Predecramps part that takes the model and produces HTML, that's the whole whole thing. And that also wraps it in a, some diffs and filings and what not. The actual work, work is done in a function called Predecramps, that takes the model, because you need to know where you are, you need to, and then there's the Boolean Slack, which tells you if you are on the first node or in some other node, then it gives you the current truth that you want to construct the Predecramps from and it will produce you a list of HTML. And this, this will call itself recursive, recursively. The first, first one is called with the flat being. Actually, I don't remember, I have to admit, I don't have code, I have only the definition here. I think it was called with the Boolean tree true, meaning that this is the first element. And after that, the recursive code will turn that Boolean to false, but I'm not sure that which, of course, means that I should get rid of the Boolean Slack and have a real pipe that is, for example, the Predecramps placement that can have two values, first and some other. Because then it would be visible on the pipe definition that what this Boolean Slack is actually used for. It would have a sensible name and it would have, well, it wouldn't have any more values or any less values than the Boolean, but it would have a sensible name and it could have a pipe and it would mean that you don't accidentally stop something incorrect there. Or even at least it would make it harder to put something incorrect there. And that thing is calling third function called decrement that takes the model root and produces a couple of string and maybe root. The string here that it produces is an actual text that is being shown. For example, in case of the home page, it just reads home. In case of the file system, it's reads star systems. In case of the Earth, the planet Earth, it will read Earth. And for that reason, the function needs the model because the model holds the, all the data that has been retrieved from the server, it has the dictionary that has the, that has the planet information and that dictionary is keyed by the planet ID that integrally, because you still can't put the planet ID as a key of the dictionary. And based on that information, this segment who understands that now we are on a, because root is of course the planet A that has two parameters, star system ID and planet ID. Based on that information, that and the model that has given the segment can read from that dictionary that is in the model. The information of the planet being currently shown and get the name of that planet and put that written that, by the way, this is not just any planet is, planet Earth. And the second parameter on the sample that is written is the neighbor root and that is used to indicate the parent of the this segment. In the case of the home, it's nothing because there's no parent, but in the case of the, for example, if we are navigating to the, or have navigated to the view about Earth, the parent will be star system A with a correct star system ID. And this will trigger the recursion in the breadcrumb function, because it notices that, okay, this has a parent, so it will go to the, but it will call the segment again. And in the root, it will give that star system as a parameter that will produce a double with a string as a soil and just star systems A as a parameter. And that, that will trigger the recursion again and from the decursion you are getting a home actually, yeah, home and nothing, because home doesn't have a parent anymore. So the, when, wherever you are, wherever the user is within the system, the breadcrumb path, when given a model will produce a list of all the pages and the names starting from the home ending to the current location. Oh, starting from the current location ending to the home, which, whichever way you, whichever way you want to use it. That was, that, that part of the program was kind of fun to code. I like, I like that. And as I said, I lifted a bar of this from the ESOT site. There's quite a bit. I, I feel that there's quite a bit neat things on the ESOT that can be done, that can, that can be used in other systems. And I'll have to use them on the L. There's a, I like, like I said, earlier you cannot use star system IDs, planet IDs, basically self-defined tags in the ESOT keys of the dictionary, that's a limitation of the end. That's a, I have had couple of packs of, because of that, because the, I have just a dictionary with a key as an index, and the index, of course, doesn't tell you what it is used for, it's just a, it's just a number. But everywhere else in the program performance, I'm not, I'm trying to keep the use of primitive data tags to the minimum instead. So all the places where I'm talking about planet, planet IDs, the identification of planets, it's the planet ID type, that is, that only wraps a index, but it gives, that wrapping gives the meaning to the index, and it keeps, you mixing the planet IDs, for example, with the star system IDs, and the same thing with the resources, I talked about the resources on the end, sorry, on the ESOT site, and on the end of the end site, there's a similar system. I couldn't figure out if, if one can use quantum tags, I think you cannot yet, or will never be able to but I still have a, I have, I still can have a resources type that has a three type of resources, the biological resources, the mechanical resources and the chemical resources. So at least I'm not going to mix biological resources and mechanical resources with this data. I might mix them in a different context, in a way that, for example, I would mix the constructions speed with the resource, with the required amount of resources and things like that, but still I'm sort of happy with the resource handling, and on the resource handling is not, but this is image and satellite resources and raw resources that play and uses to construct things, and I'm very happy how it's handled on the end site. I probably missed quite a bit while trying to explain, but if something else comes to mind, I'll record a new episode and have a feeling that if I keep working on this game, it will, it will take eights, it's like years and years to get it to somewhere, somewhat playable state, but it's a fun project. I'm having lots of fun trying to learn the Haskell and Elm and Lead Programming, and what not. So I would be interested to hear if you have any experiences, experience on Elm, how you like the language so far, it's a relatively young language, and if you have experience on the Elm and some other of these new languages like PureScript or even some JavaScript frameworks like React, and how Elm, if you can talk about the differences and the similarities between them, I would be extremely interested in hearing those on the hack-up of the radio, but this is too calm, this was quite a long episode and tried to keep this a little soul in the future, so have a good day. We are a community podcast network that releases shows every weekday Monday through Friday. Today's show, like all our shows, was contributed by an HPR listener like yourself. If you ever thought of recording a podcast, then click on our contributing to find out how easy it really is. Hack-up of the radio was founded by the digital dog pound and the infonomic computer club, and it's part of the binary revolution at binrev.com. If you have comments on today's show, please email the host directly, leave a comment on the website or record a follow-up episode yourself. Unless otherwise stated, today's show is released on the creative comments, attribution, share it, read it or license.