hnedeotes
At some point I was tasked with improving the queries/retrieval times and started converting parts of the code and not only was it possible to write tests that would convey the actual meaning of the code and crystallise it but I started finding bugs in the implementation that no-one realized were even bugs because they no longer knew what it should do when queries grew to certain complexity and the search space was in the hundreds of millions of rows that thinking through them just with napkin calcs wasn't cutting it (specially when the bugs were subtle and the results still allowed the program to work "mostly" correctly).
It's good that we now have a recorded timeline for history...
The html there's not really many places to be creative, a navbar with 3 sections, 5 links, a text card, a hero image, etc, all those are the same across thousands of projects - they're structured, there's not really many ways you can be creative about it. So in part seeing that "middle ground" design is indeed a filter for the lowest of the low effort (or not understanding how to prompt properly, or how the final thing comes together).
If you just want to prompt models and have them come up with more diverse styles that's also quite, or more, lazy - it would help if you understood (not you in particular) how the look of a web page comes together, because then you can direct the model properly - and if needed tweak the lose ends because at some point it's just easier and faster to edit the output yourself but you need to know what needs change and how. If you know how an html page comes together into the thing you see in the browser you can spec the model properly.
Nonetheless, if there's going to be a premium it has to be discernible in any particular way because software for business is always considered a cost. But what really shows this industry is half a joke, is that now there's no issue in giving 3rd party agents full access to inner code and logic, many times credentials too because these systems are being deployed in CIs. And because there's really no enforcement or punishment for leaks, or endangering users in most areas there's no reason for a premium. There's people pushing thousands of lines / min (and I think even the most professional people out there can't honestly keep up with it) although that isn't in itself meaning the overall security is worse than before, it just means that for the most part it's now un-auditable in any meaningful way.
You would also need to switch inside the handle event to deal with the different types plus the different targets that might be bound to those events inside the component so I think that for anything with a modicum of complexity it doesn't cut it, unless I'm misunderstanding how to apply them in those cases (pattern matching with multiple function heads would definitively make it read like a declarative model but is not really serviceable in JS even if you syntactic sugar it, you wouldn't be able to describe `target` html elements probably - like:
`handleEvent({type: "click", target: {TAG: "input", id: "some-id", type: "input"}) { ... }`
and then another
`handleEvent({type: "click", target: {TAG: "button", ...}) { ... }`
, etc).
The importNode I think there was some issues with some properties not being copied outside of clone? I can't recall why I defaulted to `cloneNode`, could also be I just missed the `importNode` altogether or misread it at the time, but it has worked fine since then so I didn't look for ways to do that better.
Regarding batching, I basically have been using the same class extension since I've started working with webcomponents and it works, it uses a timestamp to control if we're inside the batch window for the inner working and then the "apply/build" part of each component has to compare those and decide - this is the part I would rather not have to code and have it handled natively (some events might actually run a single pointed update while others run the "full" apply/build function). It's nonetheless a bit more wiring and someone that never seen it might have the same reaction as some people here, even though they're fine in importing 50 libs, or 20 lines of useMemo with useState and useWhatever but heavens forbid they might need to read a 50loc class module. At some point many components need to ditch the `attribute` change handles as parsing the attributes into json/objects can get expensive, and you need to start doing parent->child direct data transmission and this is the only real bottleneck I've experienced when using attributes and requires an overhaul to how data is passed into the children (either from parent orchestration from top level attribute parsing that is fairly less taxing when done once only, but at a certain point can still stall the main loop just the same, at which point you need to parent-level requests, websockets, SSR that then you can pass directly to the child child_component._set_whatever_data_function(data) or setting the prop directly if it's workable in the particular case).
The thing with being able to load html fragments (or, even if whole html docs would be what we settle into) and having it be available would be that you could separate them into cacheable requests - so if you have `/essential-templates.html` , `/signed-in-templates.html`, `/special-page-templates.html` they could be cached, which means they would only need to be refetched if they changed or TTL expired. But with no way of declaring dependencies it can (will) also introduce bugs - if there were we could probably do some cool (as in useful) things too. I guess this is what many frameworks end up doing when they need code splitting, modules, and to create the initialization tree of a page/component, but then need to be re-implemented from scratch by each and leave vanilla webc out of an inbuilt system for it.
Here I might just be lacking some knowledge, and perhaps with TS it would be possible to, but the same way you write `static get observedAttributes() { return ["data-flux"]; }` would be great to have a `prop` like system, say `observedProps` that specified the `required` props when the node is to be attached to the DOM (not before, since `createElement` doesn't take options right? for the constructor or otherwise) for the cases you're adding elements from inside another component, that don't derive their inner state/data from attributes due to parsing cost and require directly setting those props.
Shadow dom is not something I use very much because I'm not creating widgets for third parties, or having to have locked components, but I do understand their existence and think it makes sense to have that mode too.
I imagine this is a complex topic altogether to push forward in the context of wrangling so many disparate interests (companies with lots of power and the only real players when it comes to browsers) but nonetheless not having them forces everyone and the webplatform to be way more spaghetti and troublesome than it needs to be. And I think that at a certain level, these issues go beyond the implementation and RFCs into the way browsers actually work, their engines and choices made before, that don't seem to be reasonable in hindsight when looking at from where we landed but asking for a new model will have 0 traction (of the type that matters) since there's too much at stake for what I imagine are "other" reasons.
I don't really understand why people are complaining that this is unmaintainable on the replies to this snippet but there's plenty of things with webcomponents in general that could be better done on the browser side.
For one the innerHTML (or some new method) should be able to reference a `template` directly. If you want to use templates you need to do:
``` const template = document.getElementById("templates-materialization-base").content;
this.appendChild(template.cloneNode(true)); ```
And if you want to use templates then you need to render the templates in a part of the dom that is parsed before this JS is run - there's no way of specifying dependencies for this kind of things - which is a short-coming of the platform as a whole.
One the same topic there's no way of providing an url for retrieval of a fragment that contains templates and have it parsed directly and available to subsequent JS if you could do:
`<HTML-FRAGMENT href="/my-endpoint/returns-templates.html" required="true" id="MAIN_FRAGMENTS">` or doing `fetch("/my-endpoint/returns-templates.html", {DOCUMENT_ID="MAIN_FRAGMENTS")` would parse the result and make it available to the browser engine then you could have on subsequent JS:
`<script requires="MAIN_FRAGMENTS" wait="GLOBAL_LOADING_INDICATOR`>....</script>` or in a file/module `requires DOCUMENT_ID: MAIN_FRAGMENTS` and the file/script execution would block until that would be available, just that would go a long way. You could specify fragments (the component DOM templates to be used) that are needed for the webpage to work at all, fragments that would only show loading for their own content, etc (you could style the TAG with a pseudo-state indicator, so if it had a wait not resolved yet, CSS could target it with `MY-TAG:state(waiting)`).
Another issue is `attributeChangedCallback` - this doesn't take into account how most of the times one can/will update the attributes of an element, so it fires once for each change, even if you made X changes in one swoop, making it so that you have to have to make a more complex "update_render" function to work around that, or lots of small functions that are composable (ideally, but not practical or wanted in many cases where the whole thing is to be treated as a single update) or create a `batched_attributeChangedCallback` that you implement yourself as part of a class mixin and then extend the HTMLElement class on declaration and use that, because most of the times you want to re-do/update the whole component and when you have multiple properties (equivalent to react props and similar in other frameworks) and multiple components this can result in expensive updates to the page that the user feels as sluggish on their end. Something like:
`batched_attributeChangedCallback(attributes, old_values, new_values, batch_timer_window: 200, batch_timer_fn: true)` where the default for the batch window is 200ms, but can be provided a `fn` that does the evaluation to. So even if the updates are done independently but under the timer window they're batched instead of run 1 by 1 (or immediately if the `fn` returns true, defaulting to true when it's independent 1 by 1 updates).
I usually have a function `_set_handlers(boolean)` that is used on connected and disconnected callback but this is just plain js organisation:
``` _set_handlers(toggle) { let act = toggle ? "addEventListener" : "removeEventListener";
window[act]("some-window-event", this._maybe_ready);
this[act]("some-component-event", this._some_fun.bind(this));
}
```And the connectedCallback just calls `this._set_handlers(true)` and disconnected `this._set_hanlders(false)`.
I use them, you can use them to great effect, but I think the biggest problem is the lack of connection between the different APIs. This includes things like indexDB as well, it's not very complex, but it does look messy on "first-glance". Like your example, but when you actually read it, it's pretty straightforward (ignoring the bad/non-existing functionality/APIs). The same with SSE. This could be a great solution for many things, but you always need to wire up yourself how it works. Would be great if you could declare "receiving beacons", at the page level, or component level, with automatic teardown on removal/navigation. So a component could have `static SSE_BEACONS() { ["https://something.com/path"] }` and would mark the state of the component automatically with `BEACONS: [WAITING | CONNECTED | ERROR]`
The loading indications, still seems strange that after 40 years of web development the transition between webpages are basically "white page", "freeze current view". Just having some way of specifying loading states would make any webpage feel 90% of a webapp between page transitions. Make it be a restricted subset of CSS that can be included as a header at the document top level and cached for subsequent visits `<LOADING_STYLES version=X><MAIN>background-color: white;</MAIN><LOADING_INDICATOR>shape: square; rotation: 1s; main-color: blue; secondary-color: turquoise</LOADING_INDICATOR></LOADING_STYLE>`. This would also allow to evolve it while maintaining strict backwards compatibility by starting from a very basic set of possible values - but just this would make website loading a much more app like experience. It could be used together with webcomponents too: `<MY-WEBCOMPONENT ...><LOADING_STYLES>...</LOADING_STYLES></MY-WEBCOMPONENT>` that then could be automatically derived from the `states` I mentioned prior.
Anyway... Spent too much time with frameworks and webcomponents by now. It probably would also make writing code for LLMs less error prone.
Just a rant, don't take it too seriously, but sometimes I wonder with all the resources poured into frameworks by the big Gs, that must amount to millions and millions of dollars when you take into account the salaries some of the people working on them take, if it wouldn't have been better spent somewhere else on the "base" implementation.
To be honest haven't played chess for years - I did MtG for a while even as I got older but then it just annoyed me and haven't played in years - it was when I started working on my own take on tcg's
I used to play a bit of chess when I was young too, but never sticked to it nor got good at it either, but the complexity is pretty low relative to other games - specially when we talk about automated/bot scenarios.
In the variant you mention now imagine that every piece can have hundreds of different interactions depending on the other pieces on the table plus other pieces outside the table that the bot can't know for sure - I would imagine it would make the bot much weaker overall and specially against a good player independently from training - it just doesn't seem to make mathematical sense that it wouldn't but it's not my area of research so I can be missing some important thing.
There's also the decision points, in poker it's way less. You're dealt cards, the table reveals cards, you bet/ante, move to the next, bet/ante. It's a very finite sequence of moves until disclosure. Plus it's 52 cards divided by the table players while on MtG it's 60 per players that you can't know (even lands can interact beyond being a resource and in competitive lists usually they do, specially in older formats) - although with enough/infinite time/memory you can probably generate a table for all possibilities, you still have to contend with the interactions other than the card types. A 9 Diamond is a 9 diamond. A Skull Clamp is a Skull Clamp but the way it interacts, its value/threat is highly dependent on context that can/might be hidden.
While I think that MtG is indeed "poker" like underneath the keywords, it's many more levels and I think bluffing can be way more "complex" but simply isn't because even at the pro-tour level prize pools are insignificant when compared to serious poker tables. Some MtG players are known to also dabble/play poker regularly.
I also think that the structure of poker game-play is more prone to be exploited by a competent bot - if you have a "budget" and you assign a bot to a table where the antes are "in-line" with the "budget" it has, it can mathematically (within a very high degree of probability) always turn a profit - ultimately humans fail in part because they enter "bluff" kingdom against a bot as the bots can just rely on mathematical probabilities. Made up numbers but the idea being, you have $200 to play. Choose a table where this allows you to play X games at least, say antes of cents, it should be able to make money most of the time at some point.
Yes, but as the other reply mentioned, the thing is you don't know if it's red deck wins, or a RDW with a tweak for the metagame and building the "he thinks that I think that he thinks" tables would probably require for practical terms what could amount to infinite storage and any of these chains, if followed through, can land the bot in a losing position hard to come back from. Now, to be honest, most MtG players aren't that good either, they play it more like a hobby/fun game, rather than approach it as poker/probabilities.
But on MtG in particular that never really applies in full due to drawing new cards. You can play perfectly and still lose due to sheer randomness of draws.
The latent space I'm not sure how it translates to a game playing bot, but I would imagine that it would open it up to fail in the same ways a human fails.
On the game I'm designing it could do that (calculate all possibilities up to X depth, for all possible scrolls and table states) but it would be extremely expensive to do so (not a very good argument if compute power keeps increasing), but more than that, in contrast to something like chess, there can be many more paths and decision points where a bad decision turns into a loss, so if it assumes that the best play is X at some point, a sequence that it discarded due to not being the most probable can exist and the bot can never be sure, so if it makes a decision that plays into a "trap" he can't undo to a favourable position. While in Chess it's much clearer what is possible from a given state, it's unambiguous and the rules are fairly limited.
In stratego you have a 10x10 board game, a very clear objective and at most 40 pieces (with repeated pieces and simple mechanics amongst them), while in MtG and similar games a single piece (card) can have probably hundreds of different interactions depending on everything else going (and everything else hidden), at many points of decision. In stratego it also seems that for humans at least, most moves are "inconsequential", as it probably plays more at the psychological/bluff level. Maybe a human player that was given the same budget for training could spend a month training against bots might fare better as the strategies might be then better understood (by the article it's mentioned that the agent recovered from bad positions, so it seems that it was mostly human error, as the human was playing better up to that point).
While on MtG or Asummon, although there can be inconsequential moves (they don't matter given the context/stage of the game), every move carries with it a possibility of being consequential in unpredictable ways. Anyway, there should be ways of training models with just a rule abiding client for these games, without codifying all rules, that they can just keep playing to figure out the interactions, so if that theory is true then it should be possible to create an unbeatable bot - I'm just not sure it is without infinite time/compute and less so if the "meta" keeps changing rendering possible training inconsequential regularly.
But even then (not saying I'm right) I think the depth of choices, effects and so on, on a format like modern, or legacy, would be very difficult for an AI to top against pros. If you add draft into the mix it gets worse for the AI in my view too.
Because a good play in most situations can easily be a bad play under others. That doesn't happen in chess for instance, given enough decision depth to the algos to see the future game. In my own game I think those situations can occur much easier due to you always having your full deck available. Also, in MtG it's easy to get into table states that are either ahead/behind and then you kinda just have to protect your position (like with denial decks). Then you have the effects that you might remove a creature threat (graveyard) but then that enabling a combo you weren't expecting that needs a creature on the grave, or enabling delve cards or whatever have you. It's much less clear cut for a probabilistic model to make the optimal play at every single interaction. So the more you train the model on all the variations and possible follow ups, the more you dilute its certainty isn't it? In chess, or this game, or RTS such as starcraft, that doesn't really happen in my view.
In my own game you don't have shuffle/draw randomness but the pool of options is statistically tending to infinite (if I would have 500 or 1000 scrolls designed and MtG depending on the format has that depth) when compared to something like chess, or this game. On the other hand in my own game you have to account for much more depth on the possible options your opponent has.
Those new additions can invalidate the whole training data by a single new "card" that changes completely the dynamics and would be easy for a player to understand and incorporate but not for an algorithm (perhaps with enough compute to re-train it regularly it could) - that along with the decision trees being orders of magnitude deeper, wider and with more conditionalities than go, chess or stratego - even through the same turn with the same cards available and same table state - would probably pose much harder problems for a compute bound algo.
In the meanwhile I refactored it to run in a plain cheap vps (currently running on a 5€ ovh VPS) with a free supabase instance to go with it, to allow me to host it online for cheap so that at least it could be tried instead of just images and text about it. It has been previously deployed on an autoscaling cluster in AWS with all the bells and whistles and the open-source objective includes all the terraform files to automate that production use case, but otherwise can run perfectly fine for hundreds of players on a small VPS (the supabase free instance might not hold together though in that case).
Feel free to give it a spin. If you want to play against someone you don't need an account, just click "TRY IT!" and then choose "Invite someone for a Duel", send the link to the other person and try a duel with a pre-assembled deck. You can also try it by yourself by opening another tab (a private one is better so you don't experience it all collapsing into a single user if the tab idles or you refresh, since the last cookie will set both tabs to the same player).
You can also sign-up but only with Google OAuth2 - the original was using Sendgrid which no longer offers free email delivery and I haven't researched an alternative yet nor set raw email delivery.
If you like what you see consider backing the campaign, there's a link on the landing page too. While mostly it'a ready for mobile browsing, some of the things done just for the BETA (such as the try it views when waiting for a player) might not show 100% correctly - everything else should be fine.
Let me know what you think.
Remote: Yes
Willing to relocate: Yes
Technologies: Elixir, Postgresql, Javascript (plain, React, Vuejs, Webcomponents), AWS, Terraform, Docker/Podman/Systemd, Postgresql, automation, scraping, testing (including browser e2e testing) and others... I have used other languages although not as regularly and can also learn easily when needed (even before this current zeitgeist).
Website: https://micaelnussbaumer.com Github: https://github.com/mnussbaumer Contact: micaelnussbaumer [at] gmail [dot] com
Senior SE with 10+ years experience full-stack. Several MVPs and some public/online projects - currently trying to fund https://aethersummon.com a personal project (running on a cheap $5 instance right now, but previously on an AWS autoscaling cluster) - I can talk and show other projects in private (besides publicly available ones). Not anti-AI but not AI-pilled either. I can work across the full stack of a product from conception to deployment and hand-over. Available full-time or part-time, hands-on or consulting, hourly or by milestones.
Experience working across time-zones with remote, distributed teams.
But compared to meat and the whole chain of production required for that it certainly pales many moons below. Well, everyone loves their bacon.