Arghh! I'm surrounded by bullshit!

C# doesn't have sum types. I'm begining to see this as a fatal problem, and maybe I really should move to F#.

Frickin' nginx didn't start after a reboot, because it couldn't reach one of the hosts its the proxy for.

Time to move the "replace nginx with traefik" plans forward I guess.

Don't know what to do about c# though. I think I need to have more of a think about the problem. Quack.

I'm re-writing the Hydra frontend stuff, and I'm moving code out of the controller. After the user has logged in they need to be shown a 'consent' screen that asks them to confirm that they're ok with the client getting access to their data.

However, under certain conditions the consent screen is skipped and the user can be redirected without seeing it.

I was returning two values from the function, a bool 'is skip needed' and a nullable string 'redirectTarget' that's set when skipNeeded is true. However, I can instead return two nullables, the redirect string, or the info needed to show the consent screen.

Quack indeed.


There's a minigame that's shown up in a couple of places that I've liked playing, sending agents to run missions.

Some benevolent entity wants stuff done, and will reward you for doing it. You pick an available job/task/mission, assign some of your people to it, and wait for the random number generator to decide your fate.

The skill/challenge/fun comes from matching your people to tasks - Peter is a fighter, Joan is a diplomat, so send Peter to hunt deer/fight zombies, and Joan gets the negotiation jobs.

You must also manage opportunity costs - if Peter has been assigned hunting duties, they can't enter into a competition that there'd easily win.

More complex versions can bring in resource management. Peter brings back a boar from a hunt, +5 food, but took damage so -1 medicine, and they can't be assigned for a day or two.

Early on, missions can be simple templates: "The local village is being attacked by (zombies|robots|frogs), kill n for a reward from the mayor", but I kind the idea that there is a world behind the missions - hunt too many wolves and the local deer population jumps up, but that leads to overgrazing and damage to young trees.

The flow of time also needs to be modelled. Is there a 1:1 match between mission time and real time, or do missions run faster (or slower!).

How does the player interact? A point and click webpage would work fine, but maybe play by email? (Especially for something with a more sci-fi or espionage skin).


Network connection(s) for node001

Node001 is my new Raspberry Pi. I'm going to set it up as a k3s machine, and I want it to have access to some of my public IPv6 addresses (Go Mythic!)

I'm also thinking about isolating it from the local network somehow, but I don't think I can do that without having it behind some kind of hardware firewall (which would need to be ptah in this context).

I can get a WiFi card for ptah, and hang node001 off that, since I've got a "No more cables near ptah" requirement.

...

Raspberry Pi supports 'ac' WiFi ("WiFi 5", apparently), and a new card for ptah looks like £20-30. So let's work on that basis.

I can route everything from the card through to wepiu via the VPN, so even if naughty people completely own the pi, they won't be able to break into the house network.

I can also setup a hub so that the pi's can talk over ethernet to each other.


Player:

  • Create(Name)
  • Change Name(Name)
  • Delete()

Template:

  • Create(Name, Duration, Slots, Factors[])
  • ChangeAttribute
  • Delete()

The big question is how do I a) keep these organized (separate) while b) only having one Decide method.

IDecider {
 IEnumerable<Event> Decide(Command command);
}

I want a pair of top level types for Command and Event, and then I can just have a CombiningDecider that takes IDeciders and offers commands to each in turn.

I could make IDecider generic and filter based on types, or I can specify in the contract that Decide ignores (returns an empty sequence for) commands it doesn't recognise. Which I think sounds easier.

It's it worth doing the same thing for evolve?

I'm not sure about evolve, I've got a couple of things to do with each event that aren't really related (store the raw event, update the aggregate(s), post the event to web listeners). I'm getting a vague shape of each event processor having it's own copy of Evolve, but that seems inefficient (except, for sure there's going to be a JavaScript copy in the browser).

Hmm.

(Been coughing off and on all day, totally sucks. Took the day off sick, will do again tomorrow unless I'm feeling 100% when I wake up)


Mission jobs

  • Convert commands to use ids instead of instances

  • Dump factors (missions) and attributes (assets) in favour of key/value pairs

    This one needs a bit more thought. Problems include:

    • Are keys registered somewhere, or are they just convention? Convention is easier to program, keys are strings and I'm careful when I type them. Registration is safer (typo proof) but needs a registry (that, ideally, JavaScript has access to)
    • Are values typed? String/Number/Boolean opens up options, and something like units (gold, kg, hp) opens up more. Cost is that strings are easier to deal with.
    • Scope creep. If these pairs get complex enough, I can redefine missions/players as collections of pairs (instead of having some actual native properties). It's that a bad thing?
  • Start thinking about authorization/roles, splitting out admin functions on the front end, and authentication, mapping users to players


  • Do something about persistence

The caches can be updated to be async, with a fallback to something more permanent.

Should get the event storage stuff working, then can do event replay at app start time, and maybe start using event source's last id.


Hello people! I've been ill for a couple of weeks, I think that was probably covid. I've lost my sense of smell (plus the coughing, sweating, sneezing, aching, and fatigue), hopefully temporarily, but it's still weird eating and just getting texture - I can't even remember what foods tasted like.

I'm recovering now, helped by a "fit note" that's given me permission for a week off work, so I've been sleeping/relaxing/watching a lot of you tube.

I bought a Raspberry Pi (v4, 4GB) a couple of weeks back with a "build a cluster" plan, but I'm really not sure it's worth the money or effort. I don't want to hang the cluster off the home network, to protect the home network if someone cracks the cluster, so I've been looking at 4G/LTE modems, and that's got me all depressed.

I can buy a second hand Vodaphone USB modem dongle through eBay for under £20, and Id mobile will sell me unlimited 4G data for £16/month, and I'll have to (well, really want to) get a tunnel from A&A for £10/month, and I still don't know what I want to do with the cluster!

I've got a vague "kubenetes + web servers" plan, but the remote server I've got works well enough without all that messing about, and £26/month will rent me 2.9 pis from Mythic, without the up front cost of the hardware.

Ah, well. I've bought one pi, and if I come up with a use case I'll let you know.


Cooked myself an omlette for dinner, and I cooked it really quite well. I should think about doing that more often.


Tonights entertainment is setting up an iSCSI target for my new Pi, and trying to network boot off it (so I can talk to Mythic about swapping NFS for iSCSI).

I've installed dracut on the Pi to manage the initramfs (the normal Debian tools just don't cut it, apparently), and I've spun up a a VM (tayet - The One Who Weaves) as the iSCSI host.

I'm going to try to use the right terminology: iSCSI talks in terms of 'initiator' (client) and 'target' (server).

First, setup passwordless access by appending the contents of $env:USERDIR\.ssh\id_ed25519.pub to $HOME/.ssh/authorized_keys.

Config file for tayet - /etc/tgt/config.d/node001.conf (this is the 'target')

<target iqn.2023-08.uk.co.aaru:node001-root>
  backing-store /srv/iscsi/node001.img
  initiator-name iqn.2023-08.uk.co.aaru:node001-initiator01
  incominguser johnathan partridge
</target>

(yes, that's not really XML.)

I'm just going to leave the link to the instructions I followed for node001 (I'm getting tired, and they are a bit messier)


Foof! I've setup most of a network root for the pi. Still to do:

  • Install and configure dnsmasq on tayet ss a dhcp/tftp server.
  • Setup ipxe so that the pi, when it asks tayet for a kernel, gets pointed towards the right place
  • Find out how much of the iscsi client stuff I need to install on the pi. (Thinking, if the kernel has booted of the remote disk, do I need the client tools?)
  • Dream about a shared read-only /usr disk
  • Go though that all again, but this time with the USB stick (four times faster than the sd card, and I'm only doing the iscsi thing as a test/demo for Mythic)

Dnsmask doesn't do IPv6 very well, so I've installed ISC Kea, which feels a bit over-engineered, but so far so good.

I've got it installed and running with a tftp server defined in the config, but I've left it switched off for now because I need to check that it's not going to try to stomp on the BT router.

Poot. Just read the docs for Kea, and it won't run as a 'proxy' (that is, send out DHCP replies with options set but no ip address).

Bollocks to it, I'll get an OS installed on the USB stick, and then I can use that Pi for whatever.


Physical vs cloud, that old chestnut.

Cloud machines work, have good connectivity, are IPv6 only (with workarounds).

Physical machines don't have a recurring cost, have more permanance, can be used to interface to the actual world.

Hybrid cluster gives me security concerns. Gah.


To remember your current position in the blog, this page must store some data in this browser.

Are you OK with that?