The Intellectual Wilderness There is nothing more useless than doing efficiently that which should not be done at all.

2020.05.22 18:31

Getting started in DayZ Standalone v1.07

Filed under: Computing,Games — Tags: , , , , , , , — zxq9 @ 18:31

Happy free weekend! DayZ is be free to play from 2020-05-21 to 2020-05-25. What better way to spend your weekend while a pandemic sweeps the world than playing a post-apocalyptic zombie survival simulator… bwahahahahaha!

(Note: This is not a paid article and I have no connection to Bohemia Interactive — I just really like this game and wish more people understood what it’s about instead of suffering from the “expected Coke but got beer” shock and wind up missing out.)

Be warned: DayZ is hard mode all the way and you’ll die all the time at the beginning until you figure out how things work. This is actually hilarious, but not if you develop some pointless emotional investment in a freshly spawned character. Laugh at it. There aren’t any levels and you can gear back up pretty easily once you learn the basics of survival. Learning the basics of survival, though, can be hard. There is no manual (except for this post and the previous one) and the game is surprisingly realistic, making for an incredibly hostile environment (hence the “survival” part) and a near vertical learning curve.

This is a (relatively) quick guide on how to get your character from their initial hungry and thirsty starting condition to being well fed with a quenched thirst and hopefully enough gear and knowledge to start heading inland. A few critical details that directly affect survival have changed since previous versions of DayZ, so trying to follow guides for previous versions might leave you in even more shock than you’d already experience on your first visit to Chernarus (or especially Livonia).

First: Understand what DayZ by understanding what it isn’t

It isn’t an action shooter. It isn’t Rebel Fortress or Unreal Tournament or Battlefield. It isn’t WoW, either. It is none of those things. It is a hardcore zombie survival simulation. The all important noun there being “simulation” and the critical adjective being “hardcore”. I say “simulation” instead of “game” because there are no quests, no global map HUD, no global chat lobby, no ranking or guild system, no equipment “bank”, no auction house, none of that stuff. Comparing DayZ to an action shooter is like comparing a real flight simulator to Gradius III.

Your DayZ character must eat, stay hydrated, keep warm, avoid illness if possible, etc. There are 900+ items in v1.07 that actually have a function — so be mentally prepared for some things you didn’t think were possible or sometimes need to do things you’re surprised are necessary. Suffice to say there is a ton to learn and a single short guide like this written on the occasion of a free play weekend on Steam isn’t going to cover it all.

Picking a server

The first thing that trips up the freshest of fresh freshies is picking the wrong server. The basic mechanic is simple, you press “play” and the launcher links in whatever mods you’ve selected (if any) and launches the game. From there you will want to select “change server” and sort by ping to find one that has the lowest possible ping to your location. Anything under 200ms is workable (though not ideal) for PvE, and anything under 100ms is workable for PvP, though 50ms or less is best no matter what you’re doing.

In the server selection screen you’ll see at the top “Official | Community | Private”. It isn’t obvious to everyone at first glance that this is a clickable control (UI fail) but it is. If you can’t find a nearby official server, click on “Community” and sort by ping.

Example: I live in Japan. The official servers with the best ping times are in LA with around 130~250ms ping times from my location. That’s a bit annoying (but workable) for PvE, but hopeless for PvP. There are community servers local to me, though, with 30ms ping times (and fewer regional spoken language/accent issues). Note that with community servers you might pick one that has a great ping time but has mods installed. You’ll need to install and activate the same mods as the server to join it (mods are allowed to change the game in arbitrary ways, so the server and the client need to be on the same page). Starting out with vanilla DayZ is my recommendation your first time around, though.

With that out of the way, let’s get on to survival.

Hello, Freshie! A bit peckish?

You just spawned. Your character starts out with a sated appetite and hydrated, but that will change very soon. You’re a little more than halfway to getting hungry when you start out and you’ll get thirsty almost as soon as you start jogging somewhere (and jogging is totally OK — you don’t have to walk everywhere, but sprinting will wear you out and waste lots of precious water). You will have an apple or pear in your inventory to start with. Various types of food and drink provide both hydration as well as energy, water being the only one that provides only hydration and no extra nutrition.

Eat something

There is no manual (but I have made a cheat sheet for the controls), so it is useful to note that pressing <TAB> toggles your inventory screen. You can drag/drop things here. The square below your character’s image represents whatever he’s carrying. Drag a fruit to it, then press <TAB> again to get out of the inventory screen. You’ll notice a tool tip that has the left mouse button highlighted that says “to eat [HOLD]” or something similar, and this means if you hold the left mouse button down your character will start eating the fruit in his hand. Try it as soon as you spawn. It isn’t a big deal to lose your starting fruit, and that water and energy do more good in your body than in your pocket (infantry rules apply!).

Manipulating inventory

Inventory and item manipulation is pretty intuitive. Mess around with it and you’ll figure out what’s going on quickly enough.

The only counter-intuitive point is that the “tacky” point of a dragged object is the upper left corner of the item and that will be dictated by where the mouse pointer is, not necessarily where the item’s outline appears to be. Mess around with it and this will become obvious quickly. Also, note that items in inventory may be oriented the wrong way to fit, even if you have enough slots available — press the spacebar to rotate them while selected so they fit.

When you’re near a container (or a body) you will see those appear as inset containers in the “Vicinity” area on the left side of the screen. This is how you get stuff off the ground, out of containers, and off of bodies (of zombies, dead players, or unconscious saps that have been knocked out).

Orienteering

Now that you’ve had something to eat and if you haven’t been killed yet you should take your bearings (and if you did already die for whatever reason, just respawn and try again — it’s not a big deal). There is no map in the game interface but the environment is accurate enough that you can get your bearings from observing your surroundings. (There are maps in the game that your character can find, but nothing that is magically visible to the player).

The sun rises in the east and sets in the west, just like you would expect. If you can tell whether it is morning or evening you can know by the shadows which direction you’re moving. If it is morning and the sun is to your right (shadows point to the left) then you’re facing north, and this reverses in the afternoon. If shadows are super short (directly under trees) then it’s about mid-day and the short shadow tip is pointing north (or sometimes not quite visible).

The stars in the sky are actually placed accurately, and this makes the night sky a gigantic, free compass, just like in real life (Polaris, the North Star, is prominently visible and easy to navigate by on nights that aren’t overcast). On cloudless nights the light outside is actually quite good enough to see your immediate surroundings, so don’t be afraid to turn off any lights or extinguish any torches and navigate. Sometimes it’s much easier to see distance this way and is far less likely to give your position away to any zombies. Use the stars! If it is raining out and you don’t have a full rain suit, though, stay indoors for the night periods.

Time moves pretty quickly in the game (of course), with days seeming to be significantly longer than nights (perhaps this is on a planet with two suns? no idea). We’ll just handwave that away, but keep in mind that night isn’t to be dreaded and it doesn’t last too long.

There are billboards with maps with a big red “You are Here!” dot on them, usually somewhat close to a bus stop area out on the coast, or sometimes near a water pump in a larger town. There are also military and hiking maps you can find as loot drops that are extremely detailed. Get familiar with the map. If you do a web search for “DayZ map” you’ll find many nice ones, even interactive maps that have spawn locations listed. It is important to get the basic map in your head and figure out where you are as soon as you can.

The general layout of Charnarus is that the east and south are relatively straight coastlines, and this is the lower-risk/lower-reward area people spawn. As one heads northwest loot drops improve (military gear, more car chassies and parts, etc) and risk increases (to include hostile wildlife like wolf packs and bears, in addition to PvP-minded players looking for those sweet, sweet M4s and bodyarmor…).

Spend your time near the coast gearing for survival and then move inland to gear up for combat, base building, camping out, linking up with people, going cannibal, or whatever else it is you might want to do in the game world.

Survival priorities

You need to stay hydrated, eat well, keep warm, don’t get sick, and keep the red stuff in your body (don’t bleed out!).

To stay hydrated drink and eat.

To stay well fed eat and drink.

To keep warm wear well-maintained clothes and stay dry.

To stop bleeding when you’re hurt use rags or bandages to bind your wounds (put them in your hands and hold the left mouse button). You can have multiple wounds, so you may need to do this several times in succession (the “I’m cut” icon has a number on it representing how many open wounds you have).

To keep from getting sick don’t eat rotten food, don’t drink untreated water from rivers (or the ocean), and stay warm. To increase your immune system and reduce the recovery period for illnesses take vitamins if you can find some.

Survival tools: Water containers

If you can find a few water bottles, canteen, or a cooking pot, you’re set! You will eventually run across these. Almost every town has a water pump in it, at which you can fill your water container. These can be reused, so hold on to them after they are empty.

Survival tools: Bandages and rags

To make more rags (useful for more than just bandages) you can cut up clothing items you find as long as you have an edged tool in your hands. Do this frequently.

Survival tools: A trusty sharp thing

Tools are more important than weapons, and most heavy tools are very effective weapons anyway.

The biggest priority is having a blade of some sort. You need an edged tool to open canned food (or else you can’t eat it), strip bark from trees to use as kindling for starting fires, to craft fishhooks from bones, etc. The better suited the edged tool is to the job you’re doing the better it will work. For example, an improvised stone knife can be used to open a can of food, but you’ll spill 20~40% of it in the process because it’s sloppy. An axe is much better, and an actual can opener is perfect every time.

If you see a shovel, axe, hatchet, or pickaxe: GET IT

If you see a knife: GET IT

If you can’t find a knife, make one with two small stones. You will find these on the ground if you run down any forest trail or along the train tracks. Place one in your hand, then put another on in your hand (in the inventory screen you’ll get the option “combine” or “replace”, pick “combine), and then use the action button to craft an improvised knife. Stone knives wear out really fast, but they are free. They can get you by until you find something better.

Survival tools: Give a man a can of tuna, feed him for 12 hours; teach a man to fish, feed him until the bears show up

Besides a bladed tool and maybe something heavy to kill zombies with (can be the same: splitting axe, pickaxe, etc.), the next thing you need is a reliable source of food. At the very outset you can scrounge for canned food and soda in houses by the coast or killing zombies and looting their bodies, but eventually you’ll want to get into fishing and hunting.

Fishing is much lower risk than hunting, but you’ll need a fishing pole. Find a bush and get near it. You’ll see the option to cut down the bush by using the action button. This will happen in two stages, first you’ll strip a “long stick” off it, and if you keep going you’ll knock the whole thing over leaving some more sticks (there are a few varieties of this depending on the type of bush or small tree you target and whether you have a tool or are using your hands — experiment). You want the long stick. Now find a rope or make one if you have enough rags. Combine the stick with the rope and viola! we have a fishing pole. (Note: This is also the way bows are made, but they are disabled in v1.07, but will be returning soon.)

Now you need a fishing hook and some bait. To get fishing hooks you can either find them in random loot (I seem to never find them) or, more reliably, make some yourself out of bones. On the coast there are many places you’ll find chickens wandering around. Listen for them. Follow the sound the same way zombies follow you and SMACK! Kill yourself a chicken. Put a knife in your hand (or make a stone one if you haven’t found one yet) and butcher the chicken. You’ll get a few pieces of glorious chicken and a pile of bones. With your trusty knife in hand you can work those bones into fishhooks!

Hurray! Now the last thing to get is some bait. If you find some soft dirt, put a knife, shovel or pickaxe in your hand and you’ll see the option to “dig for worms”. Give that a try a few times. Once you have some worms, head over to the ocean or a river or lake (if you’re already inland) and give fishing a try. Fish provide a lot of nutrition, are unlimited in supply, and are safe to handle (unlike hunting wolves and bears).

How to combine worms with the fishing pole is not as obvious as it should be. Here’s a step-by-step (assuming you already have a pole, a hook and a worm):

  1. Remove the hook from the pole.
  2. Put the hook in your hand.
  3. Drag the worm to the hook to “combine”.
  4. Exit the inventory menu.
  5. Hold the left mouse button to “make fishing bait”.
  6. Once the fishing bait is complete, pick it up.
  7. Equip the pole.
  8. Add the baited hook to the pole.
  9. Go near the water (sometimes you need to look down toward it) and click and hold the left mouse button until you’ve caught something (hopefully not a pair of Wellies).

It goes a bit faster if you get a few hooks and worms ready all at once, and then commence fishing. This procedure should, in my opinion, be shortened to where you can combine a worm directly with a hook-equipped pole, but that’s not how it works at the moment. In any case, enjoy fishing! Fish are a super food, and after you prepare it with your knife it doesn’t even need to be cooked to be eaten.

Survival technique: Jacking zombies

Once you have a heavy thingy (sledgehammer, pickaxe, splitting axe, etc.) or pointy thingy (combat knife, spear, etc.) or just a bit of experience punching zombie heads in, you’re ready to jack zombies for loot, to clear routes, and for pleasure.

If you don’t sprint or make loud noises zombies generally won’t notice you until you get quite close. If you’re listening for them (use headphones) you’ll notice them long before they notice you. If you see a single zombie you can approach it from the rear or side at a sprint before it can react. As you near it, ready a blow with your weapon or fists and smack that sucker in the noggin until he goes down, then take whatever he has on him. You can find quite a lot of early loot this way (can openers, flashlights, soda, water, canned food, etc.).

Just don’t get cocky when a bunch of them are around. A single zombie isn’t hard to take down at all, even unarmed, but two gets interesting unless you have a weapon, and three or more can be the end of you if you get unlucky.

Whatever you do, don’t shoot in town unless you have a clear and immediate route out of there. A common beginner experience is “Oh, two zombies, I have a gun, simple [BANG!] … [5 seconds later] ZOMG WTF 15 ZOMBIES!” You’ll do it eventually. It might even be a good learning experience to try it on purpose just to see how fast things can get messed up when you’re wandering around alone!

Paramount to survival: Mindset

This is a toy. Remember that. You will die. Mess around the coast a bit and use your first few incarnations to figure out how things work. Familiarize yourself with crafting knives, fishing poles, finding and butchering chickens, fishing, getting solid shots with an axe on inattentive zombies, building fires (need wood, 2 or more rocks, and kindling (paper, tree bark, rags), and a firestarter (matches or a lighter)), basic cooking (need some meat and a long stick or a cooking pot), etc.

Don’t get invested in your character, get invested in the experience. When you die it doesn’t take long to gear up to survival level again, because “survival level” is really a skill not a piece of gear.

Once you are over the survival hump you’ll start meeting players and having wild experiences. Some people will kill you on sight (aka “KOS”, generally a jerk move, but lots of people think this is an action shooter because that’s been the way to make AAA titles without innovating or having any new ideas for the last 30 years).

Have fun out there, use voice chat with other players when you meet them, and always look on the bright side of life.

DayZ SA v1.07 Controls Cheatsheet

Filed under: Computing,Games — zxq9 @ 16:55

Just to make DayZ even more hardcore than it already is there is no manual and no tutorial area to cut your teeth. Instead, you just get your teeth smashed out and die until you figure out what’s going on (then you die in more interesting ways). Here is a cutdown of the basic default controls in the game.

For a more complete reference check your options menu.

Control Table (defaults)

MouseCharacter’s bearing
ALT/*Free look
V/ENTERToggle 1st/3rd person view (if 3rd is allowed)
W/A/S/DCharacter’s direction (foward/back and strafe left/right)
Q/ELean left/right
L CTRLWalk/Jog (hold for momentary toggle, double-tap to toggle)
L SHIFTSprint (hold for momentary, no toggling)
SPACEJump (character may use hands to assist)
CTap to toggle stand/crouch (hold to lay prone)
TABInventory screen
R MouseHold to raise/employ held item (raise gun, fists, etc.)
L MouseMain action (fire weapon, punch, select/drag item, etc.)
M MouseZoom (employs optics/weapon sights if at the ready)
FAlternate action (buttstroke with weapon, open door, etc.)
GDrop or throw held item
RChamber a round/cycle the action (clear a jam)
XToggle held weapon’s firing mode (semi/full auto)
PGUPElevate weapon sights (adjust zero up) if possible
PGDNLower weapon sights (adjust zero down) if possible
LActivate night vision/special optics
L CTRLHold breath (reduces aiming float)
(spacebar)Rotate selected/dragged item in inventory
` (backtick)Toggle item/action hotkey in HUD
09Item/action hotkeys (assignable in game)
CAPSLOCKSPEAK! GET A MIC! IMPORTANT!!!
Cycle voice volume (whisper/talk/shout)
/Text chat (you should really use voice if possible)
F1F11Gestures (play with this to learn them)
F12Screenshot (Steam default)

Driving

When driving vehicles the WASD movement controls work as expected, the mouse looks around, Q/E shift gears down/up respectively, and L Shift activates turbo (same as sprinting).

Crafting/Combining/Loading

Many items in the game can affect other items or be used for crafting. To craft a stone knife from two small stones, for example:

  1. Open the inventory screen and place one in your hands (drag to the “held” box below the character)
  2. Drag the other one to the “held” box — the right side will say “replace”, the left will say “combine”. Drop it into “combine”.
  3. Exit the inventory screen and you will see the tool-tip tell you to press and hold the left mouse button (or “F” key) to craft a stone knife.

In the same way, fast loading of magazines can be accomplished by placing a magazine in your hands, then dragging the appropriate ammunition to “combine” and then holding the action button to pump rounds into it without dragging individual rounds in.

Eating/Drinking

To eat an item, hold it in your hand. If it is a canned item you will need to open it before eating it. If it doesn’t have an easy opener you’ll need a can opener (best) or something with an edge like a knife (not too bad), an axe (spills quite a bit), or improvised stone knife (spills up to 40% of the contents, but better than starving).

Looting/Inventory

To loot a container (locker, barrel, backpack/clothes on the ground, etc.) or a body (dead zombie or dead/unconscious player, etc.) simply stand near it and activate the inventory screen. You can freely move items around as long as they fit.

2020.02.3 15:19

X-Y Problems

Filed under: Computing,Science & Tech,Society — Tags: , , , , , — zxq9 @ 15:19

People obsess about their X-Y problems to the point of ignoring accepted wisdom, plugging their ears to the deafening silence of the solution’s instructive whisper, picking themselves up as hard as they can by their own knees and wondering why they can’t fly.

They then run off and formalize their wrong solution as a PR into a core project.

If core maintainers aren’t mindful they’ll incorporate these disturbances into a previously still space, and if they are indelicate they will piss off the misguided (but industrious) boob who made the PR who is already by this point fanatically dedicated to his wrong solution and the idea that nobody “gets it” but him.

Ah, another day at the Bazaar.

2020.01.29 17:27

Erlang: Minesweeper

Filed under: Computing,Games — Tags: , , , , , — zxq9 @ 17:27

I’ve been sick the last two days and utterly uninspired to do anything productive. I’ve instead procrastinated by writing a “minesweeper” clone in Erlang.

Why? I have no idea. I was just sort of thinking of simple desktop classics to mess around with that are de-facto standard to populate a GUI app launcher like Vapor… and several hours later I had this thing. By that point I figured I was invested enough to swap text for graphics, and poof! There we are.

I still need to add win/loss conditions, a wall-clock timer and some kind of score thingy, but anyway, this was actually a much more fun way to tool around on a sick day than I expected and makes me feel just barely less of a dirtbag than I would have been had I wrapped up in bed all day feeling crappy.

I hate being sick. Ugh.

Update

I went ahead and finished it (except for recording scores — does anyone ever look at that since they can’t be sanely shared and aggregated?) and put it on gitlab just in case someone wants to see what a really hasty/disorganized codebase looks like.

It even has settings! Hahaha! “Settings” really being code for me messing around and seeing if I remembered how wxSlider widgets work (turns out I do and they are boringly easy to use).

If I find myself not feeling in the mood and going to the gym is out of the question, I suppose I could do one of these in 3D next time. Seems like “minesensor” would be a slightly more involved sort of game.

People who can do, people who can’t…

Filed under: Computing,Society — Tags: , , , — zxq9 @ 10:20

I get these weird solicitations. “Want to write for the ____ code blog?” and so on. I’m sure that would probably be a good career move if I was looking to get hired away by someone else (the main problem there being that I can’t relocate — hahaa!). But what kills me is that people have so much time to write things other than code.

A: “Want to write [prose] for ____?”
B: “No thanks, I’m too busy writing code for [system].”

That’s the exchange I would expect is most common — except that it is 2020 and it seems that over the last several years people write more lines about writing lines than they write actual code these days (and I don’t mean they are making an effort at impeccable documentation).

2020.01.22 09:34

Building Erlang R22.2 on Debian/Ubuntu

Filed under: Computing — Tags: , , , , , , , , , — zxq9 @ 09:34

As an update to my previous notes on building R22, my current notes for building Erlang R22.2 and installing ZX using kerl on a fresh system (Kubuntu 18.04.3 LTS) follow:

sudo apt update
sudo apt upgrade
sudo apt install \
    gcc curl g++ dpkg-dev build-essential automake autoconf \
    libncurses5-dev libssl-dev flex xsltproc libwxgtk3.0-dev \
    wget vim git
mkdir vcs bin
cd vcs
git clone https://github.com/kerl/kerl.git
cd ..
ln -s ~/vcs/kerl/kerl bin/kerl
kerl update releases
kerl build 22.2 22.2
kerl install 22.2 ~/.erts/22.2
echo '. "$HOME"/.erts/22.2/activate' >> .bashrc
. ~/.erts/22.2/activate
wget -q https://zxq9.com/projects/zomp/get_zx && bash get_zx

[NOTE: ~/vcs/ is where I usually put “version control system” managed code and my backup and sync scripts know to never copy or update that one.]

And that’s that. If you’re on a full desktop installation some of the packages in the apt install [stuff...] may be redundant, of course (who doesn’t already have wget and git?), but that’s no big deal.

2020.01.13 16:29

Overlooked Resources: A Really GOOD Favicon Generator and Checker

There are a number of slightly conflicting favicon standards and each system works a slightly different way. Having done searches at various times for reliable generators, I never found a good one until I accidentally saw an excellent one linked from an SO answer. It handles all the formats, and can check which systems will accept the favicons found at a particular site.

I’m just writing this to bring attention to it. Definitely worth a bookmark.

Favicon Generator for all platforms: https://realfavicongenerator.net/

OS Market Segments

Filed under: Computing — Tags: , , , , — zxq9 @ 11:22

Despite Linux and OSX only having somewhere between 2~5% desktop market share each, if I write an article about programming that gets picked up by aggregators and the trade press my site stats for Linux desktop visits jumps from about ~20% to 60~70% for about a week (OSX will jump from around 8% to 15~20%). It even overwhelms the bot numbers; quite a feat.

This is true whether the language is Python, Erlang, Guile/Scheme, or whatever else (all of these work on Windows just fine — of course there is a jump in *nix visits when I write something about Bash).

The inconvenience of trying to do multi-non-MS-language development (especially multi-node on the cheap, in house) on Windows really shows up in the stats. There is no possibility, for example, of a single person developing a multi-node game server or infrastructure system on their home network on Windows using repurposed/junk hardware. You can work on a single-node component (client-side, for example), but license entanglements, legal fears and money prevent flippantly spitting out a few prototypes.

That model of Windows is doomed to eventually adapt to this reality or die. If it weren’t for legacy small business data trapped in ancient applications and games Windows would already be dead — and the games can easily hop platforms.

2020.01.9 00:26

Packaging and Distributing/Deploying Erlang GUI apps with ZX

Filed under: Computing — Tags: , , , , , , — zxq9 @ 00:26

In the last two posts I wrote walkthroughs for how to create new CLI and GUI apps in Erlang from scratch using a tool called ZX. Today I want to show how to package apps and publish them using Zomp (the package distribution system) and get them into the hands of your users with minimal fuss.

To understand how packages are distributed to users (the “why does anything do anything?” part of grokking ZX/Zomp), one must first understand a bit about how Zomp views the world.

Packages in the system are organized by “realms”. A code realm is like a package repository for a Linux distribution. The most important thing about realm/repository configuration is that you know by each package’s signature whether it really came from the it claims as its origin. Just like Linux repositories, anyone can create or host a Zomp realm, and realms can be mirrored.

(As you will see in a future tutorial, though, administration and and mirroring with Zomp is way easier and flexible than traditional Linux repositories. As you will see below, packaging with ZX is just a single command — ZX already knows everything it needs from the zomp.meta file.)

In this example I am going to put the example CLI project, Termifier GUI (a toy example app that converts JSON to Erlang terms) into the default FOSS realm, “otpr”. Because I am the sysop I have packaging and maintenance permissions for every package in the realm, as well as the sole authority to add projects and “accept” a package into the write-only indexes (packagers have “submit” authority, maintainers have “review”, “reject” and “approve” authorities).

[Note: The indexes are write only because dependencies in ZX are statically defined (no invisible updates) and the indexes are the only complete structure that must be mirrored by every mirroring node. Packages are not copied to new mirrors, they are cached the first time they are requested, with mirror nodes connected in a tree instead of a single hub pushing to all mirrors at once. This makes starting a new mirror very light weight, even for large realms, as no packages need to be copied to start (only the realm’s update history, from which the index is constructed), and packages in high demand experience “trickle down” replication, allowing mirrors to be sparse instead of complete. Only the “prime node” for a given realm must have a complete copy of everything in that particular realm. Nodes can mirror an arbitrary number of realms, and a node that is prime for one or more realms may mirror any number of others at the same time, making hosting of private project code mixed with mirrored public FOSS code a very efficient arrangement for organizations and devops.]

In the original Termifier GUI tutorial I simply created it and launched it from the command line using ZX’s zx rundir [path] and zx runlocal commands. The package was implicitly defined as being in the otpr realm because I never defined any other, but otpr itself was never told about this, so it merely remained a locally created project that could use packages hosted by Zomp as dependencies, but was not actually available through Zomp. Let’s change that:

ceverett@okonomiyaki:~/vcs$ zx add package otpr-termifierg

Done. That’s all there is to it. I’m the sysop, so this command told ZX to send a signed instruction (signed with my sysop key) to the prime node of otpr to create an entry for that package in the realm’s index.

Next we want to package the project. Last time we messed with it it was located at ~/vcs/termifierg/, so that’s where I’ll point ZX:

ceverett@okonomiyaki:~/vcs$ zx package termifierg/
Packaging termifierg/
Writing app file: ebin/termifierg.app
Wrote archive otpr-termifierg-0.1.0.zsp

Next I need to submit the package:

ceverett@okonomiyaki:~/vcs$ zx submit otpr-termifierg-0.1.0.zsp

The idea behind submission is that normally there are two cases:

  1. A realm is a one-man show.
  2. A realm has a lot of people involved in it and there is a formal preview/approval, review/acceptance process before publication (remember, the index is write-only!).

In the case where a single person is in charge rushing through the acceptance process only involves three commands (no problem). In the case where more than one person is involved the acceptance of a package should be a staged process where everyone has a chance to see each stage of the acceptance process.

Once a package has been submitted it can be checked by anyone with permissions on that project:

ceverett@okonomiyaki:~/vcs$ zx list pending otpr-termifierg
0.1.0
ceverett@okonomiyaki:~/vcs$ zx review otpr-termifierg-0.1.0
ceverett@okonomiyaki:~/vcs$ cd otpr-termifierg-0.1.0
ceverett@okonomiyaki:~/vcs/otpr-termifierg-0.1.0$ 

What the zx review [package_id] command does is download the package, verify the signature belongs to the actual submitter, and unpacks it in a directory so you can inspect it (or more likely) run it with zx rundir [unpacked directory].

After a package is reviewed (or if you’re flying solo and already know about the project because you wrote it) then you can “approve” it:

ceverett@okonomiyaki:~/vcs$ zx approve otpr-termifierg-0.1.0

The if the sysop is someone different than the packager then the review command is actually necessary, because the next step is re-signing the package with the sysop’s key as a part of acceptance into the realm. That is, the sysop runs zx review [package_id], actually reviews the code, and then once satisfied runs zx package [unpacked_dir] which results in a .zsp file signed by the sysop. If the sysop is the original packager, though, the .zsp file that was created in the packaging step above is already signed with the sysop’s key.

The sysop is the final word on inclusion of a package. If the green light is given, the sysop must “accept” the package:

ceverett@okonomiyaki:~/vcs$ zx accept otpr-termifierg-0.1.0.zsp

Done! So now let’s see if we can search the index for it, maybe by checking for the “json” tag since we know it is a JSON project:

ceverett@okonomiyaki:~/vcs/termifierg$ zx search json
otpr-termifierg-0.1.0
otpr-zj-1.0.5
ceverett@okonomiyaki:~/vcs/termifierg$ zx describe otpr-termifierg-0.1.0
Package : otpr-termifierg-0.1.0
Name    : Termifier GUI
Type    : gui
Desc    : Create, edit and convert JSON to Erlang terms.
Author  : Craig Everett zxq9@zxq9.com
Web     : 
Repo    : https://gitlab.com/zxq9/termifierg
Tags    : ["json","eterms"]

Yay! So we can now already do zx run otpr-termifierg and it will build itself and execute from anywhere, as long as the system has ZX installed.

I notice above that the “Web” URL is missing. The original blog post is as good a reference as this project is going to get, so I would like to add it. I do that by running the “update meta” command in the project directory:

ceverett@okonomiyaki:~/vcs/termifierg$ zx update meta

DESCRIPTION DATA
[ 1] Project Name             : Termifier GUI
[ 2] Author                   : Craig Everett
[ 3] Author's Email           : zxq9@zxq9.com
[ 4] Copyright Holder         : Craig Everett
[ 5] Copyright Holder's Email : zxq9@zxq9.com
[ 6] Repo URL                 : https://gitlab.com/zxq9/termifierg
[ 7] Website URL              : 
[ 8] Description              : Create, edit and convert JSON to Erlang terms.
[ 9] Search Tags              : ["json","eterms"]
[10] File associations        : [".json"]
Press a number to select something to change, or [ENTER] to continue.
(or "QUIT"): 7
... [snip] ...

The “update meta” command is interactive so I’ll spare you the full output, but if you followed the previous two tutorials you already know how this works.

After I’ve done that I need to increase the “patch” version number (the “Z” part of the “X.Y.Z” semver scheme). I can do this with the “verup” command, also run in the project’s base directory:

ceverett@okonomiyaki:~/vcs/termifierg$ zx verup patch
Version changed from 0.1.0 to 0.1.1.

And now time to re-package and put it into the realm. Again, since I’m the sysop this is super fast for me working alone:

ceverett@okonomiyaki:~/vcs$ zx submit otpr-termifierg-0.1.1.zsp 
ceverett@okonomiyaki:~/vcs$ zx approve otpr-termifierg-0.1.1
ceverett@okonomiyaki:~/vcs$ zx accept otpr-termifierg-0.1.1.zsp

And that’s that. It can immediately be run by anyone anywhere as long as they have ZX installed.

BONUS LEVEL!

“Neat, but what about the screenshot of it running?”

Up until now we’ve been launching code using ZX from the command line. Since Termifier GUI is a GUI program and usually the target audience for GUI programs is not programmers, yesterday I started on a new graphical front end for ZX intended for ordinary users (you know, people expert at things other than programming!). This tool is called “Vapor” and is still an ugly duckling in beta, but workable enough to demonstrate its usefulness. It allows people to graphically browse projects from their desktop, and launch by clicking if the project is actually launchable.

Vapor is like low-pressure Steam, but with a strong DIY element to it, as anyone can become a developer and host their own code.

I haven’t written the window manager/desktop registration bits yet, so I will start Vapor from the command line with ZX:

You’ll notice a few things here:

  • Termifier GUI’s latest version is already selected for us, but if we click that button it will become a version selector and we can pick a specific version.
  • Observer is listed, but only as a “virtual package” because it is part of OTP, not actually a real otpr package. For this reason it lacks a version selector. (More on this below.)
  • Vapor lacks a “run” button of its own because it is already running (ZX is similarly special-cased)

When I click Termifier’s “run” button Vapor’s window goes away and we see that the termifierg-0.1.1 package is fetched from Zomp (along with deps, if they aren’t already present on the system), built and executed. If we run it a second time it will run immediately from the local cache since it and all deps are already built.

When Termifier terminates Vapor lets ZX know it is OK to shutdown the runtime.

A special note on Observer and “Virtual Packages”

[UPDATE 2020-01-12: The concept of virtual packages is going away, observer will have a different launch method soon, and a rather large interface change is coming to Vapor soon. The general principles and function the system remain the same, but the GUI will look significantly different in the future — the above is the day-2 functioning prototype.]

When other programs are run by Vapor the main Vapor window is closed. Remember, each execution environment is constructed at runtime for the specific application being run, so if we run two programs that have conflicting dependencies there will be confusion about the order to search for modules that are being called! To prevent contamination Vapor only allows a single application to be run at once from a single instance of Vapor (you can run several Vapor instances at once, though, as each invocation of ZX creates an independent Erlang runtime with its own context and environment — the various zx_daemons coordinate locally to pick a leader, though, so resource contention is avoided by proxying through the leader). If you want several inter-related apps to run at once within the same Erlang runtime, create a meta-package that has the sole function of launching them all together with commonly defined dependencies.

Because Observer is part of OTP it does not suffer from dependency or environmental conflict issues, so running Observer is safe and the “run” button does just that: it runs Observer. Vapor will stay open while Observer is running, allowing you to pick another application to run, and you can watch what it is up to using Observer as a monitoring tool, which can be quite handy (and interesting!).

If you want to run an Erlang network service type application using Vapor while using Observer (like a chat server, or even a Zomp node) you should start Vapor using the zxh command (not just plain zx), because that provides an Erlang shell on the command line so you can still interact with the program from there. You can also run anything using plain old zx run, and when the target application terminates that instance of the runtime will shut down (this is why ZX application templates define applications as “permanent“).

Cool story, bro. What Comes Next?

The next step for this little bundle of projects is to create an all-encompassing Windows installer for Erlang, ZX and Vapor (so it can all be a one-shot install for users), and add a desktop registration feature to Vapor so that Erlang applications can be “installed” on the local system, registered with desktop icons, menu entries and file associations in FreeDesktop and Windows conformant systems (I’ll have to learn how to do it on OSX, but that would be great, too!). Then users could run applications without really knowing about Vapor, because authors could write installation scripts that invoke Vapor’s registration routines directly.

If I have my way (and I always get my way eventually) Erlang will go from being the hardest and most annoying language to deploy client-side to being one of the easiest to deploy client-side across all supported platforms. BWAHAHAHA! (I admit, maybe this isn’t a world-changing goal, but for me it would be a world-changing thing…)

2019.12.28 23:56

Starting a simple GUI project in Erlang with ZX

A few days ago I wrote a tutorial about how to create a CLI program in Erlang using a new code utility called ZX that makes launching Erlang a little bit more familiar for people accustomed to modern dynamic language tooling.

Today I want to do another one in the same spirit, but with a simple GUI program as the example.

In the previous tutorial I did a CLI utility that converts files containing JSON to files containing Erlang terms. It accepts two arguments: the input file path and the desired output file path.

Today we’ll do a slightly more interesting version of this: a GUI utility that allows hand creation/editing of both the input before conversion and the output before writing. The program will have a simple interface with just three buttons at the top: “Read File”, “Convert” and “Save File”; and two text editing frames as the main body of the window: one on the left with a text control for JSON input, and one on the right a text control for Erlang terms after conversion.

First things, first: We have to choose a name and create the project. Since we did “Termifier” with a package and module name “termifier” before, today we’ll make it called “Termifier GUI” with a package and appmod “termifierg” and a project prefix “tg_”. I’ve clipped out the creation prompt output for brevity like before, but it can be found here: zx_gui_creation.txt.

ceverett@okonomiyaki:~/vcs$ zx create project

### --snip snip--
### Prompts for project meta
### --snip snip--

Writing app file: ebin/termifierg.app
Project otpr-termifierg-0.1.0 initialized.
ceverett@okonomiyaki:~/vcs$

If we run this using ZX’s zx rundir command we see a GUI window appear and some stuff happen in the terminal (assuming you’re using a GUI desktop and WX is built into the Erlang runtime you’re using).

The default templated window we see is a GUI version of a “Hello, World!”:

If we try the same again with some command line arguments we will see the change in the text frame:

The output occurring in the terminal is a mix of ZX writing to stdout about what it is building and WX’s GTK bindings warning that it can’t find an optional style module (which isn’t a big deal and happens on various systems).

So we start out with a window that contains a single multi-line text field and accepts the “close window” event from the window manager. A modest, but promising start.

What we want to do from here is make two editable text fields side by side, which will probably require increasing the main window’s size for comfort, and adding a single sizer with our three utility buttons at the top for ease of use (and our main frame, of course, being derived from the wxEvtHandler, will need to connect to the button click events to make them useful!). The text fields themselves we probably want to make have fixed-width fonts since the user will be staring at indented lines of declarative code, and it might even be handy to have a more natural “code editor” feel to the text field interface, so we can’t do any better than to use the Scintilla-type text control widget for the text controls.

Now that we know basically what we want to do, we need to figure out where to do it! To see where to make these changes we need to take a little tour of the program. It is four modules, which means it is a far different beast than our previous single-module CLI program was.

Like any project, the best way to figure out what is going on is to establish two things:

  1. How is the code structured (or is there even a clear structure)?
  2. What is called to kick things off? (“Why does anything do anything?”)

When I go into termifierg/src/ I see some very different things than before, but there is a clear pattern occurring (though it is somewhat different than the common Erlang server-side “service -> worker” pattern):

ceverett@okonomiyaki:~/vcs$ cd termifierg/src/
ceverett@okonomiyaki:~/vcs/termifierg/src$ ls -l
合計 16
-rw-rw-r-- 1 ceverett ceverett 1817 12月 27 12:50 termifierg.erl
-rw-rw-r-- 1 ceverett ceverett 3166 12月 27 12:50 tg_con.erl
-rw-rw-r-- 1 ceverett ceverett 3708 12月 27 12:50 tg_gui.erl
-rw-rw-r-- 1 ceverett ceverett 1298 12月 27 12:50 tg_sup.erl

We have the main application module termifierg.erl, the name of which we chose during the creation process, and then we also have three more modules that use the tg_ prefix we chose during creation: tg_con, tg_gui and tg_sup. As any erlanger knows, anything named *_sup.erl is going to be a supervisor, so it is logical to assume that tg_sup.erl is the top (in this case the only) supervisor for the application. It looks like there are only two “living” modules, the *_con one, which seems short for a “control” module, and the *_gui one, which seems likely to be just the code or process that controls the actual window itself.

We know that we picked termifierg as the appmod for the project, so it should be the place to find the typical OTP AppMod:start/2 function… and sure enough, there it is: termifierg:start/2 is simply call to start things by calling tg_sup:start_link/0. So next we should see what tg_sup does. Being a supervisor its entire definition should be a very boring declaration of what children the supervisor has, how they depend on one another (order), and what restart strategy is being employed by that supervisor.

(Protip: magical supervision is evil; boring, declarative supervision is good.)

init([]) ->
     RestartStrategy = {one_for_one, 0, 60},
     Clients   = {tg_con,
                  {tg_con, start_link, []},
                  permanent,
                  5000,
                  worker,
                  [tg_con]},
     Children  = [Clients],
     {ok, {RestartStrategy, Children}}.

Here we see only one thing is defined: the “control” module called tg_con. Easy enough. Knowing that we have a GUI module as well, we should expect that the tg_con module probably links to the GUI process instead of monitoring it, though it is possible that it might monitor it or maybe even use the GUI code module as a library of callback functions that the control process itself uses to render a GUI on its own.

[NOTE: Any of these approaches is valid, but which one makes the most sense depends entirely on the situation and type of program that is being written. Is the GUI a single, simple interface to a vast and complex system underneath? Does each core control component of the system have its own window or special widget or tab to render its data? Are there lots of rendered “views” on the program data, or a single view on lots of different program data? Is it OK for updates to the GUI to block on data retrieval or processing? etc.]

Here we see a program that is split between interface code and operation code. Hey! That sounds a lot like the “View” and “Control” from the classic “MVC” paradigm! And, of course, this is exactly the case. The “Model” part in this particular program being the data we are handling which is defined by the Erlang syntax on the one hand and JSON’s definition on the other (and so are implicit, not explicit, in our program).

The tg_con process is the operation code that does things, and it is spawn_linking the interface that is defined by tg_gui. If either one crashes it will take the other one down with it — easy cleanup! For most simple programs this is a good model to start with, so we’ll leave things as they are.

The tg_gui process is the one that interfaces with the back-end. In this simple of a program we could easily glom them all together without getting confused, but if we add even just a few interesting features we would bury our core logic under the enormous amounts of verbose, somewhat complex code inherent in GUI applications — and that becomes extremely frustrating to separate out later (so most people don’t do it and their single-module-per-thingy WX code becomes a collection of balls of mud that are difficult to refactor later, and that stinks!).

Since we already know what we want to do with the program and we already proved the core code necessary to accomplish it in the previous tutorial, we can move on to building an interface for it.

This is what the final program looks like, using the same example.json from the CLI example:

At this point we are going to leave the blog and I will direct you instead to the repository code, and in particular, the commit that shows the diff between the original template code generated by ZX and the modified commit that implements the program described at the beginning of this tutorial. The commit has been heavily commented to explain every part in detail — if you are curious about how this Wx program works I strongly recommend reading the code commit and comments!

Older Posts »

Powered by WordPress