(2707,'2018-12-18','Steganalysis 101',864,'Steganalysis is the process of identifying the presence of, and decrypting, steganography.','<h3 id=\"introduction\">1. Introduction</h3>\r\n<p>Hello and welcome to Hacker Public Radio, I’m Edward Miro and I’ve been a fan of HPR for a while now and really love its collaborative and random nature. It’s always been important for me to support the hacking community. I always take any opportunity to give back to this community who have given me so much throughout the years. I’ve also always subscribed to the idea that the best way to learn something is by teaching and I hope to do a good job for all you listeners. This talk is on mystical art of steganalysis which is the process of identifying the presence of and decrypting (hopefully) steganography.</p>\r\n<h3 id=\"what-is-steganography\">2. What is steganography?</h3>\r\n<p>I’m into hacking, but I’m not a professional hacker. Usually I call myself a hobbyist. I like CTFs, crypto challenges, lots of stuff from Vulnhub or OverTheWire, things like that. I’ll provide some links in the end if anyone is interested, but for those who aren’t familiar a CTF, or Capture The Flag, it’s a kind of game that helps you get better at hacking. These days there are tons of VMs that are setup to be intentionally vulnerable to different techniques or attacks. You load the VM and pretend it’s a server you want to attack and follow your standard hacking protocols. Some are setup to be boot to root challenges where you ‘win’ when you get root and some are setup with flags that you can find hidden in the target worth points. There are in person and online CTFs and they’ve gotten pretty popular with the National Cyber League being a major competition. Some are easy, some are really hard and most have really good write-ups that can teach you so much about INFOSEC, penetration testing and actually let you practice the techniques in a relatively easy and legal way.</p>\r\n<p>Where steganography comes in to this discussion is that it’s an element you sometimes see used in the kinds of challenges I mentioned previously and also in alternate reality games, online recruitment challenges by national agencies/big tech companies and militarys. They are even used in real world espionage and intelligence work or super spooky secret challenges like Cicada 3301.</p>\r\n<p>Simply put steganography (and I’m pasting this straight out of Wikipedia): “is the practice of concealing a file, message, image, or video within another file, message, image, or video”. Steganography is used to hide secrets in plain sight. It’s a way to send a message, without anyone detecting that a message is even being sent.</p>\r\n<p>I’ll give you more examples in the next section, but imagine a letter that has a secret written in invisible ink. Only the sender and receiver should know about the invisible ink and any eavesdroppers should be none the wiser. This simple example has been used by countless prisoners whose mail is routinely read and examined. Terrorists and spies the world over also use steganography and are known to embed messages in an image and post it online. With how many image hosting sites there are, with millions of people posting to them billions of images day in and day out, you can see why steganography can be such a challenge to combat. Before I move on to some more specific examples I want to stress again that I’m not an expert on cryptography or steganography. While researching for this podcast it’s overwhelmingly clear that you could spend your whole career focused on only steganography. This talk is just a primer on the subject and only the tip of the iceberg.</p>\r\n<h3 id=\"examples-also-from-wikipedia-the-great-repository-of-all-knowledge\">3. Examples (also from Wikipedia, the great repository of all knowledge)</h3>\r\n<ul>\r\n<li>Analog:\r\n<ul>\r\n<li>Head shaving</li>\r\n<li>Invisible ink</li>\r\n<li>Knots tied into ropes</li>\r\n<li>Messages hidden under stamps on envelopes</li>\r\n<li>Mixed typeface</li>\r\n<li>Using a grille cipher</li>\r\n<li>Sending messages via newspaper classifieds</li>\r\n</ul></li>\r\n<li>Digital:\r\n<ul>\r\n<li>Noise in images or sound files</li>\r\n<li>Text commented out in source html or other code</li>\r\n<li>Using different color text</li>\r\n<li>Fractionalized comments</li>\r\n<li>Audio signals/spectro</li>\r\n<li>Hidden control characters and non printing Unicode</li>\r\n</ul></li>\r\n</ul>\r\n<p>The possibilities are almost endless for how this technique can be applied.</p>\r\n<h3 id=\"why-should-we-care\">4. Why should we care?</h3>\r\n<p>When we are doing a CTF or crypto challenge and are presented with an image or media file we are pretty well assured there’s something in there, though not every image you find while doing a challenge or CTF will utilize steganography so don’t overanalyze. I’ve known people who are really into alternate reality games spending 100s of hours doing spectrographic analysis and for our purpose(and the scope of this podcast), there should be some clue that steganography is being used. The challenge then becomes how we direct our work flow as to not waste any time and be the most efficient in cracking that particular part the puzzle. There are MANY stego tools out there, some of them homebrewed, and unless the designer of the challenge puts in a clue, you might spend hours trying different algorithms or tools. And even if you do, there’s no guarantee you’ll get anything at all. A lot of the tools that will be mentioned in the next section rely on fingerprinting how known algorithms process data. This is not only a big problem for hackers like us with our CTFs and games, but even more so for governments who are charged with keeping us safe. So if you’re looking at possible steganography, you need to build a good workflow and I noticed a post on Reddit a few weeks ago with a user asking about image forensics. There was a comment posted that was so good I forwarded it to my hacking friends and it inspired me to do this podcast. I’m using the comment as a potential framework for my own personal work with images and steganography. It helped me to develop my own protocol and I wanted to share it with you all and if anyone wants to expand on it or improve it please do so. Thank you /u/Alexeyan!</p>\r\n<h3 id=\"proposed-work-flow\">5. Proposed work flow</h3>\r\n<p>This is coming straight out of the post on Reddit. I thought about rewriting it, but it didn’t seem necessary and I will be giving the author full credit. I add a couple more tools on at the bottom and a few closing thoughts:</p>\r\n<ul>\r\n<li><p>First: Look at the image. Maybe it tells you something important.</p></li>\r\n<li><p>Use binwalk to check for other file type signatures in the image file.</p></li>\r\n<li><p>Use Exiftool to check for any interesting exif-metadata.</p></li>\r\n<li><p>Use stegsolve and switch through the layers and look for abnormalities.</p></li>\r\n<li><p>Maybe the Flag is painted in the LSB image, or some QR-Code.</p></li>\r\n<li><p>Maybe there are random pixels that look strange in a certain layer, that’s a hint for Bit-Stego.</p></li>\r\n<li><p>Use zsteg to automatically test the most common bitstegos and sort by %ascii-in-results. (This one auto-solves about 50% of all image stego challenges)</p></li>\r\n<li><p>If the file is a png, you can check if the IDAT chunks are all correct and correctly ordered.</p></li>\r\n<li><p>Check with the strings tool for parts of the flag. If you found for example “CTF{W” in a chunk, check what is on that position in other IDAT chunks.</p></li>\r\n<li><p>The harder ones can be a lot more tricky though.. JPG coefficiency manipulation, Frequency analysis, …</p></li>\r\n<li><p>But usually those are frowned upon, because they require a lot of guessing (if no hiding tool is provided)</p></li>\r\n</ul>\r\n<p>Some other go to tools not mentioned above:</p>\r\n<ul>\r\n<li>Stegdetect</li>\r\n<li>DIIT(Digital Invisible Ink Toolkit )</li>\r\n<li>StegSecret</li>\r\n<li>ILook Investigator (for law enforcement)</li>\r\n</ul>\r\n<p>Detecting steganography is hard work. There are computer scientists who do only this. While we aren’t at that level for the information being presented here, it will require a lot of digging and trying different tools. Hopefully following these steps will help identify the more common techniques in an easier way than trial and error.</p>\r\n<p>One last thing I want to mention is that part of how I see detecting steganography in CTFs or cyptochallenges is having a certain mindset and always looking at things in various layers. I try to look at everything within the challenge as if there could be something right in front of my eyes. I mentally flip through different layers and see the codes within the codes. And remember if you’re playing an alternate reality game, a CTF or a crypto challenge, generally speaking, the designers want you to play through the game. They will leave clues if you need them. They want the players to get to the end. Don’t overthink things.</p>\r\n<p>Well that’s all I’ve got for today. I hope you enjoyed this podcast and got something useful out of it. Like I said in the introduction, I’m Edward Miro. Have fun, and good luck!</p>\r\n<h3 id=\"sources\">6. Sources</h3>\r\n<ul>\r\n<li>Steganography basics:\r\n<ul>\r\n<li><a href=\"https://en.wikipedia.org/wiki/Steganography\" class=\"uri\">https://en.wikipedia.org/wiki/Steganography</a></li>\r\n<li><a href=\"https://www.wired.com/story/steganography-hacker-lexicon/\" class=\"uri\">https://www.wired.com/story/steganography-hacker-lexicon/</a></li>\r\n<li><a href=\"https://null-byte.wonderhowto.com/how-to/steganography-hide-secret-data-inside-image-audio-file-seconds-0180936/\" class=\"uri\">https://null-byte.wonderhowto.com/how-to/steganography-hide-secret-data-inside-image-audio-file-seconds-0180936/</a></li>\r\n</ul></li>\r\n<li>CTFs\r\n<ul>\r\n<li><a href=\"https://www.nationalcyberleague.org/\" class=\"uri\">https://www.nationalcyberleague.org/</a></li>\r\n<li><a href=\"https://www.vulnhub.com/\" class=\"uri\">https://www.vulnhub.com/</a></li>\r\n<li><a href=\"https://ctf365.com/\" class=\"uri\">https://ctf365.com/</a></li>\r\n</ul></li>\r\n<li>Tools\r\n<ul>\r\n<li><a href=\"https://github.com/ReFirmLabs/binwalk\" class=\"uri\">https://github.com/ReFirmLabs/binwalk</a></li>\r\n<li><a href=\"https://www.sno.phy.queensu.ca/~phil/exiftool/\" class=\"uri\">https://www.sno.phy.queensu.ca/~phil/exiftool/</a></li>\r\n<li><a href=\"https://github.com/zardus/ctf-tools/tree/master/stegsolve\" class=\"uri\">https://github.com/zardus/ctf-tools/tree/master/stegsolve</a></li>\r\n<li><a href=\"https://github.com/zed-0xff/zsteg\" class=\"uri\">https://github.com/zed-0xff/zsteg</a></li>\r\n<li><a href=\"https://en.wikipedia.org/wiki/Strings_(Unix)\" class=\"uri\">https://en.wikipedia.org/wiki/Strings_(Unix)</a></li>\r\n<li><a href=\"https://github.com/abeluck/stegdetect\" class=\"uri\">https://github.com/abeluck/stegdetect</a></li>\r\n<li><a href=\"https://diit.sourceforge.net/\" class=\"uri\">https://diit.sourceforge.net/</a></li>\r\n<li><a href=\"https://stegsecret.sourceforge.net/\" class=\"uri\">https://stegsecret.sourceforge.net/</a></li>\r\n<li><a href=\"https://www.ilook-forensics.org/\" class=\"uri\">https://www.ilook-forensics.org/</a></li>\r\n</ul></li>\r\n<li>Detection\r\n<ul>\r\n<li><a href=\"https://web.cs.ucdavis.edu/~davidson/Publications/IAAI103.pdf\" class=\"uri\">https://web.cs.ucdavis.edu/~davidson/Publications/IAAI103.pdf</a></li>\r\n<li><a href=\"https://www.sans.org/reading-room/whitepapers/stenganography/steganalysis-detecting-hidden-information-computer-forensic-analysis-1014\" class=\"uri\">https://www.sans.org/reading-room/whitepapers/stenganography/steganalysis-detecting-hidden-information-computer-forensic-analysis-1014</a></li>\r\n</ul></li>\r\n</ul>\r\n',372,0,0,'CC-BY-SA','Steganalysis, steganography',0,0,1),
(2704,'2018-12-13','Intro to Scribus',2380,'Klaatu provides an overview of Scribus in part 1 of a mini-series about steganography','<p>Scribus is a page layout application. If you are familiar with common publishing industry tools, then Scribus will be very familiar to you, but if you\'re used to word processors or graphic applications, then Scribus will probably confuse you. In this episode, Klaatu talks about the workflow of page layout, and how to do some basic tasks in Scribus.\r\n</p>\r\n\r\n<p>The example files Klaatu produces in Scribus are available at <a href=\"https://slackermedia.info/tank/scribus-by-example.tar.gz\" target=\"_blank\">https://slackermedia.info/tank/scribus-by-example.tar.gz</a></p>\r\n\r\n<p>Fair warning: this episode is actually \"about\" steganography. The key you need is <strong>OGG</strong>.</p>',78,74,0,'CC-BY-SA','design, steganography, scribus, layout',0,0,1),
(2706,'2018-12-17','Why I love the IBM AS/400 computer systems',1714,'A short talk about how I came to love the IBM As/400 systems and why.','<p>This is a talk about my love for the IBM family of AS/400 computer systems.</p>\r\n<p>Although it’s a very hacker unfriendly system there is still much to admire and love.</p>\r\n<p>It’s completely different from anything else which makes it nice but also very likely to disappear in few years from now. To prevent that piece of computing history to vanish I started a small initiative called <a href=\"https://www.as400museum.org/\" class=\"uri\">https://www.as400museum.org/</a>. It’s just me, but it does show my intention with the system.</p>\r\n',369,0,1,'CC-BY-SA','as400, ibm, computing, midrange',0,0,1),
(2708,'2018-12-19','Ghostscript',1351,'Klaatu talks about manipulating PDFs with gs and pdf-stapler','<p>\r\nGhostscript is the open source implementation of Postscript. You can read its <a href=\"https://www.ghostscript.com/doc/current/Use.htm\" target=\"_blank\">docs</a> online.\r\n</p>\r\n\r\n<p>\r\nTo compress a big PDF into something possibly smaller:\r\n</p>\r\n\r\n<pre><code>\r\n$ gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dBATCH -sOutputFile=output.pdf example.pdf\r\n</code></pre>\r\n\r\n<p>\r\nThat renders basically the same PDF with all images down-res\'d to 72 DPI. Other valid setting profiles are <strong>ebook</strong>, <strong>printer</strong>, and <strong>prepress</strong>.\r\n</p>\r\n\r\n<p>\r\nTo render a version of a PDF without any raster images in it, making it cheaper and faster to print:\r\n</p>\r\n\r\n<pre><code>\r\ngs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dBATCH -dFILTERIMAGE -sOutputFile=output.pdf example.pdf\r\n</code></pre>\r\n\r\n<p>\r\nThe FILTERIMAGE option drops raster images from the file. The <strong>FILTERVECTOR</strong> option filters vector images, and <strong>FILTERTEXT</strong> filters text.\r\n</p>\r\n\r\n<p>\r\nIf <a href=\"https://hackerpublicradio.org/eps.php?id=2667\" target=\"_blank\">pdftk</a> is not available for your OS, you can use <a href=\"https://github.com/hellerbarde/stapler\" target=\"_blank\">pdf-stapler</a> instead for cutting and concatenating PDF files. It doesn\'t deal with metadata as well as pdftk does, however.</p><p>It\'s worth noting that pdftk is available as a snap package <a href=\"https://snapcraft.io/pdftk\" target=\"_blank\">https://snapcraft.io/pdftk</a>.\r\n</p>\r\n\r\n<p>\r\nIt\'s also worth noting that this is actually episode 2 in a series about steganography.</p>\r\n\r\n',78,74,0,'CC-BY-SA','pdf, ebook, bloat, print',0,0,1),
(2711,'2018-12-24','Raspberry Pi 3A+ Review',336,'In this episode of HPR, I will do a quick review of the Raspberry Pi 3A+.','<h1 id=\"raspberry-pi-3a-review\">Raspberry Pi 3A+ review</h1>\r\n<p>In this episode of HPR, I will do a quick review of the Raspberry Pi 3A+, the latest release of the Raspberry Pi foundation.</p>\r\n<p><img src=\"https://frenchguy.ch/assets/img_1710_800.jpg\" title=\"Raspberry Pi 3A+\" alt=\"Raspberry Pi 3A+\" /> <img src=\"https://frenchguy.ch/assets/img_1711_800.jpg\" title=\"Raspberry Pi 3A+\" alt=\"Raspberry Pi 3A+\" /></p>\r\n<p><strong>Specs</strong><br />\r\nThe Raspberry Pi 3A+ has almost the same hardware as its big brother/sister the 3B+ :</p>\r\n<ul>\r\n<li>BCM2837 BO SOC (system on chip), a quad core 64-bit ARM v8 processor, running at 1.4 GHz</li>\r\n<li>On board wireless :\r\n<ul>\r\n<li>WiFi : 2.4 and 5 GHz 802.11 c/y/n/ac</li>\r\n<li>Bluetooth : 4.2 and BLE</li>\r\n</ul></li>\r\n<li>MicroSD card for storing the operating system and the data</li>\r\n<li>Full size HDMI connector</li>\r\n<li>3.5 mm jack connector for audio and composite video output</li>\r\n<li>MicroUSB connector for the power supply</li>\r\n<li>40-pin header with the same pinout as every other Raspberry Pi</li>\r\n</ul>\r\n<p>The differences are :</p>\r\n<ul>\r\n<li>Only one full size USB connector, instead of four on the 3B+</li>\r\n<li>No ethernet connector</li>\r\n<li>Only 512 MB or SDRAM instead of 1 GB on the 3B+</li>\r\n</ul>\r\n<p><strong>Size</strong><br />\r\nThe Raspberry Pi 3A+ is 6.7 x 5.6 cm (2.6 x 2.2 in) and 11 mm high (.45 in). But if you plug a ribbon in the header, then it takes a lot of space.</p>\r\n<p><img src=\"https://frenchguy.ch/assets/img_1713_800.jpg\" title=\"Raspberry Pi 3A+\" alt=\"Raspberry Pi 3A+\" /></p>\r\n<p>In this case, it’s probably better to unsolder the header, and solder a right angle header in place, so the pins are pointing to the side of the board and not upwards</p>\r\n<p><img src=\"https://frenchguy.ch/assets/img_1716_800.jpg\" title=\"Raspberry Pi 3A+\" alt=\"Raspberry Pi 3A+\" /> <img src=\"https://frenchguy.ch/assets/img_1717_800.jpg\" title=\"Raspberry Pi 3A+\" alt=\"Raspberry Pi 3A+\" /></p>\r\n<p>With a bit of caution and the help of some desoldering wick, it’s not a complex operation, because there is no component near the GPIO header.</p>\r\n<p>Of course if you plan on using a HAT, then you’re better off using the straight header. The Raspberry Pi 3A+ is actually the same size than a standard HAT.</p>\r\n<p><img src=\"https://frenchguy.ch/assets/img_1718_800.jpg\" title=\"Raspberry Pi 3A+\" alt=\"Raspberry Pi 3A+\" /> <img src=\"https://frenchguy.ch/assets/img_1719_800.jpg\" title=\"Raspberry Pi 3A+\" alt=\"Raspberry Pi 3A+\" /></p>\r\n<p><strong>Use case</strong><br />\r\n</p>\r\n<p>Since the Raspberry Pi 3A+ doesn’t have an ethernet port, I think I will not use it for server stuff like <a href=\"https://mosquitto.org/\">Mosquitto</a> or <a href=\"https://pi-hole.net/\">Pi-Hole</a>, for which a good network connection is required. Also, those servers sometimes need a keyboard and a mouse, and with only one USB port, that’s not too practical.</p>\r\n<p>For me, the A+ will be used to upgrade projects currently using a Raspberry Pi ZeroW, and for which I need a little more power. The on board WiFi and the small form factor, combined with the extra power, makes the 3A+ an ideal replacement for the ZeroW.</p>\r\n<p><strong>Credits</strong><br />\r\n</p>\r\n<p>The sound used for the opening and closing sequence is <a href=\"https://www.jamendo.com/track/1405949/speaker-x-clash-jingle\">Speaker X-Clash</a> by Daniel H, and is released under a CC-BY-NC license.</p>\r\n',370,0,0,'CC-BY-SA','raspberry pi, review',0,0,1),
(2712,'2018-12-25','Steganography',1290,'Klaatu wraps up his miniseries about steganography.','<p>Did you find the hidden message contained in Klaatu\'s previous two episodes?</p>\r\n<p>If not, Klaatu reveals how to find it in this one, how to duplicate it, and what makes good steganography.</p>',78,0,0,'CC-BY-SA','steganography,message,secret decoder ring',0,0,1),
(2714,'2018-12-27','Airplane stalls and Angle of Attack',995,'A primer on why airplanes quit flying','<h1 id=\"stalls-a-primer-on-why-aircraft-fly-and-dont-fly\">stalls, a primer on why aircraft fly, and don’t fly</h1>\r\n<h2 id=\"youtube-video-of-stall-with-narration-35-seconds\">YouTube video of stall with narration (35 seconds)</h2>\r\n<p><a href=\"https://www.youtube.com/watch?v=SiOiVHUEYao\" class=\"uri\">https://www.youtube.com/watch?v=SiOiVHUEYao</a></p>\r\n<h2 id=\"aoa-gauge-from-t-38-manual\">AoA gauge from T-38 manual</h2>\r\n<p><a href=\"https://goo.gl/images/ZH5UYx\" class=\"uri\">https://goo.gl/images/ZH5UYx</a></p>\r\n<h2 id=\"some-definitions\">Some definitions</h2>\r\n<ul>\r\n<li><p>chord - an imaginary line from the front of the wing to the back</p></li>\r\n<li><p>relative wind - movement of air relative to the chord</p></li>\r\n<li><p>angle of attack - the angle of the chord of the wing to the relative wind</p></li>\r\n<li><p>stall - a condition where the air on the top of the wing is not flowing smoothly over the wing</p></li>\r\n<li><p>critical angle of attack - the angle that the wing becomes stalled</p></li>\r\n<li><p>fun - stalling and spinning and aircraft when its safe to do so</p></li>\r\n<li><p>scary - stalling and spinning and aircraft when you don’t want to</p></li>\r\n</ul>\r\n<h2 id=\"things-not-mentioned\">Things not mentioned</h2>\r\n<p>This discussion pertained to subsonic speeds, super sonic flight introduces a whole other realm of issues.</p>\r\n<p>The wings of aircraft do not stall all at once. They are designed (usually) to stall from the wing root (where the wing is attached to the fuselage) towards the tips. This ensures good roll control at slow speed and into the stall. This stalling characteristic is achieved by designing twist in the wing (washout) allowing different parts of the wing to hit the critical angle of attack at different times.</p>\r\n<p>The most dangerous situation that you can find yourself in is a low altitude situation where one wing is stalled more than the other. The airplane then enters a spin. The dangerous part is the low altitude. Spins are fun, and the plane is still controllable, but you need altitude to recover. A wise man told me when turning low to the ground keep your nose down and speed up.</p>\r\n<p>Most light aircraft will shudder or buffet as you approach the critical angle of attack this happens because of the disturbed airflow hitting the aircraft’s fuselage or tail. In larger aircraft no (i.e. airliners) no feel is given naturally as the plane approaches a stalled condition so systems like stick shakers vibrate the control artificially as you approach the critical angle of attack as measured by the AoA sensors. <a href=\"https://goo.gl/images/7xv5A5\">DC-9 stick shaker, a big cell phone vibrator</a> artificial stall warning is mandatory in fly-by-wire aircraft (i.e. Airbus, f-16) as well as pure hydraulic controls (i.e. Boeing 757)</p>\r\n<p>Author: Brian<br />\r\nCreated: 2018-12-01 Sat 07:34<br />\r\nEmacs 25.3.1 (Org mode 8.2.10)</p>\r\n',326,0,0,'CC-BY-SA','aircraft,flight,stall',0,0,1),
(2760,'2019-03-01','What is VNF',445,'A topic from the Open Networking conference in Amsterdam','<p>A short basic info about VNF</p>\r\n<p><a href=\"https://searchsdn.techtarget.com/definition/virtual-network-functions\" class=\"uri\">https://searchsdn.techtarget.com/definition/virtual-network-functions</a></p>',129,61,0,'CC-BY-SA','Virtual network function,VNF,network functions virtualization,NFV',0,0,1),
(2785,'2019-04-05','What is uCPE',399,'A short talk on telco networking standards','<ul>\r\n<li><a href=\"https://blog.advaoptical.com/en/what-is-universal-cpe\" class=\"uri\">https://blog.advaoptical.com/en/what-is-universal-cpe</a></li>\r\n<li><a href=\"https://www.audiocodes.com/solutions-products/solutions/network-function-virtualization-nfv/universal-cpe-ucpe\" class=\"uri\">https://www.audiocodes.com/solutions-products/solutions/network-function-virtualization-nfv/universal-cpe-ucpe</a></li>\r\n<li><a href=\"https://netmanias.com/en/post/blog/12703/sdn-nfv-ucpe/what-is-universal-cpe-updated-at-may-2018\" class=\"uri\">https://netmanias.com/en/post/blog/12703/sdn-nfv-ucpe/what-is-universal-cpe-updated-at-may-2018</a></li>\r\n<li><a href=\"https://www.walkerfirst.com/uploads/files/literature/Skinny_Wire_17S.pdf?as_url_id=AAAAAAWx6lVCrvi0cYObNZzKbTqds3zxZOTme09iW_1bgRwXnxj5xBhDUZFsrEovlR-8QzYp5bjEFX-8gUDCSfEtxk2YBSqlqDxvUktl5hrlcCW3RFsY5EZqzULvKHnRBTv51vleaWM2y0uBOkqJjueTHAIu\" class=\"uri\">https://www.walkerfirst.com/uploads/files/literature/Skinny_Wire_17S.pdf?as_url_id=AAAAAAWx6lVCrvi0cYObNZzKbTqds3zxZOTme09iW_1bgRwXnxj5xBhDUZFsrEovlR-8QzYp5bjEFX-8gUDCSfEtxk2YBSqlqDxvUktl5hrlcCW3RFsY5EZqzULvKHnRBTv51vleaWM2y0uBOkqJjueTHAIu</a></li>\r\n</ul>',129,0,1,'CC-BY-SA','Network Function Virtualization,NFV,Universal customer premises equipment,uCPE',0,0,1),
(2729,'2019-01-17','Bash Tips - 18',1898,'Arrays in Bash (part 3)','<h1 id=\"bash-tips---18\">Bash Tips - 18 <small><small>(Extra auxiliary Bash tips)</small></small></h1>\r\n<h2 id=\"arrays-in-bash\">Arrays in Bash</h2>\r\n<p>This is the third of a small group of shows on the subject of arrays in Bash. It is also the eighteenth show in the <em>Bash Tips</em> sub-series.</p>\r\n<p>In the last show we looked at ways of accessing elements with negative indices and how to concatenate arrays. We then launched into parameter expansion in the context of arrays.</p>\r\n<p>There are a few more parameter expansion operations to look at in this episode, then in the next episode we will look in more depth at the <code>declare</code> built in command and at some of the commands that assist with loading data into arrays.</p>\r\n<h2 id=\"long-notes\">Long notes</h2>\r\n<p>I have provided detailed notes as usual for this episode, and these can be <a href=\"https://hackerpublicradio.org/eps/hpr2729/full_shownotes.html\">viewed here</a>.</p>\r\n<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><a href=\"https://www.gnu.org/software/bash/manual/bash.html\">“<em>GNU BASH Reference Manual</em>”</a>\r\n<ul>\r\n<li>Section on <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Arrays\">“Bash Arrays”</a></li>\r\n<li>Section on <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion\">“Shell Parameter Expansion”</a></li>\r\n</ul></li>\r\n</ul>\r\n<ul>\r\n<li>Linux Documentation Project: <a href=\"https://www.tldp.org/LDP/abs/html/index.html\">Advanced Bash-Scripting Guide</a>\r\n<ul>\r\n<li><a href=\"https://www.tldp.org/LDP/abs/html/arrays.html\">Chapter 27: Arrays</a></li>\r\n</ul></li>\r\n<li><p><a href=\"https://hackerpublicradio.org/series/0042.html\">HPR series: <em>Bash Scripting</em></a></p></li>\r\n<li>Previous episodes under the heading <em>Bash Tips</em>:\r\n<ol>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1648\">HPR episode 1648 “<em>Bash parameter manipulation</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1843\">HPR episode 1843 “<em>Some Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1884\">HPR episode 1884 “<em>Some more Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1903\">HPR episode 1903 “<em>Some further Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1951\">HPR episode 1951 “<em>Some additional Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2045\">HPR episode 2045 “<em>Some other Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2278\">HPR episode 2278 “<em>Some supplementary Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2293\">HPR episode 2293 “<em>More supplementary Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2639\">HPR episode 2639 “<em>Some ancillary Bash tips - 9</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2649\">HPR episode 2649 “<em>More ancillary Bash tips - 10</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2659\">HPR episode 2659 “<em>Further ancillary Bash tips - 11</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2669\">HPR episode 2669 “<em>Additional ancillary Bash tips - 12</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2679\">HPR episode 2679 “<em>Extra ancillary Bash tips - 13</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2689\">HPR episode 2689 “<em>Bash Tips - 14 (Some auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2699\">HPR episode 2699 “<em>Bash Tips - 15 (More auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2709\">HPR episode 2709 “<em>Bash Tips - 16 (Further auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2719\">HPR episode 2719 “<em>Bash Tips - 17 (Additional auxiliary Bash tips)</em>”</a></li>\r\n</ol></li>\r\n</ul>\r\n<ul>\r\n<li>Resources:\r\n<ul>\r\n<li>Examples: <a href=\"https://hackerpublicradio.org/eps/hpr2729/bash18_ex1.sh\">bash18_ex1.sh</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2729/bash18_ex2.sh\">bash18_ex2.sh</a></li>\r\n</ul></li>\r\n</ul>\r\n',225,42,1,'CC-BY-SA','Bash,array,indexed array,associative array,parameter expansion',0,0,1),
(2724,'2019-01-10','Using a DIN Rail to mount a Raspberry Pi',549,'I created DIN rail fittings for attaching my RPi 3B+ and an SSD disk','<h2 id=\"overview\">Overview</h2>\r\n<p>A <em>DIN Rail</em> is a metal rail for mounting pieces of electrical equipment inside an equipment rack, for performing tasks in a building, in a machine, and so forth. It’s common to see DIN rails holding circuit breakers for example.</p>\r\n<p>See the <a href=\"https://en.wikipedia.org/wiki/DIN_rail\" title=\"Wikipedia article on the DIN Rail\">Wikipedia article</a> on the subject for full details.</p>\r\n<p>A number of people in the Maker Community have made use of these rails, and there are a number of freely available designs for stands that can be 3D printed on which you can mount these rails. There are also designs for mounts onto which devices like Raspberry Pis and disks can be fitted and attached to a rail.</p>\r\n<p>This show will recount my experiences with creating a compact mounting system for one of my Raspberry Pi systems. I had the help of my son and his girlfriend in 3D printing the parts for this project.</p>\r\n<h2 id=\"long-notes\">Long notes</h2>\r\n<p>I have provided detailed notes and pictures for this episode, and these can be <a href=\"https://hackerpublicradio.org/eps/hpr2724/full_shownotes.html\">viewed here</a>.</p>\r\n<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><p>Wikipedia article <a href=\"https://en.wikipedia.org/wiki/DIN_rail\"><em>DIN Rail</em></a></p></li>\r\n<li>Thingiverse designs used:\r\n<ul>\r\n<li><a href=\"https://www.thingiverse.com/thing:2610621\">DIN Mounts: Pi, Arduino and disks</a> by <a href=\"https://www.thingiverse.com/imstrng\">imstrng</a></li>\r\n<li><a href=\"https://www.thingiverse.com/thing:2068383\">DIN Rail Stand</a> by <a href=\"https://www.thingiverse.com/RedWraith\">RedWraith</a></li>\r\n</ul></li>\r\n</ul>\r\n<ul>\r\n<li>Other Thingiverse DIN Rail-related items:\r\n<ul>\r\n<li><a href=\"https://www.thingiverse.com/thing:2144527\">DIN Rail Stand v2</a> by <a href=\"https://www.thingiverse.com/philklaus\">philklaus</a></li>\r\n<li><a href=\"https://www.thingiverse.com/thing:2415721\">Raspberry Pi Zero Vertical Edge-Mounted DIN Mount</a> by <a href=\"https://www.thingiverse.com/coffeenut\">coffeenut</a></li>\r\n</ul></li>\r\n</ul>\r\n',225,0,1,'CC-BY-SA','3D printing,DIN rail,Raspberry Pi',0,0,1),
(2723,'2019-01-09','Using Elm in context of 4X game client',2671,'Tuula talks their decisions on structuring Elm application','<p>Original idea I had with my toy game project was to have Yesod render most of the user interface as static HTML and have as little client side scripting as possible. Later I realized that there would be parts with significant amount of client side code and it might be better if whole site was written in Elm.</p>\r\n<p>Couple goals I had in my mind when I started this:</p>\r\n<ul>\r\n<li>easy to work with</li>\r\n<li>type safe</li>\r\n<li>extensible</li>\r\n<li>user authorization\r\n<ul>\r\n<li>regular player</li>\r\n<li>administrator</li>\r\n</ul></li>\r\n</ul>\r\n<p>Backend is written in Haskell and front end in Elm. Communication between them is via REST interface and most of the data is in JSON. All JSON encoding / decoding is centralized (more or less), same with initiating requests to server.</p>\r\n<h2 id=\"api-endpoints\">API Endpoints</h2>\r\n<p>End points used for REST calls are defined in single data type that captures their name and parameters. These are used when initiating requests, meaning there’s smaller chance of typo slipping through.</p>\r\n<pre><code>type Endpoint\r\n    = ApiStarDate\r\n    | ApiResources\r\n    | ApiStarSystem\r\n    | ApiStar\r\n    | ApiPlanet\r\n    | ApiPopulation PlanetId\r\n    | ApiBuilding PlanetId\r\n    | ApiConstructionQueue PlanetId\r\n    | ApiConstruction Construction\r\n    | ApiBuildingConstruction\r\n    | ApiAvailableBuildings</code></pre>\r\n<p>For example, sending a GET request to retrieve all construction projects on a planet is done as:</p>\r\n<pre><code>Http.send (ApiMsgCompleted &lt;&lt; ConstructionsReceived) (get (ApiConstructionQueue planetId) (list constructionDecoder))</code></pre>\r\n<p>GET Request is sent to ApiConstructionQueue endpoint and it has planetId as parameter. When server sends response, our program will parse content of it will be a list that is parsed with constructionDecoder and create “ApiMsgCompleted ConstructionsReceived” message with result of the parsing. Update function will process this and store list of constructions somewhere safe for further use.</p>\r\n<h2 id=\"update-function\">Update function</h2>\r\n<p>Update function is in charge of reacting to messages (mouse clicks, page changes, responses from server). In a large program update function will quickly get big and unwieldy. Breaking it into smaller pieces (per page for example), will make maintenance easier. This way each page has their own message type and own update function to handle it. In addition there’s few extra ones (cleaning error display, processing API messages and reacting to page changes).</p>\r\n<p>Same way as API end points are encoded in a type, pages are too:</p>\r\n<pre><code>type Route\r\n    = HomeR\r\n    | ProfileR\r\n    | StarSystemsR\r\n    | StarSystemR StarSystemId\r\n    | PlanetR StarSystemId PlanetId\r\n    | BasesR\r\n    | FleetR\r\n    | DesignerR\r\n    | ConstructionR\r\n    | MessagesR\r\n    | AdminR\r\n    | LogoutR\r\n    | ResearchR</code></pre>\r\n<p>routeToString function is used to map Route into String, that can be placed in hyperlink. Below is an excerp:</p>\r\n<pre><code>routeToString : Route -&gt; String\r\nrouteToString route =\r\n    case route of\r\n        HomeR -&gt;\r\n            &quot;/home&quot;\r\n\r\n        StarSystemR (StarSystemId sId) -&gt;\r\n            &quot;/starsystem/&quot; ++ String.fromInt sId\r\n\r\n        PlanetR (StarSystemId sId) (PlanetId pId) -&gt;\r\n            &quot;/starsystem/&quot; ++ String.fromInt sId ++ &quot;/&quot; ++ String.fromInt pId</code></pre>\r\n<p>Because mapping needs to be bi-directional (Route used to define content of a href and string from a href used to define Route), there’s mapping to other direction too:</p>\r\n<pre><code>routes : Parser (Route -&gt; a) a\r\nroutes =\r\n    oneOf\r\n        [ map HomeR top\r\n        , map ProfileR (s &quot;profile&quot;)\r\n        , map ResearchR (s &quot;research&quot;)\r\n        , map StarSystemsR (s &quot;starsystem&quot;)\r\n        , map StarSystemR (s &quot;starsystem&quot; &lt;/&gt; starSystemId)\r\n        , map PlanetR (s &quot;starsystem&quot; &lt;/&gt; starSystemId &lt;/&gt; planetId)\r\n        , map BasesR (s &quot;base&quot;)\r\n        , map FleetR (s &quot;fleet&quot;)\r\n        , map DesignerR (s &quot;designer&quot;)\r\n        , map ConstructionR (s &quot;construction&quot;)\r\n        , map MessagesR (s &quot;message&quot;)\r\n        , map AdminR (s &quot;admin&quot;)\r\n        , map LogoutR (s &quot;logout&quot;)\r\n]</code></pre>\r\n<p>Result of parsing is Maybe Route, meaning that failure will return Nothing. Detecting and handling this is responsibility of the calling code, usually I just default to HomeR.</p>\r\n<h2 id=\"breadcrumbs\">Breadcrumbs</h2>\r\n<p>Borrowing from Yesod, client uses recursive function to define breadcrumb path. This is hierarchical view of current location in the application, allowing user to quickly navigate backwards where they came.</p>\r\n<p>Breadcrumb path consists of segments that are tuple of (String, Maybe Route). String tells text to display and Route is possible parent route of the segment. This allows hierarchical definition: “Home / Star systems / Sol / Earth”. Because route has only (for example) PlanetId, we need to pass Model too, so that the data retrieved from server can be used to figure out what name such a planet has.</p>\r\n<pre><code>{-| Build complete breadcrumb path and wrap it in enclosing HTML\r\n-}\r\nbreadcrumbPath : Model -&gt; Html Msg\r\n\r\n{-| Recursively build list of breadcrumbs from segments\r\nLast one is plain text, while parents of it are links\r\n-}\r\nbreadcrumb : Model -&gt; Bool -&gt; Route -&gt; List (Html Msg)\r\n\r\n{-| Get segment of given route in form of ( String, Maybe Route )\r\nString denotes text describing the segment, Maybe Route is possible parent\r\n-}\r\nsegment : Model -&gt; Route -&gt; ( String, Maybe Route )</code></pre>\r\n',364,0,0,'CC-BY-SA','elm',0,0,1),
(2803,'2019-05-01','Update on my Raspi 3 B OpenMedia Vault and Next Cloud instances',449,'A short podcast on how my little home servers are working or not','<ul>\r\n<li><p><a href=\"https://nextcloud.com/box/\" class=\"uri\">https://nextcloud.com/box/</a><br />\r\nThis link was the first product and it is not available any more.</p></li>\r\n<li><p><a href=\"https://ownyourbits.com/nextcloudpi/\" class=\"uri\">https://ownyourbits.com/nextcloudpi/</a><br />\r\nThis link tells you about all the different ways to do next cloud.</p></li>\r\n<li><p><a href=\"https://github.com/nextcloud/nextcloudpi/wiki/How-to-install-NextCloudPi\" class=\"uri\">https://github.com/nextcloud/nextcloudpi/wiki/How-to-install-NextCloudPi</a><br />\r\nThe link above is what worked exactly for me.</p></li>\r\n<li><p><a href=\"https://www.openmediavault.org/about.html\" class=\"uri\">https://www.openmediavault.org/about.html</a><br />\r\nThe link above is about what OMV is.</p></li>\r\n<li><p><a href=\"https://sourceforge.net/projects/openmediavault/files/Raspberry%20Pi%20images/\">https://sourceforge.net/projects/openmediavault/files/Raspberry%20Pi%20images/</a><br />\r\nIs were I got my image.</p></li>\r\n</ul>\r\n<p>I use a Toshiba 4TB non-powered drive external usb 3 drive.</p>\r\n',129,0,1,'CC-BY-SA','Raspberry Pi,NextCloud,openmediavault',0,0,1),
(2716,'2018-12-31','Really Simple YouTube',441,'Thaj explains how he makes YouTube come to him using RSS feeds','<p>Here are the two links I mentioned that let you pull RSS feeds out of YouTube</p>\r\n<ul>\r\n<li><a href=\"https://danielmiessler.com/blog/rss-feed-youtube-channel/\" class=\"uri\">https://danielmiessler.com/blog/rss-feed-youtube-channel/</a></li>\r\n<li><a href=\"https://support.google.com/youtube/answer/6224202?hl=en\" class=\"uri\">https://support.google.com/youtube/answer/6224202?hl=en</a></li>\r\n</ul>\r\n',270,0,0,'CC-BY-SA','RSS, YouTube, PeerTube, TInyTinyRSS, Internet Video',0,0,1),
(2739,'2019-01-31','Bash Tips - 19',1553,'Arrays in Bash (part 4)','<h2 id=\"arrays-in-bash\">Arrays in Bash <small><small>(Supplemental auxiliary Bash tips)</small></small></h2>\r\n<p>This is the fourth and last of a small group of shows on the subject of arrays in Bash. It is also the nineteenth show in the <em>Bash Tips</em> sub-series.</p>\r\n<p>In the last show we continued with the subject of parameter expansion in the context of arrays. There are other aspects of this that could be looked at, but we’ll leave it for the moment and may revisit it in the future.</p>\r\n<p>In this episode we will look in more depth at the <code>declare</code> (<code>typeset</code>) built in command and at some commands that are related (<code>readonly</code> and <code>local</code>), We will also look at the commands that assist with loading data into arrays: <code>mapfile</code> (<code>readarray</code>) and <code>read</code>.</p>\r\n<h2 id=\"long-notes\">Long notes</h2>\r\n<p>As usual I have provided detailed notes and examples for this episode, and these can be <a href=\"https://hackerpublicradio.org/eps/hpr2739/full_shownotes.html\">viewed here</a>.</p>\r\n<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><a href=\"https://www.gnu.org/software/bash/manual/bash.html\">“<em>GNU BASH Reference Manual</em>”</a>\r\n<ul>\r\n<li>Section on <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Arrays\">“Bash Arrays”</a></li>\r\n<li>Section on <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Shell-Builtin-Commands\">“4 Shell Builtin Commands”</a>\r\n<ul>\r\n<li>Section on <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Bourne-Shell-Builtins\">“4.1 Bourne Shell Builtins”</a></li>\r\n<li>Section on <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Bash-Builtins\">“4.2 Bash Builtin Commands”</a></li>\r\n</ul></li>\r\n</ul></li>\r\n</ul>\r\n<ul>\r\n<li>Linux Documentation Project: <a href=\"https://www.tldp.org/LDP/abs/html/index.html\">Advanced Bash-Scripting Guide</a>\r\n<ul>\r\n<li><a href=\"https://www.tldp.org/LDP/abs/html/arrays.html\">Chapter 27: Arrays</a></li>\r\n</ul></li>\r\n<li><p><a href=\"https://hackerpublicradio.org/series/0042.html\">HPR series: <em>Bash Scripting</em></a></p></li>\r\n<li>Previous episodes under the heading <em>Bash Tips</em>:\r\n<ol>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1648\">HPR episode 1648 “<em>Bash parameter manipulation</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1843\">HPR episode 1843 “<em>Some Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1884\">HPR episode 1884 “<em>Some more Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1903\">HPR episode 1903 “<em>Some further Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1951\">HPR episode 1951 “<em>Some additional Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2045\">HPR episode 2045 “<em>Some other Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2278\">HPR episode 2278 “<em>Some supplementary Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2293\">HPR episode 2293 “<em>More supplementary Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2639\">HPR episode 2639 “<em>Some ancillary Bash tips - 9</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2649\">HPR episode 2649 “<em>More ancillary Bash tips - 10</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2659\">HPR episode 2659 “<em>Further ancillary Bash tips - 11</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2669\">HPR episode 2669 “<em>Additional ancillary Bash tips - 12</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2679\">HPR episode 2679 “<em>Extra ancillary Bash tips - 13</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2689\">HPR episode 2689 “<em>Bash Tips - 14 (Some auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2699\">HPR episode 2699 “<em>Bash Tips - 15 (More auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2709\">HPR episode 2709 “<em>Bash Tips - 16 (Further auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2719\">HPR episode 2719 “<em>Bash Tips - 17 (Additional auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2729\">HPR episode 2729 “<em>Bash Tips - 18 (Extra auxiliary Bash tips)</em>”</a></li>\r\n</ol></li>\r\n</ul>\r\n<ul>\r\n<li>Resources:\r\n<ul>\r\n<li>Examples: <a href=\"https://hackerpublicradio.org/eps/hpr2739/bash19_ex1.sh\">bash19_ex1.sh</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2739/bash19_ex2.sh\">bash19_ex2.sh</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2739/bash19_ex3.sh\">bash19_ex3.sh</a></li>\r\n</ul></li>\r\n</ul>\r\n',225,42,1,'CC-BY-SA','Bash,array,declare,typeset,local,readonly,read,mapfile,readarray',0,0,1),
(2717,'2019-01-01','Mobile Device Security',621,'Cell phone cyber security 101','<h2 id=\"introduction\">Introduction</h2>\r\n<p>Hello and welcome to Hacker Public Radio, I’m Edward Miro and for this episode I decided to address mobile device security. As with most of the research and articles I’ve written in the past, these are geared toward standard users in a business setting and are meant to be a jumping off point for further research and to be a foundation for cyber security 101 level training classes. If you like what I do, and want to have me come speak to your team, feel free to email me.</p>\r\n<p>As an information security researcher, I have noticed a trend in what potential clients lately have been interested in: cell phones. Almost everyone I have consulted for in the area of private investigations make this area their main priority. This makes sense as users have started to transition to using mobile devices more and more. Not only do cell phones represent the main conduit to the internet for a huge chunk of people, but many use them for work also. Many companies have smartly presented policies against this, but there are still many organizations that allow bring-your-own-device style implementations. In the following podcast I will try to define the threats, defense and considerations in very broad strokes.</p>\r\n<p>Cell phones differ from a standard hacking target in a few ways. For the most part, many of the same vectors are still valid. Remote code execution however is more rare, but not out of the question. I’m going to attempt to present these different vectors in an ascending list of what is most likely to be used as an attack, in my humble (and possibly ignorant) opinion.</p>\r\n<h3 id=\"passive-surveillance\">1. Passive Surveillance</h3>\r\n<p>This vector is one many in the hacking world will already be familiar with and it is a major concern for mobile devices as well. Attackers can monitor an access point where the mobile device is connected and collect packets in all the usual ways. Open public WiFi is a treasure trove and tons of data that’s being sent in the clear can be collected, analyzed and leveraged by attackers.</p>\r\n<p>Defense here is a bit more complicated for the general user, but shouldn’t be too intrusive for most:</p>\r\n<ol type=\"1\">\r\n<li>Use a VPN on your mobile devices.</li>\r\n<li>Switch to a DNS provider that provides secure DNSSEC.</li>\r\n<li>Implement proper encryption on access points.</li>\r\n</ol>\r\n<h3 id=\"spyware\">2. Spyware</h3>\r\n<p>Many commercial spyware applications are readily available on both of the main app stores. The challenges for attackers lie in either gaining physical access to the unlocked device to install the spyware, or tricking the user into installing it themselves. Most often the target’s spouse or close contact does this. Some of these apps can be disguised to look like innocuous applications as a feature, but with devices that are rooted/jailbroken, they can be completely hidden from the user. I found a few surveys that state the average smart phone user has about 30 apps installed. I don’t think it’s unreasonable to suspect the average person wouldn’t notice a second calculator or calendar app. These apps feature the full gamut of what you’d expect from a spyware app.</p>\r\n<p>Defense against spyware is pretty simple:</p>\r\n<ol type=\"1\">\r\n<li>Don’t allow unsupervised access to your device.</li>\r\n<li>Use a strong passcode or biometric lock.</li>\r\n<li>Remove unused applications and be aware of new apps that may pop up.</li>\r\n<li>Don’t root or jailbreak your device.</li>\r\n</ol>\r\n<h3 id=\"social-engineering\">3. Social Engineering</h3>\r\n<p>The tried and true vector that has always worked and will continue to work is social engineering. It doesn’t matter what kind of device a target is using if you can get them to click a malicious link, open a malicious attachment, or disclose their password to the attackers. With a user’s password you can conduct a vast amount of surveillance through their Google or Apple account. Not to mention leverage their password into all their other accounts as most users still use the same password for everything. We can also callback to the previous section on spyware by mentioning that many users are already familiar with enabling the installation of 3rd party applications and can be tricked into installing a cleverly disguised spyware application.</p>\r\n<p>Basic OPSEC recommendations are applicable here:</p>\r\n<ol type=\"1\">\r\n<li>Don’t click strange or unsolicited links or attachments on your devices.</li>\r\n<li>Never disclose your password to anyone through a text message or voice call.</li>\r\n<li>Don’t install 3rd party applications. I’ll extend this to say not to install any shady or questionable apps, even ones hosted by the app stores. There have been instances of vetted apps being malicious.</li>\r\n</ol>\r\n<h3 id=\"imsi-catchersfemtocells\">4. IMSI catchers/Femtocells</h3>\r\n<p>I refer to these as DIY Stingrays. Stingrays are devices used by law enforcement to track and surveil cell phone traffic. These devices emulate a cell tower or boost cell phone signals when used in a legitimate way. Mobile phones are designed to prefer using stations that are the closest and strongest. Any technically proficient attacker can DIY one of these devices for not a lot of money. When an attacker deploys one of these devices, the target’s phone usually has no idea that the device isn’t an official cell tower and happily connects and passes traffic through it. The rogue stations can then be configured to pass the traffic on to an authentic tower and the user will have no idea. These rogue towers can not only collect identifying information about the mobile device that can be used to track or mark a target, they can also monitor voice calls, data, and SMS, as well as perform man-in-the-middle attacks. Often they can disable the native encryption of the target’s phone as well.</p>\r\n<p>Defense against this vector is a bit more complicated:</p>\r\n<ol type=\"1\">\r\n<li>As before, use a VPN.</li>\r\n<li>Use Signal or other encrypted communication apps.</li>\r\n<li>Avoid disclosing sensitive information during voice calls.</li>\r\n<li>There is software that has been developed to detect and notify the user when a rogue station has been detected, but this is not going to be super helpful for standard users. There are also maps online of known cell towers and it is possible to use software to identify your connected tower.</li>\r\n</ol>\r\n<h3 id=\"exploits\">5. Exploits</h3>\r\n<p>Speaking very generally, this attack vector is for the most part less of a concern (depending on your particular threat level), but we all know that the chance of this happening in the wild is probably remote for most people. The technical implementations of exploits such as Rowhammer, Stagefright, and Blueborne are well outside the scope of this particular talk, but we would be incorrect to not mention them and what can be done to protect against them. And we should also pay special attention to more and more exploits being developed to attack mobile devices as attackers have started putting a lot of attention in this area. Even though many of these vulnerabilities are being patched, we all know many users are still using old versions of Android and iOS, and many devices are simply outside the support period offered by the manufacturers and will never be updated past a certain point. Couple that with the general idea that mobile devices (or any device running a non Windows based OS) are “safer” because less exploits exist for them is currently a very poor assumption. This will probably get worse as the cost of keeping up with new devices now being over $1000 and many users won’t be able to get devices that are constantly being patched.</p>\r\n<p>What we can do:</p>\r\n<ol type=\"1\">\r\n<li>Keep your mobile devices updated with most current OS updates and carrier settings. Also keep applications updated. I don’t know how many times I’ve noticed friends or family with devices that are ready to be updated, but the notifications go ignored.</li>\r\n<li>If it’s possible, replace devices when they are outside the support period.</li>\r\n<li>Be paranoid, if it applies to you. What this means is when you use any computer or device, always remember that zero day exploits can exist for years before being disclosed. You could follow ALL the best OPSEC practices, and you could still be vulnerable to exploits that haven’t been disclosed and/or patched. This might not matter if you’re just a general user, but if you work for the government or do intelligence work, act as if.</li>\r\n</ol>\r\n<p>Well, thank you for taking the time to listen to my basic introduction to cell phone cyber defense. I know most of the information I provided is only the tip of the iceberg and if current trends hold up, this will only get worse in the future. If you want to add to or correct any mistakes I may have made, like I stated in the introduction, feel free to email me and let’s have a conversation. I don’t claim to know all there is to know and love feedback and any opportunities to learn more or collaborate with others in the field.</p>\r\n<p>Thanks again, and have a great 2019!</p>\r\n',372,0,1,'CC-BY-SA','Mobile Device Security',0,0,1),
(2718,'2019-01-02','Genre In Storytelling',750,'Lostnbronx takes a look at the importance of genre in storytelling.','<p>Many people see genres as being largely interchangeable, but are they really? Why can some stories only be told in a particular genre? When are genre stories truly alike? And when are setting, character, and plot more important than genre? Lostnbronx takes a quick, rambling look at this complicated subject.</p>\r\n',107,105,0,'CC-BY-SA','stories,storytelling,genre,lostnbronx',1,0,1),
(2725,'2019-01-11','The Illumos Shutdown Command Explained',812,'A short pod cast about the Illumos shutdown command','<p>In response to JWP\'s <a href=\"https://hackerpublicradio.org/eps.php?id=2697\" target=\"_blank\">episode 2697</a> and <a href=\"https://hackerpublicradio.org/eps.php?id=2697#comments\" target=\"_blank\">ClaudioM\'s comment</a>, this show covers the <code>shutdown</code> command as it appeared in Sun Solaris and OpenSolaris, and currently appears in both Oracle Solaris and <a href=\"https://openindiana.org\" target=\"_blank\">OpenIndiana</a>.\r\n\r\n<p>\r\nThe quick version&#58;\r\n</p>\r\n\r\n<ul>\r\n<li><code>shutdown</code></li>\r\n<li><code>-i</code> sets the destination init state (5 to shutdown, 6 to reboot, and so on; see <code>man init</code> for more)</li>\r\n<li><code>-y</code> to answer \"yes\" to the safeguard prompt asking you whether you really want to shutdown</li>\r\n<li><code>-g</code> to set how many seconds until shutdown. Default is 60.\r\n</li>\r\n</ul>\r\n\r\n<p>In practise, I don\'t even use the shutdown command. I use <code>poweroff</code>, which does a shutdown and poweroff.</p>\r\n\r\n<p>\r\nBoth shutdown and poweroff require root permission. On OpenIndiana, you can either use <code>sudo bash</code> or <code>pfexec bash</code> to get a root prompt.\r\n</p>\r\n\r\n<p>Some links&#58;</p>\r\n<p><a href=\"https://docs.openindiana.org/handbook/common-tasks/#system-shutdown-reboot\" target=\"_blank\">OpenIndiana handbook</a></p>\r\n<p><a href=\"https://docs.oracle.com/cd/E23824_01/html/821-1451/gldpm.html\" target=\"_blank\">Sun Microsystem docs</a> (with Oracle branding on it)</p>\r\n\r\n\r\n',78,0,0,'CC-BY-SA','sys admin,systems,unix,illumos',0,0,1),
(2733,'2019-01-23','Writing Web Game in Haskell - News and Notifications',2837,'Tuula talks about the game they\'re writing in Haskell and convoluted news system they made.','<h2 id=\"intro\">Intro</h2>\r\n<p>News and notifications are used in the game to let the players know something noteworthy has happened. It could be discovery of a new planet or construction project finally finishing.</p>\r\n<p>All relevant information in the news is hyperlinked. If news mentions a planet, player can click the link and view current information of that planet.</p>\r\n<h2 id=\"server-interface\">Server interface</h2>\r\n<p>Server has three resources for news, although we’re concentrating only one here:</p>\r\n<pre><code>/api/message           ApiMessageR      GET POST\r\n/api/message/#NewsId   ApiMessageIdR    DELETE\r\n/api/icon              ApiMessageIcons  GET</code></pre>\r\n<p>First one is for retrieving all messages and posting a new one. Second one is for marking one read and third one is for retrieving all icons that players can attach to messages written by them.</p>\r\n<h2 id=\"database\">Database</h2>\r\n<p>Database is defined in /config/models file. For news, there’s only one table:</p>\r\n<pre><code>News json\r\n    content Text\r\n    factionId FactionId\r\n    date Int\r\n    dismissed Bool\r\nderiving Show Read Eq</code></pre>\r\n<p>Content field contains the actual news article data as serialized JSON. This allows storing complex data, without having to have lots of columns or multiple tables.</p>\r\n<h2 id=\"domain-objects\">Domain objects</h2>\r\n<p>There are many kinds of messages that players might see, but we’ll concentrate on one about discovering a new planet</p>\r\n<p>All different kinds of articles are of same type: NewsArticle. Each different kind of article has their own value constructor (PlanetFound in this particular case). And each of those value constructors has single parameter of a specific type that holds information particular to that certain article (PlanetFoundNews in this case). Adding a new article means adding a new value constructor and record to hold the data.</p>\r\n<pre><code>data NewsArticle =\r\n    StarFound StarFoundNews\r\n    | PlanetFound PlanetFoundNews\r\n    | UserWritten UserWrittenNews\r\n    | DesignCreated DesignCreatedNews\r\n    | ConstructionFinished ConstructionFinishedNews\r\n\r\n\r\ndata PlanetFoundNews = PlanetFoundNews\r\n    { planetFoundNewsPlanetName :: Text\r\n    , planetFoundNewsSystemName :: Text\r\n    , planetFoundNewsSystemId   :: Key StarSystem\r\n    , planetFoundNewsPlanetId   :: Key Planet\r\n    , planetFoundNewsDate       :: Int\r\n    }</code></pre>\r\n<p>Given a News object, we can turn it into NewsArticle. These are much nicer to deal with that densely packed News that is stored in database:</p>\r\n<pre><code>parseNews :: News -&gt; Maybe NewsArticle\r\nparseNews =\r\n    decode . toLazyByteString . encodeUtf8Builder . newsContent</code></pre>\r\n<p>Because parsing arbitrary JSON might fail, we get Maybe NewsArticle, instead of NewsArticle. It is possible to write the same code in longer way:</p>\r\n<pre><code>parseNews news =\r\n    let\r\n        content = newsContent news\r\n        utf8Encoded = encodeUtf8Builder content\r\n        byteString = toLazyByteString utf8Encoded\r\n    in\r\n        decode byteString</code></pre>\r\n<p>Similarly there’s two other functions for dealing with Entities (primary key, data - pair really) and list of Entities. Note that parseNewsEntities filters out all News that it didn’t manage to turn into NewsArticle. They have following signatures:</p>\r\n<pre><code>parseNewsEntity :: Entity News -&gt; (Key News, Maybe NewsArticle)\r\n\r\nparseNewsEntities :: [Entity News] -&gt; [(Key News, NewsArticle)]</code></pre>\r\n<p>Writing JSON encoding and decoding is tedious, template Haskell can help us here:</p>\r\n<pre><code>$(deriveJSON defaultOptions &#39;&#39;PlanetFoundNews)\r\n$(deriveJSON defaultOptions &#39;&#39;NewsArticle)</code></pre>\r\n<h2 id=\"turning-articles-into-json\">Turning Articles into JSON</h2>\r\n<p>News articles aren’t much use if they stay on the server, we need to send them to clients too. We can’t have multiple declarations of same typeclass for any type, so we declare complete new type and copy data there before turning it into JSON and sending to client (this is one way of doing this).</p>\r\n<p>First step, define our types (concentrating on planet found news here):</p>\r\n<pre><code>data NewsArticleDto =\r\n    StarFoundDto StarFoundNewsDto\r\n    | PlanetFoundDto PlanetFoundNewsDto\r\n    | UserWrittenDto UserWrittenNewsDto\r\n    | DesignCreatedDto DesignCreatedNewsDto\r\n    | ConstructionFinishedDto ConstructionFinishedNewsDto\r\n    deriving (Show, Read, Eq)\r\n\r\ndata PlanetFoundNewsDto = PlanetFoundNewsDto\r\n    { planetFoundNewsDtoPlanetName :: Text\r\n    , planetFoundNewsDtoSystemName :: Text\r\n    , planetFoundNewsDtoSystemId   :: Key StarSystem\r\n    , planetFoundNewsDtoPlanetId   :: Key Planet\r\n    , planetFoundNewsDtoDate       :: Int\r\n    }\r\n    deriving (Show, Read, Eq)</code></pre>\r\n<p>We need way to move data into dto and thus define a type class for that operation:</p>\r\n<pre><code>class (ToJSON d) =&gt; ToDto c d | c -&gt; d where\r\n    toDto :: c -&gt; d</code></pre>\r\n<p>For more information about functional dependencies, check following links: <a href=\"https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-FunctionalDependencies\" class=\"uri\">https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-FunctionalDependencies</a> and <a href=\"https://wiki.haskell.org/Functional_dependencies\" class=\"uri\">https://wiki.haskell.org/Functional_dependencies</a></p>\r\n<p>Writing instances for our type class:</p>\r\n<pre><code>instance ToDto PlanetFoundNews PlanetFoundNewsDto where\r\n    toDto news =\r\n        PlanetFoundNewsDto { planetFoundNewsDtoPlanetName = planetFoundNewsPlanetName news\r\n                           , planetFoundNewsDtoSystemName = planetFoundNewsSystemName news\r\n                           , planetFoundNewsDtoSystemId = planetFoundNewsSystemId news\r\n                           , planetFoundNewsDtoPlanetId = planetFoundNewsPlanetId news\r\n                           , planetFoundNewsDtoDate = planetFoundNewsDate news\r\n                           }\r\n\r\ninstance ToDto NewsArticle NewsArticleDto where\r\n    toDto news =\r\n        case news of\r\n            (StarFound x) -&gt; StarFoundDto $ toDto x\r\n            (PlanetFound x) -&gt; PlanetFoundDto $ toDto x\r\n            (UserWritten x) -&gt; UserWrittenDto $ toDto x\r\n            (DesignCreated x) -&gt; DesignCreatedDto $ toDto x\r\n            (ConstructionFinished x) -&gt; ConstructionFinishedDto $ toDto x</code></pre>\r\n<p>Finally, we want to wrap our news into something that has all the common info (id and link to icon to show)</p>\r\n<pre><code>data NewsDto = NewsDto\r\n    { newsDtoId    :: Key News\r\n    , newsContents :: NewsArticleDto\r\n    , newsIcon     :: Text\r\n    }\r\n    deriving (Show, Read, Eq)</code></pre>\r\n<p>IconMapper knows how to turn NewsArticleDto (in this case) to corresponding link to the icon. Notice how our ToDto instance includes IconMapper in addition to Key and NewsArticle:</p>\r\n<pre><code>instance ToDto ((Key News, NewsArticle), (IconMapper NewsArticleDto)) NewsDto where\r\n    toDto ((nId, article), icons) =\r\n        let\r\n            content = toDto article\r\n        in\r\n        NewsDto { newsDtoId = nId\r\n                , newsContents = content\r\n                , newsIcon = runIconMapper icons content\r\n                }</code></pre>\r\n<h2 id=\"sideshow-iconmapper\">Sideshow: IconMapper</h2>\r\n<p>IconMapper is a function that knows how to retrieve url to icon that matches the given parameter (for example NewsArticleDto in this case):</p>\r\n<pre><code>newtype IconMapper a =\r\n    IconMapper { runIconMapper :: a -&gt; Text }</code></pre>\r\n<p>One possible implementation that knows how to deal with NewsArticleDto. We have two levels of hierarchicy here, because UserNewsDto has special rules for figuring out which icon to use:</p>\r\n<pre><code>iconMapper :: (Route App -&gt; Text) -&gt; IconMapper UserNewsIconDto -&gt; IconMapper NewsArticleDto\r\niconMapper render userIconMapper =\r\n    IconMapper $ article -&gt;\r\n        case article of\r\n            PlanetFoundDto _-&gt;\r\n                render $ StaticR images_news_planet_png\r\n\r\n            UserWrittenDto details -&gt;\r\n                runIconMapper userIconMapper $ userWrittenNewsDtoIcon details\r\n    ...</code></pre>\r\n<h2 id=\"back-to-json\">Back to JSON</h2>\r\n<p>I wrote ToJSON and FromJSON instances by hand, because I wanted full control on how the resulting JSON looks like. It’s possible to configure how template Haskell names fields for example, but I think that writing these out couple of times is good practice and makes sure that I understand what’s going on behind the scenes if I use template Haskell later.</p>\r\n<pre><code>instance ToJSON NewsDto where\r\n    toJSON (NewsDto { newsDtoId = nId\r\n                    , newsContents = contents\r\n                    , newsIcon = icon }) =\r\n        object [ &quot;id&quot; .= nId\r\n               , &quot;contents&quot; .= contents\r\n               , &quot;tag&quot; .= jsonTag contents\r\n               , &quot;icon&quot; .= icon\r\n               , &quot;starDate&quot; .= newsStarDate contents\r\n               ]\r\n\r\ninstance ToJSON PlanetFoundNewsDto where\r\n    toJSON (PlanetFoundNewsDto { planetFoundNewsDtoPlanetName = pName\r\n                               , planetFoundNewsDtoSystemId = sId\r\n                               , planetFoundNewsDtoPlanetId = pId\r\n                               , planetFoundNewsDtoSystemName = sName\r\n                               }) =\r\n        object [ &quot;planetName&quot; .= pName\r\n               , &quot;systemName&quot; .= sName\r\n               , &quot;planetId&quot; .= pId\r\n               , &quot;systemId&quot; .= sId\r\n               ]</code></pre>\r\n<h2 id=\"time-to-put-it-all-together\">Time to put it all together</h2>\r\n<p>Handler function authenticates user, check they’re member of a faction and then loads all the news:</p>\r\n<pre><code>getApiMessageR :: Handler Value\r\ngetApiMessageR = do\r\n    (_, _, fId) &lt;- apiRequireFaction\r\n    loadAllMessages fId</code></pre>\r\n<p>Loading messages involves multiple steps:</p>\r\n<ul>\r\n<li>retrieve News from database\r\n<ul>\r\n<li>correct faction, not dismissed, sort by date</li>\r\n</ul></li>\r\n<li>parse them into ( Key News, NewsArticle )</li>\r\n<li>get Url render function</li>\r\n<li>create mapper for user icons</li>\r\n<li>map all NewsArticles into ( NewsArticleDto, IconMapper )</li>\r\n<li>turn them into JSON and return that to client</li>\r\n</ul>\r\n<pre><code>loadAllMessages :: Key Faction -&gt; HandlerFor App Value\r\nloadAllMessages fId = do\r\n    loadedMessages &lt;- runDB $ selectList [ NewsFactionId ==. fId\r\n                                         , NewsDismissed ==. False ] [ Desc NewsDate ]\r\n    let parsedMessages = parseNewsEntities loadedMessages\r\n    render &lt;- getUrlRender\r\n    let userIcons = userNewsIconMapper render\r\n    return $ toJSON $ map (toDto . (flip (,) (iconMapper render userIcons))) parsedMessages</code></pre>\r\n<p>\r\n<a href=\"https://hackerpublicradio.org/eps/hpr2733/hpr2733.png\"><img src=\"https://hackerpublicradio.org/eps/hpr2733/hpr2733-small.png\" /></a>\r\n</p>\r\n',364,107,0,'CC-BY-SA','haskell, yesod',0,0,1),
(2726,'2019-01-14','Home Theater - Part 2 Software (High Level)',1249,'I go over a high level of my notes for the software on my Media box as it relates to TV/Movies/Music','<p><a href=\"https://docs.google.com/document/d/1E1xAwWpq-C4vEh8LCRw7MD7jnaclX9Faf2L3dZWiqQY\" class=\"uri\">https://docs.google.com/document/d/1E1xAwWpq-C4vEh8LCRw7MD7jnaclX9Faf2L3dZWiqQY</a></p>\r\n<ul>\r\n<li>Future Eps for Series:\r\n<ul>\r\n<li>Sonarr / Filename Fixes</li>\r\n<li>SABnzbd</li>\r\n<li>Subsonic / orpheus.network /Audio Fixes</li>\r\n</ul></li>\r\n</ul>\r\n\r\n<p><a href=\"https://hackerpublicradio.org/eps/hpr2726.pdf\">Local copy of the shownotes</a></p>',36,0,0,'CC-BY-SA','kodi, deluge,Sonarr,Plex,Subsonic,SpiderOakONE,Zoneminder,Borg Backup,rclone,Redshift,Audacity',0,0,1),
(2727,'2019-01-15','Passwords',467,'How to do passwords better. ','<h2 id=\"introduction\">Introduction</h2>\r\n<p>Hello and welcome to Hacker Public Radio, I’m Edward Miro and for this episode I decided to record an episode on the importance of good passwords. This will be part one in a series of podcasts I’m going to call “Information Security for Everyone”. As with most of the content I create in the world of infosec, my goal is to present the information in a way that a majority of people can get value from it and anyone can play this for a friend, colleague or family member and make it easy for the non-hackers in our lives to understand.</p>\r\n<h2 id=\"passwords\">Passwords</h2>\r\n<p>One of the first things most people think about when it comes to online safety is their password. We all know that passwords are to our online accounts what keys are for our locks. Would you use the same key for your house, your car, your office and your safety deposit box? Of course not. And if you did, what would happen if a bad guy could get a copy of just that one key? They’d have access to everything. With so much of our personal, confidential, financial and medical information accessible from our various online accounts, what can we do to make things as safe as possible?</p>\r\n<p>For me personally I employ and advise a three faceted approach:</p>\r\n<ol type=\"1\">\r\n<li>Complex passwords</li>\r\n<li>Unique passwords</li>\r\n<li>Two-factor authentication (where available)</li>\r\n</ol>\r\n<p>Clearly the solution is to use a unique password for each account and make them complicated enough that an attacker couldn’t guess it or crack it in an amount of time that would be actionable. One problem this presents to general users is the inconvenience and difficulty in remembering these passwords or storing them in a secure way. This leads into my first bit of advice:</p>\r\n<h2 id=\"password-managers\">Password Managers</h2>\r\n<p>My recommendation is to use a password manager. I’m going to make references to managers such as LastPass because that’s the one I’ve always used, but I’m not saying it’s the best or would be the best for you. There are many great options and I would rather people use the one that works the best for them and not merely the one I like best. Anyways. Applications like LastPass give you the ability to store all passwords in your encrypted “vault” and then request them through browser add-ons or standalone applications. They also have built in features that allow you to generate secure passwords at any length or complexity.</p>\r\n<p>When using a password manager, all you have to remember is your ONE master password. When you sign in, the manager can then decrypt all your saved passwords and let you use them. When I sign up for a website, I use LastPass to generate the longest and most complex password supported by the site and it gets stored in my vault safely for later use.</p>\r\n<p>There are various options online to choose from and I suggest you do some research and try a few different ones to see what is comfortable for you. One thing to consider when using a password manager is that the master password is your single point of failure and should be a long and complex password that you don’t use ANYWHERE else.</p>\r\n<p>If you’re wondering how to come up with a secure password that you can remember there are various strategies online, but I follow this:</p>\r\n<p>Take a poem, song lyrics or phrase that is easy for you to remember. For this example I’ll use the phrase:</p>\r\n<pre><code>&quot;The stars at night are big and bright. Deep in the heart of Texas.&quot;</code></pre>\r\n<p>Then I take the first letters from each word and that gives me:</p>\r\n<pre><code>TsanababdithoT.</code></pre>\r\n<p>Then I swap out the vowels for some numbers/special characters. And that gives me:</p>\r\n<pre><code>T5@n@b@bd1th0T</code></pre>\r\n<p>I checked that password on Dashlane’s Password Strength Checker, and got the following results:</p>\r\n<pre><code>It would take a computer about 204 million years to crack your password</code></pre>\r\n<p>And that’s just an example of a very secure password that I thought up in just a few seconds that I probably won’t ever be able to forget it.</p>\r\n<h2 id=\"fa-two-factor-authentication\">2FA (two-factor authentication)</h2>\r\n<p>Another very important recommendation I want to touch on in this episode is using two-step authentication. I use it for all accounts that offer it and it’s very easy to set-up and use. It works in tandem with an application on my mobile device called Google Authenticator(though there are others and like LastPass this is just the one I use) and it’s available for Android and iOS. After you install the app, you access the security settings for the account you want to protect and register it with your device.</p>\r\n<p>What it does is provide a “second” password when logging it that is only used one time. When you log in, the site will prompt for the two-step authentication code, you then open the Google Authenticator app and the code for the session will be listed. The codes are only available for a short time and are constantly changing. This makes someone gaining unauthorized access to your account VERY difficult.</p>\r\n<h2 id=\"a-few-closing-thoughts\">A few closing thoughts</h2>\r\n<p>Some information security professionals see a password manager as insecure due to it being a single point of failure. I can understand this and would respond that although this might be true, having a complex master password and using the manager in conjunction with two-step authentication makes it a pretty safe and solid system. And even if there is a breach, none of my passwords are the same and changing them is incredibly fast and easy with a manager.</p>\r\n<p>Also, I usually don’t recommend keeping hard copies of passwords, but if you can guarantee the physical security of your password list, this in my opinion is preferable to using the same, insecure password for all your accounts.</p>\r\n<p>Please remember, if you’re like most people on the internet and you use an easy to crack password or the same password on all your sites, all it takes is one compromised account to give bad guys access to everything.</p>\r\n<p>I’m also including a list of links in the bottom of the show notes to everything I mentioned and also a link to the site <em>Have I Been Pwned</em>. This is a service that collects accounts that have been involved in hacks and lets anyone search for their email address and see if their information is already compromised. If it is, do this NOW:</p>\r\n<ol type=\"1\">\r\n<li>Setup a password manager with a strong master password.</li>\r\n<li>Change all your passwords using the built in password generator in your password manager and save them in your vault as you go.</li>\r\n<li>In the future when breaches happen, it’s incredibly easy to change your password and you’ll also rest easy knowing that the password obtained can’t get them into anything else.</li>\r\n</ol>\r\n<p>I know this will take a long time. But it’s worth it. Then, you only have to remember one master password and you will be exponentially safer online.</p>\r\n<p>I also linked SplashData’s “The Top 100 Worst Passwords of 2018”. PLEASE don’t use anything on this list.</p>\r\n<p>Well, thank you for taking the time to listen to my basic introduction to passwords. I hope this will help any non-hackers in your life and like I say in all my podcasts, I don’t claim to know all there is to know and love feedback and any opportunities to learn more or collaborate with others in the field. As with most of the research and articles I’ve written in the past, these are geared toward standard users in a business setting and are meant to be a jumping off point for further research and to be a foundation for cyber security 101 level training classes. If you like what I do, and want to have me come speak to your team, or just wanna chat, feel free to email me.</p>\r\n<p>Thank you and have a safe 2019!</p>\r\n<h2 id=\"links\">Links:</h2>\r\n<ul>\r\n<li><a href=\"https://www.lastpass.com/\" class=\"uri\">https://www.lastpass.com/</a> - My favorite password manager.</li>\r\n<li><a href=\"https://howsecureismypassword.net/\" class=\"uri\">https://howsecureismypassword.net/</a> - Check if your password is strong enough.</li>\r\n<li><a href=\"https://twofactorauth.org/\" class=\"uri\">https://twofactorauth.org/</a> - Setup 2FA on all the accounts you can.</li>\r\n<li><a href=\"https://haveibeenpwned.com/\" class=\"uri\">https://haveibeenpwned.com/</a> - See if your email/accounts have been compromised already.</li>\r\n<li><a href=\"https://www.teamsid.com/100-worst-passwords/\" class=\"uri\">https://www.teamsid.com/100-worst-passwords/</a> - Top 100 Worst Passwords of 2018.</li>\r\n</ul>\r\n',372,74,0,'CC-BY-SA','Information Security for Everyone',0,0,1),
(2730,'2019-01-18','Resizing images for vcard on Android',688,'Automating the steps needed to get images formatted for VCard import into Android phones','<p>I have had problems importing vcards onto my Android phone. After a lot of troubleshooting, I tracked it down to embedded images in the card. The PHOTO;VALUE field to be precise.</p>\r\n\r\n<p>Some images worked and some didn\'t, and looking at the properties some that worked were larger than others that didn\'t. In the end I tracked down a post on <a href=\"https://stackoverflow.com/questions/17834815/how-to-find-the-max-image-size-supported-for-contacts-images\">stackoverflow</a> that hinted that the aspect ratio was important. And sure enough it was.</p>\r\n\r\n<blockquote class=\"wp-block-quote\">\r\n<p>starting with jelly bean (4.1), android now supports contact images that are 720x720.<br />before, starting with ICS (4.0), android has supported contact images that are 256x256.<br />and before that, contact photos had just a size of a thumbnail - 96x96.</p>\r\n<cite><a href=\"https://stackoverflow.com/users/878126/android-developer\">Stack exchange</a> </cite>\r\n</blockquote>\r\n\r\n\r\n<p>I tried a 720x720 on a few phones but decided to settle on 256x256 for now. </p>\r\n\r\n\r\n<p>To do image manipulation, I tend to use the <a href=\"https://www.graphicsmagick.org/\">GraphicsMagick</a> tools instead of the more popular <a href=\"https://www.imagemagick.org/script/index.php\">ImageMagick</a> suite. You should be able to achieve the same result in either.</p>\r\n\r\n\r\n<p>My requirements were:</p>\r\n<ul>\r\n<li>The images should be scaled so that the maximum height/width shrinks to 256, maintaining the aspect ratio.</li>\r\n<li>The images should always be 256x256 in size.</li>\r\n<li>Scaled images should be padded and centered on a white background.</li>\r\n<li>All color profile information should be removed.</li>\r\n</ul>\r\n\r\n\r\n<p>To use an example I took the following image and saved it as Linus_Torvalds.jpg</p>\r\n\r\n\r\n<p>By <a title=\"User:Krd\" href=\"//commons.wikimedia.org/wiki/User:Krd\">Krd</a> (photo)<a class=\"new\" title=\"User:Von Sprat (page does not exist)\" href=\"//commons.wikimedia.org/w/index.php?title=User:Von_Sprat&amp;action=edit&amp;redlink=1\">Von Sprat</a> (crop/extraction) - <a title=\"File:LinuxCon Europe Linus Torvalds 03.jpg\" href=\"//commons.wikimedia.org/wiki/File:LinuxCon_Europe_Linus_Torvalds_03.jpg\">File:LinuxCon Europe Linus Torvalds 03.jpg</a>, <a title=\"Creative Commons Attribution-Share Alike 4.0\" href=\"https://creativecommons.org/licenses/by-sa/4.0\">CC BY-SA 4.0</a>, <a href=\"https://commons.wikimedia.org/w/index.php?curid=54706023\">Link</a></p>\r\n\r\n\r\n<p>Step one is to use the <a href=\"https://href=&quot;https://www.graphicsmagick.org/GraphicsMagick.html#details-size\">-size</a> 256x256 option which you would think would do the scaling, but in fact it only reduces the file to 366x509 which is not what I expected.</p>\r\n\r\n<pre><code>$ gm convert -size 256x256 \"Linus_Torvalds.jpg\" Linus_Torvalds_1.jpg<br />$ gm identify Linus_Torvalds_1.jpg\r\nLinus_Torvalds_1.jpg JPEG 366x509+0+0 DirectClass 8-bit 56.1Ki 0.000u 0m:0.000002</code></pre>\r\n\r\n\r\n<p><img style=\"border-style: solid;\" src=\"https://hackerpublicradio.org/eps/hpr2730/Linus_Torvalds_1.jpg\" /></p>\r\n\r\n\r\n<p>However it appears that the option is used when creating new files, and is also used by the processor to determine the intended target size. Which is why I left it in. So what we actually need is the <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-resize\">-resize</a> option.</p>\r\n\r\n<pre><code>\r\n$ gm convert -size 256x256 \"Linus_Torvalds.jpg\" -resize 256x256 Linus_Torvalds_2.jpg\r\n$ gm identify Linus_Torvalds_2.jpg\r\nLinus_Torvalds_2.jpg JPEG 184x256+0+0 DirectClass 8-bit 47.7Ki 0.000u 0m:0.000001s</code><code>\r\n</code></pre>\r\n\r\n<p><img style=\"border-style: solid;\" src=\"https://hackerpublicradio.org/eps/hpr2730/Linus_Torvalds_2.jpg\" /></p>\r\n\r\n<p>So this has done a good job at scaling the image down. It\'s now scaled correctly so that the biggest edge is scaled down to 256. In this case it was the height but the width is now shorter than what we need. We do want to maintain the aspect ratio so that we don\'t distort the image but 184x256 is not 1:1 aspect ratio nor is it the needed dimensions of 256x256.</p>\r\n\r\n<p>The solution to this is to use the <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-extent\">-extent</a> command.</p>\r\n\r\n<pre><code>$ gm convert -size 256x256 \"Linus_Torvalds.jpg\" -resize 256x256 -extent 256x256 Linus_Torvalds_3.jpg\r\n$ gm identify Linus_Torvalds_3.jpg\r\nLinus_Torvalds_3.jpg JPEG 256x256+0+0 DirectClass 8-bit 48.0Ki 0.000u 0m:0.000001s</code></pre>\r\n\r\n\r\n<p><img style=\"border-style: solid;\" src=\"https://hackerpublicradio.org/eps/hpr2730/Linus_Torvalds_3.jpg\" /></p>\r\n\r\n\r\n<p>This gives us the correct size and a 1:1 aspect ratio, but the image is left justified. To fix this we need to use the <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-gravity\">-gravity</a> command. That needs to be the first argument of the command. Finding the correct order of the commands took some trial and error.</p>\r\n\r\n<pre><code>$ gm convert -gravity center -size 256x256 \"Linus_Torvalds.jpg\" -resize 256x256 -extent 256x256 Linus_Torvalds_4.jpg\r\n$ gm identify Linus_Torvalds_4.jpg\r\nLinus_Torvalds_4.jpg JPEG 256x256+0+0 DirectClass 8-bit 48.5Ki 0.000u 0m:0.000001s</code></pre>\r\n\r\n<p><img style=\"border-style: solid;\" src=\"https://hackerpublicradio.org/eps/hpr2730/Linus_Torvalds_4.jpg\" /></p>\r\n\r\n<p>Finally we remove all profile information using <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-profile\">+profile</a> which should make the image more generic.</p>\r\n\r\n<pre><code>$ gm convert -gravity center -size 256x256 \"Linus_Torvalds.jpg\" -resize 256x256 -extent 256x256 +profile \"*\" Linus_Torvalds_5.jpg\r\n$ gm identify Linus_Torvalds_5.jpg\r\nLinus_Torvalds_5.jpg JPEG 256x256+0+0 DirectClass 8-bit 5.7Ki 0.000u 0m:0.000001s</code></pre>\r\n\r\n<p>Putting it all together we get.</p>\r\n\r\n<pre><code>gm convert <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-gravity\">-gravity</a> center <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-size\">-size</a> 256x256 \"big-image.jpg\" <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-resize\">-resize</a> 256x256 <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-extent\">-extent</a> 256x256 <a href=\"https://www.graphicsmagick.org/GraphicsMagick.html#details-profile\">+profile</a> \"*\" \"256x256_image.jpg\"\r\n</code></pre>\r\n\r\n<p><img style=\"border-style: solid;\" src=\"https://hackerpublicradio.org/eps/hpr2730/Linus_Torvalds_5.jpg\" /></p>\r\n\r\n<p>You should now be able to add these images to vcards without any problem.</p>\r\n\r\n<p>Here is a one liner to create 96x96 256x256 and 720x720 thumbnails of all the jpg images in a directory.</p>\r\n\r\n<p>&nbsp;</p>\r\n\r\n<pre><code>for image in *jpg;do for size in 96x96 256x256 720x720; do gm convert -gravity center -size ${size} \"${image}\" -resize ${size} -extent ${size} +profile \"*\" \"thumbnail-${size}-${image}\";done;done</code></pre>\r\n\r\n<p>Also available <a href=\"https://kenfallon.com/resizing-images-for-vcard-on-android/\">here</a></p>\r\n',30,0,1,'CC-BY-SA','GraphicsMagick, ImageMagick, VCard, Android, LinageOS',0,0,1),
(2728,'2019-01-16','The Unreliable Narrator In Storytelling',814,'Lostnbronx looks at unreliable narrators and narrative techniques in stories.','<p>In some stories, the narrator or dominating character can’t be trusted by the audience, creating opportunities for various storytelling effects. What makes for an unreliable narrator? What are some of the strengths and weaknesses of this technique? How can the underlying structure of a tale be similar to an unreliable narrator, even if the story doesn’t actually have one? Lostnbronx takes a rambling, off-the-cuff look at this interesting literary tool</p>\r\n',107,105,0,'CC-BY-SA','stories,storytelling,narration,lostnbronx',0,0,1),
(2731,'2019-01-21','My 8 bit Christmas',1579,'I got a new, old computer for Christmas - an Acorn BBC microcomputer model B.','<p>For Christmas 2018 Santa – well, Mrs mcnalu – gave me a <a href=\"https://en.wikipedia.org/wiki/BBC_Micro\">BBC Model B</a> which was my first computer back in the early 1980s. This request was heavily implied in <a href=\"https://tuxjam.otherside.network/?p=382\">TuxJam 70 - Gift for Geeks</a>.</p>\r\n<p>I can highly <a href=\"https://www.ebay.co.uk/usr/retrofix-uk?_trksid=p2047675.l2559\">recommend the seller</a> who, as you will hear, was extremely helpful when this 36 year old bundle of 8 bit loveliness became very poorly on Boxing Day. It came with a Turbo MMC installed and you can see it in action on <a href=\"https://www.youtube.com/watch?v=FunVINQS0Rw\">another BBC Model B in this video</a>.</p>\r\n<p>The noise you hear at the start - the beeeeee BEEP - is the sound of me turning on the BBC. I mention in the show that mode 0 of the Beeb, as it is affectionately known, has 80 columns and 40 rows. This isn’t quite right, there are only 32 rows in mode 0.</p>\r\n',268,0,0,'CC-BY-SA','retro,BBC,8-bit,assembler',0,0,1),
(2734,'2019-01-24','Mashpodder',1139,'A poor rushed attempt at covering the excellent podcast client mashppoder','<p>After I recorded this episode I had a little look on the HPR site I found that Ken Fallon had already covered mashpodder, no doubt he did a better job than me as this was done in a bit of a rush.</p>\r\n<p>Hopefully somebody will find this of some use</p>\r\n<p>Related links below:-</p>\r\n<ul>\r\n<li><p>HPR episode by Ken Fallon covering Mashpodder<br />\r\n<a href=\"https://hackerpublicradio.org/eps.php?id=0481\" class=\"uri\">https://hackerpublicradio.org/eps.php?id=0481</a></p></li>\r\n<li><p>HPR episode where I talk about my Compaq Ipaq home server<br />\r\n<a href=\"https://hackerpublicradio.org/eps.php?id=2112\" class=\"uri\">https://hackerpublicradio.org/eps.php?id=2112</a></p></li>\r\n<li><p>HPR episode where I cover my previous pocast client Hpodder<br />\r\n<a href=\"https://hackerpublicradio.org/eps.php?id=2106\" class=\"uri\">https://hackerpublicradio.org/eps.php?id=2106</a></p></li>\r\n<li><p>Bashpodder homepage<br />\r\n<a href=\"https://lincgeek.org/bashpodder/\" class=\"uri\">https://lincgeek.org/bashpodder/</a></p></li>\r\n<li><p>Mashpodder homepage<br />\r\n<a href=\"https://github.com/chessgriffin/mashpodder\" class=\"uri\">https://github.com/chessgriffin/mashpodder</a> The original link to mashpodder on google code is dead, currently now on github</p></li>\r\n<li><p>Link to the original Linux reality also now dead, but found a link archive to the shows on podbay<br />\r\n<a href=\"https://podbay.fm/show/125849458\" class=\"uri\">https://podbay.fm/show/125849458</a></p></li>\r\n<li><p>Link to the excellent GNU world order by Klaatu, I think it was this episode that he mentioned the great Chess Griffin from Linux reality. Apologies if this is the wrong episode.<br />\r\n<a href=\"https://gnuworldorder.info/audiophile/gnuWorldOrder_12x24.ogg\" class=\"uri\">https://gnuworldorder.info/audiophile/gnuWorldOrder_12x24.ogg</a></p></li>\r\n</ul>\r\n',201,0,1,'CC-BY-SA','Podcast, ncurses, command-line',0,0,1),
(2750,'2019-02-15','Windmill is on the Fritz',270,'Using Fritzing to help reverse engineer a circuit in a winter model village windmill','<p>\r\nIn this episode Ken uses <a href=\"https://fritzing.org/\">Fritzing</a> tool to keep track of how a winter model village windmill is wired together. Leading to identifying the problem component.\r\n</p>\r\n<p><a href=\"https://hackerpublicradio.org/eps/hpr2750/xmas-mill.fzz\"><img src=\"https://hackerpublicradio.org/eps/hpr2750/xmas-mill_schem.jpg\" /></a></p>\r\n\r\n<p>\r\nFritzing is an open-source initiative to develop amateur or hobby CAD software for the design of electronics hardware, to support designers and artists ready to move from experimenting with a prototype to building a more permanent circuit. It was developed at the University of Applied Sciences of Potsdam.\r\n<br />\r\nFrom <a href=\"https://en.wikipedia.org/wiki/Fritzing\">https://en.wikipedia.org/wiki/Fritzing</a></p>',30,103,0,'CC-BY-SA','Fritzing, Reverse Engineering, LED',0,0,1),
(2732,'2019-01-22','Storytelling formula compliance',1692,'Telling a story? want a reaction? USE THE FORMULA','<p>\r\nStorytelling has had a formula for yearsAndYears. Some people speak of it in disdain (\"it was too formulaïc\") and others (creative writing and intro film teachers, mostly) praise it. Everybody else (us) is a sucker for it.\r\n</p>\r\n\r\n<p>\r\nHere is the literal formula, in pseudo code:\r\n</p>\r\n\r\n<pre><code>{A} \r\n{A} Reinforced\r\n\r\n{Z}\r\n\r\n{A} Returned\r\n\r\n{B...Y}\r\n\r\n{Z} Returned\r\n</code></pre>\r\n\r\n<p>\r\nYou can (and should, because it\'s free and you can throw out your work if you don\'t like it) practise this formula by plugging in events to represent A and Z, where A and Z are polar opposites.\r\n</p>\r\n\r\n<p>\r\nReally obvious examples are any given romantic comedy:\r\n</p>\r\n\r\n<pre><code>{A} Jack is A=\"single and free\"\r\n{A} Scene to reinforce that Jack is in relationships with no strings attached. Jack is {A}.\r\n\r\n{Z} Jack meets Jill, realises she makes him happy. He decides he\'s had enough of being {A} and want to be {Z=married}\r\n\r\n{A} Reunion with old school mate makes Jack question his resolve. He leaves Jill so he can be {A}\r\n\r\n{B...Y} Plot happens. Jack does stuff, Jill does stuff. Funny? Tragic? You decide!\r\n\r\n{Z} Jack realizes at last that he\'s only happy with Jill, and that being {Z} with Jill is the only way to be truly free.\r\n</code></pre>\r\n\r\n<p>\r\nYou can also try it with the old Evil Empire plot line.\r\n</p>\r\n\r\n<pre><code>{A} Jill is an {A=obedient citizen}. Loves her mama, loves Jesus and America, too.\r\n{A} Scene in which Jill witnesses a Rebel being mistreated unjustly, but does nothing to stand up for what is right, because she is {A}.\r\n\r\n{Z} Jill meets Jack, an outlaw and rebel against the Empire. He\'s in trouble, so she helps him evade the police.\r\n\r\n{A} Jill, horrified at her own rebellion, conforms all the more. She is dedicated to the Empire, and works diligently to hunt down Jack and his rag tag band of rebels.\r\n\r\n{B...Y} Plot happens. Action, laser guns, laser swords, nationalism, motorcycle gangs.\r\n\r\n{Z} Jill, seeing the devastation her allegiance has caused, realises that the Empire is actually Evil. She joins the rebels to fight for freedom.\r\n</code></pre>\r\n\r\n<p>\r\nNow go practice this. Soon you will be telling stories, jokes, and anecdotes that have a clear beginning, a clear conflict, and a clear ending.\r\n</p>\r\n\r\n',78,99,1,'CC-BY-SA','story, character, plot, writing',0,0,1),
(2735,'2019-01-25','Soffritto',138,'A short episode on a common cookery technique','<p>Hello and a belated Happy New Year to you all in HPR land, Ken has recently made a call for more shows as the queue is a little light at the moment so I was pondering what to waffle on about.</p>\r\n<p>You may know from a couple of my previous shows that as well as being into tech and Linux I’m also a keen Cook, and try and prepare as much of the food we eat at home from scratch as possible.</p>\r\n<p>One of the keys to good dishes is a base of sweated vegetables such as onion, celery carrot and garlic which when cooked in olive oil, is called a <em>Soffritto</em> in Italian cookery. In other parts of the Mediterranean and Latin America where Europeans settled this base to dishes may include other vegetables such as peppers, tomatoes and mushrooms, and have other names such as <em>mirepoix</em> (/mɪərˈpwɑː/ meer-PWAH); but the idea is the same to give a base flavour to soups, sauces, risotto and stew type dishes.</p>\r\n<p>Although not called the same thing this is also replicated in Asian cookery where spices and other aromatics are included such as ginger, lemon grass, chillies, cumin and coriander seeds.</p>\r\n<p>While it is not obligatory to start dishes in such a way if you do use a base of flavours like this when cooking you will find that the finished dish has a more complex and deep flavour at the end, so if you don’t do this give it a try.</p>\r\n<p>A simple starter is to make a tomato sauce for pasta using a base of finely chopped onion, celery, carrot and garlic soften all the vegetables in a pan with some olive oil, add a tin of tomatoes or jar of passata (sieved tomatoes) reduce for 10-15 minutes until all the flavours combine and use as a sauce over pasta with grated cheese.</p>\r\n<p><a href=\"https://en.wikipedia.org/wiki/Sofrito\" class=\"uri\">https://en.wikipedia.org/wiki/Sofrito</a></p>\r\n',338,93,0,'CC-BY-SA','Food, cookery, how to, food preparation',0,0,1),
(2736,'2019-01-28','Response to show 2720',1104,'Some suggestions on how to improve a Bash script','<h2 id=\"introduction\">Introduction</h2>\r\n<p>On January 4<sup>th</sup> 2019 Ken Fallon did a great show entitled <a href=\"https://hackerpublicradio.org/eps.php?id=2720\" title=\"Download youtube channels using the rss feeds\"><em>hpr2720 :: Download youtube channels using the rss feeds</em></a> where he presented a Bash script called <a href=\"https://hackerpublicradio.org/eps/hpr2720/youtube-rss.bash\" title=\"youtube-rss.bash\"><code>youtube-rss.bash</code></a> for managing YouTube downloads through RSS feeds.</p>\r\n<p>Ken said he welcomed constructive feedback <font size=\"+3\">☺</font></p>\r\n<p>When I see a Bash script these days I usually find myself looking for ways to rewrite it to make it fit in with what I have been learning while doing my <em>Bash Tips</em> sub-series. Either that or I find it’s got some better ideas than I’ve been using which I have to find out about.</p>\r\n<p>I also spend time going over my own old scripts (I was writing them in the 1990’s in some cases) and trying to incorporate newer Bash features.</p>\r\n<p>Suffice it to say that I spotted some areas for improvement in Ken’s script and thought this might be the way to share my thoughts about them. We’re low on shows as I write this, so that gave me more motivation to make a show rather than add a comment or send Ken an email.</p>\r\n<p><small><b>Apology:</b> I’m still suffering from the aftermath of some flu-like illness so have had to edit coughing fits out of the audio at various points. If you detect any remnants then I’m sorry!</small></p>\r\n<h2 id=\"long-notes\">Long notes</h2>\r\n<p>I have provided detailed notes as usual for this episode, and these can be <a href=\"https://hackerpublicradio.org/eps/hpr2736/full_shownotes.html\">viewed here</a>.</p>\r\n<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2720\">HPR episode 2720 “<em>hpr2720 :: Download youtube channels using the rss feeds</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps/hpr2720/youtube-rss.bash\"><code>youtube-rss.bash</code></a></li>\r\n<li><a href=\"https://en.wikipedia.org/wiki/Cat_(Unix)\">Wikipedia article on <code>cat</code></a>\r\n<ul>\r\n<li><a href=\"https://en.wikipedia.org/wiki/Cat_(Unix)#Useless_use_of_cat\">Useless use of <code>cat</code></a></li>\r\n</ul></li>\r\n</ul>',225,42,1,'CC-BY-SA','Bash,ShellCheck',0,0,1),
(2737,'2019-01-29','My Pioneer RT-707 Reel-to-Reel Tape Deck',1381,'An intro to more of my legacy audio equipment.','<p>I\'ve had this Pioneer RT-707 reel-to-reel tape deck for something like 10 years, but only recently started using it with enthusiasm. In this episode I talk about the tape deck, about the technology, and about my memories of using this kind of audio tape as a kid. I demonstrate playback of one of my parents\' mix tapes, and I also used this machine to record the last few minutes of the podcast onto a reel to reel tape, which of course I then had to transfer back to digital before submitting the show.</p>\r\n\r\n<p>Click image below to see a photo album relating to the tape deck.</p>\r\n\r\n<a href=\"https://www.flickr.com/photos/137675441@N05/albums/72157705976621534\" title=\"Pioneer Reel-to-Reel Tape Deck\"><img src=\"https://hackerpublicradio.org/eps/hpr2737_46803567611_7e1583f534_z.jpg\" alt=\"Pioneer Reel-to-Reel Tape Deck\"></a>\r\n\r\n<p>Tape deck in action (video)</p>\r\n\r\n<p>\r\n<a href=\"https://www.youtube.com/embed/VezOKPwhZgg\"><img src=\"https://hackerpublicradio.org/eps/hpr2737_maxresdefault.jpg\" />\r\n</p>',238,0,0,'CC-BY-SA','audio, vintage audio, stereo components, audio tape, recording',0,0,1),
(3046,'2020-04-06','HPR Community News for March 2020',4545,'HPR Volunteers talk about shows released and comments posted in March 2020','<style>\ntable td.shrink {\n    white-space:nowrap\n}\n</style>\n\n<h2>New hosts</h2>\n<p>\nWelcome to our new host: <br />\n\n    <a href=\"https://hackerpublicradio.org/correspondents/0385.html\" target=\"_blank\">crvs</a>.\n</p>\n\n<h2>Last Month\'s Shows</h2>\n<table id=\"t01\">\n<tr>\n<th>Id</th>\n<th>Day</th>\n<th>Date</th>\n<th>Title</th>\n<th>Host</th>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3021\" target=\"_blank\">3021</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-03-02</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3021\" target=\"_blank\">HPR Community News for February 2020</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0159.html\" target=\"_blank\">HPR Volunteers</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3022\" target=\"_blank\">3022</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-03-03</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3022\" target=\"_blank\">FOSDEM 2020 Stand Interviews</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3023\" target=\"_blank\">3023</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-03-04</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3023\" target=\"_blank\">Critique My Script, Episode 1 - Qots-Crew-Gen</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0380.html\" target=\"_blank\">Carl</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3024\" target=\"_blank\">3024</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-03-05</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3024\" target=\"_blank\">A funny thing happened the other day</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0201.html\" target=\"_blank\">MrX</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3025\" target=\"_blank\">3025</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-03-06</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3025\" target=\"_blank\">Keep unwanted messages off the Fediverse</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3026\" target=\"_blank\">3026</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-03-09</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3026\" target=\"_blank\">Hex Bug and Battle Bots</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3027\" target=\"_blank\">3027</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-03-10</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3027\" target=\"_blank\">What is quantum computing and why should we care?</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0379.html\" target=\"_blank\">mightbemike</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3028\" target=\"_blank\">3028</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-03-11</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3028\" target=\"_blank\">Monads and Haskell</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0385.html\" target=\"_blank\">crvs</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3029\" target=\"_blank\">3029</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-03-12</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3029\" target=\"_blank\">At Union Station with a train delay</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0318.html\" target=\"_blank\">Archer72</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3030\" target=\"_blank\">3030</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-03-13</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3030\" target=\"_blank\">My new Samsung tablet</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0201.html\" target=\"_blank\">MrX</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3031\" target=\"_blank\">3031</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-03-16</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3031\" target=\"_blank\">Daniel Persson - Me? Me!</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0382.html\" target=\"_blank\">Daniel Persson</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3032\" target=\"_blank\">3032</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-03-17</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3032\" target=\"_blank\">piCore on a Raspberry Pi 1 Model B</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0152.html\" target=\"_blank\">Claudio Miranda</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3033\" target=\"_blank\">3033</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-03-18</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3033\" target=\"_blank\">32 Bit Time Travel</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3034\" target=\"_blank\">3034</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-03-19</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3034\" target=\"_blank\">How to bridge Freenode IRC rooms to Matrix.org</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3035\" target=\"_blank\">3035</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-03-20</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3035\" target=\"_blank\">Decentralised Hashtag Search and Subscription in Federated Social Networks</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3036\" target=\"_blank\">3036</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-03-23</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3036\" target=\"_blank\">WiiU is dead long live WiiU!</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3037\" target=\"_blank\">3037</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-03-24</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3037\" target=\"_blank\">Ambient recording at Union Station</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0318.html\" target=\"_blank\">Archer72</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3038\" target=\"_blank\">3038</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-03-25</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3038\" target=\"_blank\">Solo Magic</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0078.html\" target=\"_blank\">klaatu</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3039\" target=\"_blank\">3039</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-03-26</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3039\" target=\"_blank\">Making a Raspberry Pi status display</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3040\" target=\"_blank\">3040</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-03-27</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3040\" target=\"_blank\">Why use GNU Autotools</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0078.html\" target=\"_blank\">klaatu</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3041\" target=\"_blank\">3041</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-03-30</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3041\" target=\"_blank\">How to use GNU Autotools</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0078.html\" target=\"_blank\">klaatu</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3042\" target=\"_blank\">3042</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-03-31</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3042\" target=\"_blank\">The COVID-19 Work From Home Stream - Day 0</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a></td>\n</tr>\n</table>\n\n<h2>Comments this month</h2>\n\n<p>These are comments which have been made during the past month, either to shows released during the month or to past shows.\nThere are 23 comments in total.</p>\n<h3>Past shows</h3>\n<p>There are 2 comments on\n2 previous shows:</p>\n<ul>\n<li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3009#comments\" target=\"_blank\">hpr3009</a></strong>\n(2020-02-13) \"<em>Linux Inlaws S01 E01</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3009#5\" target=\"_blank\">Comment 5</a>:\nbittin on 2020-03-05:\n\"yay\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3019#comments\" target=\"_blank\">hpr3019</a></strong>\n(2020-02-27) \"<em>Linux Inlaws S01E02 FOSDEM shenanigans</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3019#1\" target=\"_blank\">Comment 1</a>:\nClaudioM on 2020-03-05:\n\"FLOSS Weekly #568\"</li></ul><br/>\n</li></ul>\n<h3>This month\'s shows</h3>\n<p>There are 21 comments on 8 of this month\'s shows:</p>\n<ul><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3023#comments\" target=\"_blank\">hpr3023</a></strong>\n(2020-03-04) \"<em>Critique My Script, Episode 1 - Qots-Crew-Gen</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0380.html\" target=\"_blank\">Carl</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#1\" target=\"_blank\">Comment 1</a>:\nDave Morriss on 2020-03-04:\n\"Bash arithmetic\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#2\" target=\"_blank\">Comment 2</a>:\nDave Morriss on 2020-03-04:\n\"Another Bash-ism that might be useful\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#3\" target=\"_blank\">Comment 3</a>:\nnobody on 2020-03-04:\n\"There must be an easier way\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#4\" target=\"_blank\">Comment 4</a>:\nnobody on 2020-03-04:\n\"Little correction to my comment\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#5\" target=\"_blank\">Comment 5</a>:\nCarl on 2020-03-05:\n\"Thanks for the comments\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#6\" target=\"_blank\">Comment 6</a>:\nCarl on 2020-03-05:\n\"Thanks for the comments\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#7\" target=\"_blank\">Comment 7</a>:\nnobody on 2020-03-05:\n\"Re: Re:\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#8\" target=\"_blank\">Comment 8</a>:\nnobody on 2020-03-05:\n\"Standalone increment in ash\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#9\" target=\"_blank\">Comment 9</a>:\nCarl on 2020-03-05:\n\"Neat\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#10\" target=\"_blank\">Comment 10</a>:\nnobody on 2020-03-05:\n\"$(())\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3023#11\" target=\"_blank\">Comment 11</a>:\nCarl on 2020-03-05:\n\"Version 3\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3024#comments\" target=\"_blank\">hpr3024</a></strong>\n(2020-03-05) \"<em>A funny thing happened the other day</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0201.html\" target=\"_blank\">MrX</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3024#1\" target=\"_blank\">Comment 1</a>:\nTuula on 2020-03-05:\n\"great storytelling\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3024#2\" target=\"_blank\">Comment 2</a>:\nMrX on 2020-03-07:\n\"Re great storytelling\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3025#comments\" target=\"_blank\">hpr3025</a></strong>\n(2020-03-06) \"<em>Keep unwanted messages off the Fediverse</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3025#1\" target=\"_blank\">Comment 1</a>:\nKen Fallon on 2020-03-09:\n\"I disagree\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3025#2\" target=\"_blank\">Comment 2</a>:\nAhuka on 2020-03-09:\n\"Further discussion\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3026#comments\" target=\"_blank\">hpr3026</a></strong>\n(2020-03-09) \"<em>Hex Bug and Battle Bots</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3026#1\" target=\"_blank\">Comment 1</a>:\nWindigo on 2020-03-25:\n\"Great episode\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3028#comments\" target=\"_blank\">hpr3028</a></strong>\n(2020-03-11) \"<em>Monads and Haskell</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0385.html\" target=\"_blank\">crvs</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3028#1\" target=\"_blank\">Comment 1</a>:\nTuula on 2020-03-11:\n\"welcome!\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3028#2\" target=\"_blank\">Comment 2</a>:\ncrvs on 2020-03-11:\n\"Re: welcome!\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3031#comments\" target=\"_blank\">hpr3031</a></strong>\n(2020-03-16) \"<em>Daniel Persson - Me? Me!</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0382.html\" target=\"_blank\">Daniel Persson</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3031#1\" target=\"_blank\">Comment 1</a>:\nKlaatu on 2020-03-22:\n\"History\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3032#comments\" target=\"_blank\">hpr3032</a></strong>\n(2020-03-17) \"<em>piCore on a Raspberry Pi 1 Model B</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0152.html\" target=\"_blank\">Claudio Miranda</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3032#1\" target=\"_blank\">Comment 1</a>:\nWindigo on 2020-03-26:\n\"Minimal distros are the best\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3034#comments\" target=\"_blank\">hpr3034</a></strong>\n(2020-03-19) \"<em>How to bridge Freenode IRC rooms to Matrix.org</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3034#1\" target=\"_blank\">Comment 1</a>:\nKlaatu on 2020-03-22:\n\"Did not know this\"</li></ul><br/>\n</li></ul>\n\n<h2>Mailing List discussions</h2>\n<p>\nPolicy decisions surrounding HPR are taken by the community as a whole. This\ndiscussion takes place on the <a href=\"https://hackerpublicradio.org/maillist\"\ntarget=\"_blank\">Mail List</a> which is open to all HPR listeners and\ncontributors. The discussions are open and available on the HPR server under\n<a href=\"https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/\">Mailman</a>.\n</p>\n<p>The threaded discussions this month can be found here:</p>\n<a href=\"https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/2020-March/thread.html\" target=\"_blank\">https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/2020-March/thread.html</a>\n\n\n<h2>Events Calendar</h2>\n<p>With the kind permission of <strong>LWN.net</strong> we are linking to\n<a href=\"https://lwn.net/Calendar/\" target=\"_blank\">The LWN.net Community Calendar</a>.</p>\n<p>Quoting the site:</p>\n<blockquote>This is the LWN.net community event calendar, where we track\nevents of interest to people using and developing Linux and free software.\nClicking on individual events will take you to the appropriate web\npage.</blockquote>\n\n<h2>Any other business</h2>\n<h3 id=\"tags-and-summaries\">Tags and Summaries</h3>\n<p>Thanks to the following contributors for sending in updates in the past month:<br />\n<b><a href=\"https://hackerpublicradio.org/correspondents/0385.html\">crvs</a>, <a href=\"https://hackerpublicradio.org/correspondents/0215.html\">Windigo</a>, <a href=\"https://hackerpublicradio.org/correspondents/0318.html\">Archer72</a>, <a href=\"https://hackerpublicradio.org/correspondents/0225.html\">Dave Morriss</a></b></p>\n<p>Over the period tags and/or summaries have been added to 28 shows which were without them.</p>\n<p>If you would like to contribute to the tag/summary project visit the summary page at <a href=\"https://hackerpublicradio.org/report_missing_tags.php\" class=\"uri\">https://hackerpublicradio.org/report_missing_tags.php</a> and follow the instructions there.</p>\n\n\n',159,47,1,'CC-BY-SA','Community News',0,0,1),
(2745,'2019-02-08','My YouTube Subscriptions #1',1262,'Part one of my list of subscribed channels','<p>I am subscribed to a number of YouTube channels, and I am sharing them with you</p>\r\n<ul>\r\n<li>Deep Look - <a href=\"https://www.youtube.com/channel/UC-3SbfTPJsL8fJAPKiVqBLg\" class=\"uri\">https://www.youtube.com/channel/UC-3SbfTPJsL8fJAPKiVqBLg</a></li>\r\n<li>Axanar - <a href=\"https://www.youtube.com/channel/UCxRrQIpejUXUi8i4mAbzSlg\" class=\"uri\">https://www.youtube.com/channel/UCxRrQIpejUXUi8i4mAbzSlg</a></li>\r\n<li>Lawrence Systems - <a href=\"https://www.youtube.com/channel/UCHkYOD-3fZbuGhwsADBd9ZQ\" class=\"uri\">https://www.youtube.com/channel/UCHkYOD-3fZbuGhwsADBd9ZQ</a></li>\r\n<li>Rick Beato - <a href=\"https://www.youtube.com/channel/UCJquYOG5EL82sKTfH9aMA9Q\" class=\"uri\">https://www.youtube.com/channel/UCJquYOG5EL82sKTfH9aMA9Q</a></li>\r\n<li>Wolters’ World - <a href=\"https://www.youtube.com/channel/UCFr3sz2t3bDp6Cux08B93KQ\" class=\"uri\">https://www.youtube.com/channel/UCFr3sz2t3bDp6Cux08B93KQ</a></li>\r\n<li>Fab Four Archivist - <a href=\"https://www.youtube.com/channel/UCxWFyPG8Qgj-1BVqC_r6rLg\" class=\"uri\">https://www.youtube.com/channel/UCxWFyPG8Qgj-1BVqC_r6rLg</a></li>\r\n<li>Fraser Cain - <a href=\"https://www.youtube.com/channel/UCogrSQkBJn1KF0N9I4oM7eQ\" class=\"uri\">https://www.youtube.com/channel/UCogrSQkBJn1KF0N9I4oM7eQ</a></li>\r\n<li>Science and Futurism with Isaac Arthur - <a href=\"https://www.youtube.com/channel/UCZFipeZtQM5CKUjx6grh54g\" class=\"uri\">https://www.youtube.com/channel/UCZFipeZtQM5CKUjx6grh54g</a></li>\r\n<li>Creativity RV - <a href=\"https://www.youtube.com/channel/UCigPwB_DERbV5BlwV4OY9mw\" class=\"uri\">https://www.youtube.com/channel/UCigPwB_DERbV5BlwV4OY9mw</a></li>\r\n<li>Drivin’ and Vibin’ - <a href=\"https://www.youtube.com/channel/UClkhrrakVty75SWLJIbcxDA\" class=\"uri\">https://www.youtube.com/channel/UClkhrrakVty75SWLJIbcxDA</a></li>\r\n<li>Hebard’s Travels - <a href=\"https://www.youtube.com/channel/UCQ5BTuWY7B0hTaa9zK0JKNg\" class=\"uri\">https://www.youtube.com/channel/UCQ5BTuWY7B0hTaa9zK0JKNg</a></li>\r\n<li>RV Roof Installation - <a href=\"https://www.youtube.com/channel/UCPbqiR5gZQukf6uk8waWcoA\" class=\"uri\">https://www.youtube.com/channel/UCPbqiR5gZQukf6uk8waWcoA</a></li>\r\n<li>Enjoy the Journey.Life - <a href=\"https://www.youtube.com/channel/UCuhIeTBsCysER-73DnGEegQ\" class=\"uri\">https://www.youtube.com/channel/UCuhIeTBsCysER-73DnGEegQ</a></li>\r\n<li>Geeks on Tour - <a href=\"https://www.youtube.com/channel/UCLM_wnCtDaGBWkYGQS4T6Bw\" class=\"uri\">https://www.youtube.com/channel/UCLM_wnCtDaGBWkYGQS4T6Bw</a></li>\r\n<li>History with Hilbert - <a href=\"https://www.youtube.com/channel/UC1Zc6_BhPXiCWZlrZP4EsEg\" class=\"uri\">https://www.youtube.com/channel/UC1Zc6_BhPXiCWZlrZP4EsEg</a></li>\r\n<li>Keep Your Daydream - <a href=\"https://www.youtube.com/channel/UCEhJLsShZt8McryMf_DHLZQ\" class=\"uri\">https://www.youtube.com/channel/UCEhJLsShZt8McryMf_DHLZQ</a></li>\r\n<li>Living Free Forever - <a href=\"https://www.youtube.com/channel/UCozdfxd0Z7EwZFnZpBkl9Pw\" class=\"uri\">https://www.youtube.com/channel/UCozdfxd0Z7EwZFnZpBkl9Pw</a></li>\r\n<li>Mike Lux Media - <a href=\"https://www.youtube.com/channel/UCBEHEEUFV6IFY7gF2xhyPYw\" class=\"uri\">https://www.youtube.com/channel/UCBEHEEUFV6IFY7gF2xhyPYw</a></li>\r\n<li>RV Love - <a href=\"https://www.youtube.com/channel/UCsjA83xRW2iaqPox8IbDLKQ\" class=\"uri\">https://www.youtube.com/channel/UCsjA83xRW2iaqPox8IbDLKQ</a></li>\r\n<li>Shadiversity - <a href=\"https://www.youtube.com/channel/UCkmMACUKpQeIxN9D9ARli1Q\" class=\"uri\">https://www.youtube.com/channel/UCkmMACUKpQeIxN9D9ARli1Q</a></li>\r\n<li>The Fit RV - <a href=\"https://www.youtube.com/channel/UCxPSwn42fcQlQdp8DTQGRUA\" class=\"uri\">https://www.youtube.com/channel/UCxPSwn42fcQlQdp8DTQGRUA</a></li>\r\n<li>The More We Explore - <a href=\"https://www.youtube.com/channel/UC33Loj6OxDXepBuc3ry0rMg\" class=\"uri\">https://www.youtube.com/channel/UC33Loj6OxDXepBuc3ry0rMg</a></li>\r\n<li>All About RVs - <a href=\"https://www.youtube.com/channel/UCAxGFcQGIzzyS9OdHijsaLg\" class=\"uri\">https://www.youtube.com/channel/UCAxGFcQGIzzyS9OdHijsaLg</a></li>\r\n<li><a href=\"https://www.palain.com/\" class=\"uri\">https://www.palain.com/</a></li>\r\n</ul>\r\n',198,106,0,'CC-BY-SA','YouTube, Channels, Subscriptions',0,0,1),
(2755,'2019-02-22','My YouTube Subscriptions #2',1329,'Part two of my list of subscribed channels','<p>I am subscribed to a number of YouTube channels, and I am sharing them with you</p>\r\n<ul>\r\n<li>Anthony Robustelli - <a href=\"https://www.youtube.com/channel/UCxgAH7EcmKhC9bLm7xQ971g\" class=\"uri\">https://www.youtube.com/channel/UCxgAH7EcmKhC9bLm7xQ971g</a></li>\r\n<li>Apple Scruff Radio - <a href=\"https://www.youtube.com/channel/UCGAFIXNYCwA7mJWMY5zFxzw\" class=\"uri\">https://www.youtube.com/channel/UCGAFIXNYCwA7mJWMY5zFxzw</a></li>\r\n<li>Arthur C Clarke Center for Human Imagination - <a href=\"https://www.youtube.com/channel/UCigIJEygfuAhNEc9kavK2QA\" class=\"uri\">https://www.youtube.com/channel/UCigIJEygfuAhNEc9kavK2QA</a></li>\r\n<li>Baker Street - <a href=\"https://www.youtube.com/channel/UC8IaZ7-169c2vl3GOehxa6w\" class=\"uri\">https://www.youtube.com/channel/UC8IaZ7-169c2vl3GOehxa6w</a></li>\r\n<li>BBC Earth Unplugged - <a href=\"https://www.youtube.com/channel/UCbwp5B-uDBy-fS4bDA0TEaw\" class=\"uri\">https://www.youtube.com/channel/UCbwp5B-uDBy-fS4bDA0TEaw</a></li>\r\n<li>Brain Stuff - <a href=\"https://www.youtube.com/channel/UCiefLm_nIz_gOH7XHbgpdCQ\" class=\"uri\">https://www.youtube.com/channel/UCiefLm_nIz_gOH7XHbgpdCQ</a></li>\r\n<li>Candyrat Records - <a href=\"https://www.youtube.com/channel/UCMJecdKUslHToOEpeuRGwXg\" class=\"uri\">https://www.youtube.com/channel/UCMJecdKUslHToOEpeuRGwXg</a></li>\r\n<li>Cheryl Brin - <a href=\"https://www.youtube.com/channel/UCtbMXq5siIn3l-u_HKbAmrw\" class=\"uri\">https://www.youtube.com/channel/UCtbMXq5siIn3l-u_HKbAmrw</a></li>\r\n<li>Colonial Airstream - <a href=\"https://www.youtube.com/channel/UCaZKKtI5caSI6-WO4zm3VGQ\" class=\"uri\">https://www.youtube.com/channel/UCaZKKtI5caSI6-WO4zm3VGQ</a></li>\r\n<li>Computerphile - <a href=\"https://www.youtube.com/channel/UC9-y-6csu5WGm29I7JiwpnA\" class=\"uri\">https://www.youtube.com/channel/UC9-y-6csu5WGm29I7JiwpnA</a></li>\r\n<li>Couch’s RV Nation - <a href=\"https://www.youtube.com/channel/UCvAONLxaOn8oc7PS33KN22Q\" class=\"uri\">https://www.youtube.com/channel/UCvAONLxaOn8oc7PS33KN22Q</a></li>\r\n<li>Darren Kitchen - <a href=\"https://www.youtube.com/channel/UCTkpeicFNBuHJCvp4LZEuvw\" class=\"uri\">https://www.youtube.com/channel/UCTkpeicFNBuHJCvp4LZEuvw</a></li>\r\n<li>Don Ross - <a href=\"https://www.youtube.com/channel/UCRd5EO6FvhIrqQnk0cscSDA\" class=\"uri\">https://www.youtube.com/channel/UCRd5EO6FvhIrqQnk0cscSDA</a></li>\r\n<li>Geeks on Tour - <a href=\"https://www.youtube.com/channel/UCLM_wnCtDaGBWkYGQS4T6Bw\" class=\"uri\">https://www.youtube.com/channel/UCLM_wnCtDaGBWkYGQS4T6Bw</a></li>\r\n<li>Duet Justus - <a href=\"https://www.youtube.com/channel/UCIeTn13FYQI1YL4InzvuWuQ\" class=\"uri\">https://www.youtube.com/channel/UCIeTn13FYQI1YL4InzvuWuQ</a></li>\r\n<li>Firesign Theatre - <a href=\"https://www.youtube.com/channel/UCXdhVqpbttKSvBWGWHSBkgw\" class=\"uri\">https://www.youtube.com/channel/UCXdhVqpbttKSvBWGWHSBkgw</a></li>\r\n<li>Hana Malhas - <a href=\"https://www.youtube.com/channel/UCpoMVaoVRf3Xvf10_EIZKrg\" class=\"uri\">https://www.youtube.com/channel/UCpoMVaoVRf3Xvf10_EIZKrg</a></li>\r\n<li>Healthcare Triage - <a href=\"https://www.youtube.com/channel/UCabaQPYxxKepWUsEVQMT4Kw\" class=\"uri\">https://www.youtube.com/channel/UCabaQPYxxKepWUsEVQMT4Kw</a></li>\r\n<li>How Stuff Works - <a href=\"https://www.youtube.com/channel/UCa35qyNpnlZ_u8n9qoAZbMQ\" class=\"uri\">https://www.youtube.com/channel/UCa35qyNpnlZ_u8n9qoAZbMQ</a></li>\r\n<li>Jeff Pevar - <a href=\"https://www.youtube.com/channel/UCGd3v3LEwBJOsXkN-RZgFzQ\" class=\"uri\">https://www.youtube.com/channel/UCGd3v3LEwBJOsXkN-RZgFzQ</a></li>\r\n<li><a href=\"https://www.palain.com/\" class=\"uri\">https://www.palain.com/</a></li>\r\n</ul>\r\n',198,106,0,'CC-BY-SA','YouTube, Channels, Subscriptions',0,0,1),
(2765,'2019-03-08','My YouTube Subscriptions #3',1329,'Part three of my list of subscribed channels','<p>I am subscribed to a number of YouTube channels, and I am sharing them with you</p>\r\n<ul>\r\n<li>Jennie Breeden - <a href=\"https://www.youtube.com/channel/UCMwWHArL7o7n-So1r-T_u3w\" class=\"uri\">https://www.youtube.com/channel/UCMwWHArL7o7n-So1r-T_u3w</a></li>\r\n<li>Kate Techtonics - <a href=\"https://www.youtube.com/channel/UC4uxJvPa2nGe1ItPJsz2ORg\" class=\"uri\">https://www.youtube.com/channel/UC4uxJvPa2nGe1ItPJsz2ORg</a></li>\r\n<li>Lydian Collective - <a href=\"https://www.youtube.com/channel/UCGFAwyexOW5Vi24zvYOSc-A\" class=\"uri\">https://www.youtube.com/channel/UCGFAwyexOW5Vi24zvYOSc-A</a></li>\r\n<li>Metropole Orkest - <a href=\"https://www.youtube.com/channel/UClOuC_V57_bW5sZ5yuh2IKw\" class=\"uri\">https://www.youtube.com/channel/UClOuC_V57_bW5sZ5yuh2IKw</a></li>\r\n<li>Mike Pachelli - <a href=\"https://www.youtube.com/channel/UCHnZrxYdMc0lNk8kEZVUoTA\" class=\"uri\">https://www.youtube.com/channel/UCHnZrxYdMc0lNk8kEZVUoTA</a></li>\r\n<li>Mortons on the Move - <a href=\"https://www.youtube.com/channel/UCirNI5XV3xZZApeIe0a5-6Q\" class=\"uri\">https://www.youtube.com/channel/UCirNI5XV3xZZApeIe0a5-6Q</a></li>\r\n<li>Nixie Pixel - <a href=\"https://www.youtube.com/channel/UCBE-FO9JUOghSysV9gjTeHw\" class=\"uri\">https://www.youtube.com/channel/UCBE-FO9JUOghSysV9gjTeHw</a></li>\r\n<li>Numberphile - <a href=\"https://www.youtube.com/channel/UCoxcjq-8xIDTYp3uz647V5A\" class=\"uri\">https://www.youtube.com/channel/UCoxcjq-8xIDTYp3uz647V5A</a></li>\r\n<li>Nature Video - <a href=\"https://www.youtube.com/channel/UC7c8mE90qCtu11z47U0KErg\" class=\"uri\">https://www.youtube.com/channel/UC7c8mE90qCtu11z47U0KErg</a></li>\r\n<li>Ohio LinuxFest - <a href=\"https://www.youtube.com/channel/UCpbGjYCdBwaenhnN2OKXmRg\" class=\"uri\">https://www.youtube.com/channel/UCpbGjYCdBwaenhnN2OKXmRg</a></li>\r\n<li>Piled Higher and Deeper - <a href=\"https://www.youtube.com/channel/UCUL-pmhmDcZDwsA4cX2HO5w\" class=\"uri\">https://www.youtube.com/channel/UCUL-pmhmDcZDwsA4cX2HO5w</a></li>\r\n<li>Postmodern Jukebox - <a href=\"https://www.youtube.com/channel/UCORIeT1hk6tYBuntEXsguLg\" class=\"uri\">https://www.youtube.com/channel/UCORIeT1hk6tYBuntEXsguLg</a></li>\r\n<li>RV Geeks - <a href=\"https://www.youtube.com/channel/UC2EOriLgUuwQn-uCHl58m_Q\" class=\"uri\">https://www.youtube.com/channel/UC2EOriLgUuwQn-uCHl58m_Q</a></li>\r\n<li>RVtravel - <a href=\"https://www.youtube.com/channel/UCARpsGWj6MJ7JE78OcfWKWw\" class=\"uri\">https://www.youtube.com/channel/UCARpsGWj6MJ7JE78OcfWKWw</a></li>\r\n<li>Science News - <a href=\"https://www.youtube.com/channel/UCBX5er6E37_yWB3gCM32p3g\" class=\"uri\">https://www.youtube.com/channel/UCBX5er6E37_yWB3gCM32p3g</a></li>\r\n<li>SciShow - <a href=\"https://www.youtube.com/channel/UCZYTClx2T1of7BRZ86-8fow\" class=\"uri\">https://www.youtube.com/channel/UCZYTClx2T1of7BRZ86-8fow</a></li>\r\n<li>SciShow Space - <a href=\"https://www.youtube.com/channel/UCrMePiHCWG4Vwqv3t7W9EFg\" class=\"uri\">https://www.youtube.com/channel/UCrMePiHCWG4Vwqv3t7W9EFg</a></li>\r\n<li>Sophie Alloway - <a href=\"https://www.youtube.com/channel/UCCwcpSK-9Zbo8QDsPWdM1Bg\" class=\"uri\">https://www.youtube.com/channel/UCCwcpSK-9Zbo8QDsPWdM1Bg</a></li>\r\n<li>Ten Minute History - <a href=\"https://www.youtube.com/channel/UC22BdTgxefuvUivrjesETjg\" class=\"uri\">https://www.youtube.com/channel/UC22BdTgxefuvUivrjesETjg</a></li>\r\n<li>The Fab Faux - <a href=\"https://www.youtube.com/channel/UCsU8AeRj_497u2IMxVA6OcQ\" class=\"uri\">https://www.youtube.com/channel/UCsU8AeRj_497u2IMxVA6OcQ</a></li>\r\n<li><a href=\"https://www.palain.com/\" class=\"uri\">https://www.palain.com/</a></li>\r\n</ul>\r\n',198,106,0,'CC-BY-SA','YouTube, Channels, Subscriptions',0,0,1),
(2775,'2019-03-22','My YouTube Subscriptions #4',1198,'Part four of my list of subscribed channels','<p>I am subscribed to a number of YouTube channels, and I am sharing them with you</p>\r\n<ul>\r\n<li>The HollyHobs - <a href=\"https://www.youtube.com/channel/UCkhSH-DB2xK4BIJZoql9djQ\" class=\"uri\">https://www.youtube.com/channel/UCkhSH-DB2xK4BIJZoql9djQ</a></li>\r\n<li>Adam Neely - <a href=\"https://www.youtube.com/channel/UCnkp4xDOwqqJD7sSM3xdUiQ\" class=\"uri\">https://www.youtube.com/channel/UCnkp4xDOwqqJD7sSM3xdUiQ</a></li>\r\n<li>Airstream of Scottsdale - <a href=\"https://www.youtube.com/channel/UChNNDq91qW6zDkUXM2IuIYQ\" class=\"uri\">https://www.youtube.com/channel/UChNNDq91qW6zDkUXM2IuIYQ</a></li>\r\n<li>Alternate History Hub - <a href=\"https://www.youtube.com/channel/UClfEht64_NrzHf8Y0slKEjw\" class=\"uri\">https://www.youtube.com/channel/UClfEht64_NrzHf8Y0slKEjw</a></li>\r\n<li>Alton Brown - <a href=\"https://www.youtube.com/channel/UCfDNi1aEljAQ17mUrfUjkvg\" class=\"uri\">https://www.youtube.com/channel/UCfDNi1aEljAQ17mUrfUjkvg</a></li>\r\n<li>Apartment Sessions - <a href=\"https://www.youtube.com/channel/UCpU_PAsVFl2fO649QF6Zj0Q\" class=\"uri\">https://www.youtube.com/channel/UCpU_PAsVFl2fO649QF6Zj0Q</a></li>\r\n<li>AStreaminLife - <a href=\"https://www.youtube.com/channel/UCtrZvxP1SQkBJ8kZLsslimw\" class=\"uri\">https://www.youtube.com/channel/UCtrZvxP1SQkBJ8kZLsslimw</a></li>\r\n<li>Big Truck Big RV - <a href=\"https://www.youtube.com/channel/UCaX2-JkluLd8aG0DXp0L2Xw\" class=\"uri\">https://www.youtube.com/channel/UCaX2-JkluLd8aG0DXp0L2Xw</a></li>\r\n<li>Bill Holbrook - <a href=\"https://www.youtube.com/channel/UChE4ujkOdzJ02k-F9ZqwpMw\" class=\"uri\">https://www.youtube.com/channel/UChE4ujkOdzJ02k-F9ZqwpMw</a></li>\r\n<li>CGP Grey - <a href=\"https://www.youtube.com/channel/UC2C_jShtL725hvbm1arSV9w\" class=\"uri\">https://www.youtube.com/channel/UC2C_jShtL725hvbm1arSV9w</a></li>\r\n<li>Crash Course - <a href=\"https://www.youtube.com/channel/UCX6b17PVsYBQ0ip5gyeme-Q\" class=\"uri\">https://www.youtube.com/channel/UCX6b17PVsYBQ0ip5gyeme-Q</a></li>\r\n<li>Deep Sky Videos - <a href=\"https://www.youtube.com/channel/UCo-3ThNQmPmQSQL_L6Lx1_w\" class=\"uri\">https://www.youtube.com/channel/UCo-3ThNQmPmQSQL_L6Lx1_w</a></li>\r\n<li>Doctor Who - <a href=\"https://www.youtube.com/channel/UCcOkA2Xmk1valTOWSyKyp4g\" class=\"uri\">https://www.youtube.com/channel/UCcOkA2Xmk1valTOWSyKyp4g</a></li>\r\n<li>Emperor Tigerstar - <a href=\"https://www.youtube.com/channel/UCUXqYwTCR6R3Wr-FkLTD4AQ\" class=\"uri\">https://www.youtube.com/channel/UCUXqYwTCR6R3Wr-FkLTD4AQ</a></li>\r\n<li>Fastway Trailer - <a href=\"https://www.youtube.com/channel/UCDKtrIOnj4IvatnpJkh2aXA\" class=\"uri\">https://www.youtube.com/channel/UCDKtrIOnj4IvatnpJkh2aXA</a></li>\r\n<li>fyfluiddynamics - <a href=\"https://www.youtube.com/channel/UCxuET3jfy0v8EJa7TKNiI2g\" class=\"uri\">https://www.youtube.com/channel/UCxuET3jfy0v8EJa7TKNiI2g</a></li>\r\n<li>Haylett RV - <a href=\"https://www.youtube.com/channel/UCRS9u1f7074u0Rrgu05K9Wg\" class=\"uri\">https://www.youtube.com/channel/UCRS9u1f7074u0Rrgu05K9Wg</a></li>\r\n<li>It’s OK To Be Smart - <a href=\"https://www.youtube.com/channel/UCH4BNI0-FOK2dMXoFtViWHw\" class=\"uri\">https://www.youtube.com/channel/UCH4BNI0-FOK2dMXoFtViWHw</a></li>\r\n<li>Less Junk, More Journey - <a href=\"https://www.youtube.com/channel/UC2IENUorXc6kRtIiAGPRKZA\" class=\"uri\">https://www.youtube.com/channel/UC2IENUorXc6kRtIiAGPRKZA</a></li>\r\n<li>Long, Long Honeymoon - <a href=\"https://www.youtube.com/channel/UCw5WYtMXQ799GErKpvR_5Rw\" class=\"uri\">https://www.youtube.com/channel/UCw5WYtMXQ799GErKpvR_5Rw</a></li>\r\n<li>Matt’s RV Reviews - <a href=\"https://www.youtube.com/channel/UCBHww2yk8soPJ9IcbZ0n_Uw\" class=\"uri\">https://www.youtube.com/channel/UCBHww2yk8soPJ9IcbZ0n_Uw</a></li>\r\n<li><a href=\"https://www.palain.com/\" class=\"uri\">https://www.palain.com/</a></li>\r\n</ul>\r\n',198,106,0,'CC-BY-SA','YouTube, Channels, Subscriptions',0,0,1),
(2790,'2019-04-12','My YouTube Subscriptions #5',1206,'Part five of my list of subscribed channels','<p>I am subscribed to a number of YouTube channels, and I am sharing them with you</p>\r\n<ul>\r\n<li>Mental Floss - <a href=\"https://www.youtube.com/channel/UCpZ5qUqpW4hW4zdfuBxMSJA\" class=\"uri\">https://www.youtube.com/channel/UCpZ5qUqpW4hW4zdfuBxMSJA</a></li>\r\n<li>Minute Earth - <a href=\"https://www.youtube.com/channel/UCeiYXex_fwgYDonaTcSIk6w\" class=\"uri\">https://www.youtube.com/channel/UCeiYXex_fwgYDonaTcSIk6w</a></li>\r\n<li>Minute Physics - <a href=\"https://www.youtube.com/channel/UCUHW94eEFW7hkUMVaZz4eDg\" class=\"uri\">https://www.youtube.com/channel/UCUHW94eEFW7hkUMVaZz4eDg</a></li>\r\n<li>Mona Lisa Twins - <a href=\"https://www.youtube.com/channel/UCWK_fTtt5p1nBw__P_V_qBw\" class=\"uri\">https://www.youtube.com/channel/UCWK_fTtt5p1nBw__P_V_qBw</a></li>\r\n<li>Monty Python - <a href=\"https://www.youtube.com/channel/UCGm3CO6LPcN-Y7HIuyE0Rew\" class=\"uri\">https://www.youtube.com/channel/UCGm3CO6LPcN-Y7HIuyE0Rew</a></li>\r\n<li>Objectivity - <a href=\"https://www.youtube.com/channel/UCtwKon9qMt5YLVgQt1tvJKg\" class=\"uri\">https://www.youtube.com/channel/UCtwKon9qMt5YLVgQt1tvJKg</a></li>\r\n<li>OfficialGoRVing - <a href=\"https://www.youtube.com/channel/UC8nwC2SO4k6AF-E2liOiSQQ\" class=\"uri\">https://www.youtube.com/channel/UC8nwC2SO4k6AF-E2liOiSQQ</a></li>\r\n<li>PBS Eons - <a href=\"https://www.youtube.com/channel/UCzR-rom72PHN9Zg7RML9EbA\" class=\"uri\">https://www.youtube.com/channel/UCzR-rom72PHN9Zg7RML9EbA</a></li>\r\n<li>PBS SpaceTime - <a href=\"https://www.youtube.com/channel/UC7_gcs09iThXybpVgjHZ_7g\" class=\"uri\">https://www.youtube.com/channel/UC7_gcs09iThXybpVgjHZ_7g</a></li>\r\n<li>Periodic Videos - <a href=\"https://www.youtube.com/channel/UCtESv1e7ntJaLJYKIO1FoYw\" class=\"uri\">https://www.youtube.com/channel/UCtESv1e7ntJaLJYKIO1FoYw</a></li>\r\n<li>Physics Girl - <a href=\"https://www.youtube.com/channel/UC7DdEm33SyaTDtWYGO2CwdA\" class=\"uri\">https://www.youtube.com/channel/UC7DdEm33SyaTDtWYGO2CwdA</a></li>\r\n<li>Rollin’ On TV - <a href=\"https://www.youtube.com/channel/UCAfquicUYGba3nuzQ-n0tnw\" class=\"uri\">https://www.youtube.com/channel/UCAfquicUYGba3nuzQ-n0tnw</a></li>\r\n<li>RV Education 101 - <a href=\"https://www.youtube.com/channel/UCQNg-4bXbDGS61casEa5LyQ\" class=\"uri\">https://www.youtube.com/channel/UCQNg-4bXbDGS61casEa5LyQ</a></li>\r\n<li>RV to Freedom - <a href=\"https://www.youtube.com/channel/UCJxweRfyWOMcbwxpK4FnsyA\" class=\"uri\">https://www.youtube.com/channel/UCJxweRfyWOMcbwxpK4FnsyA</a></li>\r\n<li>Sciencium - <a href=\"https://www.youtube.com/channel/UCGRB1ZjIqAiaGwt-XLq9CnA\" class=\"uri\">https://www.youtube.com/channel/UCGRB1ZjIqAiaGwt-XLq9CnA</a></li>\r\n<li>SciFri - <a href=\"https://www.youtube.com/channel/UCDjGU4DP3b-eGxrsipCvoVQ\" class=\"uri\">https://www.youtube.com/channel/UCDjGU4DP3b-eGxrsipCvoVQ</a></li>\r\n<li>SciShow Psych - <a href=\"https://www.youtube.com/channel/UCUdettijNYvLAm4AixZv4RA\" class=\"uri\">https://www.youtube.com/channel/UCUdettijNYvLAm4AixZv4RA</a></li>\r\n<li><a href=\"https://www.palain.com/\" class=\"uri\">https://www.palain.com/</a></li>\r\n</ul>\r\n',198,106,0,'CC-BY-SA','YouTube, Channels, Subscriptions',0,0,1),
(2800,'2019-04-26','My YouTube Subscriptions #6',1169,'Part six of my list of subscribed channels','<p>I am subscribed to a number of YouTube channels, and I am sharing them with you</p>\r\n<ul>\r\n<li>SgtPepper Channel - <a href=\"https://www.youtube.com/channel/UCAZZwDyOoSG32tIpMjQ-EKA\" class=\"uri\">https://www.youtube.com/channel/UCAZZwDyOoSG32tIpMjQ-EKA</a></li>\r\n<li>Sid Meier’s Civilization - <a href=\"https://www.youtube.com/channel/UCWj7XnnfbKHGVnZ8iSoETSQ\" class=\"uri\">https://www.youtube.com/channel/UCWj7XnnfbKHGVnZ8iSoETSQ</a></li>\r\n<li>Sixty Symbols - <a href=\"https://www.youtube.com/channel/UCvBqzzvUBLCs8Y7Axb-jZew\" class=\"uri\">https://www.youtube.com/channel/UCvBqzzvUBLCs8Y7Axb-jZew</a></li>\r\n<li>Smarter Every Day - <a href=\"https://www.youtube.com/channel/UC6107grRI4m0o2-emgoDnAA\" class=\"uri\">https://www.youtube.com/channel/UC6107grRI4m0o2-emgoDnAA</a></li>\r\n<li>Space Frontier Foundation - <a href=\"https://www.youtube.com/channel/UCe_aC8RselByR6B2UMnprQA\" class=\"uri\">https://www.youtube.com/channel/UCe_aC8RselByR6B2UMnprQA</a></li>\r\n<li>Streamin’ Freedom - <a href=\"https://www.youtube.com/channel/UCEl_3AAj2pA-GvkxTS7-mxg\" class=\"uri\">https://www.youtube.com/channel/UCEl_3AAj2pA-GvkxTS7-mxg</a></li>\r\n<li>Suibhne - <a href=\"https://www.youtube.com/channel/UCQD-0MjUbDBwm2UTVYr0Dag\" class=\"uri\">https://www.youtube.com/channel/UCQD-0MjUbDBwm2UTVYr0Dag</a></li>\r\n<li>Talk More Talk - <a href=\"https://www.youtube.com/channel/UC7rNO8_kPBH-caQH9vzNe8A\" class=\"uri\">https://www.youtube.com/channel/UC7rNO8_kPBH-caQH9vzNe8A</a></li>\r\n<li>The Beatles - <a href=\"https://www.youtube.com/channel/UCc4K7bAqpdBP8jh1j9XZAww\" class=\"uri\">https://www.youtube.com/channel/UCc4K7bAqpdBP8jh1j9XZAww</a></li>\r\n<li>The Economist - <a href=\"https://www.youtube.com/channel/UC0p5jTq6Xx_DosDFxVXnWaQ\" class=\"uri\">https://www.youtube.com/channel/UC0p5jTq6Xx_DosDFxVXnWaQ</a></li>\r\n<li>The Extraordinary Universe - <a href=\"https://www.youtube.com/channel/UC_2MM6tCMKWCj-AnvjIhJtw\" class=\"uri\">https://www.youtube.com/channel/UC_2MM6tCMKWCj-AnvjIhJtw</a></li>\r\n<li>The Great War - <a href=\"https://www.youtube.com/channel/UCUcyEsEjhPEDf69RRVhRh4A\" class=\"uri\">https://www.youtube.com/channel/UCUcyEsEjhPEDf69RRVhRh4A</a></li>\r\n<li>The Planetary Society - <a href=\"https://www.youtube.com/channel/UCi0TZmFfgS4oQPcRQ6-KRXg\" class=\"uri\">https://www.youtube.com/channel/UCi0TZmFfgS4oQPcRQ6-KRXg</a></li>\r\n<li>The Saxy Gamer - <a href=\"https://www.youtube.com/channel/UCJCY4j5zSuV1TFN2VQGeD0Q\" class=\"uri\">https://www.youtube.com/channel/UCJCY4j5zSuV1TFN2VQGeD0Q</a></li>\r\n<li>Totally Trailer - <a href=\"https://www.youtube.com/channel/UCuMYtpUa2kaPaG4tBlJAZOA\" class=\"uri\">https://www.youtube.com/channel/UCuMYtpUa2kaPaG4tBlJAZOA</a></li>\r\n<li>Trailer Life DIY - <a href=\"https://www.youtube.com/channel/UCMmzjxJREn4kDK-ypq9oA7w\" class=\"uri\">https://www.youtube.com/channel/UCMmzjxJREn4kDK-ypq9oA7w</a></li>\r\n<li>Veritasium - <a href=\"https://www.youtube.com/channel/UCHnyfMqiRRG1u-2MsSQLbXA\" class=\"uri\">https://www.youtube.com/channel/UCHnyfMqiRRG1u-2MsSQLbXA</a></li>\r\n<li>Vintage space - <a href=\"https://www.youtube.com/channel/UCw95T_TgbGHhTml4xZ9yIqg\" class=\"uri\">https://www.youtube.com/channel/UCw95T_TgbGHhTml4xZ9yIqg</a></li>\r\n<li>Vlogbrothers - <a href=\"https://www.youtube.com/channel/UCGaVdbSav8xWuFWTadK6loA\" class=\"uri\">https://www.youtube.com/channel/UCGaVdbSav8xWuFWTadK6loA</a></li>\r\n<li><a href=\"https://www.palain.com/\" class=\"uri\">https://www.palain.com/</a></li>\r\n</ul>\r\n',198,106,0,'CC-BY-SA','YouTube, Channels, Subscriptions',0,0,1),
(2738,'2019-01-30','My Applications',229,'just a short show on the applications I use on my Linux Mint Box','<p>Hi again, this is Tony Hughes from Blackpool in the UK. Ken is still short of shows so here is another quick show to help out with the queue.</p>\r\n<p>This one is going to be about the applications I use on my Linux Mint 19.1 install. I’ve been using Linux for over 10 years now and during that time have never felt that there was anything that was lacking in the software department for day to day productivity and general day to day use, so this is just a list of some of the things that I, and I suspect most computer users, need to make electronic life a reality.</p>\r\n<p>So for internet browsing I use Firefox, I’ve been using this since my Windows days and it was just natural that, as this is the default web browser in Linux Mint, that this is what I would continue to use when I moved over to Linux.</p>\r\n<p>Email – I have several web based accounts which means these are operating system agnostic, but for my Internet Service provider account I use Thunderbird to download and store my e-mail onto my main desktop PC. I can also use this to access my web based accounts and store emails for these off line as well if needed.</p>\r\n<p>Office productivity is provided for with LibreOffice which is a very mature and comprehensive office suite comprising of all the main tools needed such as a word processor, spreadsheet and presentation software. It also has a Database and drawing package, and for maths geeks an advanced maths formula creating program which I have never used, but could be very useful for students and scientists.</p>\r\n<p>For audio and video playback I use VLC which again is something I first used back in my windows days, it works with all the audio and video codecs you can throw at it, and if you have the Libdvdcss codecs installed will play proprietary DVD’s.</p>\r\n<p>For recording and editing audio including this podcast I use Audacity, which is again a cross platform programme and a very powerful piece of software, as myself and many others that use it will be able to tell you</p>\r\n<p>So that is a short list of the programmes that I use on a day to day basis. I hope you found it useful, if not it doesn’t matter as Ken still got a show out of me.</p>\r\n<p>Well that’s it for this one. This is Tony Hughes signing off for now.</p>\r\n',338,0,0,'CC-BY-SA','productivity software',0,0,1),
(2740,'2019-02-01','Pop!_OS 18.10 (quick) review',438,'In this episode, Yannick does a quick review of Pop OS 18.10','<p>This episode is a re-edition of the review of Pop_OS! I did for <a href=\"https://tuxjam.otherside.network/?p=391\">TuxJam</a> back in December 2018. Pop_OS! is published by <a href=\"https://system76.com/pop\">System76</a>.</p>\r\n',370,0,0,'CC-BY-SA','linux,distro,distribution,pop_os,system76,ubuntu',0,0,1),
(2744,'2019-02-07','Yet Another Rambling Drive Into Work',2022,'Yet another rambling attempt at making a show on the way into work','<p>I came across this show sitting in my digital recorder I recorded it back in November 2017 but never posted it, my thoughts on some of the things I mention in this show have since evolved, I’ll stick these changed thoughts at the end of these notes and may also stick in an extra recorded section at the end of the show.</p>\r\n<ul>\r\n<li><p>Previous Ford Focus<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Ford_Focus#First_generation_(1998%E2%80%932004)\">https://en.wikipedia.org/wiki/Ford_Focus#First_generation_(1998%E2%80%932004)</a></p></li>\r\n<li><p>Renault 19, 16V<br />\r\nMine was not a a soft top<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Renault_19#16S\" class=\"uri\">https://en.wikipedia.org/wiki/Renault_19#16S</a><br />\r\n<img src=\"https://upload.wikimedia.org/wikipedia/commons/d/d8/Ren1916vcabph1b.jpg\" alt=\"https://upload.wikimedia.org/wikipedia/commons/d/d8/Ren1916vcabph1b.jpg\" /></p></li>\r\n<li><p>Current Ford Focus<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Ford_Focus#Second_generation_(2004%E2%80%932011)\">https://en.wikipedia.org/wiki/Ford_Focus#Second_generation_(2004%E2%80%932011)</a></p></li>\r\n<li><p>Nissan Leaf 24kw<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Nissan_Leaf#2014/15_model_year\" class=\"uri\">https://en.wikipedia.org/wiki/Nissan_Leaf#2014/15_model_year</a></p></li>\r\n<li><p>Nissan Leaf 30Kw<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Nissan_Leaf#2016_model_year\" class=\"uri\">https://en.wikipedia.org/wiki/Nissan_Leaf#2016_model_year</a></p></li>\r\n<li><p>Nissan leaf 40Kw<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Nissan_Leaf#Second_generation_(2017%E2%80%93present)\">https://en.wikipedia.org/wiki/Nissan_Leaf#Second_generation_(2017%E2%80%93present)</a></p></li>\r\n<li><p>Kilts<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Kilt\" class=\"uri\">https://en.wikipedia.org/wiki/Kilt</a></p></li>\r\n<li><p>Bagpipes<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Bagpipes\" class=\"uri\">https://en.wikipedia.org/wiki/Bagpipes</a></p></li>\r\n<li><p>Accordion<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Accordion\" class=\"uri\">https://en.wikipedia.org/wiki/Accordion</a></p></li>\r\n<li><p>Squeeze Box<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Squeezebox\" class=\"uri\">https://en.wikipedia.org/wiki/Squeezebox</a></p></li>\r\n<li><p>Haggis<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Haggis\" class=\"uri\">https://en.wikipedia.org/wiki/Haggis</a></p></li>\r\n<li><p>Co-op<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Cooperative\" class=\"uri\">https://en.wikipedia.org/wiki/Cooperative</a></p></li>\r\n<li><p>Example of a Haggis Pizza, though not from the Co-op<br />\r\n<a href=\"https://www.sainsburys.co.uk/webapp/wcs/stores/servlet/gb/groceries/cosmo-haggis-pizza-450g?langId=44&amp;storeId=10151&amp;krypto=9555DKfWSs9%2FPZXDDPtNmunNVefFVynanbSeQICSqvaqFAqsHBIPIKiSBqw2aq4oL2g8H8Mht9FuPj%2FYvtWLegub3%2F9KqGLI16COGk2qTEwkFeo9zgw2ELE4DtGbDzzRldgf51yrZVaYL9WXmfOvDS%2FiJx9pqI12OIXlHwmPkmc%3D&amp;ddkey=https%3Agb%2Fgroceries%2Fcosmo-haggis-pizza-450g\">https://www.sainsburys.co.uk/webapp/wcs/stores/servlet/gb/groceries/cosmo-haggis-pizza-450g?langId=44&amp;storeId=10151&amp;krypto=9555DKfWSs9%2FPZXDDPtNmunNVefFVynanbSeQICSqvaqFAqsHBIPIKiSBqw2aq4oL2g8H8Mht9FuPj%2FYvtWLegub3%2F9KqGLI16COGk2qTEwkFeo9zgw2ELE4DtGbDzzRldgf51yrZVaYL9WXmfOvDS%2FiJx9pqI12OIXlHwmPkmc%3D&amp;ddkey=https%3Agb%2Fgroceries%2Fcosmo-haggis-pizza-450g</a></p></li>\r\n<li><p>Nissan Leaf Phone App to remotely control heating system<br />\r\n<a href=\"https://youplus.nissan.co.uk/GB/en/YouPlus/ConnectedServices.html\" class=\"uri\">https://youplus.nissan.co.uk/GB/en/YouPlus/ConnectedServices.html</a></p></li>\r\n<li><p>Citroen BX, Hydraulic suspension<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Citro%C3%ABn_BX\">https://en.wikipedia.org/wiki/Citro%C3%ABn_BX</a></p></li>\r\n<li><p>Reversing sensors, and camera<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Parking_sensor\" class=\"uri\">https://en.wikipedia.org/wiki/Parking_sensor</a></p></li>\r\n</ul>\r\n<p>Here are the changes since I recorded this show in November 2017, it is now October 2018.</p>\r\n<p>Think there was a £4,500 pound grant on new EV cars however it has been announced that this grant will in the near future will be cut to £3500.</p>\r\n<p>I think the Government and Nissan together had a £2000 contribution scheme when you traded in an old car for a 2nd hand leaf I think this is no longer available now that the leaf is more popular.</p>\r\n<p>Fuel costs have gone up and I may have miscalculated I think my true annual fuel bill is nearer to £2,000</p>\r\n<p>Nissan leaf road tax is free</p>\r\n<p>Because of supply and demand the depreciation situation has completely changed had I bought this leaf in November 2017 it would now be worth more today in October 2018. Only time will tell how it all pans out, things are changing rapidly.</p>\r\n<p>After further investigation it looks like battery degradation is less than I first thought and would likely still be in pretty good condition at 6 years old, particularly in a cooler country like here in the UK in Scotland.</p>\r\n<p>There has been some controversy about the new 40kw leaf which may also impact in the older leaf making the older leaf’s more appealing contributing further to the high demand for the older 30kw and 24kw leafs.<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Nissan_Leaf#Criticism\" class=\"uri\">https://en.wikipedia.org/wiki/Nissan_Leaf#Criticism</a><br />\r\n<a href=\"https://www.greencarreports.com/news/1116139_2018-nissan-leaf-electric-car-is-there-a-fast-charging-problem\" class=\"uri\">https://www.greencarreports.com/news/1116139_2018-nissan-leaf-electric-car-is-there-a-fast-charging-problem</a></p>\r\n<p>With the increased popularity of the older 24 and 30Kw leafs Nissan may no longer be so keen to give you a no quibble test drive.</p>\r\n<p>I think it’s looking increasingly like I made the wrong decision.</p>\r\n',201,0,1,'CC-BY-SA','Podcast, Cars',0,0,1),
(2746,'2019-02-11','My software part 2',326,'More about the software I use regularly on Linux ','<p>Good day to all in HPR land, this is Tony Hughes coming to you from Blackpool in the UK again. This is a second instalment about some of the software I use on Linux Mint 19.1, on a regular basis. So without further ado lets get on with the show.</p>\r\n<ul>\r\n<li><p>USB Image writer</p></li>\r\n<li><p>VirtualBox – Virtualisation software to virtualise x86 and AMD64 bit PC’s</p></li>\r\n<li><p>OBS – Open Broadcast software</p></li>\r\n<li><p>Brasero/XFburn – CD/DVD writing software</p></li>\r\n<li><p>GIMP – GNU Image manipulation Program</p></li>\r\n</ul>\r\n<p>So that’s it for this episode. I’ll be back to talk about some of the utilities I use on Mint on another show. This is Tony Hughes signing off for now.</p>\r\n',338,0,0,'CC-BY-SA','Linux Mint 19.1,utilities',0,0,1),
(2747,'2019-02-12','checking oil',317,'checking your oil may not be so simple','<blockquote>\r\n<p>a 914 shows up…<br />\r\nit has a 911 engine…<br />\r\ni check the oil…<br />\r\nthe car lives…</p>\r\n</blockquote>\r\n',329,0,1,'CC-BY-SA','automotive',0,0,1),
(2748,'2019-02-13','Writing Web Game in Haskell - Special events',2645,'Tuula walks through implementation of special events in web based game','<h2 id=\"intro\">Intro</h2>\r\n<p>I was tasked to write kragii worms in the game and informed that they’re small (10cm / 4 inches) long worms that burrow in ground and are drawn to farming fields and people. They’re dangerous and might eat harvest or people.</p>\r\n<p>Special events build on top of the new system I explained in <a href=\"https://hackerpublicradio.org/eps.php?id=2733\">episode 2733</a>. They are read from same API as regular news and need same <code>ToJSON</code>, <code>FromJSON</code>, <code>ToDto</code> and <code>FromDto</code> instances as regular news (for translating them data transfer objects and then into JSON for sending to client).</p>\r\n<h2 id=\"loading\">Loading</h2>\r\n<p>Starting from the API interface, the first real difference is when JSON stored into database is turned into <code>NewsArticle</code>. Two cases, where special news have available options added to them and regular news are left unchanged. These options tell player what choices they have when dealing with the situation and evaluated every time special event is loaded, because situation might have changed since special event got stored into database and available options might have changed.</p>\r\n<pre><code>addOptions (key, article) = case article of\r\n                                Special news -&gt;\r\n                                    (key, Special $ availableOptions news)\r\n                                _ -&gt;\r\n                                    (key, article)\r\n\r\navailableOptions :: SpecialNews -&gt; SpecialNews\r\navailableOptions x =\r\n    case x of\r\n        KragiiWorms event _ choice -&gt;\r\n            KragiiWorms event (eventOptions event) choice</code></pre>\r\n<p><code>eventOptions</code> is one of the events defined in <code>SpecialEvent</code> type class that specifies two functions every special event has to have. <code>eventOptions</code> lists what options the event has currently available and <code>resolveEvent</code> resolves the event according to choice user might have made (hence <code>Maybe</code> in it).</p>\r\n<p>Type class is parametrized with three types (imaginatively named to <code>a</code>, <code>b</code> and <code>c</code>). First is data type that holds information about special event (where it’s happening and to who for example), second one is one that tells all possible choices player has and third one lists various results that might occur when resolving the event. In this example they’re <code>KragiiWormsEvent</code>, <code>KragiiWormsChoice</code> and <code>KragiiResults</code>.</p>\r\n<pre><code>data KragiiWormsEvent = KragiiWormsEvent\r\n    { kragiiWormsPlanetId   :: Key Planet\r\n    , kragiiWormsPlanetName :: Text\r\n    , kragiiWormsSystemId   :: Key StarSystem\r\n    , kragiiWormsSystemName :: Text\r\n    , kragiiWormsDate       :: Int\r\n    }\r\n\r\ndata KragiiWormsChoice =\r\n    EvadeWorms\r\n    | AttackWorms\r\n    | TameWorms\r\n\r\ndata KragiiResults =\r\n    WormsStillPresent\r\n    | WormsRemoved\r\n    | WormsTamed\r\n    | CropsDestroyed (RawResource Biological)\r\n    | FarmersInjured</code></pre>\r\n<p>Definition of the <code>SpecialEvent</code> type class is shown below. Type signature of <code>resolveEvent</code> is gnarly because it’s reading and writing database.</p>\r\n<pre><code>class SpecialEvent a b c | a -&gt; b, a -&gt; c where\r\n    eventOptions :: a -&gt; [UserOption b]\r\n    resolveEvent :: ( PersistQueryRead backend, PersistQueryWrite backend\r\n                    , MonadIO m, BaseBackend backend ~ SqlBackend ) =&gt;\r\n                    (Key News, a) -&gt; Maybe b -&gt; ReaderT backend m (Maybe EventRemoval, [c])</code></pre>\r\n<p>One more piece we need is <code>UserOption</code>. This records options in a format that is useful in the client side. Each option player has are given title and explanation that are shown on UI.</p>\r\n<pre><code>data UserOption a =\r\n    UserOption { userOptionTitle :: Text\r\n               , userOptionExplanation :: [Text]\r\n               , userOptionChoice :: a\r\n               }</code></pre>\r\n<p>Current implementation of <code>eventOptions</code> doesn’t allow database access, but I’m planning on adding that at the point where I need it. Example doesn’t show all different options, as they all have same structure. Only first option in the list is shown:</p>\r\n<pre><code>eventOptions _ = [ UserOption { userOptionTitle = &quot;Avoid the worms&quot;\r\n                              , userOptionExplanation = [ &quot;Keep using fields, while avoiding the worms and hope they&#39;ll eventually leave.&quot;\r\n                                                        , &quot;50 units of biologicals lost&quot;\r\n                                                        , &quot;25% chance of worms leaving&quot;\r\n                                                        ]\r\n                              , userOptionChoice = EvadeWorms\r\n                            }\r\n                   , ...\r\n                   ]</code></pre>\r\n<h2 id=\"making-choice\">Making choice</h2>\r\n<p><code>putApiMessageIdR</code> handles updating news with <code>HTTP PUT</code> messages. First steps is to check that caller has autenticated and retrieve id of their faction. News article that is transferred in body as JSON is parsed and checked for type. Updating regular news articles isn’t supported and is signaled with <code>HTTP 403</code> status code. One more check to perform is to check that news article being edited actually belong to the faction player is member of. If that’s not the case <code>HTTP 404</code> message is returned.</p>\r\n<p>If we got this far, news article is updated with the content sent by client (that also contains possible choice made by user). There’s no check that type of news article doesn’t change or that the option selected doesn’t change (I need to add these at later point). In the end, list of all messages is returned back to the client.</p>\r\n<pre><code>putApiMessageIdR :: Key News -&gt; Handler Value\r\nputApiMessageIdR mId = do\r\n    (_, _, fId) &lt;- apiRequireFaction\r\n    msg &lt;- requireJsonBody\r\n    let article = fromDto msg\r\n    _ &lt;- if isSpecialEvent article\r\n            then do\r\n                loadedMessages &lt;- runDB $ selectList [ NewsId ==. mId\r\n                                                     , NewsFactionId ==. fId ] [ Asc NewsDate ]\r\n                if length loadedMessages == 0\r\n                    then apiNotFound\r\n                    else runDB $ update mId [ NewsContent =. (toStrict $ encodeToLazyText article) ]\r\n            else apiForbidden &quot;unsupported article type&quot;\r\n    loadAllMessages fId</code></pre>\r\n<h2 id=\"resolving-event\">Resolving event</h2>\r\n<p>Special event occured, user made (or did not) a choice. Now it’s time to simulate what happens. Below is <code>resolveEvent</code> for kragii attack.</p>\r\n<pre><code>resolveEvent keyEventPair (Just choice) =\r\n    runWriterT . runMaybeT $\r\n        case choice of\r\n                EvadeWorms -&gt;\r\n                    chooseToAvoid keyEventPair\r\n\r\n                AttackWorms -&gt;\r\n                    chooseToAttack keyEventPair\r\n\r\n                TameWorms -&gt;\r\n                    chooseToTame keyEventPair\r\n\r\nresolveEvent keyEventPair Nothing =\r\n    runWriterT . runMaybeT $ noChoice keyEventPair</code></pre>\r\n<p><code>runWriterT</code> and <code>runMaybeT</code> are used as code being called uses monad transformers to add some extra handling. <code>WriterT</code> adds ability to record data (<code>KragiiResult</code> in this case) and <code>MaybeT</code> adds ability to stop computation early if one of the steps return <code>Nothing</code> value.</p>\r\n<p>Let’s walk through what happens when user has chosen to avoid kragii worms and keep working only part of the fields. First step is to load faction information. If faction couldn’t be found, we abort. Next amount of biological matter consumed and how much is left is calculated. Again, if calculation isn’t possible, we’ll abort. This step reaches into database and updates amount of biological matter stored by the faction (again, possibility to stop early). Final step is to check if kragii leave or not (again, chance of abort).</p>\r\n<pre><code>chooseToAvoid :: ( MonadIO m, PersistQueryWrite backend\r\n                 , BaseBackend backend ~ SqlBackend ) =&gt;\r\n                 (Key News, KragiiWormsEvent)\r\n                 -&gt; MaybeT (WriterT [KragiiResults] (ReaderT backend m)) EventRemoval\r\nchooseToAvoid (_, event) = do\r\n    faction &lt;- getFaction event\r\n    (cost, bioLeft) &lt;- calculateNewBio (RawResource 50) (entityVal faction)\r\n    _ &lt;- destroyCrops faction cost bioLeft\r\n    removeNews $ PercentileChance 25</code></pre>\r\n<p>Loading faction has several step. Id is stored in the event is used to load planet. Planet might or might have an owner faction, depending on if it has been settled. This faction id is used to load faction data. Loading might fail if corresponding record has been removed from database and planet might not be settled at the given time. Any of these cases will result <code>Nothing</code> be returned and whole event resolution being aborted. I’m starting to really like that I don’t have to write separate <code>if</code> statements to take care of these special cases.</p>\r\n<pre><code>getFaction :: ( MonadIO m, PersistStoreRead backend\r\n              , BaseBackend backend ~ SqlBackend ) =&gt;\r\n              KragiiWormsEvent\r\n              -&gt; MaybeT (WriterT [KragiiResults] (ReaderT backend m)) (Entity Faction)\r\ngetFaction event = MaybeT $ do\r\n    planet &lt;- lift $ get $ kragiiWormsPlanetId event\r\n    let owner = join $ fmap planetOwnerId planet\r\n    res &lt;- lift $ mapM getEntity owner\r\n    return $ join res</code></pre>\r\n<p>Amount of biological matter in store is stored in faction information. If it’s zero or less, <code>Nothing</code> is returned as there’s nothing to do really. In other cases, amount of biological matter left is calculated and result returned in form of <code>( cost, biological matter left )</code>. I’m carrying around the cost, as it’s later needed for reporting how much matter was removed.</p>\r\n<pre><code>calculateNewBio :: Monad m =&gt;\r\n                RawResource Biological -&gt; Faction\r\n                -&gt; MaybeT (WriterT [KragiiResults] m) ((RawResource Biological), (RawResource Biological))\r\ncalculateNewBio cost faction = MaybeT $ do\r\n    let currentBio = factionBiologicals faction\r\n    return $ if currentBio &gt; 0\r\n                then Just $ ( cost\r\n                            , RawResource $ max 0 (currentBio - unRawResource cost))\r\n                else Nothing</code></pre>\r\n<p><code>destroyCrops</code> updates database with new amount of biological matter in store for the faction and records amount of destruction in <code>CropsDestroyed</code>. <code>tell</code> requires that we have <code>Writer</code> at our disposal and makes recording information nice and easy.</p>\r\n<pre><code>destroyCrops :: ( MonadIO m, PersistQueryWrite backend, BaseBackend backend ~ SqlBackend ) =&gt;\r\n                Entity Faction -&gt; RawResource Biological\r\n                -&gt; RawResource Biological -&gt; MaybeT (WriterT [KragiiResults] (ReaderT backend m)) ()\r\ndestroyCrops faction cost bioLeft = MaybeT $ do\r\n    _ &lt;- lift $ updateWhere [ FactionId ==. entityKey faction ]\r\n                            [ FactionBiologicals =. unRawResource bioLeft ]\r\n    tell [ CropsDestroyed cost ]\r\n    return $ Just ()</code></pre>\r\n<p>Final step is to roll a percentile die against given odds and see what happens. In case of <code>Success</code>, we record that worms were removed and value of function will be <code>Just RemoveOriginalEvent</code>. If we didn’t beat the odds, <code>WormsStillPresent</code> gets recorded and value of function is <code>Just KeepOriginalEvent</code>. Return value will then be used later to mark special event handled.</p>\r\n<pre><code>removeNews :: ( PersistStoreWrite backend, MonadIO m, BaseBackend backend ~ SqlBackend ) =&gt;\r\n              PercentileChance -&gt; MaybeT (WriterT [KragiiResults] (ReaderT backend m)) EventRemoval\r\nremoveNews odds = MaybeT $ do\r\nres &lt;- liftIO $ roll odds\r\n    case res of\r\n        Success -&gt; do\r\n            _ &lt;- tell [ WormsRemoved ]\r\n            return $ Just RemoveOriginalEvent\r\n        Failure -&gt; do\r\n            _ &lt;- tell [ WormsStillPresent ]\r\n            return $ Just KeepOriginalEvent</code></pre>\r\n<p>So result of this whole matter is:</p>\r\n<pre><code>( [KragiiResults], Maybe EventRemoval )</code></pre>\r\n<p>and whole lot of database activity.</p>\r\n<h2 id=\"handling-events-during-simulation\">Handling events during simulation</h2>\r\n<p>Pieces are now in place, time to put things in motion. When handling special events for a faction, first step is to load all unhandled ones and then call <code>handleSpecialEvent</code> for each of them.</p>\r\n<pre><code>handleFactionEvents :: (BaseBackend backend ~ SqlBackend\r\n                       , PersistStoreWrite backend, PersistQueryRead backend\r\n                       , PersistQueryWrite backend, MonadIO m) =&gt;\r\n                       Time -&gt; Entity Faction -&gt; ReaderT backend m [Key News]\r\nhandleFactionEvents date faction = do\r\n    loadedMessages &lt;- selectList [ NewsFactionId ==. (entityKey faction)\r\n                                 , NewsSpecialEvent ==. UnhandledSpecialEvent ] [ Desc NewsDate ]\r\n    let specials = mapMaybe extractSpecialNews $ parseNewsEntities loadedMessages\r\n    mapM (handleSpecialEvent (entityKey faction) date) specials</code></pre>\r\n<p><code>resolveEvent</code> resolves event based on choice user maybe made (this is what we explored earlier in the episode). Depending on the result of <code>resolveEvent</code>, event gets marked to handled and dismissed. In any case, a news article spelling out what happend is created and saved.</p>\r\n<pre><code>handleSpecialEvent :: (PersistQueryWrite backend, MonadIO m\r\n                      , BaseBackend backend ~ SqlBackend) =&gt;\r\n                      Key Faction -&gt; Time -&gt; (Key News, SpecialNews) -&gt; ReaderT backend m (Key News)\r\nhandleSpecialEvent fId date (nId, (KragiiWorms event _ choice)) = do\r\n    (removal, results) &lt;- resolveEvent (nId, event) choice\r\n    _ &lt;- when (removal /= Just KeepOriginalEvent) $\r\n                    updateWhere [ NewsId ==. nId ]\r\n                                [ NewsSpecialEvent =. HandledSpecialEvent\r\n                                , NewsDismissed =. True ]\r\n    insert $ report fId date event choice results</code></pre>\r\n<p>Result article creation is abstracted by <code>ResultReport</code> type class. It has single function <code>report</code> that takes parameters: database key of the faction the event concerns of, current time, special event that was processed, choice that was made and list of records telling what happened during resolution. It will return <code>News</code> that is ready to be saved into database.</p>\r\n<pre><code>class ResultsReport a b c | a -&gt; b, a -&gt; c where\r\nreport :: Key Faction -&gt; Time -&gt; a -&gt; Maybe b -&gt; [c] -&gt; News</code></pre>\r\n<ul>\r\n<li>quite long and verbose instance</li>\r\n<li>essentially take event, choice and results and build a string explaining what actually happened</li>\r\n<li>&lt;&gt; is monoid operation for combining things, here used for text</li>\r\n</ul>\r\n<p>Instance declaration is pretty long, because there’s many different cases to account for and by definition they’re all pretty verbose. I have included it in its entirity below, as it might be interesting to glance over and see different kinds of combinations that resolution might create.</p>\r\n<pre><code>instance ResultsReport KragiiWormsEvent KragiiWormsChoice KragiiResults where\r\n    report fId date event choice results =\r\n        let\r\n            content = KragiiNews { kragiiNewsPlanetId = kragiiWormsPlanetId event\r\n                                 , kragiiNewsPlanetName = kragiiWormsPlanetName event\r\n                                 , kragiiNewsSystemId = kragiiWormsSystemId event\r\n                                 , kragiiNewsSystemName = kragiiWormsSystemName event\r\n                                 , kragiiNewsExplanation = repText\r\n                                 , kragiiNewsDate = timeCurrentTime date\r\n                                 }\r\n        in\r\n            mkNews fId date $ KragiiResolution content\r\n        where\r\n            repText = header choice &lt;&gt; &quot; &quot; &lt;&gt; removed choice (WormsRemoved `elem` results) &lt;&gt; &quot; &quot; &lt;&gt; injury &lt;&gt; &quot; &quot; &lt;&gt; destruction &lt;&gt; &quot; &quot;\r\n\r\n            header (Just EvadeWorms) = &quot;Local farmers had chosen to work on their fields, while avoiding the kragii worms.&quot;\r\n            header (Just AttackWorms) = &quot;Local farmers had decided to attack the worms with chemicals and burning.&quot;\r\n            header (Just TameWorms) = &quot;Decision to try and tame the kragii had been taken.&quot;\r\n            header Nothing = &quot;No decision what to do about worms had been taken.&quot;\r\n\r\n            removed (Just EvadeWorms) True = &quot;After some time, there has been no new kragii sightings and it seems that the threat is now over.&quot;\r\n            removed (Just AttackWorms) True = &quot;Attacks seem to have worked and there has been no new kragii sightings.&quot;\r\n            removed (Just TameWorms) True = &quot;Kragii has been tamed and put into use of improving soil quality.&quot;\r\n            removed Nothing True = &quot;Despite farmers doing nothing at all about the situation, kragii worms disappeared eventually.&quot;\r\n            removed (Just EvadeWorms) False = &quot;Kragii are still present on the planet and hamper farming operations considerability.&quot;\r\n            removed (Just AttackWorms) False = &quot;Despite the best efforts of farmers, kragii threat is still present.&quot;\r\n            removed (Just TameWorms) False = &quot;Taming of the worms was much harder than anticipated and they remain wild.&quot;\r\n            removed Nothing False = &quot;While farmers were debating best course of action, kragii reigned free and destroyed crops.&quot;\r\n\r\n            injury = if FarmersInjured `elem` results\r\n                        then &quot;Some of the personnel involved in the event were seriously injured.&quot;\r\n                        else &quot;There are no known reports of personnel injuries.&quot;\r\n\r\n            totalDestroyed = mconcat $ map (x -&gt; case x of\r\n                                                    CropsDestroyed n -&gt; n\r\n                                                    _ -&gt; mempty) results\r\n            destruction = if totalDestroyed &gt; RawResource 0\r\n                            then &quot;In the end, &quot; &lt;&gt; pack (show (unRawResource totalDestroyed)) &lt;&gt; &quot; units of harvest was destroyed.&quot;\r\n                            else &quot;Despite of all this, no harvest was destroyed.&quot;</code></pre>\r\n<p>While there are still pieces left that need a bit work or are completely missing, the overall structure is in place. While this one took quite a bit of work to get working, I’m hoping that the next special event will be a lot easier to implement. Thanks for listening the episode.</p>\r\n<p>Easiest way to catch me nowdays is either via email or on fediverse where I’m Tuula@mastodon.social</p>\r\n',364,107,0,'CC-BY-SA','haskell, yesod',0,0,1),
(2743,'2019-02-06','Character build in the d20 system',3949,'Klaatu and Lostnbronx build an RPG character in the d20 system of Starfinder','<p>Klaatu and Lostnbronx spend an hour building an RPG character at a leisurely, and hopefully informative, pace. While the build process here is technically specific to the sci-fi (or science fantasy, really) game Starfinder, the idea is to convey the generic process of stepping through a character build instruction, cross-referencing important rules, and generally learning how to build a character in an unfamiliar system.\r\n</p>',78,99,0,'CC-BY-SA','Starfinder,RPG,character,build',0,0,1),
(2749,'2019-02-14','Lostnbronx and Klaatu commentary from episode 2743',890,'Thoughts about RPG character building, modern RPG play style compared to the Old School, and more','<p>\r\nOut-takes from episode 2743. This is commentary about modern RPG play style, the character build process, Starfinder as a system, and more.\r\n</p>\r\n<p>\r\nDid you know that Lostnbronx and Klaatu have a gaming blog? We do! You should go subscribe to it at <a href=\"https://mixedsignals.ml\" target=\"_blank\">mixedsignals.ml</a></p>\r\n\r\n<p>The blog features commentary about gaming, tech, geek culture, a podcast or two, and lots more.</p>',78,0,0,'CC-BY-SA','rpg, game, gaming',0,0,1),
(2751,'2019-02-18','Battling with English - part 3',822,'Misunderstandings about English grammar, spelling, punctuation, etc.','<h1 id=\"battling-with-english---part-3\">Battling with English - part 3</h1>\r\n<h2 id=\"some-word-confusions\">Some word confusions</h2>\r\n<p>In this episode, the third of this series, I’m looking at some words that are sometimes used in the wrong places, often being confused one with another. These words are often particularly difficult to differentiate by people for whom <a href=\"https://www.englishpractice.com/common-mistakes\" title=\"English Practice - Common Mistakes\">English is not their first language</a>.</p>\r\n<h2 id=\"long-notes\">Long notes</h2>\r\n<p>As usual I have provided detailed notes and examples for this episode, and these can be <a href=\"https://hackerpublicradio.org/eps/hpr2751/full_shownotes.html\">viewed here</a>.</p>\r\n<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li>Been:\r\n<ul>\r\n<li>Oxford Dictionaries: <a href=\"https://en.oxforddictionaries.com/definition/been\">Definition of “been”</a></li>\r\n<li>Online Etymology Dictionary: <a href=\"https://www.etymonline.com/word/been\">“been”</a></li>\r\n</ul></li>\r\n<li>Being:\r\n<ul>\r\n<li>Oxford Dictionaries: <a href=\"https://en.oxforddictionaries.com/definition/being\">Definition of “being”</a></li>\r\n<li>Online Etymology Dictionary: <a href=\"https://www.etymonline.com/word/being\">“being”</a></li>\r\n</ul></li>\r\n<li>Been versus Being\r\n<ul>\r\n<li><a href=\"https://www.englishpractice.com/common-mistakes/difference-9/\">English Practice - Difference between being and been</a></li>\r\n</ul></li>\r\n<li>Examples of the use of Being:\r\n<ul>\r\n<li><a href=\"https://sentence.yourdictionary.com/being\">Example sentences using <em>being</em></a></li>\r\n</ul></li>\r\n</ul>\r\n<ul>\r\n<li>Weather:\r\n<ul>\r\n<li>Oxford Dictionaries: <a href=\"https://en.oxforddictionaries.com/definition/weather\">Definition of “weather”</a></li>\r\n<li>Online Etymology Dictionary: <a href=\"https://www.etymonline.com/word/weather\">“weather”</a></li>\r\n</ul></li>\r\n<li>Wether:\r\n<ul>\r\n<li>Oxford Dictionaries: <a href=\"https://en.oxforddictionaries.com/definition/wether\">Definition of “wether”</a></li>\r\n<li>Online Etymology Dictionary: <a href=\"https://www.etymonline.com/word/wether\">“wether”</a></li>\r\n</ul></li>\r\n<li>Whether:\r\n<ul>\r\n<li>Oxford Dictionaries: <a href=\"https://en.oxforddictionaries.com/definition/whether\">Definition of “whether”</a></li>\r\n<li>Online Etymology Dictionary: <a href=\"https://www.etymonline.com/word/whether\">“whether”</a></li>\r\n</ul></li>\r\n<li>Wither:\r\n<ul>\r\n<li>Oxford Dictionaries: <a href=\"https://en.oxforddictionaries.com/definition/wither\">Definition of “wither”</a></li>\r\n<li>Online Etymology Dictionary: <a href=\"https://www.etymonline.com/word/wither\">“wither”</a></li>\r\n</ul></li>\r\n<li>Whither:\r\n<ul>\r\n<li>Oxford Dictionaries: <a href=\"https://en.oxforddictionaries.com/definition/whither\">Definition of “whither”</a></li>\r\n<li>Online Etymology Dictionary: <a href=\"https://www.etymonline.com/word/whither\">“whither”</a></li>\r\n</ul></li>\r\n<li>Weather, wether, and the rest:\r\n<ul>\r\n<li><a href=\"https://grammarist.com/usage/wither-whither/\">Grammarist</a></li>\r\n<li><a href=\"https://www.grammar-monster.com/easily_confused/weather_whether_wether.htm\">Grammar Monster</a></li>\r\n</ul></li>\r\n</ul>\r\n<ul>\r\n<li>Previous episodes in this series:\r\n<ul>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2558\">Battling with English - part 1</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2596\">Battling with English - part 2</a></li>\r\n</ul></li>\r\n</ul>',225,120,1,'CC-BY-SA','grammar,spelling,punctuation,word misuse,English',0,0,1),
(3857,'2023-05-16','Yesterday I saw a solar flare',668,'An account of the first time I saw a solar flare with my own eyes.','<p>A solar flare is a huge release of energy at and near the surface of the Sun in the form of electromagnetic radiation and fast particles. On 19 January 2023 at around 11:00 UTC I was lucky enough to see a solar flare with my own eyes using a <a href=\"https://www.meadeuk.com/Coronado-Personal-Solar-Telescope-PST.html\">Coronado PST Solar Telescope</a> that belongs to the <a href=\"https://theasg.org.uk/\">Astronomical Society of Glasgow</a>.</p>\n\n<p>This audio was recorded the day after I had seen it so the details remained fresh in my mind.</p>\n\n<p>A view of how the Sun appears through the Coronado PST H&alpha; telescope taken with the main camera of Samsung Galaxy S9+ phone at the eyepiece, after much trial and error! This was taken on 20 January 2023 at 13:08 UTC the day after the flare. The enormous sun spot is still visible.</p>\n<p><a href=\"https://hackerpublicradio.org/eps/hpr3857/20230120_111458_1.jpg\"><img src=\"https://hackerpublicradio.org/eps/hpr3857/20230120_111458_1_thumbnail.jpg\" title=\"The enormous sun spot is still visible on 20 January 2023 at 13:08 UTC.\" alt=\"Sunspot\" /></a></p>\n<!-- INSERT 20230120_111458_1.jpg -->\n\n<p>The X-ray flux from the Sun measured by the <a href=\"https://www.swpc.noaa.gov/products/goes-x-ray-flux\">GOES satellite(s)</a>.</p>\n<p><a href=\"https://hackerpublicradio.org/eps/hpr3857/goes_190123.png\"><img src=\"https://hackerpublicradio.org/eps/hpr3857/goes_190123_thumbnail.png\" title=\"The X-ray flux from the Sun\" alt=\"X-ray flux\" /></a></p>\n<!-- INSERT goes_190123.png -->\n\n<p>A short movie of images covering the period from 10:01 UTC to 11:21 UTC  observed by the <a href=\"https://sdo.gsfc.nasa.gov/data/\">SDO satellite\'s AIA instrument</a>.</p>\n<video controls width=\"800\">\n<source src=\"https://hackerpublicradio.org/eps/hpr3857/2023_01_19_10_01_17_2023_01_19_11_21_41_AIA_304-hq.mp4\" type=\"video/mp4\">\nYour browser does not support the video tag.\n</video>\n<!-- INSERT  2023_01_19_10_01_17_2023_01_19_11_21_41_AIA_304-hq.mp4 -->\n',268,0,0,'CC-BY-SA','solar,astronomy,telescopes,planes',0,0,1),
(2752,'2019-02-19','XSV for fast CSV manipulations - Part 2',1359,'Part 2 of my introduction to the XSV tool','<h1 id=\"xsv-for-fast-csv-manipulations---part-1-basic-usage\">XSV for fast CSV manipulations - Part 1: Basic Usage</h1>\r\n<blockquote>\r\n<p><a href=\"https://github.com/BurntSushi/xsv\" class=\"uri\">https://github.com/BurntSushi/xsv</a></p>\r\n</blockquote>\r\n<h2 id=\"introduction\">Introduction</h2>\r\n<p>xsv is a command line program for indexing, slicing, analyzing, splitting and joining CSV files. Commands should be simple, fast and composable:</p>\r\n<ol>\r\n<li>Simple tasks should be easy.</li>\r\n<li>Performance trade offs should be exposed in the CLI interface.</li>\r\n<li>Composition should not come at the expense of performance.</li>\r\n</ol>\r\n<p>We will be using the CSV file provided in the <a href=\"https://burntsushi.net/stuff/worldcitiespop.csv\">documentation</a>.</p>\r\n<h2 id=\"commands-covered-in-this-episode\">Commands covered in this episode</h2>\r\n<ul>\r\n<li><strong>fixedlengths</strong> - Force a CSV file to have same-length records by either padding or truncating them.</li>\r\n<li><strong>fmt</strong> - Reformat CSV data with different delimiters, record terminators or quoting rules. (Supports ASCII delimited data.)</li>\r\n<li><strong>input</strong> - Read CSV data with exotic quoting/escaping rules.</li>\r\n<li><strong>partition</strong> - Partition CSV data based on a column value.</li>\r\n<li><strong>split</strong> - Split one CSV file into many CSV files of N chunks.</li>\r\n<li><strong>sample</strong> - Randomly draw rows from CSV data using reservoir sampling (i.e., use memory proportional to the size of the sample).</li>\r\n<li><strong>cat</strong> - Concatenate CSV files by row or by column.</li>\r\n</ul>\r\n',300,0,0,'CC-BY-SA','csv,command-line,data',0,0,1),
(2759,'2019-02-28','Cleaning the Potentiometers on a Peavey Bandit 65',1244,'I disassemble and clean the pots on my Peavey Bandit 65 to fix static in the knobs.','<p>Since my daughter has been learning a bit of guitar in the last several months, I\'ve actually gotten my old electric guitar and amplifier back out again after many years in the closet. The amp is a Peavey Bandit 65, which was a an affordable solid-state workhorse kind of amp back in the mid-80s and I\'ve had it since it was new. In this episode I talk through the process of removing the brains of the amp and cleaning the potentiometers to try to get rid of some of the static that\'s happening when I turn the knobs. I also discover belatedly that the reason I was not getting any distortion when I turned the saturation up was that the amp was stuck on the clean channel — shows how long it\'s been since I used the amp, I kind of forgot how the thing works!</p>\r\n\r\n<p>Click image below to view photo gallery</p>\r\n\r\n<p><a href=\"https://www.flickr.com/photos/137675441@N05/albums/72157706214884694\" title=\"Peavey Bandit 65 Cleaning\" target=\"_blank\"><img src=\"https://hackerpublicradio.org/eps/hpr2759.jpg\" alt=\"Peavey Bandit 65 Cleaning\"></a></p>\r\n\r\n<h2>Links</h2>\r\n\r\n<ul>\r\n	<li><a href=\"https://peavey.com/\">Peavey Electronics Corporation</a></li>\r\n	<li><a href=\"https://www.fender.com/products/electric-guitars/stratocaster\">The Fender Stratocaster</a></li>\r\n</ul>\r\n\r\n<h2>Credits</h2>\r\n\r\n<ul>\r\n	<li>Music bumpers are from Kimiko Ishizaka\'s <em>The Open Goldberg Variations</em>: <a href=\"https://www.opengoldbergvariations.org/\">https://www.opengoldbergvariations.org/</a>, used by permission of their <a href=\"https://creativecommons.org/publicdomain/zero/1.0/\">CC0 1.0 Universal (CC0 1.0) Public Domain Dedication license</a>.</li>\r\n</ul>',238,0,0,'CC-BY-SA','Guitars, electronics, amplifiers, maintenance, repair',0,0,1),
(2753,'2019-02-20','Specific Settings In Storytelling',1027,'Lostnbronx looks at why you might choose specific settings for your tales.','<p>How does setting interact with plot or character? Why would you choose one type of setting over another? And how do certain specific settings become intrinsic aspects of the story itself?</p>\r\n<p>Lostnbronx takes a breezy, mostly incoherent stab at this rather complicated topic.</p>\r\n',107,105,0,'CC-BY-SA','stories, storytelling, setting, lostnbronx',0,0,1),
(2758,'2019-02-27','Haskell - Data types and database actions',2566,'Brief summary of how to declare your own datatypes in Haskell and how to store data in database','<h2 id=\"intro\">Intro</h2>\r\n<p>I have been doing series about web programming in Haskell and realized that I might have skipped over some very basic details. Better later than never, I’ll go over some of them briefly (data types and database actions). Hopefully things will make more sense after this (like with my friend, whose last programming course was programming 101 and they said afterwards that now all that 3d and game programming is suddenly making sense).</p>\r\n<h2 id=\"data-types\">Data types</h2>\r\n<p>Data here has nothing to do with databases (yet). This is how you can declare your own data types in Haskell. They’re declared with keyword <code>data</code> followed with type name, equals sign and one or more value constructors. Type name and value constructors have to start with uppercase letter.</p>\r\n<p>Simplest type is following:</p>\r\n<pre><code>data Simple = One</code></pre>\r\n<p>This declares a type called <code>Simple</code> that has single possible value: <code>One</code>.</p>\r\n<p>More interesting type is shown below. <code>Colour</code> has three possible values: <code>Red</code>, <code>Green</code> and <code>Blue</code>.</p>\r\n<pre><code>data Colour =\r\n    Red\r\n    | Green\r\n    | Blue</code></pre>\r\n<p>It’s possible to have parameters in value constructor. Following is <code>Payment</code> type that could be used to indicate how payment was done. In case of <code>Cash</code> amount is stored. In case of <code>IOU</code> free text is recorded.</p>\r\n<pre><code>data Payment =\r\n    Cash Double\r\n    | IOU Text</code></pre>\r\n<p>Fictional usage of the <code>Payment</code> is shown below. Function <code>paymentExplanation</code> takes a <code>Payment</code> as parameter and returns <code>Text</code> describing the payment. In case of cash payment, brief explanation of how much was paid is returned. In case of IOU slip the function returns explanation stored in <code>IOU</code> value.</p>\r\n<p><code>paymentExplanation :: Payment -&gt; Text</code> part is type declaration. It states that <code>paymentExplanation</code> takes argument of type <code>Payment</code> and returns result as <code>Text</code>.</p>\r\n<pre><code>paymentExplanation :: Payment -&gt; Text\r\npaymentExplanation payment =\r\n    case payment of\r\n        Cash amount -&gt;\r\n            &quot;Cash payment of &quot; &lt;&gt; (show amount) &lt;&gt; &quot; euros&quot;\r\n        IOU explanation -&gt;\r\n            explanation</code></pre>\r\n<p>Parameters don’t have to be hard coded in the type definition. Parametrized types allows creating more general code. <code>Maybe</code> is very useful data type that is often used for data that might or might not be present. It can have two values: <code>Nothing</code> indicating that there isn’t value and <code>Just a</code> indicating that value is present.</p>\r\n<pre><code>data Maybe a =\r\n    Nothing\r\n    | Just a</code></pre>\r\n<p><code>a</code> is type parameter that is filled in when declaring type. Below is a function that takes <code>Maybe Payment</code> as a parameter and if value of <code>payment</code> parameter is <code>Just</code> returns explanation of it (reusing the function we declared earlier). In case of <code>Nothing</code> <code>&quot;No payment to handle&quot;</code> is returned.</p>\r\n<pre><code>invoice :: Maybe Payment -&gt; Text\r\ninvoice payment =\r\n    case payment of\r\n        Just x -&gt;\r\n            paymentExplanation x\r\n        Nothing -&gt;\r\n            &quot;No payment to handle&quot;</code></pre>\r\n<p>Alternatively one can omit <code>case</code> expression as shown below and write different value constructors directly as parameters. In both cases, compiler will check that programmer has covered all cases and emit a warning if that’s not the case.</p>\r\n<pre><code>invoice :: Maybe Payment -&gt; Text\r\ninvoice (Just payment) =\r\n    paymentExplanation payment\r\n\r\ninvoice Nothing =\r\n    &quot;No payment to handle&quot;</code></pre>\r\n<p>Having several parameters gets soon unwieldy, so lets introduce records. With them, fields have names that can be used when referring to them (either when creating or when accessing the data). Below is <code>Person</code> record with two fields. <code>personName</code> is of type <code>Text</code> and <code>personAge</code> of type <code>Age</code> (that we’ll define in the next step).</p>\r\n<pre><code>data Person = Person\r\n    { personName :: Text\r\n    , personAge :: Age\r\n    }</code></pre>\r\n<p>To access data in a record, just use field as a function (there’s a bug, I’m turning 40, this month (today even, to be specific, didn’t realize this until I was about to upload the episode), but forgot such a minor detail when recording the episode):</p>\r\n<pre><code>me = Person { personName = &quot;Tuukka&quot;, personAge = 37 }\r\nmyAge = personAge me\r\nmyName = personName me</code></pre>\r\n<p>New type is special type of record that can has only one field. It is often used to make sure one doesn’t mix similar data types (shoe size and age can both be Ints and thus mixed if programmer isn’t being careful). Compiler will optimize new types away during compilation, after checking that they’re being used correctly. This offers a tiny performance boost and makes sure one doesn’t accidentally mix different things that happen to look similar.</p>\r\n<pre><code>newtype Age = { getAge :: Int }</code></pre>\r\n<p>One can instruct compiler to derive some common functions for the data types. There are quite many of these, but the most common ones I’m using are <code>Show</code> (for turning data into text), <code>Read</code> (turning text into data) and <code>Eq</code> (comparing equality).</p>\r\n<pre><code>data Payment =\r\n    Cash Double\r\n    | IOU Text\r\n    deriving (Show, Read, Eq)</code></pre>\r\n<h2 id=\"database\">Database</h2>\r\n<p>In case of Yesod and Persistent, database structure is defined in models file that usually located in config directory. It is read during compile time and used to generate data types that match the database. When the program starts up, it can check structure of the database and update it to match the models file, if migrations are turned on. While this is handy for development, I wouldn’t dare to use it for production data.</p>\r\n<p>Following definitions are lifted from the models file of the game I’m working.</p>\r\n<pre><code>StarSystem\r\n    name Text\r\n    coordX Int\r\n    coordY Int\r\n    deriving Show Read Eq</code></pre>\r\n<p>This defines a table <code>star_system</code> with columns <code>id</code>, <code>name</code>, <code>coord_x</code>, <code>coord_y</code>. All columns have <code>NOT NULL</code> constraint on them. It also defines record <code>StarSystem</code> with fields <code>starSystemName</code>, <code>starSystemCoordX</code> and <code>starSystemCoordY</code>.</p>\r\n<pre><code>Star\r\n    name Text\r\n    starSystemId StarSystemId\r\n    spectralType SpectralType\r\n    luminosityClass LuminosityClass\r\n    deriving Show Read Eq</code></pre>\r\n<p>This works in the same way and defines table <code>star</code> and record <code>Star</code>. New here is column <code>star_system_id</code> that has foreign key constraint linking it to <code>star_system</code> table. <code>Star</code> record has field <code>starStarSystemId</code> (silly name, I know, but that’s how the generated names go), which has type <code>Key StarSystem</code>.</p>\r\n<p><code>spectral_type</code> and <code>luminosity_class</code> columns in the database are textual (I think <code>VARCHAR</code>), but in the code they’re represented with <code>SpectralType</code> and <code>LuminosityClass</code> data types. In order this to work, we have to define them as normal data types and use <code>derivePersistField</code> that generates extra code needed to store them as text in database:</p>\r\n<pre><code>data SpectralType = O | B | A | F | G | K | M | L | T\r\n    deriving (Show, Read, Eq)\r\nderivePersistField &quot;SpectralType&quot;\r\n\r\ndata LuminosityClass = Iap | Ia | Iab | Ib | II | III | IV | V | VI | VII\r\n    deriving (Show, Read, Eq)\r\nderivePersistField &quot;LuminosityClass&quot;</code></pre>\r\n<p>Final piece in the example is <code>Planet</code>:</p>\r\n<pre><code>Planet\r\n    name Text\r\n    position Int\r\n    starSystemId StarSystemId\r\n    ownerId FactionId Maybe\r\n    gravity Double\r\n    SystemPosition starSystemId position\r\n    deriving Show Read Eq</code></pre>\r\n<p>This introduces two new things: <code>ownerId FactionId Maybe</code> removes <code>NOT NULL</code> constraint for this column in the database, allowing us to omit storing a value there. It also changes type of <code>planetOwnerId</code> into <code>Maybe (Key Faction)</code>. Thus, planet might or might not have an owner, but if it has, database ensures that the link between <code>planet</code> and <code>faction</code> (not shown here) is always valid.</p>\r\n<p>Second new thing is <code>SystemPosition starSystemId position</code> that creates unique index on columns <code>star_system_id</code> and <code>position</code>. Now only one planet can exists on any given position in a star system.</p>\r\n<p>Database isn’t any good, if we can’t insert any data into it. We can do that with a function shown below, that create a solar system with a single planet:</p>\r\n<pre><code>createSolarSystem = do\r\n    systemId &lt;- insert $ StarSystem &quot;Solar system&quot; 0 0\r\n    starId &lt;- insert $ Star &quot;Sol&quot; systemId G V\r\n    planetId &lt;- insert $ Planet &quot;Terra&quot; 3 systemId Nothing 1.0\r\n    return (systemId, starId, planetId)</code></pre>\r\n<p>To use the function, we have to use <code>runDB</code> function that handles the database transaction:</p>\r\n<pre><code>res &lt;- runDB createSolarSystem</code></pre>\r\n<p>There are various ways of loading data from database. For loading a list of them, <code>selectList</code> is used. Here we’re loading all planets that have gravity exactly 1.0 and ordering results by the primary key in ascending order:</p>\r\n<pre><code>planets &lt;- runDB $ selectList [ PlanetGravity ==. 1.0 ] [ Asc PlanetId ]</code></pre>\r\n<p>Loading by primary key is done with <code>get</code>. It returns <code>Maybe</code>, because data might or might be present that match the primary key. Programmer then has to account both cases when handling the result:</p>\r\n<pre><code>planet &lt;- runDB $ get planetId</code></pre>\r\n<p>Updating a specific row is done with <code>update</code> function (<code>updateWhere</code> is for multiple rows):</p>\r\n<pre><code>_ &lt;- runDB $ update planetId [ PlanetName =. &quot;Earth&quot; ]</code></pre>\r\n<p>Finally, sometimes it’s nice to be able to delete the data:</p>\r\n<pre><code>_ &lt;- runDB $ delete planetId\r\n_ &lt;- runDB $ deleteWhere [ PlanetGravity &gt;. 2 ]</code></pre>\r\n<p>While persistent is relatively easy to use after you get used to it, it lacks ability to do joins. In such cases one can use library called Esqueleto, that is more powerful and has somewhat more complex API.</p>\r\n<h2 id=\"extra\">Extra</h2>\r\n<p>Because functions are values in Haskell, nothing prevents storing them in data types:</p>\r\n<pre><code>data Handler =\r\n    Simple (Int -&gt; Boolean)\r\n    | Complex (Int -&gt; Int -&gt; Int)</code></pre>\r\n<p><code>Handler</code> type has two possible values: <code>Simple</code> has a function that turns <code>Int</code> into <code>Boolean</code> (for example <code>odd</code> used to check if given number is odd) and <code>Complex</code> that takes two values of type <code>Int</code> and returns <code>Int</code> (basic arithmetic for example, adding and subtracting).</p>\r\n<p>Hopefully this helps you to follow along as I work on the game.</p>\r\n<p>Easiest way to catch me nowadays is either via email or on fediverse where I’m Tuula@mastodon.social</p>\r\n',364,107,0,'CC-BY-SA','haskell, database',0,0,1),
(2754,'2019-02-21','Craigslist Scam Catch',460,'Helped a client avoid being scammed on Craigslist and wanted to share some tips to HPR.','<h2 id=\"introduction\">Introduction</h2>\r\n<p>Hello and welcome to Hacker Public Radio, I’m Edward Miro and for this episode I decided to record on a personal experience I had recently helping a client catch a Craigslist Scam. This will be part two in my series I’m calling “Information Security for Everyone”. As with most of the content I publish in the world of INFOSEC, my goal is to present the information in a way that a majority of people can get value from and anyone can play this for a friend, colleague or family member and make it easy for the non-hackers in our lives to understand. This particular episode shows a powerful way social-engineering can be implemented to steal money from unsuspecting victims and I will break down a few main points and red flags to look out for at the end.</p>\r\n<p>A couple weeks ago I was sitting with a client when she asked me offhandedly if I’d ever sent a Moneygram before. I told her I had and ask curiously why she wanted to know. She explained that she was very excited to be adopting a puppy from online and she needed to send $350 USD to the service that ships pets across the country. This immediately caused my hacker-sense to start tingling so I probed a bit more about the transaction.</p>\r\n<p>I asked if she had spoken to the seller on the phone, and she said she hadn’t. I said that seemed weird, but she assured me that the seller said it had to do with her religion. I wasn’t aware of any religious prohibitions to speaking on the phone that also allowed using Craigslist, but okay. I told her that that seemed a bit fishy to me. She asserted that she thought it did too at first, but she knew it was legit because she wasn’t sending the money to the seller, it was being sent to a third party pet transportation company that the seller had had contact her. She even showed the website of the company on her cell phone, which to be blunt, to my eyes looked extremely janky. I asked her if we could sit down for a few minutes and take a look at a few details before she sends anyone any money. She reluctantly agreed and really wanted this puppy.</p>\r\n<p>The first thing I asked to look at was the emails back and forth from the seller. I checked Google and all other major social media sites for the sellers name. No matches. Couldn’t Google the sellers email address due to the Craigslist email relay system. This in and of itself might be okay, we all use pseudonyms online sometimes and Craigslist is a site you might not wanna use your real name. Fine.</p>\r\n<p>She then showed me the email thread with the shipping company.</p>\r\n<p>The first strange thing I noticed from the emails was the link to the pet shipping company. The name didn’t match the URL in the link. You’d think a business would be able to get their own name right. I also saw that if you Googled the name given by the shipper, it’s extremely similar to a legitimate pet shipping company and indeed that legit company comes up as the first site found due to Google “fixing” our query. When you go to the link in the email however, the site itself was terrible to my eyes, but not to my client who is not as seasoned as I am at catching scams. I also showed her that the “company” didn’t have any social media presence. At all. No Facebook, Twitter, anything. Also the email address that was contacting her was <code>reallylongcompanyname@outlook.com</code></p>\r\n<p>She also told me she had spoken to the shippers on the phone and I asked if she still had their number. She did, but she told me she couldn’t ever get through when she called them and they’d always have to call her back. I asked for the number and called it on my phone. It was a Google Voice number! Not only that it was set to screening mode. She also told me when he did call her, he was rude and tried to get her to hurry up and send the money. I told her I was 100% confident this was a scam and I advised her to not go through with the deal.</p>\r\n<p>At this point she was extremely unhappy, but felt it was still a legitimate transaction because she had pictures sent to her of not only the puppy, but of the puppy in the shipping crate at the shipping company waiting for payment to be shipped. She explained that it’s not like it was a person trying to sell dogs or from a puppy mill. It was a lady giving it away for free and the money was for was the shipping. She just didn’t see why a scammer would go to the trouble of doing that and felt the pictures were authentic. I asked her to save all the images to her device and then showed her a site she could use to do reverse image searches. Before she did it, I asked her if she agreed that if this wasn’t a scam those pictures wouldn’t exist anywhere on the internet. She agreed and each of the pictures was found at least 9 other places online. Her heart sank and she didn’t have any further rebuttals to my concerns. She knew it was a scam and I just saved her from losing at least $350 USD. Not to mention that the scammer would have also asked for more money later for “shots” and “insurance”. Who knows how far they might have gotten.</p>\r\n<p>So here are the main red flags:</p>\r\n<ul>\r\n<li>Seller wouldn’t talk on phone</li>\r\n<li>Seller name didn’t seem legitimate</li>\r\n<li>Name of shipping company didn’t match URL in email</li>\r\n<li>Googling company name shows close match with legitimate company</li>\r\n<li>Company website very poorly designed and implemented</li>\r\n<li>Company has no social media presence</li>\r\n<li>Email address of contact at company using generic email address and not a legit domain</li>\r\n<li>Contact at company could only call her and she was never able to make inbound calls</li>\r\n<li>Phone number of company was Google Voice number</li>\r\n<li>Reverse image searches showed “proof” photos unoriginal</li>\r\n</ul>\r\n<p>A few of the tricks used by the scammers in this scam to make it more successful:</p>\r\n<ul>\r\n<li>Listed as adoption versus a sale to alleviate concern</li>\r\n<li>Handed off to “second party” to build legitimacy</li>\r\n<li>Use cute puppy pictures to appeal to emotion and overrule suspicion</li>\r\n<li>Counted on target not paying attention to detail</li>\r\n<li>Shipper established a sense of urgency</li>\r\n</ul>\r\n<p>She was very thankful and I told her to be very careful when anyone from online ever asks her to send money. I told her in all likelihood this was probably one person the whole time, hence why the person adopting out the dog “couldn’t talk on the phone”. They were also probably not even in this country as we know many of these scams aren’t. She did say that the shippers English wasn’t good. I also told her to make she shares this experience with all her friends and family. I always feel the best way to handle someone getting caught in a scam is to be on their side and never shame them. We are all susceptible to scams and social engineering and the best way to proceed is to empower them to share what they’ve learned. I also sent her a link to an article on the BBB site about these very types of scams that I’ll also link below. She was shocked how similar her experience was to the ones explained on the article.</p>\r\n<p>Well, thank you for taking the time to listen to my experience helping a client avoid getting caught in the all too common Craigslist scam. I hope this will help any non-hackers in your life and like I say in all my podcasts, I don’t claim to know all there is to know and love feedback and any opportunities to learn more or collaborate with others in the field. As with most of the research and articles I’ve written in the past, these are geared toward standard users in a business setting and are meant to be a jumping off point for further research and to be a foundation for cyber security 101 level training classes. If you like what I do, and want to have me come speak to your team, or just wanna chat, feel free to email me.</p>\r\n<p>Thank you and have a great day!</p>\r\n<h2 id=\"links\">Links:</h2>\r\n<p><a href=\"https://www.bbb.org/article/investigations/14214-puppy-scams-how-fake-online-pet-sellers-steal-from-unsuspecting-pet-buyers-a-bbb-study\" class=\"uri\">https://www.bbb.org/article/investigations/14214-puppy-scams-how-fake-online-pet-sellers-steal-from-unsuspecting-pet-buyers-a-bbb-study</a></p>\r\n<p><a href=\"https://www.rover.com/blog/internet-dog-puppy-scams/\" class=\"uri\">https://www.rover.com/blog/internet-dog-puppy-scams/</a></p>\r\n',372,74,1,'CC-BY-SA','craigslist,scam,con,social engineering,puppy,dog,money,moneygram,infosec,cyber-security 101',0,0,1),
(2756,'2019-02-25','Bash Tips - 20',1955,'Deleting arrays; positional and special parameters in Bash','<h2 id=\"tidying-loose-ends-some-collateral-bash-tips\">Tidying loose ends <small><small>(Some collateral Bash tips)</small></small></h2>\r\n<h3 id=\"deleting-arrays\">Deleting arrays</h3>\r\n<p>I forgot to cover one thing on my list when doing the last show: I forgot to explain how to delete arrays and array elements. I’ll cover that topic in this episode.</p>\r\n<h3 id=\"positional-and-special-parameters\">Positional and Special parameters</h3>\r\n<p>I have also avoided talking much about the positional and special parameters in Bash: <code>\'$1\'</code>, <code>\'$2\'</code>, <code>\'$#\'</code> and the rest. I will cover (some of) these in this episode.</p>\r\n<h3 id=\"silly-titles\">Silly titles</h3>\r\n<p>I stopped doing the weird episode titles by episode 14 because I thought the joke was getting tired. However, I think a few people missed them (and a certain HPR colleague was found <em>vandalising my new titles as they were being posted</em> ;-), so I have added them inside the notes on the older shows and am adding one here – as a homage to silliness.</p>\r\n<h2 id=\"long-notes\">Long notes</h2>\r\n<p>I have provided detailed notes as usual for this episode, and these can be <a href=\"https://hackerpublicradio.org/eps/hpr2756/full_shownotes.html\">viewed here</a>.</p>\r\n<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><a href=\"https://www.gnu.org/software/bash/manual/bash.html\">“<em>GNU BASH Reference Manual</em>”</a>\r\n<ul>\r\n<li>Section <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion\">“3.4 Shell Parameters”</a></li>\r\n<li>Section <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Shell-Builtin-Commands\">“4 Shell Builtin Commands”</a>\r\n<ul>\r\n<li>Section <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Bourne-Shell-Builtins\">“4.1 Bourne Shell Builtins”</a></li>\r\n<li>Section <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Bash-Builtins\">“4.2 Bash Builtin Commands”</a></li>\r\n</ul></li>\r\n<li>Section <a href=\"https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin\">“4.3.1 The Set Builtin”</a></li>\r\n</ul></li>\r\n</ul>\r\n<ul>\r\n<li><p>POSIX Shell Command Language: <a href=\"https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset\"><em>unset</em></a></p></li>\r\n<li><p><a href=\"https://hackerpublicradio.org/series/0042.html\">HPR series: <em>Bash Scripting</em></a></p></li>\r\n<li>Previous episodes under the heading <em>Bash Tips</em>:\r\n<ol>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1648\">HPR episode 1648 “<em>Bash parameter manipulation</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1843\">HPR episode 1843 “<em>Some Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1884\">HPR episode 1884 “<em>Some more Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1903\">HPR episode 1903 “<em>Some further Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=1951\">HPR episode 1951 “<em>Some additional Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2045\">HPR episode 2045 “<em>Some other Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2278\">HPR episode 2278 “<em>Some supplementary Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2293\">HPR episode 2293 “<em>More supplementary Bash tips</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2639\">HPR episode 2639 “<em>Some ancillary Bash tips - 9</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2649\">HPR episode 2649 “<em>More ancillary Bash tips - 10</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2659\">HPR episode 2659 “<em>Further ancillary Bash tips - 11</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2669\">HPR episode 2669 “<em>Additional ancillary Bash tips - 12</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2679\">HPR episode 2679 “<em>Extra ancillary Bash tips - 13</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2689\">HPR episode 2689 “<em>Bash Tips - 14 (Some auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2699\">HPR episode 2699 “<em>Bash Tips - 15 (More auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2709\">HPR episode 2709 “<em>Bash Tips - 16 (Further auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2719\">HPR episode 2719 “<em>Bash Tips - 17 (Additional auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2729\">HPR episode 2729 “<em>Bash Tips - 18 (Extra auxiliary Bash tips)</em>”</a></li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2739\">HPR episode 2739 “<em>Bash Tips - 19 (Supplemental auxiliary Bash tips)</em>”</a></li>\r\n</ol></li>\r\n</ul>\r\n<ul>\r\n<li>Resources:\r\n<ul>\r\n<li>Examples: <a href=\"https://hackerpublicradio.org/eps/hpr2756/bash20_ex1.sh\">bash20_ex1.sh</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2756/bash20_ex2.sh\">bash20_ex2.sh</a></li>\r\n</ul></li>\r\n</ul>\r\n',225,42,1,'CC-BY-SA','Bash,array,delete,positional parameters',0,0,1),
(2757,'2019-02-26','How to DM',2694,'Klaatu explains how to DM an RPG, and Lostnbronx demonstrates, step by step, how to build a dungeon','<h2>Klaatu</h2>\r\n<p>\r\nI\'ve gotten a lot of great feedback on the Interface Zero play-through and the episode about getting started with RPGs I did with Lostnbronx.\r\nPeople have told me that one of the biggest blockers to getting started is knowing what to do as GM.</p><p>\r\nNow, I\'ve read lots of rulebooks and GM guides, and it seems to me that most of them assume you\'ve either played an RPG before, and so you\'ve seen an example of a Game Master at play, or you\'ve seen one on Youtube or Twitch. It\'s a safe assumption, but it\'s easy to forget all of those great examples under pressure.\r\nSo in this episode, Lostnbronx and I are going to provide you with some clear and direct instructions on what exactly a GM does.\r\n</p><p>\r\nThe short version is this:</p>\r\n<ol><li><p>\r\nTell the players where they are and what they see around them.\r\n</p></li><li><p>\r\nListen to the players when they tell you what they want to do.\r\n</p></li><li><p>\r\nTell the players the outcome, based on your privileged knowledge of the game world or on a roll of the dice, of their actions.\r\n</p></li></ol>\r\n<p>\r\nYou loop over that sequence, and you\'re game mastering!\r\n</p><p>\r\nBut that makes for a short episode, and anyway, there are details about the process that we can talk about to make you feel more comfortable with the prospect of deciphering a game world with your friends.\r\n</p><p>\r\nTo that end, Lostnbronx and I have started a <a href=\"https://mixedsignals.ml\" target=\"_blank\">website dedicated to gaming</a>&#33; You should check it out, subscribe to our feed. We discuss everything game-related there, plus a little tech and all manner of topics of interest to geeks.\r\n</p>\r\n\r\n<h2>Lostnbronx</h2>\r\n<p>\r\nRight off the bat, it\'s important to understand that every GM is different. No two styles of running a game match completely, nor should they. And while there\'s no one correct way to run a game, there are plenty of ways to do it poorly. The GM wears many hats, but in my opinion, the most important job is to make sure that everyone has a good time. Your players are giving you an evening out of their lives. Next week they\'ll probably give you another. It\'s your job to make sure that time isn\'t wasted.\r\n</p><p>\r\nBy definition, games, even role-playing games, are a form of entertainment -- like reading a book, watching a movie, or enjoying the circus. When you go to that, the GM is the ringmaster, presenting the show; while the players are both the audience, and the main attraction. The GM controls the world, the people, the monsters, the history, even the weather. The GM controls everything, in fact...except for the player characters. A game master presents the situation, but it\'s the players who decide what to do with that information.\r\n</p><p>\r\nNow, this is all pretty vague, and describing RPG\'s is far less informative than playing them. Considering this is a podcast, I encourage you to go back and listen to Klaatu\'s aforementioned \"Interface Zero\" episodes. These are excellent examples of actual game play. If you\'re having a hard time imagining how RPG\'s are presented and experienced, you\'ll appreciate those shows.\r\n</p><p>\r\nNow then, almost all games are divided into genre types: sword and sorcery; space opera; spies; super-heroes; and pretty much everything else. And I mean everything! If there\'s a genre of fiction and storytelling that you enjoy, chances are there\'s a game or game setting for it somewhere. The most popular style of RPG\'s out there are fantasy. Think \"Lord of the Rings\". Think \"Harry Potter\". Think of anything, in fact, because all of it is possible.\r\n</p><p>\r\nA staple of the high fantasy genre of gaming is the dungeon. Now, that term has two meanings in this sort of game: first, the usual meaning, of what amounts to the basement of a castle, with jails, interrogation rooms, storage rooms, and more. The other meaning refers specifically to a type of adventuring environment. Both of these are usually found underground, but an adventuring dungeon may have nothing to do with any castle. It might be a lost crypt, a cave system, an abandoned gold mine, or the lair of some dreaded beast that\'s been terrorizing the countryside. In the dungeon might be enemies, monsters, and treasure protected by deadly traps. Magic abounds. There might be puzzles, dark secrets, or a kidnapped prince to rescue.\r\n</p><p>\r\nAs a new GM, you can start off any way you want, but in my experience, the best way to get used to how the game works, and how the whole process of providing an evening\'s entertainment to your friends or family works in this context, is to create a dungeon and run your players through it.\r\n</p><p>\r\nDungeons generally require set-up time; that is to say, you have to design it in advance. Now, Klaatu and I are currently working on ways to ease that burden, with the ultimate goal of eliminating the pre-work entirely. But for now, let\'s talk about the traditional way to approach all this. What follows is a step-by-step process, but understand, it\'s only one of an infinite possible number of them.\r\n</p><p>\r\nSTEP 01 -- CREATE THE COUNTRYSIDE\r\nSome GM\'s say creating the world is the first step. Some say creating the godly pantheons of the world is the first. Some say it\'s the history, or the fantasy races. They\'re not wrong, but trust me, when you\'re just starting out, none of that stuff matters. In this example, you\'ll be running the players through a dungeon. That dungeon is out in the country, within the middle of a large forest.\r\n</p><p>\r\nNow, it will make the beginning and end of the adventure easier if you have a small village nearby where the player characters all live. We\'ll call it Forestdale for the lack of anything better. In Forestdale, there\'s an inn or tavern. This is where people get together, tell tall tales, and become inspired to go adventuring, so let\'s give it a name as well: \"The Prancing Unicorn\". That\'s home base. Every player character knows this place, and everyone in it knows them.\r\n</p><p>\r\nOne of the stories being swapped at \"The Unicorn\" lately is about a tribe of dangerous creatures living in an underground lair somewhere within the forest. They are led by an evil wizard, or so the tales go. They have been attacking farmers and merchants who travel through the roads and foot paths of the woods in order to sell their goods in Forestdale. One of the merchants says he saw them travel down the Western path near the Old Bridge. Something must be done, but who would be brave or foolhardy enough to even try?\r\n</p><p>\r\nAnd that\'s all you need to create for the world right now. Remember, this stuff is new; no one needs large amounts of detail just yet, least of all you. You\'ll have enough to juggle.\r\n</p><p>\r\n\r\n\r\nSTEP 02 -- CREATE THE DUNGEON FLOOR PLAN\r\nOne of the rumors to be heard at \"The Prancing Unicorn\" is that there\'s an underground cave system or labyrinth somewhere in the forest. Some say it\'s a myth, others say their cousin\'s uncle\'s sister\'s best friend came across it once. Either way, its existence is shrouded in mystery, and people are said to go in, but not always come out.\r\n</p><p>\r\nThis is your first dungeon. You don\'t want to do more work than you need to. Let\'s make this dungeon a single level. Later, you can add a secret panel somewhere that can reveal a set of stairs down to a second level (and from there, a third, fourth, tenth, or more). Right now, it\'s one level, hidden below the forest. It\'s dark, it\'s dangerous. It\'s plenty.\r\n</p><p>\r\nPutting a dungeon together can be difficult, but it doesn\'t have to be. The traditional way to create one of these is to use graph or hex paper and draw out the floor map. Each square of the graph paper is equal to ten feet, or, say, three meters. You make note of all rooms, caves, doors, hallways, stairs up or down, floor traps, hidden doors, and anything else you want in there. Be sure to put a set of stone stairs that lead from the forest above, down to this dank and gloomy dungeon.\r\n</p><p>\r\nThere are no standard symbols for the different things on the map, despite what anyone might tell you, but for now, let\'s turn the paper landscape style, and at the top of the page, now held that way, outline one square of the graph paper with a pencil. Inside the square, draw three or four small lines at an angle. This will represent a set of stairs. Next to the stairs, write the letter \"U\". This is the way to get to the forest above. Granted, it\'s how the player characters will come down here to begin with, but once they are here, they have to go up to leave, hence the \"U\". If that\'s confusing, you can write, \"To The Forest Above\", next to this square, maybe with a little arrow. You can write anything you want, but this is how the player characters will get in and out of your dungeon.\r\n</p>\r\n<img src=\"https://mixedsignals.ml/games/blog/user/pages/_img/01-stairs-down-600x337.jpg\" />\r\n<p>\r\nWe\'re going to draw the floor plan from the top of the page down. The entire dungeon map will be on this one side of the paper. In the corner, draw an arrow pointing up, and put a letter \"N\" there. That\'s North. We\'ll be using compass directions from now on. Granted that when underground, it\'s hard to get your bearings without a compass, but for this first dungeon, we won\'t worry about that. North, South, East, West. It makes life easy.\r\n</p><p>\r\nOn the bottom of the page, to the South, draw a box in the middle of the page that\'s ten by ten squares in size. This is where the dungeon tunnels all will be leading, and where we\'ll have the biggest fight of the adventure. We\'re setting that up now, so we always know where we\'re heading. Now go back to the stairs at the top of the page.\r\n</p><p>\r\nDraw a long line from the lower edge of the stairs going West. Stop the line a square or two from the edge of the paper. Now do the same thing going East. Next, move down one square, and draw another line parallel to both of these, going entirely from one side of the page to the other, East to West. You\'ve just created a place for the players to explore, so imagine it for a moment: they come down some broken, forgotten stairs. Let\'s say they travel at least a hundred feet down, tripping over tree roots and walking through cobwebs, until the stairs deposit them in the middle of a dark tunnel, ten feet wide. It stretches to either side, running East and West out of sight (you know that it goes hundreds of feet in both directions, but you\'ll let them discover that for themselves). They listen, and can hear nothing but the scurrying of unseen vermin. At least, they hope that\'s what it is. Not a bad start.\r\n</p>\r\n<img src=\"https://mixedsignals.ml/games/blog/user/pages/_img/02-first-tunnel-600x337.jpg\" />\r\n<p>\r\nAlong this hallway, you\'ll draw little rectangles, like black bars, on random squares along the Southern side of the tunnel. Not too many, just a few here and there, with generous space in between. These are heavy wooden doors. Some may be locked. That\'s your choice. If they are, put a little symbol near them. It could be as simple as the letter \"L\", so let\'s go with that. Now you know where the all doors are in this particular tunnel, and you know which of them will be a challenge for the player characters to open.\r\n</p><p>\r\nThis is just the first tunnel of a larger complex. This complex can be as big or as small as you\'d like. Let\'s say it\'s moderately sized. Before we draw more tunnels, let\'s draw the rooms behind those doors. This will tell us how much map space we\'ll have for further tunnels. Some GM\'s like to draw all the tunnels first, and then fit in the rooms. You can do it however way you want later on; right now, let\'s just use this method. Pick a door. Draw a box behind it, three or four squares in size. That\'s the room. Do the same behind the other doors. Make the rooms different shapes and sizes, but not too big. Let the big room at the bottom be the star. When you\'re done, you have a huge tunnel, with several mysterious doors, behind which are some good-sized rooms.\r\n</p><p>\r\nOn the part of the tunnel that ends on the West side, draw a connecting tunnel South for five squares, and then turn the direction back to the East. Draw this tunnel going that way for ten squares. Put a door or two along here, and draw some rooms for them. Turn the tunnel South again, and go five or six squares, and turn it East again for four squares. Draw a door and room. Maybe it\'s locked, maybe not. Continue with this meandering, jagged floor plan, wandering East and then West, but always moving South. Add occasional doors and rooms as you go, until your tunnel finally ends on the Western side of the large ten by ten square room at the bottom of the page. Draw a door to get in there.\r\n</p>\r\n<img src=\"https://mixedsignals.ml/games/blog/user/pages/_img/03-west-side-600x337.jpg\" />\r\n<p>\r\nNow go back up to the long tunnel at the top, and repeat this whole process on the Eastern side, eventually bringing that part of the tunnel to the Eastern edge of the big room at the bottom. Put a door there.\r\n</p>\r\n<img src=\"https://mixedsignals.ml/games/blog/user/pages/_img/04-east-side-600x337.jpg\" />\r\n<p>\r\nNow, number your rooms on the map, starting at at the top, and working your way down, until you\'ve marked each one. Room numbers are essential, because you\'ll be keeping track of each one.\r\n</p>\r\n<img src=\"https://mixedsignals.ml/games/blog/user/pages/_img/05-numbered-rooms-600x337.jpg\" />\r\n<p>\r\nThe floor plan to your first dungeon is complete. Now you need to put interesting things in it.\r\n</p><p>\r\n\r\nSTEP 03 -- POPULATE YOUR DUNGEON\r\nOkay, on a separate piece of paper, list the rooms of your dungeon. Start at #1, and go down. Beside the room number, you put in a brief description, along with any monsters, treasure, or other points of interest. You\'ll be consulting this list throughout the game, so write down everything you need to know, in order to minimize the amount of time you\'ll inevitably have your nose in the rulebook while playing. Monster statistics, including their weapons, and and the damage they do, should all be on this list, though there are ways to simplify the process, once of which I\'ll go into in a moment.\r\n</p>\r\n<img src=\"https://mixedsignals.ml/games/blog/user/pages/_img/06-room-list-pg1-pg2-600x533.jpg\" />\r\n<p>\r\nWhen putting creatures and things into your dungeon, the first thing to remember is to not overload it. Each room does not need a monster. Not every room needs treasure. It might be helpful to think in terms of what you\'d like to see in the dungeon as a whole. Remember the stories of evil creatures, and possibly a wizard, which you heard at \"The Dancing Unicorn\"? We\'ll use that as our springboard. This is a starting dungeon, not just for you, but also for the player characters. Starting dungeons mean low-level monsters, so let\'s go with goblins.\r\n</p><p>\r\nGoblins are generally quite impressed with magic, so we\'re going to assume a wizard of dubious character has bullied a small tribe of them into being his thugs. They\'ve been waylaying passing merchants and farmers, stealing their wares, and carrying off food (along with the occasional peasant worker, as goblins love the taste of human flesh). Stupid, but dreadful creatures, they have displayed a level of tactical organization that\'s not normal for them. This, of course, is because the wizard\'s in charge. Look up the statistics for goblins, and understand what they\'re like. For this adventure, we\'re not going to worry about goblin captains, or goblin chiefs, both of which are tougher than your average goblin. No, all the creatures for this adventure have the same statistics. Don\'t drive yourself crazy writing them down, over and over. Write them once at the bottom of the room description page, and every time the player characters run into a goblin, consult them.\r\n</p><p>\r\nLet\'s say there are a total of fifteen goblins in this dungeon. They won\'t all be together; the player characters will encounter a few of them here and there, in various rooms, or maybe ust wandering the tunnels. The rooms themselves will have the spoils of all their raids, including barrels of wine, hams and sides of beef; furs, and a few copper, silver, and gold coins. If there\'s wine in one of the rooms, maybe the goblins there are drunk, fighting at a penalty to hit and damage. And remember, not all rooms need things in them. Maybe this was once a temple, and there\'s just broken furniture, and rotting religious robes in some of the rooms. In one, there might also be a tapestry against the wall, depicting a miracle of whatever god this place was once dedicated to. What you might not tell the player characters up front is that the tapestry could fetch a fair amount of gold coins in the market back in Forestdale. Too big to carry while exploring the dungeon, such a thing could always be rolled up and fetched on their way out. Not all treasure is found in wooden chests.\r\n</p><p>\r\nThen again, a lot of it is, so why not put one in the big room to the South? Of course, you have to defeat the evil wizard and his goblin cohorts, wh are hanging out in there. As a rule of thumb, you might want to sprinkle half the goblins throughout the dungeon, leaving the other half here, for the final fight. Stealth matters. Approaching the big room noisily, and kicking open one of the doors, is not stealthy. The player characters might be able to catch the wizard and his minions off-guard, if they move quietly.\r\n</p><p>\r\nIn order to be a credible threat to the player characters, this wizard should be of a slightly higher level, say 2nd or 3rd. He\'ll have some aggressive spells, and he\'ll have his goblins handy. You\'ll roll up the wizard the same way the players rolled up their characters, only you\'ll make him more experienced, and with more spells at his command. Maybe he even has a magic item of some sort. Should the players defeat this guy, this magic item will be part of the treasure; until then, it\'s something the wizard will use against them. Don\'t make it too tough. Maybe don\'t make it tough at all: a +1 Ring of Protection, maybe. Or perhaps, a +1 dagger. That might not sound like much, but it\'s more than the player character\'s have when they start.\r\n</p><p>\r\nNot enough excitement, maybe? Just add in a couple of giant rats in one of the rooms. Maybe some large spiders in another. Don\'t forget to put their statistics down in the room description. Judging how tough or easy a dungeon needs to be comes with experience. My suggestion is to err on the side of toughness, to put more challenges in there than maybe you feel comfortable with. If the player characters are looking depleted and injured, you can say the room is empty, instead of filled with spiders. Also, it doesn\'t hurt at all to remind the players now and then that it\'s okay to retreat. They can always come back another day when they\'re rested, and have made plans based on the knowledge they gained the first time around. It sets up a grudge match...the heroes vs. the evil wizard and his goblin hoard. You, as the GM, just repopulate the goblins, move them around a bit, so they\'re not all in the same rooms as before (though the big room should still be for the final fight), and //voila//! You\'ve just provided your players with two night\'s worth of entertainment, for the effort of only one.\r\n</p><p>\r\nAnd there you have it: a stocked dungeon that dovetails into the local lore of the countryside, ready for your players to explore.\r\n</p><p>\r\n\r\n\r\nSTEP 04 -- ROLLING UP CHARACTERS\r\nSome GM\'s will want a whole night just for this process. Others will just have the players arrive at the game with their characters ready to go, especially if they are experienced with the game. I won\'t go over the character creation process here, because each game is different, and some are VERY different. I mention this now, though, because the players need characters, and creating them comes before the adventure starts. If the game is as new to them as it is to you, take that whole night to help them create their characters. It\'s fun all on its own, and it allow\'s everyone to be familiar with the other characters -- something vital to party survival.\r\n</p><p>\r\nI\'m not going to go into detail about the process of rolling up characters, because, like you, Klaatu and I have dedicated an evening just to this process. In a previous episode in this mini-series, the two of us created a character from the ground up, so you can hear what\'s involved, and how you might want to approach the process with your own players.\r\n</p>\r\n<h2>Klaatu</h2>\r\n<p>\r\nIf designing your own custom dungeon seems intimidating to you, there is another way. And it\'s a time-honoured, legitimate way to play, and it\'s quite often the way I play: you go find an adventure that someone else has already written.\r\n</p><p>\r\nAn adventure is the scenario you and your players experience when you sit down at the table to play. It\'s arguably the *game* (the rulebooks are the game engine, or the mechanics). Wizards of the Coast, Paizo, Catalyst, Kobold Press, Frog God, and many others publish adventures (sometimes called \"modules\", \"scenarios\", or \"adventure paths\") written by professional game designers. Published adventures provide the story framework for your game.\r\n</p><p>\r\nNot all systems publish adventures, though, or you may choose not to use one. If that\'s the case, spend some time developing a story. Writing a good game is part science, part craft, and part magic, but if you and your players are up to the challenge, then running blindly through a story that\'s mostly being created spontaneously on the spot can be a lot of fun. If that sounds overwhelming, though, get a published adventure!\r\n</p><p>\r\nQuick tip: Free, small, or introductory adventures are often available from https://drivethrurpg.com, https://dmsguild.com, and https://www.opengamingstore.com\r\n</p><p>\r\nMany adventures have text blocks that provide you with introductory text for each part of the game, they explain clearly what the goal of the players is during that segment, and give you guidance on what players will find in the area and how those discoveries lead to the next plot point.\r\n</p><p>\r\nBroadly speaking, there are two types of published adventures: there are \"one-shots\" and there are \"modules\" or \"adventure paths\".\r\n</p><p>\r\nA one-shot adventure is analogous to a quest in a video game: it\'s a single, clearly-defined task with a very obvious and immediate result; for example, goblins are terrorizing the hapless citizens of the local village, so go to their cave and clear it out: if you do, you\'ll relieve the villagers of the horrors, and you get to keep any gold or weapons you find.\r\n</p><p>\r\nThe advantage is that it\'s designed to be a quick, one-time game session, so it\'s perfect for playing with friends you only see once in a while, or with someone who\'s never played before and just isn\'t sure if it\'s something they want to commit to. Don\'t be fooled by the page count of these small adventures: it may only be 5 to 10 pages long, sometimes less, but you\'ll be surprised at how long players can spend exploring a boundless world existing only in their imagination.\r\n</p><p>\r\nAdventure paths or modules or campaigns are bigger stories with\r\nloftier goals. You can think of them as lots of little one-shots\r\nstrung together so that once players accomplish all the tasks and\r\nsolve all the mysteries over the course of 200 pages, they have a\r\nfinal showdown with some Big Bad, and win themselves a place in the\r\nlegends of the game world. It\'s an epic poem instead of a short\r\nstory. It feels grander, it feels important. The losses along the way\r\nare more profound, and the victories sweeter. These campaigns take\r\nmonths to play through and usually expect a gaming group to meet\r\nweekly or fortnightly or at least monthtly to work their way through\r\nthe tale.\r\n</p><p>\r\nI should mention one more kind of book you might stumble across, and\r\nthose are source books. I mention this because I\'ve had friends go and\r\nbuy books more or less blindly, and then they bring them back home\r\ndisappointed that instead of a book of lore about dark elves, they\r\nbought an adventure set in the underdark. Or the other way round: they\r\nwanted an adventure and ended up with a rule book.\r\n</p><p>\r\nThis happens with the bigger systems that produce a lot of media, like\r\n{D&amp;D, Shadowrun, Pathfinder, Warhammer}, so get clarity on what you\'re\r\nbuying before you make a purchase. If you come across a cool ShadowRun\r\nbook called RUN FASTER expecting a campaign to run with your friends,\r\nyou\'ll be surprised to find that you\'ve purchased a source book full\r\nof metatypes, expanded rules, and alternate character creation\r\nmethods: sort of a Shadowrun Core Rulebook part 2. Same goes for, say,\r\nVolo\'s Guide with D&amp;D, or Ultimate Campaign in Pathfinder. It can be\r\noverwhelming and they\'re not aways labelled clearly (or if they are,\r\nthe label gets lost in the word cloud of RPG jargon that you\'re not\r\nused to yet), so do a little research first.\r\n</p><p>\r\nI\'ve played through dungeons that a GM created over his lunch break, and I\'ve played through adventures written by clever game designers, and I can confidently say that they\'re both great ways to RPG. But as a GM, if you feel overwhelmed by the idea of designing a dungeon, a published adventure is a great way to start. Aside from reading a chapter ahead before each game night, all the prep work is done for you, and there\'s very little thinking required.\r\n</p><p>\r\nAnother part of being GM is deciding when a die roll is necessary. Die rolls represent the chance of success or failure when a specific action is taken, but the confusing thing is: if you think hard enough about anything in the world you can find a chance of success or failure. As a GM, it\'s up to you to decide what\'s \"important\" enough for a roll. Strictly speaking, that\'s determined by the rules. The rules told you what requires a roll, and you\'re expected to know the rules well enough to make the call.\r\n</p><p>\r\nIn practise, however, you have a lot of stuff to track in you head, and remembering what requires a die roll, or deciding to request a die roll even though it may not be strictly required, can feel overwhelming for a new GM.\r\n</p><p>\r\nGood news: Players intuitively know when to roll dice. A player knows their character\'s skills (because they built the character and wrote it down on their character sheet), so sometimes the actions they choose to take are chosen because it falls within a category of a skill they happen to have. A thief probably wouldn\'t ever think to *look* for hidden door if the thief were a fighter (who would more likely think to pound on the wall rather than to slyly look for a hidden door). So if your player reaches for dice, let them roll because they\'re probably right.\r\n</p><p>\r\nI\'m sure it\'s possible to take it too far, but people like to roll dice. It\'s part of the fun of an RPG, the uncertainty of subjecting yourself to the whims of fate. So when in doubt, either make your players roll dice, or roll dice yourself. I use dice rolls to help me decide everything from NPC reactions to weather conditions. It\'s usually safe to default to rolling.\r\n</p><p>\r\nWorst case scenario is that die are only picked up for fights and a literal interpretation of skills: and that works because those are the rules as written.\r\n</p><h2>Klaatu</h2>\r\n<p>\r\nPlayers drive the story. In video game or movie terminology, they control the \"camera\". When players are exploring or investigating, let them ask questions or take actions (\"I look in the closet\"), and answer them as you see fit (\"You open the closest and see an array of fine garments.\")\r\n</p><p>\r\n\"I\'ll move the clothes aside and examine the walls, and the floor. I\'m looking for trap doors or hidden compartments, or anything suspicious.\"\r\n</p><p>\r\nAnd so on. Players can choose to investigate and explore for as much as they want. That\'s the beauty of a pen-and-paper RPG: the world is infinite. That said, you\'re the GM and you owe it to your players to keep the game moving. You don\'t to let your players spend 3 real hours searching a room that, in the end, has no bearing upon the plot whatsoever.    That can be a delicate matter, because the nature of the game means that you know things that the other players don\'t, meaning much of the puzzle for players is what they don\'t know.\r\n</p><p>\r\nUsually I let players explore a space on their own until I feel that they\'ve explored the obvious parts of it, and then I remind them where the exits are, or I remind them how many other rooms there are to explore, or some subtle clue to say, without saying, that they\'ve secured an area.\r\n</p><p>\r\nIf players are especially suspicious of something, though, you certainly have the power to generate a subplot, and often times you should do that. It\'s fun for you and rewarding to players. For instance, if a player is convinced that there\'s a secret panel in a closet and spends a lot of time investigating, then you might decide that there IS a secret panel in the closet, and then roll on a random table to determine what could possible inside that compartment. Or you could leave the compartment empty, thereby creating a story hook to return to later...what used to be in that compartment? who took it, and why? What were the implications?\r\n</p><p>\r\nKeeping the gaming moving is an inexact, unscientific process, but usually it comes pretty naturally. When you start to get bored of the players exploring, you can bet that they\'re probably getting bored too, and that\'s when you know to urge them forward. If all else fails, you can always have something lure them from one space to another: a mysterious sound, an oncoming threat, or a supernatural or divine instinct.\r\n</p>\r\n',78,95,0,'CC-BY-SA','rpg,dm,gm,game master,dungeon master,dnd',0,0,1),
(2762,'2019-03-05','What You Really Are',996,'Lostnbronx looks back at his early gaming days.','<p>I got into Dungeons &amp; Dragons back in the 1970s. This is my memory of that time and that gaming group, and especially, of the guy who taught me how to play.</p>',107,95,0,'CC-BY-SA','gaming, D&D, lostnbronx',0,0,1),
(2763,'2019-03-06','Deepgeek explains SPF records',849,'Confused about SPF? Klaatu was. Here\'s Deepgeek\'s explanation.','<p>\r\nKlaatu reads a <a href=\"https://gopher.info-underground.net:70/scottphlog/9997-SPF-Intro.txt\" target=\"_blog\">phlog &#40;gopher&#41; post</a> by Deepgeek explaining the practical uses of SPF records.\r\n</p>',78,99,0,'CC-BY-SA','email,spf,mx,postfix,smtp',0,0,1),
(2770,'2019-03-15','Navigating the maze of RPG books',1873,'There are so many kinds of RPG books out there, where do you start? Klaatu tells all!','<p>\r\nTaxonomy of RPG-related books:\r\n</p>\r\n\r\n<ol>\r\n<li><p>\r\nRulebooks tell you how to play the game.\r\n</p></li>\r\n<li><p>\r\nOptional books of rules add modular components to the base game. They add nuance to specific actions (for example, a book might add rules on owning and managing a castle in a fantasy world, or it might add rules on hacking in a sci fi game; these are things you can do without rules in the game, but if you want added stakes, then these books are ones you would want to obtain).\r\n</p></li>\r\n<li><p>\r\nAdventures (formerly called \"modules\") provide game plots and locations, in the event that you have no interest in designing your own.\r\n</p></li>\r\n<li><p>\r\nSource books or \"settings\" provide additional information on the setting of a game, sometimes even providing an alternate game universe with additional rules.\r\n</p></li>\r\n<li><p>\r\nExtra media, like novels, comics, movies, and video games, provide more information (sometimes in canon, sometimes not) about the game universe in which you are playing. Rarely do these have impact on the rules of the game, but they may provide a common language and shared experience for the players.\r\n</p></li>\r\n</ol>\r\n\r\n<p>\r\nThe only essential purchase is the rulebook. Everything else can be generated by gamers. Purchasing additional material is optional, and can either be seen as a great way to support a company providing your entertainment, or as an insidious plot by greedy corporations to rope you into a perpetual cycle of capitalism.  However, RPG is a pretty healthy (and often open) system, so free and open content abounds.\r\n</p>\r\n\r\n\r\n',78,95,0,'CC-BY-SA','book,rpg,game',0,0,1),
(2782,'2019-04-02','Never stop gaming',1277,'Ways to feed the gaming impulse, even when you can\'t game','<p>\r\nShownotes are on <a href=\"https://mixedsignals.ml/games/blog/blog/blog_lifestyle-gamer\" target=\"_blank\">mixedsignals.ml</a>\r\n</p>',78,95,0,'CC-BY-SA','rpg,dm,gm,game master,dungeon master,dnd',0,0,1),
(2795,'2019-04-19','Dead Earth',2210,'A review of a 20-year old, GNU Free Documentation Licensed, RPG about post-apocalyptic turmoil','<p>\r\nFull shownotes are on <a href=\"https://mixedsignals.ml/games/blog/blog/blog_dead-earth\" target=\"_blank\">mixedsignals.ml</a>\r\n</p>\r\n\r\n<p>\r\nYou can download Klaatu\'s update revision of the game materials here: <a href=\"https://mixedsignals.ml/download/deadearth-bundle-gfdl.7z\">https://mixedsignals.ml/download/deadearth-bundle-gfdl.7z</a>\r\n</p>',78,95,0,'CC-BY-SA','RPG,Tabletop Game,Dead Earth',0,0,1),
(2768,'2019-03-13','Writing Web Game in Haskell - Planetary statuses',1122,'Tuula describes system for recording planetary statuses in their game','<h2 id=\"intro\">Intro</h2>\r\n<p>In episode hpr2748 Writing Web Game in Haskell - Special events, I talked about how to add special events in the game. One drawback with the system presented there was that the kragii worms might attack planet that already had kragii worms present. This time we’ll look into how to prevent this. As a nice bonus, we also come up with system that can be used to record when a planet has particularly good harvest season.</p>\r\n<h2 id=\"data-types-and-database\">Data types and Database</h2>\r\n<p>We need a way to represent different kinds of statuses that a planet might have. These will include things like on going kragii attack or a particularly good harvest season. And since these are will be stored in database, we are also going to use derivePersistField to generate code needed for that.</p>\r\n<pre><code>data PlanetaryStatus =\r\n    GoodHarvest\r\n    | PoorHarvest\r\n    | GoodMechanicals\r\n    | PoorMechanicals\r\n    | GoodChemicals\r\n    | PoorChemicals\r\n    | KragiiAttack\r\n\r\nderivePersistField &quot;PlanetaryStatus&quot;</code></pre>\r\n<p>We could have recorded statuses as strings, but declaring a separate data type means that compiler can catch typos for us. It also makes code easier to read as <code>PlanetaryStatus</code> is much more informative than <code>String</code> or <code>Text</code>.</p>\r\n<p>For database, we use following definition shown below in models file. It creates database table <code>planet_status</code> and respective Haskell data type <code>PlanetStatus</code>. There will be one row in database for each status that a planet has. I could have stored all statuses in a list and store that in database, effectively having one row for any planet. Now there’s one row for any planet + status combination. Choice wasn’t really based on any deep analysis, but merely a gut feeling that this feels like a good idea.</p>\r\n<pre><code>PlanetStatus json\r\n    planetId PlanetId\r\n    status PlanetaryStatus\r\n    expiration Int Maybe\r\n    deriving Show Read Eq</code></pre>\r\n<p><code>expiration</code> column doesn’t have <code>NOT NULL</code> constraint like all other columns in the table. This is reflected in <code>PlanetStatus</code> record where data type of <code>planetStatusExpiration</code> is <code>Maybe Int</code> instead of <code>Int</code>. So some statuses will have expiration time, while others might not. I originally chose to represent time as <code>Int</code> instead of own data type, but I have been recently wondering if that was really a good decision.</p>\r\n<h2 id=\"kragii-attack-redux\">Kragii attack, redux</h2>\r\n<p>Code that does actual database query looks pretty scary on a first glance and it’s rather long. First part of the code is there to query database and join several tables into the query. Second part of the code deals with counting and grouping data and eventually returning <code>[Entity Planet]</code> data that contains all planets that match the criteria.</p>\r\n<pre><code>-- | Load planets that are kragii attack candidates\r\nkragiiTargetPlanets :: (MonadIO m, BackendCompatible SqlBackend backend\r\n                           , PersistQueryRead backend, PersistUniqueRead backend) =&gt;\r\n                           Int -&gt; Int -&gt; Key Faction -&gt; ReaderT backend m [Entity Planet]\r\nkragiiTargetPlanets pop farms fId = do\r\n    planets &lt;- E.select $\r\n        E.from $ (planet `E.LeftOuterJoin` population `E.LeftOuterJoin` building `E.LeftOuterJoin` status) -&gt; do\r\n            E.on (status E.?. PlanetStatusPlanetId E.==. E.just (planet E.^. PlanetId)\r\n                  E.&amp;&amp;. status E.?. PlanetStatusStatus E.==. E.val (Just KragiiAttack))\r\n            E.on (building E.?. BuildingPlanetId E.==. E.just (planet E.^. PlanetId))\r\n            E.on (population E.?. PlanetPopulationPlanetId E.==. E.just (planet E.^. PlanetId))\r\n            E.where_ (planet E.^. PlanetOwnerId E.==. E.val (Just fId)\r\n                      E.&amp;&amp;. building E.?. BuildingType E.==. E.val (Just Farm)\r\n                      E.&amp;&amp;. E.isNothing (status E.?. PlanetStatusStatus))\r\n            E.orderBy [ E.asc (planet E.^. PlanetId) ]\r\n            return (planet, population, building)\r\n    let grouped = groupBy ((a, _, _) (b, _, _) -&gt; entityKey a == entityKey b) planets\r\n    let counted = catMaybes $ fmap farmAndPopCount grouped\r\n    let filtered = filter ((_, p, f) -&gt;\r\n                                p &gt;= pop\r\n                                || f &gt;= farms) counted\r\n    let mapped = fmap ((ent, _, _) -&gt; ent) filtered\r\n    return mapped</code></pre>\r\n<p>In any case, when we’re querying for possible kragii attack candidates, the query selects all planets that are owned by a given faction and have population of at least 10 (left outer join to <code>planet_population</code> table), have at least 5 farming complex (left outer join to <code>building</code> table) and don’t have on going kragii attack (left outer join to <code>planet_status</code> table). This is encapsulated in <code>kragiiTargetPlanets 10 5</code> function in the <code>kragiiAttack</code> function shown below.</p>\r\n<p>Rest of the code deals with selecting a random planet from candidates, inserting a new <code>planet_status</code> row to record that kragii are attacking the planet and creating special event so player is informed about the situation and can react accordingly.</p>\r\n<pre><code>kragiiAttack date faction = do\r\n    planets &lt;- kragiiTargetPlanets 10 5 $ entityKey faction\r\n    if length planets == 0\r\n        then return Nothing\r\n        else do\r\n            n &lt;- liftIO $ randomRIO (0, length planets - 1)\r\n            let planet = maybeGet n planets\r\n            let statusRec = PlanetStatus &lt;$&gt; fmap entityKey planet\r\n                                         &lt;*&gt; Just KragiiAttack\r\n                                         &lt;*&gt; Just Nothing\r\n            _ &lt;- mapM insert statusRec\r\n            starSystem &lt;- mapM (getEntity . planetStarSystemId . entityVal) planet\r\n            let event = join $ kragiiWormsEvent &lt;$&gt; planet &lt;*&gt; join starSystem &lt;*&gt; Just date\r\n            mapM insert event</code></pre>\r\n<p>Second piece to the puzzle is status removal. In can happen manually or automatically when the prerecorded date has passed. Former method is useful for special events and latter for kind of seasonal things (good harvest for example).</p>\r\n<p>For example, in case of removing kragii attack status, code below serves as an example. The interesting part is <code>deleteWhere</code> that does actual database activity and removes all <code>KragiiAttack</code> statuses from given planet.</p>\r\n<pre><code>removeNews event odds = MaybeT $ do\r\n    res &lt;- liftIO $ roll odds\r\n    case res of\r\n        Success -&gt; do\r\n            _ &lt;- lift $ deleteWhere [ PlanetStatusPlanetId ==. kragiiWormsPlanetId event\r\n                                    , PlanetStatusStatus ==. KragiiAttack\r\n                                    ]\r\n            _ &lt;- tell [ WormsRemoved ]\r\n            return $ Just RemoveOriginalEvent\r\n        Failure -&gt; do\r\n            _ &lt;- tell [ WormsStillPresent ]\r\n    return $ Just KeepOriginalEvent</code></pre>\r\n<p>Removal of expired statuses is done based on the date, by using <code>&lt;=.</code> operator to compare <code>expiration</code> column to given date.</p>\r\n<pre><code>_ &lt;- deleteWhere [ PlanetStatusExpiration &lt;=. Just date]</code></pre>\r\n<h2 id=\"other-uses-and-further-plans\">Other uses and further plans</h2>\r\n<p>Like mentioned before, planet statuses can be used for variety of things. One such application is recording particularly good (or poor) harvest season. When such thing occurs, new <code>planet_status</code> record is inserted into database with <code>expiration</code> to set some suitable point in future. System will then automatically remove the status after that date is reached.</p>\r\n<p>In the meantime, every time food production is calculated, we have to check for possible statuses that might affect it and take them into account (as form of small bonus or malus).</p>\r\n<p>While this system is for planet statuses only, similar systems can be build for other uses (like statuses that affect a single ship or whole star system).</p>\r\n<p>Easiest way to catch me nowadays is either via email or on fediverse where I’m Tuula@mastodon.social</p>\r\n',364,107,0,'CC-BY-SA','haskell',0,0,1),
(2764,'2019-03-07','Personal password algorithms',2444,'Is it possible to generate a unique password for every site? Klaatu tries.','<p>\r\nHere is a bash script to generate an org-mode word list matrix.\r\nIt requires at least one file ending in <code>.list</code> to be used as a source of words or strings.\r\n</p>\r\n\r\n<pre><code>\r\n#!/bin/bash\r\n\r\nif [ -z $1 ]; then\r\n    DEST=matrix.org\r\nelse\r\n    DEST=$1\r\nfi\r\n\r\ncat &gt;&gt; \"${DEST}\" &lt;&lt;EOF\r\n| | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z | ? |\r\n|-+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|\r\nEOF\r\n\r\nVERT=(a b c d e f g h i j k l m n o p q r s t u v w x y z ?)\r\n\r\ncat *list &gt; tmp || exit\r\n\r\nBIG=`wc -l tmp | cut -f1 -d\' \'`\r\n\r\nc=\"0\"\r\n\r\nwhile [ \"$c\" -lt \"27\" ]; do\r\n    # horizontal row across\r\n    n=\"0\"\r\n    v=`echo ${VERT[$c]}`\r\n    printf \"| $v |\" &gt;&gt; \"${DEST}\"\r\n    while [ \"$n\" -lt \"27\" ]; do\r\n	i=`echo $((1 + RANDOM % $BIG))`\r\n	w=`awk \"FNR==$i\" tmp`\r\n	#reduce chance of empty cell\r\n	if [[ -z $w ]]; then\r\n	    i=`echo $((1 + RANDOM % $BIG))`\r\n	    w=`awk \"FNR==$i\" tmp`\r\n	    echo \"blank cell found\"\r\n	fi\r\n	printf \"$w | \" &gt;&gt; \"${DEST}\"\r\n	n=$[$n+1]\r\n    done\r\n    echo \" \" &gt;&gt; \"${DEST}\"\r\n    c=$[$c+1]\r\ndone\r\n\r\n/usr/bin/rm tmp\r\n</code></pre>\r\n\r\n<p>\r\nWhen you open the resulting file (matrix.org by default) in emacs, use the fill-paragraph (m-x fill-paragraph) function to align the cells into a pretty table.\r\n</p>\r\n\r\n<p>\r\nInvent your own key, and generate some test passwords.\r\nDo this 6 or 8 times, and then try to reverse the key using the passwords and the table.\r\nIf the logic to reverse the key is too simple, then try using values relying on the metadata, rather than data, of the table (for instance, the number of letters in the first word in the table starting with the same letter as the site name, or whatever).\r\n</p>\r\n\r\n<p>\r\nDo you have analogue methods of generating passwords?\r\nPost ideas to either the comments or, better yet, as an HPR episode!\r\n</p>\r\n\r\n<p>\r\n    Here is a word list for testing:<br/>\r\n    <a href=\"https://hackerpublicradio.org/eps/hpr2764_wordlist.html\">https://hackerpublicradio.org/eps/hpr2764_wordlist.html</a>\r\n</p>\r\n',78,99,0,'CC-BY-SA','password,security,algorithm,puzzle,cipher',0,0,1),
(2766,'2019-03-11','Disk enumeration on Linux',1443,'Klaatu reviews the various commands used to enumerate drives on Linux','<p>\r\nThe old way:\r\n</p>\r\n\r\n<pre><code>\r\n$ ls /dev/sd*\r\n</code></pre>\r\n\r\n<p>\r\nAnother old way:\r\n</p>\r\n\r\n<pre><code>\r\n$ fdisk --list\r\n</code></pre>\r\n\r\n<p>\r\nAn old way to see what you just plugged in:\r\n</p>\r\n\r\n<pre><code>\r\n$ sudo dmesg | tail\r\n</code></pre>\r\n\r\n<p>\r\nSome new tricks:\r\n</p>\r\n<pre><code>\r\n$ lsblk\r\nNAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT\r\nsda      8:0    0   2.7T  0 disk \r\n├─sda1   8:1    0  23.3G  0 part \r\n└─sda2   8:2    0   2.7T  0 part \r\nsdb      8:16   0   3.9G  0 disk \r\nsdc      8:32   0 111.8G  0 disk \r\n├─sdc1   8:33   0   100M  0 part /boot/efi\r\n└─sdc2   8:34   0 111.7G  0 part /\r\nsdd      8:48   0   1.8T  0 disk \r\n├─sdd1   8:49   0   120G  0 part /var\r\n├─sdd2   8:50   0   120G  0 part /tmp\r\n├─sdd3   8:51   0    60G  0 part /opt\r\n└─sdd4   8:52   0   1.5T  0 part /home\r\nsde      8:64   0 298.1G  0 disk \r\n├─sde1   8:65   0   500M  0 part \r\n├─sde2   8:66   0 296.8G  0 part \r\n└─sde3   8:67   0   826M  0 part \r\nsdf      8:80   0 931.5G  0 disk \r\n└─sdf1   8:81   0 931.5G  0 part \r\nsdg      8:96   1   7.5G  0 disk \r\n└─sdg1   8:97   1   7.5G  0 part \r\n</code></pre>\r\n\r\n<p>\r\nUser-friendly udisks:\r\n</p>\r\n\r\n<pre><code>\r\n$ udisks --monitor /dev\r\nCtrl-c\r\n$ udisk --enumerate | sort\r\n/org/freedesktop/UDisks/devices/sda\r\n/org/freedesktop/UDisks/devices/sda1\r\n/org/freedesktop/UDisks/devices/sda2\r\n/org/freedesktop/UDisks/devices/sdb\r\n/org/freedesktop/UDisks/devices/sdc\r\n/org/freedesktop/UDisks/devices/sdc1\r\n[...]\r\n$ udisks --mount /dev/sdc1\r\nMounted /dev/sdc1 on /media/mythumbdrive\r\n$ udisks --unmount /dev/sdc1\r\n</code></pre>\r\n',78,0,0,'CC-BY-SA','fdisk,dmesg,lsblk,udisks',0,0,1),
(2767,'2019-03-12','Djvu and other paperless document formats',1935,'A tutorial on how to read and generate djvu files','<p>\r\nDjVu is a digital document format with advanced compression technology. \r\nDjVu allows for the distribution of very high resolution images of scanned documents, digital documents, and photographs. \r\nDjVu viewers are available for the <a href=\"https://github.com/RussCoder/djvujs\" target=\"_blank\">web browser</a> (search for djvujs in Firefox for an extension), the desktop ( <a href=\"https://wiki.gnome.org/Apps/Evince\" target=\"_blank\">Evince</a>,  <a href=\"https://okular.kde.org/\" target=\"_blank\">Okular</a> an BSD/Linux, and <a href=\"https://djvu.sourceforge.net/djview4.html\" target=\"_blank\">djview</a> on BSD/Linux/Windows/Mac), and <a href=\"https://f-droid.org/en/packages/org.sufficientlysecure.viewer/\" target=\"_blank\">mobile</a> devices.\r\n</p>\r\n\r\n<p>\r\nThe toolchain for encoding and decoding DjVu is \r\n<a href=\"https://djvu.sourceforge.net/\" target=\"_blank\">djvulibre</a>\r\n</p>\r\n<p>\r\n<a href=\"https://djvu.js.org/\" target=\"_blank\">djvu.js</a> is a Javascript library useful for online viewing.\r\n</p>\r\n\r\n<p>\r\n<a href=\"https://djvu.org/\" target=\"_blank\">djvu.org</a> contains sample documents and specification documents.</p>\r\n\r\n<h2>Creating a djvu file</h2>\r\n\r\n<p>\r\nThe tool you use to convert something to the .djvu format depends on your requirements. If you\'re converting a basic, black-and-white document, then <code>cjb2</code> (part of the djvulibre distribution) works:\r\n</p>\r\n\r\n<pre><code>\r\n$ cjb2 -dpi 300 foo.tiff\r\n$ ls\r\nfoo.tiff\r\nfoo.djvu\r\n</code></pre>\r\n\r\n<p>\r\nIf you want to convert something more complex, then use <code>c44</code> (also a part of the djvulibre distribution):\r\n</p>\r\n\r\n<pre><code>\r\n$ c44 -dpi 300 bar.jpg bar.djvu\r\n$ ls\r\nbar.jpg\r\nbar.djvu\r\n</code></pre>\r\n\r\n<p>\r\nTo put both of these files in a single DjVu container:\r\n</p>\r\n\r\n<pre><code>\r\n$ djvm -c baz.djvu foo.djvu bar.djvu\r\n$ ls\r\nbar.djvu\r\nbaz.djvu\r\nfoo.djvu\r\n</code></pre>\r\n\r\n<p>\r\nYou can add bookmarks, too.\r\nOpen a text file called <code>book.marks</code> (or any name you prefer) and enter:\r\n<p/>\r\n\r\n<pre><code>\r\n(bookmarks\r\n(\"Foo\" \"#1\")\r\n(\"Bar\" \"#2\")\r\n)\r\n</code></pre>\r\n\r\n<p>\r\nAnd then apply it to your DjVu file:\r\n</p>\r\n\r\n<pre><code>\r\n$ djvused -e \'set-outline book.marks\' -s baz.djvu\r\n</code></pre>\r\n\r\n<p>\r\nThere\'s more you can do with DjVu, but this has been an overview of how I use it.\r\n</p>\r\n',78,0,0,'CC-BY-SA','pdf, ebook, bloat, djvu',0,0,1),
(2773,'2019-03-20','Lead/Acid Battery Maintenance and Calcium Charge Voltage',1869,'Discussion on installing new Calcium battery into older vehicle and resulting maintenance issues.','<p>Although Lead/Acid batteries are old tech, the use of Calcium as an alloy metal has been a more modern development. Unfortunately many people do not realize this causes an incompatibility with older vehicles due to charging voltage. This episode discusses the use of smart chargers for long term battery maintenance.</p>',373,0,0,'CC-BY-SA','automotive, battery, maintenance, charger',0,0,1),
(2769,'2019-03-14','Quick Review of the AstroAI WH5000A Multimeter',1455,'NYbill reviews, yet another, inexpensive multimeter.','<p>NYbill does <b>yet another</b> inexpensive multimeter review. This time the AstroAI WH5000A. (Its time for a multimeter intervention!)</p>\r\n<p>The meter:</p>\r\n<ul>\r\n<li><a href=\"https://www.astroai.com/portfolio-items/astroai-digital-multimeter-trms-6000-counts-multimeters/\" class=\"uri\">https://www.astroai.com/portfolio-items/astroai-digital-multimeter-trms-6000-counts-multimeters/</a></li>\r\n</ul>\r\n<p>Pics for the episode:</p>\r\n<ul>\r\n<li><a href=\"https://media.gunmonkeynet.net/u/nybill/collection/astroai-wh5000a-dmm/\" class=\"uri\">https://media.gunmonkeynet.net/u/nybill/collection/astroai-wh5000a-dmm/</a></li>\r\n</ul>',235,0,0,'CC-BY-SA','multimeter, electronics, test equipment, hardware review',0,0,1),
(2771,'2019-03-18','Embedding hidden text in Djvu files',2476,'Part 2 of Klaatu\'s Djvu mini series','<p>\r\nTo embed text into a Djvu file, you must create a <code>djvused</code> script detailing the page and bitmap location of one of: character, word, line, paragraph, or region.\r\n</p>\r\n\r\n<p>\r\nFor good measure, you should first list the contents of your Djvu bundle:\r\n</p>\r\n\r\n<pre><code>$ djvused -e \'select; ls\' test.djvu\r\n   1 P   177062  p0001.djvu\r\n   2 P   199144  p0002.djvu\r\n   3 P    12323  p0003.djvu\r\n   4 P    57059  p0004.djvu\r\n   5 P    96725  p0005.djvu\r\n   6 P    53868  p0006.djvu\r\n</code></pre>\r\n\r\n<p>\r\nThen define the location of text in a file called, for instance, <code>content.dsed</code>. Assume that my page is 1000 px by 1000 px&#58;\r\n</p>\r\n\r\n<pre><code>select; remove-ant; remove-txt\r\n\r\nselect \"p0004.djvu\" # page 4\r\nset-txt\r\n(page 0 0 1000 1000\r\n (word 100 600 450 800 \"Hello\" )\r\n (word 100 600 450 800 \"world\" ))\r\n\r\n.\r\n\r\nselect \"p0005.djvu\"\r\nset-txt\r\n(page 0 0 1000 1000\r\n (line 100 400 900 600 \"Hacker Puppy Radio\"))\r\n</code></pre>\r\n\r\n<p>\r\nApply this script to your Djvu file with <code>dvjused</code>&#58;\r\n</p>\r\n\r\n<pre><code>djvused -f ./content.dsed -s test.djvu\r\n</code></pre>\r\n\r\n<h2>Converting from PDF to Djvu</h2>\r\n\r\n<p>\r\nYou can convert PDF files to Djvu with the <code>djvudigital</code> command. Due to license incompatibility, it does require you to compile a Ghostscript plugin, but it\'s an easy build. Get the <a href=\"https://sourceforge.net/projects/djvu/files/GSDjVu/1.10\" target=\"_blank\">gsdjvu</a> code, and then follow its README instructions.\r\n</p>\r\n\r\n<p>\r\nOnce you\'ve built the Ghostscript driver, you can convert PDF to Djvu:\r\n</p>\r\n\r\n<pre><code>djvudigital --words foo.pdf foo.djvu\r\n</code></pre>\r\n',78,0,0,'CC-BY-SA','pdf, ebook, bloat, djvu',0,0,1),
(2772,'2019-03-19','My applications and software part 3',585,'A short show about the software I use in Linux Mint','<p>Hallo HPR listeners – in my recent episodes hpr2738 and hpr2746 I talked about some of the applications and software I regularly use as part of my day to day use of Linux Mint. This follow up show will continue with a few more of the same.</p>\r\n<ul>\r\n<li><p>CUPS – Common Unix Printing Software; printing in Linux with this utility is fairly well supported, if you don’t have a very recent printer it’s a good chance that CUPS will be able to find a driver for your printer if a Linux one has not been supplied when you bought it or through the manufacturers support site. In the menu just search for print and it will bring up the application for adding a new printer.</p></li>\r\n<li><p>Gparted – fully featured disc management tool for formatting and partitioning discs</p></li>\r\n<li><p>Document viewer – generic pdf viewer</p></li>\r\n<li><p>Software manager</p>\r\n<ul>\r\n<li>Synaptic package manager</li>\r\n</ul></li>\r\n<li><p>Terminal – apt command for updating the system and installing new software</p></li>\r\n<li><p>get_iplayer</p></li>\r\n</ul>\r\n',338,0,0,'CC-BY-SA','Software, applications, utilities',0,0,1),
(2774,'2019-03-21','CJDNS and Yggdrasil',629,'A summary of the things I like about CJDNS and Yggdrasil, and the places I think they could improve.','<p>This is my first time doing this sort of thing, so I’m sorry if it’s not very good.</p>\r\n<ul>\r\n<li><a href=\"https://github.com/cjdelisle/cjdns/\">https://github.com/cjdelisle/cjdns/</a></li>\r\n<li><a href=\"https://yggdrasil-network.github.io/\">https://yggdrasil-network.github.io/</a></li>\r\n</ul>',374,0,0,'CC-BY-SA','CJDNS,Yggdrasil',0,0,1),
(2776,'2019-03-25','Sub-Plots In Storytelling',1093,'Lostnbronx looks at the importance of tightly-structured subplots in storytelling.','<p>What makes for strong subplots? Why can some subplots be chopped out of a tale without harming it? Why can some be chopped out, and it actually makes the tale stronger? Is this modular approach the best way to bring in subplots, or is there another method that might be better?</p>\r\n<p>Story construction is a complicated topic; Lostnbronx tries (and largely fails) to make sense of this small part of it.</p>\r\n',107,105,0,'CC-BY-SA','stories, storytelling, sub-plots, lostnbronx',0,0,1),
(2777,'2019-03-26','The quest for the perfect laptop.',1867,'Knightwise is out looking for a new laptop and describes what he is looking for and why.','<p>Looking for a new laptop.</p>\r\n<p>Candidates</p>\r\n<ul>\r\n<li>HP Envy x360</li>\r\n<li>Lenovo X280</li>\r\n<li>Lenovo X380</li>\r\n<li>Lenovo X380 Yoga</li>\r\n<li>Lenovo X1</li>\r\n<li>Lenovo X1 Yoga</li>\r\n</ul>\r\n',111,0,0,'CC-BY-SA','computer, hardware, geek, buy',0,0,1),
(2786,'2019-04-08','My YouTube Channels',423,'A short show about some of my YouTube channels inspired by Ahuka','<p>Hallo HPR listeners this is Tony Hughes again coming from Blackpool in the UK.</p>\r\n<p>Recently Ahuka started a series on the YouTube channels that he subscribes to and this seems like a good topic to share some of my favourite YouTube channels. This time I’ll share some of the tech and Linux based channels I watch.</p>\r\n<ul>\r\n<li><p>bigclive.com – Clive strips down and tests equipment particularly cheap Chinese electronics - <a href=\"https://www.youtube.com/user/bigclivedotcom/videos\" class=\"uri\">https://www.youtube.com/user/bigclivedotcom/videos</a></p></li>\r\n<li><p>Category5 Technology TV – A general technology based show with a large focus on Linux and open source software. <a href=\"https://www.youtube.com/user/category5tv\" class=\"uri\">https://www.youtube.com/user/category5tv</a></p></li>\r\n<li><p>Explaining Computers – Exactly what it says on the tin, they review new computer hardware and computer related tech, including single board Computers such as the Raspberry Pi and Pine 64. <a href=\"https://www.youtube.com/user/explainingcomputers\" class=\"uri\">https://www.youtube.com/user/explainingcomputers</a></p></li>\r\n<li><p>DASGeek – Ryan is a fairly new person to Linux and is part of the Destination Linux podcast crew - <a href=\"https://destinationlinux.org/\" class=\"uri\">https://destinationlinux.org/</a> Ryan is an avid gamer and as well as reviewing Linux he will often look at the latest games and how well they will work on a Linux PC. <a href=\"https://www.youtube.com/channel/UCIme1suHyN7cAGrTy8RBdhQ\" class=\"uri\">https://www.youtube.com/channel/UCIme1suHyN7cAGrTy8RBdhQ</a></p></li>\r\n<li><p>Big Daddy Linux – A new video LUG which have a new episode every week at 8pm EST or you can watch a recording of the show later. <a href=\"https://www.youtube.com/channel/UCtZRKfyvx7GUEi-Lr7f4Nxg/videos\" class=\"uri\">https://www.youtube.com/channel/UCtZRKfyvx7GUEi-Lr7f4Nxg/videos</a></p></li>\r\n<li><p>Raspberry Pi – Videos from the Foundation and community contributors. <a href=\"https://www.youtube.com/channel/UCFIjVWFZ__KhtTXHDJ7vgng/videos\" class=\"uri\">https://www.youtube.com/channel/UCFIjVWFZ__KhtTXHDJ7vgng/videos</a></p></li>\r\n<li><p>Free Audacity Tutorials – Very handy for those of us that regularly record and edit audio with Audacity, for learning more about how to do various things with this software. <a href=\"https://www.youtube.com/user/FreeAudacityTutorial/videos\" class=\"uri\">https://www.youtube.com/user/FreeAudacityTutorial/videos</a></p></li>\r\n</ul>\r\n<p>And finally for this episode</p>\r\n<ul>\r\n<li>Linus Tech Tips – Another Computer review show all about tips and tricks relating to all stuff geeky. Be aware that this show is heavily sponsored although Linus does seem to be very fair with both praise and criticism for what he is reviewing. <a href=\"https://www.youtube.com/user/LinusTechTips/videos\" class=\"uri\">https://www.youtube.com/user/LinusTechTips/videos</a></li>\r\n</ul>\r\n',338,106,0,'CC-BY-SA','Linux, Computers, YouTube, Gaming, Electronics, Audacity',0,0,1),
(2778,'2019-03-27','Functor and applicative in Haskell',1841,'Brief introduction on functor and applicative patterns in Haskell and where they can be used','<p>Two common patterns that I seem to run all the time while working on my 4x space game are functor and applicative. This episode explains them briefly.</p>\r\n<h2 id=\"functor\">Functor</h2>\r\n<p>Functor is a way to apply function over a structure we don’t want to alter. Type of the structure stays same, but values inside of it can change. One of the most common one is list, but there are many others.</p>\r\n<p>Functor type class is defined below. There’s one function <code>fmap</code> that takes two parameters: a function from <code>a</code> to <code>b</code> and structure <code>f a</code>. Result will be structure <code>f b</code>.</p>\r\n<pre><code>class Functor f where\r\n    fmap :: (a -&gt; b) -&gt; f a -&gt; f b</code></pre>\r\n<p>This is fairly abstract, so couple example might help. First we define a little helper function that raises it’s argument to 2nd power (in the episode I talk about doubling the value, my mistake there).</p>\r\n<pre><code>-- | this really raises x to 2nd power and doesn&#39;t double it\r\ndouble x = x * x</code></pre>\r\n<p>Given a list of <code>Int</code> we can raise them to power of two by using <code>fmap</code>:</p>\r\n<pre><code>&gt; fmap double [1, 2, 3, 4, 5]\r\n[1, 4, 9, 16, 25]</code></pre>\r\n<p>Since function being applied to structure is type of <code>(a -&gt; b)</code>, we can change type of the value inside of the structure. Below is example of turning list of <code>Int</code> to list of <code>Text</code>.</p>\r\n<pre><code>&gt; fmap show [1, 2, 3, 4, 5]\r\n[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;]</code></pre>\r\n<p>This pattern isn’t limited to list and there are many others. You can even define your own ones, if you’re so inclined. The pattern stays the same. One function, <code>fmap</code>, that takes function of type <code>(a -&gt; b)</code> and structure <code>f a</code> and turns it into structure of <code>f b</code>. Details how this is actually done depend on the specific functor.</p>\r\n<p>Other common functor is <code>Maybe</code> that is often used in cases where data might or might not be present. <code>Maybe a</code> has two possible values <code>Just a</code> indicating that value <code>a</code> is present and <code>Nothing</code> indicating that there is no value present. When <code>fmap</code> is used in this context, <code>Just a</code> will turn to <code>Just b</code> and <code>Nothing</code> will stay as <code>Nothing</code>.</p>\r\n<pre><code>&gt; fmap (x -&gt; x * x) $ Just 2\r\nJust 4\r\n&gt; fmap (x -&gt; x * x) Nothing\r\nNothing</code></pre>\r\n<p><code>Either a b</code> is sometimes used for value that can be correct or an error. It has two value constructors <code>Right b</code> indicates that value is correct, <code>Left a</code> indicates an error case. <code>a</code> and <code>b</code> don’t have to be of same type (and usually aren’t). For example, if we have <code>Either Text Int</code>, then we have value where error case is <code>Text</code> and correct value is <code>Int</code>.</p>\r\n<pre><code>&gt; fmap double $ Right 5\r\nRight 25\r\n&gt; fmap double $ Left &quot;distance calculation failed because of flux-capacitor malfunction&quot;\r\nLeft &quot;distance calculation failed because of flux-capacitor malfunction&quot;</code></pre>\r\n<p>Functors can be placed inside of functors. The only difference is that you have to reach through multiple layers. Simplest way of doing that is to compose multiple <code>fmap</code> functions together like in the example below. Pay attention to in which order nested functors are defined as <code>Maybe [Int]</code> and <code>[Maybe Int]</code> are different things. Former is for case where list of <code>Int</code> might or might not be present. Latter is for case where there’s always list, but single element inside of the list might or might not be present.</p>\r\n<pre><code>&gt; (fmap . fmap) double (Just [1, 2, 3, 4])\r\nJust [1, 4, 9, 16]\r\n&gt; (fmap . fmap) double Nothing :: Maybe Int\r\nNothing\r\n&gt; (fmap . fmap) double [Just 1, Just 2, Nothing, Just 3]\r\n[Just 1, Just 4, Nothing, Just 9]</code></pre>\r\n<p>There’s also infix operator, that does exactly same thing as <code>fmap</code>, called <code>&lt;$&gt;</code>. The choice which one to use is often either personal or depends on the surrounding code (because Haskell doesn’t use parenthesis in function application, so sometimes it’s easier to use <code>fmap</code> and sometimes <code>&lt;$&gt;</code>).</p>\r\n<pre><code>&gt; fmap show [1, 2, 3, 4, 5]\r\n[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;]\r\n\r\n&gt; show &lt;$&gt; [1, 2, 3, 4, 5]\r\n[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;]</code></pre>\r\n<p>There are many more functors, one place to check them is: <a href=\"https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor.html\" class=\"uri\">https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Functor.html</a></p>\r\n<h2 id=\"applicative\">Applicative</h2>\r\n<p>While functor works fine when function applied has only one parameter, we need applicative in cases of multiparameter functions. Calling <code>fmap (+) [1, 2]</code> will produce list of functions waiting for second parameter. While it would be possible to handle these cases manually, we like to abstract it to more general solution.</p>\r\n<pre><code>class Functor f =&gt; Applicative f where\r\n    pure :: a -&gt; f a\r\n    (&lt;*&gt;) :: f (a -&gt; b) -&gt; f a -&gt; f b</code></pre>\r\n<p>Applicative is similar to functor. The big difference is that function being applied is now embedded inside of same type of structure. While functor has <code>(a -&gt; b)</code>, applicative has <code>f (a -&gt; b)</code>.</p>\r\n<p>Below is an example of using list applicative to calculate all possible ways of summing two lists of <code>Int</code>.</p>\r\n<pre><code>&gt; (+) &lt;$&gt; [1, 2, 3] &lt;*&gt; [4, 5, 6]\r\n[5,6,7,6,7,8,7,8,9]</code></pre>\r\n<p><code>Maybe Int</code> works with the same pattern. First we use <code>&lt;$&gt;</code> to get started, this results <code>Maybe</code> containing a function that is waiting for second parameter. Then we use <code>&lt;*&gt;</code> to apply the second parameter so we get the result.</p>\r\n<pre><code>&gt; (+) &lt;$&gt; Just 2 &lt;*&gt; Just 5\r\nJust 7\r\n&gt; (+) &lt;$&gt; Just 2 &lt;*&gt; Nothing\r\nNothing</code></pre>\r\n<p>As long as there’s only <code>Just a</code> in play, result is <code>Just</code>, but as soon as there’s even single <code>Nothing</code> the end result will be nothing.</p>\r\n<p>If you have questions or comments, I would be delighted to hear about them. You can catch me on fediverse, where I’m <code>Tuula@mastodon.social</code>. Even better, you could record your own HPR episode.</p>\r\n<p>Ad astra!</p>\r\n',364,107,0,'CC-BY-SA','haskell, functor, applicative',0,0,1),
(2779,'2019-03-28','HTTP, IPFS, and torrents',711,'Replacing the web with new, decentralized protocols','<p>Some ramblings about how we might replace HTTP with more robust, decentralized protocols.</p>\r\n<ul>\r\n<li><a href=\"https://en.wikipedia.org/wiki/InterPlanetary_File_System\">https://en.wikipedia.org/wiki/InterPlanetary_File_System</a></li>\r\n<li><a href=\"https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol\">https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol</a></li>\r\n</ul>',374,0,0,'CC-BY-SA','HTTP, IPFS, torrents',0,0,1),
(2780,'2019-03-29','My SBC Nextcloud Install Pt. 1 - Hardware',1375,'How I built my self-enclosed Nextcloud server using a single board computer and a RAID enclosure','<p>I explain the build process for my home Nextcloud server using a single board computer and a 4 bay RAID enclosure. This is part 1 of a 3 part series.</p>\r\n<p>My parts list for the server build:</p>\r\n<ul>\r\n<li><p>Rockpro64<br />\r\n<a href=\"https://www.pine64.org/?product=rockpro64-4gb-single-board-computer\" class=\"uri\">https://www.pine64.org/?product=rockpro64-4gb-single-board-computer</a></p></li>\r\n<li><p>eMMC module<br />\r\n<a href=\"https://www.pine64.org/?product=16gb-emmc\" class=\"uri\">https://www.pine64.org/?product=16gb-emmc</a></p></li>\r\n<li><p>USB Adapter for eMMC module<br />\r\n<a href=\"https://www.pine64.org/?product=usb-adapter-for-emmc-module\" class=\"uri\">https://www.pine64.org/?product=usb-adapter-for-emmc-module</a></p></li>\r\n<li><p>Power supply<br />\r\n<a href=\"https://www.pine64.org/?product=rockpro64-12v-5a-us-power-supply\" class=\"uri\">https://www.pine64.org/?product=rockpro64-12v-5a-us-power-supply</a></p></li>\r\n<li><p>Heatsink<br />\r\n<a href=\"https://www.pine64.org/?product=rockpro64-20mm-mid-profile-heatsink\" class=\"uri\">https://www.pine64.org/?product=rockpro64-20mm-mid-profile-heatsink</a></p></li>\r\n<li><p>90˚ male to female USB extension<br />\r\n<a href=\"https://www.amazon.com/wawpi-Cable-Extension-Degree-Female/dp/B01EDOGO4E\" class=\"uri\">https://www.amazon.com/wawpi-Cable-Extension-Degree-Female/dp/B01EDOGO4E</a></p></li>\r\n<li><p>4 bay RAID enclosure<br />\r\n<a href=\"https://www.mediasonic.ca/product.php?id=1358153144\" class=\"uri\">https://www.mediasonic.ca/product.php?id=1358153144</a></p></li>\r\n<li><p>HDDs<br />\r\nThe 4TB HDDs were ones I already had but you can use any ones, just make sure they are the same brand/model/size/etc to minimize any complications.</p></li>\r\n</ul>\r\n<p>minnix at uymail dot com for help, questions, or just general chatter</p>\r\n',375,0,0,'CC-BY-SA','nextcloud,single board computer,home server,sbc,arm',0,0,1),
(2783,'2019-04-03','The Windows \"Shutdown.exe\" Command Explained',923,'A rundown of the Windows \"shutdown.exe\" command.','<h3>Shutdown.exe</h3>\r\n<ul>\r\n<li>Introduced in Windows 2000 as a way to shutdown the PC via the command prompt.</li>\r\n<li>Included in all versions since Windows 2000 all the way to Windows 10 and Windows Server 2019.</li>\r\n<li>ReactOS, the open source binary-compatible clone of Windows, also includes the shutdown.exe command and the commands are the same.</li>\r\n<li>Located in %windir%\\System32. The variable %windir% is usually c:\\windows. In ReactOS, the variable is usually c:\\reactos (failed to mention this in the recording).\r\n</li>\r\n</ul>\r\n<p>Links: </p>\r\n<ul>\r\n<li><a href=\"https://ipfs.io/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Shutdown.exe.html\">https://ipfs.io/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Shutdown.exe.html</a></li>\r\n<li><a href=\"https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/shutdown\">https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/shutdown</a></li>\r\n<li><a href=\"https://ss64.com/nt/shutdown.html\">https://ss64.com/nt/shutdown.html</a></li>\r\n<li><a href=\"https://en.wikipedia.org/wiki/Shutdown_(computing)#Windows_and_ReactOS\">https://en.wikipedia.org/wiki/Shutdown_(computing)#Windows_and_ReactOS</a></li>\r\n</li>\r\n</ul>\r\n',152,0,0,'CC-BY-SA','shutdown, windows, commandprompt, cmd',0,0,1),
(2805,'2019-05-03','My 50th Show',1064,'This is a review of the other 49 shows I\'ve posted in the last 3 years','<p>Hallo this is again Tony Hughes for HPR. This is an auspicious show for me as it’s my 50th show that I have recorded and released on HPR in my own right. However prior to my 1st show in my own right I did guest on 2 shows.</p>\r\n<p>The first of these was:</p>\r\n<ul>\r\n<li>hpr0844 :: The Flying Handbag hosted by HPR Volunteers<br />\r\nReleased: 2011-10-26</li>\r\n</ul>\r\n<p>Which was a show that was recorded at Barcamp Blackpool in 2011, when a group of us got together to record a podcast, the hilarious thing was that the only place we could find to record was a stairwell which happened to be next to the toilets, definitely not family friendly but if you want a laugh have a listen.</p>\r\n<p>The next show I appeared on was an interview I did with Ken Fallon at my first OggCamp in the same year.</p>\r\n<ul>\r\n<li>hpr0863 :: Tony Hughes Free Cycle hosted by Ken Fallon<br />\r\nReleased: 2011-11-22.</li>\r\n</ul>\r\n<p>Ken was as usual trying to recruit new hosts and interviewed me with the hope that I would become one. Well I did but it took another 5 years before I finally recorded my first show in my own right.</p>\r\n<p>First just to say the idea for this show comes from hpr2700 in which Ken created a script to automate the bot voice reading a list of every show that has been released on HPR, so to celebrate my 50th Show I thought I would list my shows but with me running through them and do a brief summary of the show where appropriate.</p>\r\n<ol type=\"1\">\r\n<li><p>hpr2051 :: My Linux Journey<br />\r\nReleased on 2016-06-13<br />\r\nin this episode I talked about my journey in computing and starting to use Linux</p></li>\r\n<li><p>hpr2056 :: Interview with a young hacker<br />\r\nReleased on 2016-06-20<br />\r\nThis was my first of several interviews with <span class=\"citation\" data-cites=\"All_about_Code\">@All_about_Code</span> at my local Raspberry Jam</p></li>\r\n<li><p>hpr2065 :: Whats in My Bag<br />\r\nReleased on 2016-07-01<br />\r\nLooking at this show so tells me I have to redo this show as my bag is very different these days</p></li>\r\n<li><p>hpr2076 :: What Magazines I read Part 1<br />\r\nReleased on 2016-07-18<br />\r\njust what the title said, I talked about the magazines I was reading at that point in time.</p></li>\r\n<li><p>hpr2087 :: Magazines I read Part 2<br />\r\nReleased on 2016-08-02<br />\r\nThis was a follow up of the last show</p></li>\r\n<li><p>hpr2097 :: New Toys<br />\r\nReleased on 2016-08-16<br />\r\nI talked about my hardware journey over the last 30 odd years and talked about the i7 system I had just bought 2nd hand</p></li>\r\n<li><p>hpr2101 :: What’s on my podcatcher<br />\r\nReleased on 2016-08-22<br />\r\nA show about the podcasts I listen to.</p></li>\r\n<li><p>hpr2144 :: An Interview with All About Code at Manchester BarCamp<br />\r\nReleased on 2016-10-20<br />\r\na follow up interview with Josh</p></li>\r\n<li><p>hpr2151 :: BarCamp Manchester part 2<br />\r\nReleased on 2016-10-31<br />\r\nAn interview with Claire, the organiser of BarCamp Manchester.</p></li>\r\n<li><p>hpr2157 :: BarCamp Manchester part 3<br />\r\nReleased on 2016-11-08<br />\r\nThis was an interview with Alan O’Donohoe who had started the Raspberry Jam movement</p></li>\r\n<li><p>hpr2257 :: Watt OS<br />\r\nReleased on 2017-03-28<br />\r\nAcer Aspire One Netbook – Review</p></li>\r\n<li><p>hpr2265 :: WattOS on Lenovo X61s<br />\r\nReleased on 2017<br />\r\nLenovo X61s – Review</p></li>\r\n<li><p>hpr2271 :: Raspberry Pi Zero W<br />\r\nReleased on 2017-04-17<br />\r\nReview Episode on the then New Pi Zero W</p></li>\r\n<li><p>hpr2280 :: Lenovo X61s Part 2<br />\r\nReleased on 2017-04-28<br />\r\nFollow up review after a SSD upgrade and using Linux Lite</p></li>\r\n<li><p>hpr2286 :: Surviving a Stroke<br />\r\nReleased on 2017-05-08<br />\r\nA very personal episode about my surviving a Stroke in February 2017</p></li>\r\n<li><p>hpr2295 :: MX Linux<br />\r\nReleased on 2017-05-19<br />\r\nA review episode using this OS on a Lenovo X230i after a hardware boot issue with Linux Mint and an SSD</p></li>\r\n<li><p>hpr2331 :: Liverpool Makefest 2017 Show 1<br />\r\nReleased on 2017-07-10<br />\r\nThe first of a number of interview shows from the 2017 Liverpool Makefest</p></li>\r\n<li><p>hpr2336 :: Liverpool Makefest 2017 Show 2<br />\r\nReleased on 2017-07-17</p></li>\r\n<li><p>hpr2341 :: Liverpool Makefest 2017 Show 3<br />\r\nReleased on 2017-07-24</p></li>\r\n<li><p>hpr2346 :: Liverpool Makefest 2017 Show 4<br />\r\nReleased on 2017-07-31</p></li>\r\n<li><p>hpr2352 :: Liverpool Makefest 2017 Show 5<br />\r\nReleased on 2017-08-08</p></li>\r\n<li><p>hpr2362 :: Raspbian X86 on Lenovo x61s<br />\r\nReleased on 2017-08-22<br />\r\nReview of Raspbian X86 on a Lenovo X61s</p></li>\r\n<li><p>hpr2366 :: Making Bramble Jelly<br />\r\nReleased on 2017-08-28<br />\r\nJust what it says on the tin I talk about making Bramble jelly,</p></li>\r\n<li><p>hpr2374 :: How to Make Sauerkraut<br />\r\nReleased on 2017-09-07<br />\r\nAnother food show on how to make Sauerkraut</p></li>\r\n<li><p>hpr2380 :: Raspbian X86 on P4 Tower<br />\r\nReleased on 2017-09-15<br />\r\nFollow up this time running Raspbian X86 on an old P4 Tower</p></li>\r\n<li><p>hpr2405 :: Nokia 6 Review<br />\r\nReleased on 2017-10-20<br />\r\nI reviewed my new phone</p></li>\r\n<li><p>hpr2432 :: Living with the Nokia 6 – an update to HPR 2405<br />\r\nReleased on 2017-11-28<br />\r\nFollow up update show having lived with the phone for a couple of months.</p></li>\r\n<li><p>hpr2442 :: The sound of Woodbrooke Quaker Study centre in the Spring<br />\r\nReleased on 2017-12-12<br />\r\nThis was a soundscape recording I made at Woodbrooke Quaker Study Centre in Birmingham UK while I was there in April 2017.</p></li>\r\n<li><p>hpr2579 :: Ubuntu 18.04 Mate<br />\r\nReleased on 2018-06-21<br />\r\nA review of the recently released Ubuntu 18.04 Mate</p></li>\r\n<li><p>hpr2590 :: Blowing a PC Power Supply<br />\r\nReleased on 2018-07-06<br />\r\nA show about how not to blow your PC power supply</p></li>\r\n<li><p>hpr2595 :: New laptop bargain?<br />\r\nReleased on 2018-07-13<br />\r\nA review on my recently purchased secondhand Toshiba Z30 laptop</p></li>\r\n<li><p>hpr2601 :: Liverpool Makerfest 2018<br />\r\nReleased on 2018-07-23<br />\r\nChris Dell</p></li>\r\n<li><p>hpr2606 :: Liverpool Makefest 2018 - interview with Dan Lynch<br />\r\nReleased on 2018-07-30<br />\r\nA podcast Legend</p></li>\r\n<li><p>hpr2612 :: Liverpool Makefest 2018 - interview with Joe aka Concrete Dog<br />\r\nReleased on 2018-08-07<br />\r\nAbout Rocketry</p></li>\r\n<li><p>hpr2616 :: Liverpool Makefest 2018 - interview with Josh - A.K.A - All About Code<br />\r\nReleased on 2018-08-13.<br />\r\nThis is another short interview recorded at Liverpool Makefest, with Josh talking about EduBlocks.</p></li>\r\n<li><p>hpr2621 :: Liverpool Makefest 2018 - Chan’nel Thomas a.k.a little pink maker<br />\r\nReleased on 2018-08-20<br />\r\nI talk to Chan’nel Thomas aka little pink maker.</p></li>\r\n<li><p>hpr2626 :: Liverpool Makefest 2018 - interviews with Helen and Chris<br />\r\nReleased on 2018-08-27<br />\r\nIn this episode I talk to Helen from Manchester Hackspace and Chris from Wirral Code Club</p></li>\r\n<li><p>hpr2632 :: Liverpool Makefest 2018 - interviews with Robert and Carl<br />\r\nReleased on 2018-09-04<br />\r\nIn this episode I talk to Robert from Roberts Workshop and Carl from Edgehill University</p></li>\r\n<li><p>hpr2636 :: Liverpool Makefest 2018 - interviews with Noel from JMU FabLab<br />\r\nReleased on 2018-09-10</p></li>\r\n<li><p>hpr2641 :: Liverpool Makefest 2018 - interview with Rachel from the MicroBit Foundation<br />\r\nReleased on 2018-09-17</p></li>\r\n<li><p>hpr2646 :: Liverpool Makefest 2018 - Interview with Steve and Gerrard from the Liverpool Astronomical society.<br />\r\nReleased on 2018-09-24</p></li>\r\n<li><p>hpr2652 :: Liverpool Makefest 2018 - Interview with Caroline and John<br />\r\nReleased on 2018-10-02 under a CC-BY-SA license.<br />\r\nThis was the final interview from Makefest 2018 in Liverpool. In this interview I interview one of the founder members of Makefest, Caroline Keep, and the Head Teacher of the school where she works, John Carling.</p></li>\r\n<li><p>hpr2663 :: Short review on a 2.5 inch SSD/HDD caddy<br />\r\nReleased on 2018-10-17<br />\r\nQuick hardware review</p></li>\r\n<li><p>hpr2702 :: Audacity set up and response to episode 2658<br />\r\nReleased on 2018-12-11<br />\r\nI post my response to show 2658 by Dave and Al</p></li>\r\n<li><p>hpr2735 :: Soffritto<br />\r\nReleased on 2019-01-25<br />\r\nAnother food show</p></li>\r\n<li><p>hpr2738 :: My Applications<br />\r\nReleased on 2019-01-30<br />\r\nThis and my 47th episode were about the applications I use in Linux</p></li>\r\n<li><p>hpr2746 :: My software part 2<br />\r\nReleased on 2019-02-11</p></li>\r\n<li><p>hpr2772 :: My applications and software part 3<br />\r\nA short show about the software I use in Linux Mint</p></li>\r\n<li><p>hpr2786 :: My YouTube Channels<br />\r\nA short show about some of my YouTube channels inspired by Ahuka</p></li>\r\n</ol>\r\n<p><a href=\"https://hackerpublicradio.org/correspondents/0338.html\" class=\"uri\">https://hackerpublicradio.org/correspondents/0338.html</a></p>\r\n',338,0,0,'CC-BY-SA','HPR, Linacityux, podcasting, Audacity',0,0,1),
(2784,'2019-04-04','The Yamaha Disklavier',1440,'I talk about the Yamaha Disklavier DKC500RW that\'s in my office at work','<p>In this episode I talk about the <a href=\"https://en.wikipedia.org/wiki/Disklavier\" target=\"_blank\">Yamaha Disklavier</a> DKC500RW that\'s in my office at work. This is a very high-tech player piano and one of the coolest pieces of music gear I\'ve ever seen.</p>\r\n\r\n<h3>Photo Album (click image)</h3>\r\n\r\n<p><a data-flickr-embed=\"true\"  href=\"https://www.flickr.com/photos/137675441@N05/albums/72157707383776874\" title=\"Yamaha Disklavier\" target=\"_blank\"><img src=\"https://farm8.staticflickr.com/7862/33424303208_c9f831fce7.jpg\" width=\"500\" height=\"375\" alt=\"Yamaha Disklavier\"></a></p>\r\n\r\n<h2>Links</h2>\r\n\r\n<ul>\r\n<li>Website showing how to determine which model disklavier you have: <a href=\"https://yamahaden.com/news/disklavier-tips/item/276-how-to-determine-your-disklavier-model/276-how-to-determine-your-disklavier-model\" target=\"_blank\">Yamahaden</a></li>\r\n<li><a href=\"https://www.kuhmann.com/Yamaha.htm\" target=\"_blank\">DisklavierTM  World</a>: This is a privately operated, Public Service (non-profit) webpage. 10,781 piano-music files in \'FIL\' (e-SEQ) & MIDI format & Software for the Yamaha Disklavier. PUBLIC-DOMAIN / \'Live\' MIDI-Performances / FREE Sequences</li>\r\n<li>Video: Jonathan Kulp, <em>Three Easy Pieces for Piano Four-Hands</em>: <a href=\"https://www.youtube.com/watch?v=y4loSIApjPA\" target=\"_blank\">Video of premiere performance</a></li>\r\n<li>Video: <a href=\"https://youtu.be/_hNzz_DubCo\" target=\"_blank\">Disklavier in action</a></li>\r\n</ul>',238,0,1,'CC-BY-SA','Music, Piano, Keyboard, Musical Instruments, Player Pianos, Recording Devices',0,0,1),
(2810,'2019-05-10','Wi-Fi on Android',462,'Ken fixes an Android Firewalled Wi-Fi connection that reports no Internet and won’t connect','<h3>Background</h3>\r\n<p>\r\nYou\'re running a firewall on your work and home networks right, so of course you\'re running one on your Smart Phone. Given this device holds more information about you than you probably know yourself, it would be only prudent to make sure that you are protecting what gets in but also what gets out.\r\n</p>\r\n<p>\r\nI run <a href=\"https://f-droid.org/en/packages/dev.ukanth.ufirewall/\">AFWall+</a> which is available from the <a href=\"https://f-droid.org/\">F-Droid</a> app store. It runs fine on <a href=\"https://www.lineageos.org/\">LineageOS</a>.\r\n</p>\r\n<p>\r\nI then set it on the children\'s phone so that no application is allowed to use mobile data, and then only applications that need Internet get Internet Access. This works well as it\'s a normal use case for mobile applications to have intermittent access to the Internet.\r\n</p>\r\n<p>\r\nI see no reason why the Linux Kernel should need unfettered access to the Internet, so it\'s not allowed out. One issue you may come across is that even though you know that there is a Connection your phone doesn\'t, and so it will display the <em>Wi-Fi Connected, no Internet</em> message. \r\n</p>\r\n<p>\r\n<img src=\"https://hackerpublicradio.org/eps/hpr2810_1.png\" />\r\n</p>\r\n<p>\r\nI\'m not sure how this check is done but <a href=\"https://android.stackexchange.com/users/53535/abqnm\">abqnm</a> suggests at in the StackExchange question <a href=\"https://android.stackexchange.com/questions/63481/how-does-android-determine-if-it-has-an-internet-connection\">How does Android determine if it has an Internet connection?</a> that it may be related to Google Cloud Messaging.\r\n</p>\r\n\r\n<quote>\r\n... this means that the device is unable to receive a response from GCM (Google Cloud Messaging, the framework that handles push notifications). This traffic is sent through ports 5228, 5229, and 5230. If the AP is blocking or interfering with traffic on those ports, push notifications won\'t work ... \r\n<quote>\r\n<p>\r\nI do indeed see blocked attempts by Google Play Services on my own phone, but not on the other phones that have no google services installed. The only entry I see in the logs is an ICMP attempt to \"Comcast Cable Communications, Inc\". If you know more please record a show for <a href=\"https://hackerpublicradio.org\">Hacker Public Radio</a> about it.\r\n</p>\r\n\r\n<h3>Giving Access</h3>\r\n<p>\r\nNormally you will get a message saying that the Wi-Fi has no Internet access. \r\n</p>\r\n<p>\r\n<img alt=\"Android System. Wi-Fi has no Internet access. Tap for options\" src=\"https://hackerpublicradio.org/eps/hpr2810_2.png\" />\r\n</p>\r\n<p>\r\nIf you tap the message a popup will allow you to stay connected and will let you remember the choice.\r\n</p>\r\n<p>\r\n<img alt=\"OpenWireless.Org. This network has no Internet access. Stay connected? [] Don\'t ask again for this network NO YES\" src=\"https://hackerpublicradio.org/eps/hpr2810_3.png\" />\r\n</p>\r\n<p>\r\nIn some cases the router helpfully resets the connection before you can reply to the message meaning it goes into a loop continually popping up the message but not reacting to it.\r\n</p>\r\n<p>\r\nIn this case we can use <a href=\"https://f-droid.org/en/packages/com.termux/\">Termux</a> a Android Terminal emulator, to drop to a shell and fix the problem.\r\n</p>\r\n<p>\r\n<img src=\"https://hackerpublicradio.org/eps/hpr2810_4.png\" />\r\n</p>\r\n\r\n<p>\r\nI used <em>su</em> to get root access but you could also change to the user <em>wifi</em>.\r\n</p>\r\n<p>\r\nThe file you need to edit is <strong>/data/misc/wifi/wpa_supplicant.conf</strong>. It\'s probably best to edit this file with the wifi off.\r\n</p>\r\n<pre>\r\nnetwork={\r\n	ssid=\"OpenWireless.Org\"\r\n	key_mgmt=NONE\r\n	priority=15\r\n	id_str=\"{snip}\"\r\n}\r\n</pre>\r\n<p>\r\nScroll down to the network that is giving you trouble and add <strong>disabled=1</strong>\r\n</p>\r\n<pre>\r\nnetwork={\r\n	ssid=\"OpenWireless.Org\"\r\n	key_mgmt=NONE\r\n	priority=15\r\n	disabled=1\r\n	id_str=\"{snip}\"\r\n}\r\n</pre>\r\n<p>\r\nI ended up copying the file to the sdcard, and editing it there. I then copied it back as su and used <strong>chown wifi:wifi /data/misc/wifi/wpa_supplicant.conf</strong> to fix the permissions.\r\n</p>\r\n\r\n<p>\r\nOnce that\'s done you can reboot the phone and connect to the network without a problem. You should also consider putting up an <a href=\"https://openwireless.org/\">Open Wireless</a> access point yourself.\r\n</p>\r\n',30,0,1,'CC-BY-SA','Android, fdroid, lineageos, AFWall+, Wi-Fi, wpa_supplicant.conf, termux',0,0,1),
(2787,'2019-04-09','NodeJS Part 1',613,'I don\'t know Javascript do ?','<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><a href=\"https://github.com/crazy-max/nodejs-portable\" class=\"uri\">https://github.com/crazy-max/nodejs-portable</a></li>\r\n<li><a href=\"https://github.com/GoogleChrome/puppeteer\" class=\"uri\">https://github.com/GoogleChrome/puppeteer</a></li>\r\n</ul>\r\n',36,0,0,'CC-BY-SA','NodeJS,puppeteer,programming,Javascript',0,0,1),
(2796,'2019-04-22','IRS,Credit Freezes and Junk Mail Ohh My!',746,'IRS Credit Freezes and Junk Mail','<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><p><a href=\"https://darknetdiaries.com/episode/26/\" class=\"uri\">https://darknetdiaries.com/episode/26/</a></p></li>\r\n<li><a href=\"https://clark.com/personal-finance-credit/credit-freeze-and-thaw-guide/\" class=\"uri\">https://clark.com/personal-finance-credit/credit-freeze-and-thaw-guide/</a></li>\r\n<li><a href=\"https://clark.com/personal-finance-credit/free-credit-freezes/\" class=\"uri\">https://clark.com/personal-finance-credit/free-credit-freezes/</a></li>\r\n<li><p><a href=\"https://clark.com/consumer-issues-id-theft/opting-out-of-assorted-junk-mailings/\" class=\"uri\">https://clark.com/consumer-issues-id-theft/opting-out-of-assorted-junk-mailings/</a></p></li>\r\n<li><p><a href=\"https://www.youtube.com/watch?v=zWVoyrzqRbU\" class=\"uri\">https://www.youtube.com/watch?v=zWVoyrzqRbU</a> DROP HOE!</p></li>\r\n</ul>\r\n',36,0,0,'CC-BY-SA','IRS,Credit Freeze,Junk Mail,hacking',0,0,1),
(2788,'2019-04-10','Looping in Haskell',2848,'Tuula describes some loop-like constructs in Haskell','<p>Haskell is functional language where data is immutable. This means that regular for-loops don’t really exist. Looping however is very common pattern in programs in general. Here are some patterns how to do that in Haskell.</p>\r\n<h2 id=\"recursion\">Recursion</h2>\r\n<p>Calculating Fibonacci numbers is common example (sort of like hello world in Haskell). There’s many different implementations at https://wiki.haskell.org/The_Fibonacci_sequence if you’re interested on having a look.</p>\r\n<p>Simple recursive definition:</p>\r\n<pre><code>fibs :: Integer -&gt; Integer\r\nfibs 0 = 0\r\nfibs 1 = 1\r\nfibs n = fibs (n-1) + fibs (n-2)</code></pre>\r\n<p>When called with <code>0</code> result is <code>0</code>. When called with <code>1</code> result is <code>1</code>. For all other cases, <code>fibs</code> is called with values <code>n-1</code> and <code>n-1</code> and the results are summed together. This works fine when <code>n</code> is small, but calculation gets slow really quickly with bigger values.</p>\r\n<p>Another way is to define list of all Fibonacci numbers recursively:</p>\r\n<pre><code>allFibs :: [Integer]\r\nallFibs = 0 : 1 : zipWith (+) allFibs (tail allFibs)</code></pre>\r\n<p>Here a list is constructed. First element is <code>0</code>, second element is <code>1</code> and rest of the list is obtained by summing the list with its tail (everything but the first element of the list). Definition is recursive and defines all Fibonacci numbers. However, Haskell doesn’t evaluate whole list, but only as much of it as is required.</p>\r\n<p>Common pattern of processing elements in a list, producing a new list:</p>\r\n<pre><code>addOne :: [Integer] -&gt; [Integer]\r\naddOne [] = []\r\naddOne (x:xs) = x + 1 : addOne xs</code></pre>\r\n<p>Two cases, when called with an empty list <code>[]</code>, result is empty list. For all other cases, list is taken apart <code>(x:xs)</code>, <code>x</code> contains first element of the list and <code>xs</code> is rest of the list. Body of the function creates a new list where head is <code>x + 1</code> and tail is <code>addOne xs</code>. This processes whole list of <code>Integer</code> by adding one to each value. It also reverses the list.</p>\r\n<p>Second common pattern is processing a list and reducing it to a single value:</p>\r\n<pre><code>sumAll :: Integer -&gt; [Integer] -&gt; Integer\r\nsumAll n [] = n\r\nsumAll n (x:xs) = sumAll (n + x) xs</code></pre>\r\n<p>If given list is empty (the terminal case), result is <code>n</code>. Second case again takes list apart <code>(x:xs)</code>, adds <code>x</code> and <code>n</code> together and recursive call <code>sumAll</code> with tail of the list.</p>\r\n<p>This common pattern is discarding some elements of a list:</p>\r\n<pre><code>evenOnly :: [Integer] -&gt; [Integer]\r\nevenOnly [] = []\r\nevenOnly (x:xs) = \r\n    if even x\r\n        then x : evenOnly xs\r\n        else evenOnly xs</code></pre>\r\n<p>Again, result of empty list is just empty list. In all other cases we first check if <code>x</code> is even. If so, new list is constructed where head is <code>x</code> and tail is <code>evenOnly xs</code>. If <code>x</code> isn’t even, it’s discarded and <code>evenOnly</code> is called recursively with tail of the list.</p>\r\n<h2 id=\"more-tools\">More tools</h2>\r\n<p>Writing recursion by hand gets tedious and sometimes confusing (if you listened to the show, you probably noticed how I got confused and had to check that <code>evenOnly</code> actually works as I thought it would). For that reason, there are tools that abstract these common patterns and given them names.</p>\r\n<p>First is <code>map</code>. It applies given function to each element of a list, thus producing a new list:</p>\r\n<pre><code>&gt; map (+1) [1..10]\r\n[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]\r\n&gt; map odd [1..10]\r\n[True, False, True, False, True, False, True, False, True, False]</code></pre>\r\n<p>Second is <code>fold</code>. There is good article at https://wiki.haskell.org/Foldr_Foldl_Foldl%27 that talks about differences between different folds.</p>\r\n<p>The basic idea behind each fold is the same, they take a function and initial value and then apply them to first element of list, producing a value. This value is then applied with the function to the second element of the list and so on, until whole list has been reduced to a single value. Calculating a sum of list is so common operation that there’s specific function for that: <code>sum</code>.</p>\r\n<pre><code>&gt; foldr (+) 0 [1..10]\r\n55\r\n&gt; foldl (+) 0 [1..10]\r\n55\r\n&gt; sum [1..10]\r\n55</code></pre>\r\n<p><code>scan</code> is similar to <code>fold</code>, except for returning only the final value, it also returns intermediate ones. Here it’s easier to observe how <code>scanr</code> and <code>scanl</code> differ from each other:</p>\r\n<pre><code>&gt; scanr (+) 0 [1..10]\r\n[55,54,52,49,45,40,34,27,19,10,0]\r\n&gt; scanl (+) 0 [1..10]\r\n[0,1,3,6,10,15,21,28,36,45,55]</code></pre>\r\n<p>Last of the trifecta is <code>filter</code> that is used to select some of the elements in a list based on a supplied function.</p>\r\n<pre><code>&gt; filter odd [1..10]\r\n[1, 3, 5, 7, 9]\r\n&gt; filter even [1..]\r\n[2, 4, 6, 8, 10, 12, 14, 16...]\r\n&gt; take 5 $ filter even [1..] \r\n[2, 4, 6, 8, 10]</code></pre>\r\n<h2 id=\"even-more-tools\">Even more tools</h2>\r\n<p>There are even more tools at our disposal. Prelude is basic library of Haskell and browsing online documentation at https://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html might yield interesting information.</p>\r\n<p>For example, constructing some lists:</p>\r\n<ul>\r\n<li><code>iterate :: (a -&gt; a) -&gt; a -&gt; [a]</code> For list where function is applied repeatedly.</li>\r\n<li><code>repeat :: a -&gt; [a]</code> for a list that contains infinite amount of <code>a</code>.</li>\r\n<li><code>replicate :: Int -&gt; a -&gt; [a]</code> For a list that contains finite amount of <code>a</code>.</li>\r\n<li><code>cycle :: [a] -&gt; [a]</code> For a infinite list that repeats same list over and over again.</li>\r\n</ul>\r\n<h2 id=\"finding-tools\">Finding tools</h2>\r\n<p>It’s all about knowing the right tools and finding them when needed. Luckily, you don’t have to memorize big stack of notes, but can turn to https://hoogle.haskell.org/ which is Haskell API search engine. It can search based on name or type signature. I often use it to find out if somebody has already written a function that I’m thinking of writing myself.</p>\r\n<p>If you want to send questions or comments, I can be reached with email or at fediverse where I’m Tuula@mastodon.social. This episode is direct result of feedback that I got from previous one. If there’s Haskell topic you would love to hear more, drop me line or even better, research it by yourself and make a cool Hacker Public Radio episode.</p>\r\n',364,107,0,'CC-BY-SA','haskell, programming',0,0,1),
(2789,'2019-04-11','Pacing In Storytelling',998,'Lostnbronx takes a stab at explaining why the pace of your story matters.','<p>Some stories, that are otherwise cookie-cutter in form, possessing familiar situations and clichéd characters, seem to nonetheless stand out. Other tales that might have great ideas, intriguing plots, and vivid characters, seem to hit the ground with a thud. The determining value here may lie with the pacing of the story.</p>\r\n<p>How does pacing (that is, timing) affect your story? Why does it matter? Can you make improvements in the pace by moving things around? What’s the best approach for creating it to begin with?</p>\r\n<p>Lostnbronx meanders for a while, often losing his way, and rarely making a coherent point regarding this complicated topic.</p>',107,105,0,'CC-0','stories, storytelling, pacing, lostnbronx',0,0,1),
(2791,'2019-04-15','LUKS like truecrypt',1523,'Klaatu demonstrates how to use LVM and cryptsetup to create and use portable encrypted filesystems','<p>\r\nCreate an empty file of a predetermined size:\r\n</p>\r\n\r\n<pre><code>$ fallocate --length 512M foo.img\r\n</code></pre>\r\n<p>Create a LUKS container on it:</p>\r\n<pre><code>$ cryptsetup --verify-passphrase luksFormat foo.img\r\n</code></pre>\r\n<p>Set it up:</p>\r\n<pre><code>$ sudo cryptsetup luksOpen foo.img foo\r\n$ ls /dev/mapper\r\nfoo\r\n$\r\n</code></pre>\r\n<p>Make a file system on it:</p>\r\n<pre><code>$ sudo mkfs.ext2 /dev/mapper/foo\r\n</code></pre>\r\n<p>If you don\'t need it for anything now, you can close it:\r\n</p>\r\n<pre><code>$ sudo cryptsetup luksClose foo\r\n$ ls /dev/mapper\r\n$\r\n</code></pre>\r\n<p>Mount it as a usable filesystem:</p>\r\n<pre><code>$ sudo mkdir /crypt\r\n$ sudo mount /dev/mapper/foo /crypt\r\n</code></pre>\r\n<p>\r\nDepending on your system configuration, you may need to set up reasonable permissions:\r\n</p>\r\n<pre><code>$ sudo mkdir /crypt/mystuff\r\n$ sudo chown klaatu:users /crypt/mystuff\r\n$ sudo chmod 770 /crypt/mystuff\r\n$ echo \"hello world\" &gt;&gt; /crypt/mystuff/file.txt\r\n</code></pre>\r\n<p>\r\nWhen you\'re finished using your encrypted vault, unmount and close it:\r\n</p>\r\n<pre><code>$ sudo umount /crypt\r\n$ sudo cryptsetup luksClose foo\r\n</code></pre>\r\n\r\n',78,74,0,'CC-BY-SA','encryption',0,0,1),
(2793,'2019-04-17','bash coproc: the future (2009) is here',1276,'clacke discovers bash\'s coproc keyword and explains some toy examples','<p>If you want the full manuscript, that’s at <a href=\"https://gitlab.com/clacke/hpr/blob/master/hpr2793_bash_coproc_manuscript.adoc\">gitlab: hpr2793_bash_coproc_manuscript.adoc</a>. It’s almost a transcript, but I added spontaneous commentary while reading the examples, so that’s not in the manuscript.</p>\r\n<p>Episode errata:</p>\r\n<ul>\r\n<li><p>Command substitution with <code>$()</code> is perfectly valid according to POSIX, and is accepted both by <code>dash</code> and by <code>bash --posix</code>. It’s not to be considered a bashism.</p></li>\r\n<li><p>I fumbled the pronunciation of the <code>printf</code> format string in one place and said &quot;parenthesis&quot; instead of &quot;percentage sign&quot;.</p></li>\r\n<li><p>I tried to say &quot;space&quot; every time there’s a space, but I know I forgot it in a few places. But you probably need to look at the show notes to really make sense of the commands anyway.</p></li>\r\n</ul>\r\n<p>Example #1:</p>\r\n<div class=\"sourceCode\" id=\"cb1\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><a class=\"sourceLine\" id=\"cb1-1\" data-line-number=\"1\">$ <span class=\"bu\">echo</span> <span class=\"va\">$(</span><span class=\"bu\">echo</span> hacker public radio<span class=\"va\">)</span></a>\r\n<a class=\"sourceLine\" id=\"cb1-2\" data-line-number=\"2\"><span class=\"ex\">hacker</span> public radio</a>\r\n<a class=\"sourceLine\" id=\"cb1-3\" data-line-number=\"3\">$ <span class=\"va\">$(</span><span class=\"bu\">echo</span> echo hacker public radio<span class=\"va\">)</span>  # <span class=\"ex\">It</span> can even supply the command itself, not just parameters. Note the word splitting.</a>\r\n<a class=\"sourceLine\" id=\"cb1-4\" data-line-number=\"4\"><span class=\"ex\">hacker</span> public radio</a>\r\n<a class=\"sourceLine\" id=\"cb1-5\" data-line-number=\"5\">$ <span class=\"st\">&quot;</span><span class=\"va\">$(</span><span class=\"bu\">echo</span> echo hacker public radio<span class=\"va\">)</span><span class=\"st\">&quot;</span>  # <span class=\"ex\">Counteract</span> word splitting by putting the command substitution in quotes.</a>\r\n<a class=\"sourceLine\" id=\"cb1-6\" data-line-number=\"6\"><span class=\"ex\">bash</span>: echo hacker public radio: command not found</a>\r\n<a class=\"sourceLine\" id=\"cb1-7\" data-line-number=\"7\">$ <span class=\"kw\">`</span><span class=\"bu\">echo</span> echo hacker public radio<span class=\"kw\">`</span>  # <span class=\"ex\">Old-style</span> command substitution</a>\r\n<a class=\"sourceLine\" id=\"cb1-8\" data-line-number=\"8\"><span class=\"ex\">hacker</span> public radio</a></code></pre></div>\r\n<p>More on command substitution in Dave’s <a href=\"https://hackerpublicradio.org/eps.php?id=1903\">hpr1903: Some further Bash tips</a>.</p>\r\n<p>Example #2:</p>\r\n<div class=\"sourceCode\" id=\"cb2\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><a class=\"sourceLine\" id=\"cb2-1\" data-line-number=\"1\">$ <span class=\"bu\">echo</span> <span class=\"op\">&lt;(</span><span class=\"bu\">echo</span> hacker public radio<span class=\"op\">)</span></a>\r\n<a class=\"sourceLine\" id=\"cb2-2\" data-line-number=\"2\"><span class=\"ex\">/dev/fd/63</span></a>\r\n<a class=\"sourceLine\" id=\"cb2-3\" data-line-number=\"3\">$ <span class=\"fu\">cat</span> <span class=\"op\">&lt;(</span><span class=\"bu\">echo</span> hacker public radio<span class=\"op\">)</span></a>\r\n<a class=\"sourceLine\" id=\"cb2-4\" data-line-number=\"4\"><span class=\"ex\">hacker</span> public radio</a></code></pre></div>\r\n<p>You can also combine process substitution with redirection.</p>\r\n<p>Example #3:</p>\r\n<div class=\"sourceCode\" id=\"cb3\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><a class=\"sourceLine\" id=\"cb3-1\" data-line-number=\"1\">$ <span class=\"bu\">echo</span> hacker public radio <span class=\"op\">&gt;</span> <span class=\"op\">&gt;(</span><span class=\"fu\">sed</span> -e <span class=\"st\">&#39;s/$/!/&#39;</span><span class=\"op\">)</span>  # You need the space between the greater-thans here!</a>\r\n<a class=\"sourceLine\" id=\"cb3-2\" data-line-number=\"2\"><span class=\"ex\">hacker</span> public radio!</a></code></pre></div>\r\n<p>More on process substitution in Dave’s <a href=\"https://hackerpublicradio.org/eps.php?id=2045\">hpr2045: Some other Bash tips</a>.</p>\r\n<p>For a description of a hack for creating bidirectional anonymous pipes in bash, see <a href=\"https://libranet.de/display/0b6b25a8-135c-83e5-1f4b-82a136800329\">my Fediverse post on this</a>, and I owe you a show.</p>\r\n<p>A coprocess in bash is a subshell to which you have access to two file descriptors: Its stdin and its stdout.</p>\r\n<p>The two file descriptors will be put in a bash array. To learn more about arrays, check out Dave’s series within the bash series, a whopping five-part quadrology including <a href=\"https://hackerpublicradio.org/eps.php?id=2709\">hpr2709</a>, <a href=\"https://hackerpublicradio.org/eps.php?id=2719\">hpr2719</a>, <a href=\"https://hackerpublicradio.org/eps.php?id=2729\">hpr2729</a>, <a href=\"https://hackerpublicradio.org/eps.php?id=2739\">hpr2739</a> and <a href=\"https://hackerpublicradio.org/eps.php?id=2756\">hpr2756</a>.</p>\r\n<p>You create a coprocess using the <code>coproc</code> keyword, brand spanking new since bash 4 from 2009. I am filing issues to <a href=\"https://bitbucket.org/birkenfeld/pygments-main/issues\">pygments</a> and <a href=\"https://savannah.gnu.org/bugs/?group=src-highlite\">GNU src-highlite</a> to support it.</p>\r\n<p>There are two ways to call coproc. The first way is to give <code>coproc</code> a <em>simple command</em>.</p>\r\n<p>Example #4:</p>\r\n<div class=\"sourceCode\" id=\"cb4\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><a class=\"sourceLine\" id=\"cb4-1\" data-line-number=\"1\">$ <span class=\"ex\">coproc</span> :<span class=\"kw\">;</span> <span class=\"bu\">declare</span> -p <span class=\"va\">COPROC</span></a>\r\n<a class=\"sourceLine\" id=\"cb4-2\" data-line-number=\"2\">[<span class=\"ex\">1</span>] 25155</a>\r\n<a class=\"sourceLine\" id=\"cb4-3\" data-line-number=\"3\"><span class=\"bu\">declare</span> -a <span class=\"va\">COPROC=([0]=</span><span class=\"st\">&quot;63&quot;</span> <span class=\"va\">[1]=</span><span class=\"st\">&quot;60&quot;</span><span class=\"va\">)</span></a>\r\n<a class=\"sourceLine\" id=\"cb4-4\" data-line-number=\"4\">[<span class=\"ex\">1</span>]+  Done                    coproc COPROC :</a></code></pre></div>\r\n<p>The other way is to give <code>coproc</code> an explicit name and a <a href=\"https://www.gnu.org/software/bash/manual/bash.html#Command-Grouping\">Command Grouping</a>.</p>\r\n<p>Example #5:</p>\r\n<div class=\"sourceCode\" id=\"cb5\"><pre class=\"sourceCode bash\"><code class=\"sourceCode bash\"><a class=\"sourceLine\" id=\"cb5-1\" data-line-number=\"1\">$ <span class=\"ex\">coproc</span> HPR (:); <span class=\"bu\">declare</span> -p <span class=\"va\">HPR</span></a>\r\n<a class=\"sourceLine\" id=\"cb5-2\" data-line-number=\"2\">[<span class=\"ex\">1</span>] 25469</a>\r\n<a class=\"sourceLine\" id=\"cb5-3\" data-line-number=\"3\"><span class=\"bu\">declare</span> -a <span class=\"va\">HPR=([0]=</span><span class=\"st\">&quot;63&quot;</span> <span class=\"va\">[1]=</span><span class=\"st\">&quot;60&quot;</span><span class=\"va\">)</span></a>\r\n<a class=\"sourceLine\" id=\"cb5-4\" data-line-number=\"4\">[<span class=\"ex\">1</span>]+  Done                    coproc HPR ( : )</a></code></pre></div>\r\n<p>Slightly less contrived example #6:</p>\r\n<pre><code>$ coproc GREP (grep --line-buffered pub); printf &#39;%s\\n&#39; hacker public radio &gt;&amp;${GREP[1]}; cat &lt;&amp;${GREP[0]}\r\n[1] 25627\r\npublic\r\n^C\r\n$ kill %1\r\n[1]+  Terminated              coproc GREP ( grep --color=auto --line-buffered pub )</code></pre>\r\n<p>Here grep and cat wait forever for more input, so we have to kill them to continue our lesson.</p>\r\n<p>But we know that <code>GREP</code> will only return one line, so we can just read that one line. And when we are done feeding it lines, we can close our side of its stdin, and it will notice this and exit gracefully.</p>\r\n<p>I’m glad I stumbled over that <code>{YOURVARIABLE}&gt;&amp;-</code> syntax for having a dereferenced variable as the left FD of a redirection. Originally I used an ugly <code>eval</code>.</p>\r\n<p>Example #7:</p>\r\n<pre><code>$ coproc GREP (grep --line-buffered pub); printf &#39;%s\\n&#39; hacker public radio &gt;&amp;${GREP[1]}; head -n1 &lt;&amp;${GREP[0]}; exec {GREP[1]}&gt;&amp;-\r\n[1] 25706\r\npublic\r\n[1]+  Done                    coproc GREP ( grep --color=auto --line-buffered pub )</code></pre>\r\n<p>There we go! Not the most brilliant example, but it shows all the relevant moving parts, and we covered a couple of caveats.</p>\r\n<p>Now go out and play with this and come back with an example on how this is actually useful in the real world, and submit a show!</p>\r\n\r\n',311,42,0,'CC-BY-SA','bash, coproc, subshell',0,0,1),
(2797,'2019-04-23','Writing Web Game in Haskell - Simulation at high level',1547,'Tuula gives overview of simulation in their 4x game','<p>So far we have been concentrating on separate pieces of the game. Now it’s time to put some of them together as a simulation.</p>\n<h2 id=\"overview-of-simulation\">Overview of simulation</h2>\n<p>Simulation is done in discrete steps. Each step is roughly 1 earth month (completely arbitrary decision). Shorter than that and there might not be enough happening during turns to keep things interesting. Much longer than that and player might not have enough control on how to react things.</p>\n<p>In any case, current time is stored in database in table <code>time</code>. There should be only one row in that table at any given time. And that row has only one value, current time. Time is stored as integer as I didn’t want to deal with problems that you get when adding fractions to a float time after time. So current time (March 2019) would be <code>2019.3</code> in game terms and stored as <code>20193</code> in database.</p>\n<p>Main processing is done in function called <code>processTurn</code> that is shown below. It advances time for one decimal month, removes all expired statuses as explained in <a href=\"https://hackerpublicradio.org/eps.php?id=2768\">episode 2768</a> and then loads all factions.</p>\n<p>After that, various steps of the simulation are carried out for all loaded factions. These include handling special events as explained in <a href=\"https://hackerpublicradio.org/eps.php?id=2748\">episode 2748</a> and doing observations and report writing in manner described <a href=\"https://hackerpublicradio.org/eps.php?id=2703\">episode 2703</a>.</p>\n<pre><code>processTurn :: (BaseBackend backend ~ SqlBackend,\n    BackendCompatible SqlBackend backend, PersistUniqueRead backend,\n    PersistQueryWrite backend,\n    PersistQueryRead backend, PersistStoreWrite backend, MonadIO m) =&gt;\n    ReaderT backend m Time\nprocessTurn = do\n    newTime &lt;- advanceTime\n    _ &lt;- removeExpiredStatuses newTime\n    factions &lt;- selectList [] [ Asc FactionId ]\n    _ &lt;- mapM (handleFactionEvents newTime) factions\n    mapM_ handleFactionFood factions\n    mapM_ (handleFactionConstruction newTime) factions\n    _ &lt;- mapM (addSpecialEvents newTime) factions\n    -- Doing observations should always be done last to ensure players have\n    -- recent reports of property they have full control, ie. planets.\n    -- Otherwise it&#39;s possible that they&#39;ll receive reports that are one\n    -- turn out of sync.\n    mapM_ (handleFactionObservations newTime) factions\n    return newTime</code></pre>\n<h2 id=\"more-mapping\">More mapping</h2>\n<p>Remember <code>map</code> and <code>fmap</code> that are used to run a function to each element in a list or general structure? <code>mapM</code> works in a similar way, but is used in monadic context. In <code>processTurn</code> function, we’re dealing with input and output and have IO monad present to allow us to do that (<code>MonadIO m</code> part of the type signature).</p>\n<p>If you step back a bit and squint a bit, then <code>map :: (a -&gt; b) -&gt; [a] -&gt; [b]</code> and <code>fmap :: (a -&gt; b) -&gt; f a -&gt; f b</code> and <code>mapM :: Monad m =&gt; (a -&gt; m b) -&gt; t a -&gt; m (t b)</code> look pretty similar. Each take a function, structure and produce a new structure which values were created by running the given function for each element of the original structure.</p>\n<p>The difference is that <code>map</code> works only for lists, <code>fmap</code> works for functors (that were covered in <a href=\"https://hackerpublicradio.org/eps.php?id=2778\">episode 2778</a>) and <code>mapM</code> works for structures in monadic context.</p>\n<p>Best way to contact me nowadays is either by email or through fediverse where I’m Tuula@mastodon.social.</p>\n',364,107,0,'CC-BY-SA','haskell, persistent',0,0,1),
(2798,'2019-04-24','Should Podcasters be Pirates ?',725,'Knightwise waxes nostalgically on the early days of podcasting and wonders if we all sold out?','<p>In a car rant I think back to the early days of podcasting and how the ambience and vision of podcasting was far from the mainstream media approach from today. Have we all sold out ?</p>\r\n',111,0,1,'CC-BY-SA','podcast,pirate radio,decentralisation',0,0,1),
(2802,'2019-04-30','Mid-life (?) assessment',991,'It seems life goes faster and faster and then turns around and goes slower and slower','<p>At 40, I’m at the middle of the mean life expectancy in most parts of the world. What’s happened so far, and where do I go from here?</p>\r\n<p>I look at my life’s past in increasingly smaller chunks of years, and then at my life’s future in increasingly larger chunks of years, and speculate about those 80 years — or perhaps many more? — of expected lifetime.</p>\r\n<p>I’m saying mostly the things I wrote at <a href=\"https://loadaverage.org/conversation/10689347\" class=\"uri\">https://loadaverage.org/conversation/10689347</a> but with some small updates from the last 9 months.</p>\r\n',311,0,0,'CC-BY-SA','life, kids, work, medicine, future',0,0,1),
(2792,'2019-04-16','Playing around with text to speech synthesis on Linux',1203,'Playing around with different text to speech programs to see what is possible.','<p>Below the script I used to generate a bunch of wav files with different text to speech applications.</p>\r\n<pre><code>#!/bin/bash\r\n\r\nstring=&quot;This is HPR episode 2792 entitled \\&quot;Playing around with text to speech synthesis on Linux\\&quot; and is part of the series \\&quot;Sound Scapes\\&quot;. It is hosted by Yeroon Bahten and is about 20 minutes long and carries a clean flag.&quot;\r\necho &quot;${string}&quot; &gt; text.txt\r\n\r\nespeak -w espeak.wav &quot;${string}&quot; \r\nespeak -w espeak-ng-v-mb-us1.wav -v mb-us1 &quot;${string}&quot;\r\nespeak -w espeak-ng-v-mb-us2.wav -v mb-us2 &quot;${string}&quot;\r\nespeak -w espeak-ng-v-mb-us3.wav  -v mb-us3 &quot;${string}&quot;\r\nespeak-ng &quot;${string}&quot;\r\nespeak-ng -v en-gb &quot;${string}&quot;\r\nespeak-ng -w espeak-ng-en-gb-scotland.wav -v en-gb-scotland &quot;${string}&quot;\r\nespeak-ng -w espeak-ng-en-us.wav  -v en-us &quot;${string}&quot;\r\n\r\nflite -o flite-voice-cmu_us_slt.wav -voice cmu_us_slt  &quot;${string}&quot;\r\n\r\necho &quot;${string}&quot;| festival --language english --tts # same as next line\r\necho &quot;${string}&quot;| text2wave --language british_english --tts -o festival_british_english.wav\r\ntext2wave -o festival_british_english.wav  text.txt\r\n\r\nfor voice in don_diphone kal_diphone ked_diphone rab_diphone\r\ndo\r\n  text2wave -o festival_voice_${voice}.wav -eval &quot;(voice_${voice} )&quot;  text.txt\r\ndone\r\n\r\n# Gnustep say, recorded with audio recorder.\r\nsay &quot;${string}&quot;\r\n\r\ntext2wave -o festival_voice_cmu_us_slt_arctic_hts.wav -eval &quot;(voice_cmu_us_slt_arctic_hts )&quot; text.txt\r\n\r\n# merlin https://github.com/CSTR-Edinburgh/merlin\r\n\r\n# marytts: https://github.com/marytts</code></pre>\r\n',369,101,0,'CC-BY-SA','speech synthesis linux',0,0,1),
(2794,'2019-04-18','Interview with Martin Wimpress',2412,'In this episode, Yannick talks with Martin Wimpress about the Ubuntu MATE project','<p>Ubuntu, MATE.</p>\r\n<p>Two words which, taken separately, refer to great products.</p>\r\n<p>On one side, Ubuntu, one of the most popular, if not <em>the</em> most popular, linux distribution.</p>\r\n<p>On the other side, the MATE desktop environment, also very popular.</p>\r\n<p>One person took those two elements and combined them together to make Ubuntu MATE. That person is Martin Wimpress, and he joined me on the 21st of March to talk about the past, present, and future of the project.</p>\r\n',370,78,0,'CC-BY-SA','ubuntu, mate, ubuntu mate, martin wimpress, raspberry pi, desktop environment, linux',0,0,1),
(2808,'2019-05-08','Haskell function types',1469,'Tuula gives overview of function types in Haskell','<p>Haskell is statically typed language, meaning that during compilation, programs are checked for type correctness. This means that you won’t accidentally mix for example text and numbers. Haskell does type inference. The compiler will try and figure out what kind of types would make your program to be valid in terms of types. Programmer could completely omit types, but it’s often helpful to write type signatures for at least top level definitions. These will be helpful for both the programmers and compilers.</p>\r\n<h2 id=\"concrete-types\">concrete types</h2>\r\n<p>Simplest case is where types are spelled out definitely. Function <code>add</code> below takes two <code>Integer</code> parameters and produces <code>Integer</code> value. Note that types are written in upper case.</p>\r\n<p><code>add :: Integer -&gt; Integer -&gt; Integer</code></p>\r\n<p>It’s possible to not use concrete types. In following example <code>a</code> (note the lower case) can be anything. So function takes two values of <code>a</code>, a <code>Boolea</code> and produces <code>a</code>. This is useful technique for writing very general functions.</p>\r\n<p><code>choose :: a -&gt; a -&gt; Boolean -&gt; a</code></p>\r\n<h2 id=\"ad-hoc-polymorphism\">ad hoc polymorphism</h2>\r\n<p>In previous example, we wouldn’t be able to do much at all with <code>a</code> as we don’t know its type. Sometimes we need to know a bit more about type, without specifically declaring its type. For those cases type constraints are useful.</p>\r\n<p><code>add :: (Num a) =&gt; a -&gt; a -&gt; a</code></p>\r\n<p>This version of <code>add</code> again takes two parameters, both being type <code>a</code> and produces value <code>a</code>. But <code>(Num a) =&gt;</code> part in the signature constraints <code>a</code> to be instance of <code>Num</code>. This type class (I’ll talk about these some other time) defines that each instance of it will have set of functions: <code>+</code>, <code>-</code>, <code>*</code>, <code>negate</code>, <code>abs</code>, <code>signum</code> and <code>fromInteger</code>. So now our <code>add</code> function can use those functions, regardless of what specific type <code>a</code> is.</p>\r\n<h2 id=\"parametrized-functions\">parametrized functions</h2>\r\n<p>Types used in function signature can be parametrized. If we wanted a function that returns a first element of any list, we could have following signature: <code>first :: [a] -&gt; Maybe a</code></p>\r\n<p><code>first</code> takes single parameter, list of <code>a</code> and returns <code>Maybe a</code>. <code>Maybe</code> is a type that is used to signify a value that might or might not be present and has following definition:</p>\r\n<pre><code>data Maybe a =\r\n     Nothing\r\n     | Just a</code></pre>\r\n<p>So our function would return <code>Nothing</code> when given an empty list and <code>Just a</code> when given a list of at least one element.</p>\r\n<h2 id=\"using-functions\">using functions</h2>\r\n<p>Function application in Haskell doesn’t require parentheses around arguments. Calling our <code>add</code> function is just <code>add 1 2</code>. If one of the values is result of another function call, we need to tell which parameters belong to which function. Using <code>$</code> is one option: <code>add 1 $ add 2 3</code>, another option is to use parentheses: <code>add 1 (add 2 3)</code>.</p>\r\n<p>When function is called with less parameters than it expect, instead of run time error you’ll going to receive a function. In following example <code>addLots 5</code> will produce same value as <code>add 1000 5</code>:</p>\r\n<pre><code>addLots = add 1000\r\naddLots 5</code></pre>\r\n<p>Another contrived example of partial application:</p>\r\n<pre><code>findPodcasts :: [Podcast] -&gt; Text -&gt; [Podcast]\r\nsearch = findPodcasts loadedPodcasts\r\nmyPodcasts = search &quot;Tuula&quot;</code></pre>\r\n<h2 id=\"functions-as-types\">functions as types</h2>\r\n<p>Functions have type (that’s what the signature is for after all) and functions can be used as values. You can return function from another function or you can pass in a function as a parameter.</p>\r\n<p>Common example is <code>filter</code>, which has following signature: <code>filter :: (a -&gt; Bool) -&gt; [a] -&gt; [a]</code></p>\r\n<p>It takes two parameters, first one is function that has type <code>a -&gt; Bool</code> and second one is list of <code>a</code>. Return value is list of <code>a</code>. You can produce a list of odd numbers between 1 and 10 with <code>filter odd [1..10]</code>.</p>\r\n<h2 id=\"anonymous-functions\">anonymous functions</h2>\r\n<p>Sometimes you need a function to pass in as a parameter, but the function is so small that you don’t want to give it a name. For those cases, anonymous function are good. If you wanted to produce a list of odd numbers that are greater that 5 in range from 1 10, you could write it as: <code>filter (\\x -&gt; odd x &amp;&amp; x &gt; 5) [1..10]</code>. If you squint hard enough <code>\\</code> looks almost like a lowercase greek letter λ.</p>\r\n<p>Easiest way to catch me is either email or fediverse where I’m Tuula@mastodon.social</p>\r\n',364,107,0,'CC-BY-SA','haskell',0,0,1);
INSERT INTO `eps` (`id`, `date`, `title`, `duration`, `summary`, `notes`, `hostid`, `series`, `explicit`, `license`, `tags`, `version`, `downloads`, `valid`) VALUES (2799,'2019-04-25','building an arduino programmer',1212,'turn an arduino nano into a programmer','<ol type=\"1\">\r\n<li>intro</li>\r\n</ol>\r\n<p>1.1 brian in ohio</p>\r\n<p>1.2 out from under my rock</p>\r\n<ol start=\"2\" type=\"1\">\r\n<li>motivation</li>\r\n</ol>\r\n<p>2.1 ken fallon bootloader episode</p>\r\n<ul>\r\n<li>hpr 2660</li>\r\n<li>burned many bootloaders</li>\r\n<li>used usbtiny programmer</li>\r\n<li>putting together a programmer would be a good learning experience</li>\r\n</ul>\r\n<p>2.2 still use arduino</p>\r\n<ul>\r\n<li>easy to check out a new piece of hardware</li>\r\n<li>boards are cheap and easy to find</li>\r\n<li>boards are robust</li>\r\n</ul>\r\n<p>2.3 need to run an arduino board at lower frequency</p>\r\n<ul>\r\n<li>developing a data logger</li>\r\n<li>write code in c using the avr open source tool chain</li>\r\n<li>prototype on arduino board</li>\r\n</ul>\r\n<ol start=\"3\" type=\"1\">\r\n<li>needed supplies</li>\r\n</ol>\r\n<p>3.1 arduino ide</p>\r\n<ul>\r\n<li>get from your distro’s repository</li>\r\n<li>slackbuilds i used the version that repackages the binaries, the little a arduino</li>\r\n<li>read this good information<br />\r\n<a href=\"https://www.arduino.cc/en/Tutorial/ArduinoISP\" class=\"uri\">https://www.arduino.cc/en/Tutorial/ArduinoISP</a></li>\r\n</ul>\r\n<p>3.2 avrdude</p>\r\n<ul>\r\n<li>use it to test the programmer outside of the arduino environment</li>\r\n<li>part of the gnu avr toolchain</li>\r\n</ul>\r\n<p>3.3 arduino nano clone - un assembled</p>\r\n<p><img src=\"https://www.hackerpublicradio.org/eps/hpr2799-bare-nano.jpg\" alt=\"hpr2799-bare-nano.jpg\" /></p>\r\n<ul>\r\n<li>look for the boards that have the unpoplated icsp header</li>\r\n<li>make sure its a nano and not a pro-mini</li>\r\n</ul>\r\n<p>3.4 3 leds 3mm or smaller</p>\r\n<p><img src=\"https://www.hackerpublicradio.org/eps/hpr2799-led.jpg\" alt=\"hpr2799-led.jpg\" /></p>\r\n<ul>\r\n<li>optional but are useful, especially the heartbeat led</li>\r\n</ul>\r\n<p>3.5 3 resistors 200 ohm - small</p>\r\n<ul>\r\n<li>if you install the led’s</li>\r\n</ul>\r\n<p>3.6 1 5-10 uF electrolytic capacitor</p>\r\n<p>3.7 3-4 inch long jumper wire</p>\r\n<p>3.8 2x3 female header</p>\r\n<p><img src=\"https://www.hackerpublicradio.org/eps/hpr2799-2x3header.jpg\" alt=\"hpr2799-2x3header.jpg\" /></p>\r\n<p>3.9 some way to cut wire</p>\r\n<p>3.10 soldering supplies</p>\r\n<ol start=\"4\" type=\"1\">\r\n<li>howto</li>\r\n</ol>\r\n<p>4.1 upload arduino isp sketch to nano</p>\r\n<p>File→Examples→11.ArduinoISP→ArduinoISP</p>\r\n<ul>\r\n<li>i modified the sketch changing where the led’s are placed</li>\r\n<li><p>i put the led’s at digital 9, 7, and 5 for spacing</p>\r\n<pre><code>#define RESET 10 // Use pin 10 to reset the target rather than SS\r\n#define LED_HB 9 // No change define LED_ERR 7 // changed define\r\n#LED_PMODE 5 // changed</code></pre></li>\r\n<li><p>upload the sketch</p></li>\r\n</ul>\r\n<p>4.2 solder on led’s</p>\r\n<p><img src=\"https://www.hackerpublicradio.org/eps/hpr2799-led-on-board.jpg\" alt=\"hpr2799-led-on-board.jpg\" /></p>\r\n<ul>\r\n<li>solder the anode leg to the apropriate digital pin on the board</li>\r\n<li>add a resistor to the cathode leg of the led (usually the shorter leg)</li>\r\n<li>solder the resistor attached to the cathode to ground pin of the board</li>\r\n<li>i started with pin 9</li>\r\n<li>you can test each led before moving on to the next led</li>\r\n<li>my soldering ended up messy but it gets the job done</li>\r\n</ul>\r\n<p><img src=\"https://www.hackerpublicradio.org/eps/hpr2799-leds-done.jpg\" alt=\"hpr2799-leds-done.jpg\" /></p>\r\n<p>4.3 modify sketch and test leds</p>\r\n<ul>\r\n<li>you can modify the sketch</li>\r\n<li>change the heartbeat pin to whatever led you just soldered</li>\r\n<li>upload the modified sketch</li>\r\n<li>the led you just soldered should pulse</li>\r\n</ul>\r\n<p>4.4 clip jumper wire and attach</p>\r\n<p><img src=\"https://www.hackerpublicradio.org/eps/hpr2799-reset-wire.jpg\" alt=\"hpr2799-reset-wire.jpg\" /></p>\r\n<ul>\r\n<li>pin 10</li>\r\n<li>used the hole on the end of the board as strain relief</li>\r\n</ul>\r\n<p>4.5 add capacitor</p>\r\n<ul>\r\n<li>watch polarity</li>\r\n<li>no more auto reset</li>\r\n<li>if you want to program with arduino ide, you need to push the reset button</li>\r\n</ul>\r\n<p>4.6 2x3 header</p>\r\n<pre class=\"___\"><code>                         MISO -|o o|-+Vcc\r\n                          SCK -|o o|-MOSI\r\n Do not attach-Reset-|o o|-Gnd\r\n                                     -----</code></pre>\r\n<p><img src=\"https://www.hackerpublicradio.org/eps/hpr2799-header-mod.jpg\" alt=\"hpr2799-header-mod.jpg\" /></p>\r\n<ul>\r\n<li>remove reset connecter south-west connector</li>\r\n<li>solder the remaining 5 pins</li>\r\n<li>the header is soldered on the bottom of the board</li>\r\n</ul>\r\n<p><img src=\"https://www.hackerpublicradio.org/eps/hpr2799-header-soldered.jpg\" alt=\"hpr2799-header-soldered.jpg\" /></p>\r\n<ol start=\"5\" type=\"1\">\r\n<li>how to use</li>\r\n</ol>\r\n<p>5.1 plug usb cable into programmer and your computer</p>\r\n<p>5.2 start the arduino ide</p>\r\n<p>5.3 plug programmer onto target board remember to plug the wire into the reset pin of the target</p>\r\n<p>5.4 in the tools folder of the ide make sure your usb port is selected</p>\r\n<p>Tools→Port<code>&quot;/dev/ttyUSBx&quot;</code>→<code>/dev/ttyUSBx</code></p>\r\n<p>5.5 and that in the programmer section you select arduino as isp not arduinoisp</p>\r\n<p>Tools→Programmer→Arduino as ISP</p>\r\n<p>5.6 at this point you can burn a bootloader as Ken described</p>\r\n<p>5.7 upload a program</p>\r\n<p>5.7.1 bring up the blink example sketch</p>\r\n<p>5.7.2 under tools make sure your target board type is selected</p>\r\n<p>Tools→Boards</p>\r\n<p>5.7.3 under the sketch menu you’ll see upload using a programmer</p>\r\n<p>Sketch→Upload Using Programer</p>\r\n<p>5.7.4 when you select that the blink sketch will be compiled and uploaded</p>\r\n<ol start=\"6\" type=\"1\">\r\n<li>at the command line</li>\r\n</ol>\r\n<p>6.1 check functionallity</p>\r\n<pre><code>bash-4.3$ avrdude -p m328p -c arduino -P /dev/ttyUSB0 -b 19200</code></pre>\r\n<p>6.2 output</p>\r\n<pre><code>  avrdude: AVR device initialized and ready to accept instructions\r\n\r\n  Reading | ################################################## | 100%\r\n  0.01s\r\n\r\n  avrdude: Device signature = 0x1e950f (probably m328p)\r\n\r\n  avrdude: safemode: Fuses OK (E:FD, H:DE, L:FF)\r\n\r\n  avrdude done.  Thank you.</code></pre>\r\n<ol start=\"7\" type=\"1\">\r\n<li>things to look out for</li>\r\n</ol>\r\n<p>7.1 permissions issues - arch wiki gentoo</p>\r\n<p>7.2 when you upload this way you overwrite bootloader</p>\r\n<p>7.3 arduino ide boards.txt has some fuse errors</p>\r\n<p>7.4 avrdude version 6.2 will not work</p>\r\n<p>7.5 baud rate using avrdude command line</p>\r\n<p>7.6 capacitor is non-optional, but makes uploading to that board non-trivial</p>\r\n<ol start=\"8\" type=\"1\">\r\n<li>conclusion</li>\r\n</ol>\r\n<p>8.1 upload via icsp vs usb serial</p>\r\n<p>8.2 do you need a bootloader?</p>\r\n<p>8.3 challenge to max out any 8bit microcontroller</p>\r\n<ul>\r\n<li>if you need to do one or two things use a microcontroller i.e. arduino</li>\r\n<li>if you need to do many things use a linux single board computer i.e. raspberry pi</li>\r\n</ul>\r\n',326,91,0,'CC-BY-SA','Arduino,ArduinoISP',0,0,1),
(2801,'2019-04-29','Guitar Set Up Part 1.',1724,'NYbill talks about setting up a guitar.','<p>NYbill talks about setting up a guitar.</p>\r\n<p>Pics for the episode:</p>\r\n<p><a href=\"https://media.gunmonkeynet.net/u/nybill/collection/guitar-set-up/\" class=\"uri\">https://media.gunmonkeynet.net/u/nybill/collection/guitar-set-up/</a></p>\r\n',235,0,0,'CC-BY-SA','Guitar, DIY',0,0,1),
(2804,'2019-05-02','Awk Part 13: Fix-Width Field Processing',381,'In this episode, I discuss how to deal with fix-width field text files using Awk','<h1 id=\"basic-usage\">Basic usage</h1>\r\n<p>Use the <code>FIELDWIDTHS = &quot;n1 n2 n3 ...&quot;</code> annotation in the <code>BEGIN</code> section of an awk command to specify the widths of the fields.</p>\r\n<p>For instance, the following file has widths of 20, 10, and 12 characters.</p>\r\n<pre><code>NAME                STATE     TELEPHONE\r\nJohn Smith          WA        418-311-4111\r\nMary Hartford       CA        319-219-4341\r\nEvan Nolan          IL        219-532-5301\r\nBoris Ratinski      NC        201-553-5555\r\n</code></pre>\r\n<p>Below is an example of processing such a file:</p>\r\n<pre><code>BEGIN  { FIELDWIDTHS = &quot;20 10 12&quot; }\r\nNR &gt; 1 {\r\n    name = $1\r\n    state = $2\r\n    phone = $3\r\n    sub(/ +$/, &quot;&quot;, name)\r\n    sub(/ +$/, &quot;&quot;, state)\r\n    sub(/ +$/, &quot;&quot;, phone)\r\n    printf(&quot;%s lives in %s. The phone number is %s.\\n&quot;, name, state, phone)\r\n}\r\n</code></pre>\r\n<p>Then you can run the command:</p>\r\n<pre><code>awk -f process_fixed_width.awk fixed_width.txt\r\n</code></pre>\r\n',300,94,1,'CC-BY-SA','bash,linux,cli,command-line,awk',0,0,1),
(2807,'2019-05-07','Are bash local variables local?',661,'A lesson on dynamic scope vs lexical scope','<p><a href=\"https://en.wikipedia.org/wiki/Scope_%28computer_science%29\">https://en.wikipedia.org/wiki/Scope_%28computer_science%29</a></p>\r\n<p>In <a href=\"https://hackerpublicradio.org/eps.php?id=2739\">hpr2739</a>, Dave talked briefly about local variables. But what are they?</p>\r\n<p>In most modern languages, especially in compiled languages, &quot;local&quot; means that the value of a variable cannot be directly known, by looking up the name, outside the bounds of that function, but that’s not how it works in bash.</p>\r\n<p>Languages like C and Python have <em>lexical scope</em>. Lexical scope means local variables are local in the <em>text</em>. The names are local.</p>\r\n<p>If I’m writing code that is textually located outside the function, I cannot even describe how to access the variables within the function, because <code>myvariable</code> in my function is not the same variable, not the same place, as <code>myvariable</code> in your function.</p>\r\n<p>Languages like Bash and Elisp have <em>dynamic scope</em>. That means local variables are local in <em>time</em>. The names are global.</p>\r\n<p>What happens when you declare a variable <code>local</code> in bash is that the existing value of that variable is stowed away, to be brought back when your function exits.</p>\r\n<pre><code>#!/usr/bin/env bash\r\nfunction sayscope() {\r\n    echo The scope is $whatsmyscope\r\n}\r\n\r\nfunction globalscope() {\r\n    whatsmyscope=global\r\n}\r\n\r\nfunction dynamicscope() {\r\n    whatsmyscope=dynamic\r\n}\r\n\r\nfunction localscope() {\r\n    local whatsmyscope=local\r\n    sayscope\r\n    dynamicscope\r\n    sayscope\r\n}\r\n\r\nglobalscope\r\nsayscope\r\nlocalscope\r\nsayscope</code></pre>\r\n<pre><code>The scope is global\r\nThe scope is local\r\nThe scope is dynamic\r\nThe scope is global</code></pre>\r\n<p>Perl has both, and it calls them <code>local</code> (dynamic scope, like bash) and <code>my</code> (lexical scope):</p>\r\n<pre><code>#!/usr/bin/env perl\r\nuse v5.10;\r\n\r\nsub sayscope {\r\n    say &quot;Dynamic scope is $whatsmyscope&quot;;\r\n}\r\n\r\nsub globalscope {\r\n    $whatsmyscope=&quot;global&quot;;\r\n}\r\n\r\nsub dynamicscope {\r\n    $whatsmyscope=&quot;dynamic&quot;;\r\n}\r\n\r\nsub lexicalscope {\r\n    my $whatsmyscope=&quot;lexical&quot;;\r\n    say &quot;Lexical scope is $whatsmyscope&quot;;\r\n    sayscope;\r\n}\r\n\r\nsub localscope {\r\n    local $whatsmyscope=&quot;local&quot;;\r\n    sayscope;\r\n    dynamicscope;\r\n    sayscope;\r\n    lexicalscope;\r\n}\r\n\r\nglobalscope;\r\nsayscope;\r\nlocalscope;\r\nsayscope;</code></pre>\r\n<pre><code>Dynamic scope is global\r\nDynamic scope is local\r\nDynamic scope is dynamic\r\nLexical scope is lexical\r\nDynamic scope is dynamic\r\nDynamic scope is global</code></pre>\r\n<p>You almost never want to use <code>local</code> in Perl, it’s mostly there for historical reasons — lexical scope is a Perl 5 feature. <a href=\"https://perl.plover.com/local.html\" class=\"uri\">https://perl.plover.com/local.html</a> covers well the remaining few and narrow exceptions where <code>local</code> might be useful.</p>\r\n<p>As dynamic scope has <em>some</em> valid use, it’s available in some otherwise lexically scoped languages. For example, Common LISP has the <em>special</em> form, and several Schemes and Racket have <em>parameter objects</em>:</p>\r\n<ul>\r\n<li><p><a href=\"https://www.lispworks.com/documentation/HyperSpec/Body/d_specia.htm\" class=\"uri\">https://www.lispworks.com/documentation/HyperSpec/Body/d_specia.htm</a></p></li>\r\n<li><p><a href=\"https://srfi.schemers.org/srfi-39/srfi-39.html\" class=\"uri\">https://srfi.schemers.org/srfi-39/srfi-39.html</a></p></li>\r\n<li><p><a href=\"https://docs.racket-lang.org/reference/parameters.html\" class=\"uri\">https://docs.racket-lang.org/reference/parameters.html</a></p></li>\r\n</ul>\r\n<p>To dig fully into the history and flora of dynamic and lexical scope merits another episode.</p>\r\n\r\n\r\n',311,42,0,'CC-BY-SA','bash, perl, scope, dynamic scope, lexical scope',0,0,1),
(2822,'2019-05-28','What\'s in the Box! Part 1',1265,'NYbill opens a mystery box he found in the mail box.','<p>NYbill opens a mystery box that arrived in the mail.</p>\r\n<p>No spoilers. But, it involves soldering…</p>\r\n<p>Pics for the episode:</p>\r\n<p><a href=\"https://media.gunmonkeynet.net/u/nybill/collection/what-s-in-the-box/\" class=\"uri\">https://media.gunmonkeynet.net/u/nybill/collection/what-s-in-the-box/</a></p>',235,103,0,'CC-BY-SA','DIY, Soldering, Guitar, electronics',0,0,1),
(2823,'2019-05-29','Gentoo and why I use it',748,'I talk about what Gentoo is, and why I love it so much.','<p>Thanks to <a href=\"https://hackerpublicradio.org/correspondents/0342.html\">norrist</a> for suggesting I do this episode!</p>\r\n<ul>\r\n<li><a href=\"https://gentoo.org/\" class=\"uri\">https://gentoo.org/</a></li>\r\n</ul>\r\n',374,0,0,'CC-BY-SA','Gentoo',0,0,1),
(2824,'2019-05-30','Gnu Awk - Part 15',1916,'Redirection of input and output - part 2','<h2 id=\"introduction\">Introduction</h2>\r\n<p>This is the fifteenth episode of the “<a href=\"https://hackerpublicradio.org/series/0094.html\" title=\"Learning Awk\">Learning Awk</a>” series which is being produced by <a href=\"https://hackerpublicradio.org/correspondents/0300.html\" title=\"b-yeezi\">b-yeezi</a> and myself.</p>\r\n<p>This is the second of a pair of episodes looking at <em>redirection</em> in Awk scripts.</p>\r\n<p>In this episode I will spend some time looking at the <code>getline</code> command used for <em>explicit input</em> (as opposed to the usual <em>implicit</em> sort), often with redirection. The <code>getline</code> command is a complex subject which I will cover only relatively briefly. You are directed to the <a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Getline\" title=\"Explicit Input with getline\"><code>getline</code> section</a> of the GNU Awk User’s Guide for the full details.</p>\r\n<h2 id=\"long-notes\">Long notes</h2>\r\n<p>I have provided detailed notes as usual for this episode, and these can be <a href=\"https://hackerpublicradio.org/eps/hpr2824/full_shownotes.html\">viewed here</a>.</p>\r\n<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/html_node/index.html\"><em>GNU Awk User’s Guide</em></a>\r\n<ul>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Getline\">Explicit Input with <code>getline</code></a></li>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Plain-Getline\">Using <code>getline</code> with No Arguments</a></li>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Getline_002fCoprocess\">Using <code>getline</code> with a <em>coprocess</em></a></li>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Getline-Notes\">Getline notes</a></li>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Two_002dway-I_002fO\">Two-way I/O</a></li>\r\n</ul></li>\r\n</ul>\r\n<ul>\r\n<li>Previous shows in this series on HPR:\r\n<ul>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2114\">“<em>Gnu Awk - Part 1</em>”</a> - episode 2114</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2129\">“<em>Gnu Awk - Part 2</em>”</a> - episode 2129</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2143\">“<em>Gnu Awk - Part 3</em>”</a> - episode 2143</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2163\">“<em>Gnu Awk - Part 4</em>”</a> - episode 2163</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2184\">“<em>Gnu Awk - Part 5</em>”</a> - episode 2184</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2238\">“<em>Gnu Awk - Part 6</em>”</a> - episode 2238</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2330\">“<em>Gnu Awk - Part 7</em>”</a> - episode 2330</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2438\">“<em>Gnu Awk - Part 8</em>”</a> - episode 2438</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2476\">“<em>Gnu Awk - Part 9</em>”</a> - episode 2476</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2526\">“<em>Gnu Awk - Part 10</em>”</a> - episode 2526</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2554\">“<em>Gnu Awk - Part 11</em>”</a> - episode 2554</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2610\">“<em>Gnu Awk - Part 12</em>”</a> - episode 2610</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2804\">“<em>Gnu Awk - Part 13</em>”</a> - episode 2804</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2816\">“<em>Gnu Awk - Part 14</em>”</a> - episode 2816</li>\r\n</ul></li>\r\n<li>Resources:\r\n<ul>\r\n<li><a href=\"https://hackerpublicradio.org/eps/hpr2824/full_shownotes.epub\">ePub version of these notes</a></li>\r\n<li>Examples: <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_testdata1\">awk15_testdata1</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_ex1.awk\">awk15_ex1.awk</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_ex2.awk\">awk15_ex2.awk</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_testdata2\">awk15_testdata2</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_ex3.awk\">awk15_ex3.awk</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_ex4.awk\">awk15_ex4.awk</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_ex5.awk\">awk15_ex5.awk</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_ex6.awk\">awk15_ex6.awk</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2824/awk15_ex7.awk\">awk15_ex7.awk</a></li>\r\n</ul></li>\r\n</ul>\r\n',225,94,1,'CC-BY-SA','Awk utility, Awk Language, gawk, redirection',0,0,1),
(2809,'2019-05-09','The Blue Oak Model License and Its One Big Gotcha',1268,'Introducing and examining a new and elegant permissive software license.','<p>The Blue Oak Model License 1.0.0 was just released this month. In this episode I read the license, explain where it sits in among other software licenses, and enumerate some of the problems it purports to solve.</p>\r\n<p>I’m no legal expert, so take all of this as sort of a rough introduction to the license.</p>\r\n<p>Overall, if you are looking at permissive (vs copyleft) licenses, I would strongly suggest you consider this license! It’s concise, robust, it was developed by credible people, and gives your users future-proof safety from a number of common legal traps.</p>\r\n<p>However: just note that it has a feature, some would say bug, that <em>might</em> be a big deciding factor in whether you feel comfortable with it (listen for details)</p>\r\n<p>Nevertheless, I believe this license, or at least its style of language, will soon become extremely common.</p>\r\n<p>Further links:</p>\r\n<ul>\r\n<li><a href=\"https://blueoakcouncil.org/license/1.0.0\">The Blue Oak Model License 1.0.0</a> — the license itself. You may also wish to read <a href=\"https://blueoakcouncil.org/2019/03/06/model.html\">the group’s statement</a> about their methodology and how the license came to be.</li>\r\n<li><a href=\"https://writing.kemitchell.com/2019/03/09/Deprecation-Notice.html\"><em>Deprecation Notice: MIT and BSD</em></a> — the blog post I mention in the recording, by Blue Oak council member, developer and IP lawyer Kyle Mitchell. He explains some problems he sees with the MIT and BSD licenses and how the BOML addresses them.</li>\r\n<li><a href=\"https://news.ycombinator.com/item?id=19347797\">Discussion on Hacker News</a> — This was a pretty good discussion. Kyle Mitchell also chimed in here to respond to some criticisms and tire-kicking of this license (you can recognize him by his handle <code>kemitchell</code>).</li>\r\n</ul>\r\n<p>Not mentioned in the recording: One thing that caused me a bit of confusion at first was the term “attribution”. Kyle and the Blue Oak folks use this term mainly to talk about <em>license terms</em>, not <em>authorship</em> or <em>credit</em>. So for them an attribution requirement is a requirement to include the <em>license terms</em> with any distributed copies, not a requirement to give authorship credit to people.</p>\r\n<p>If you want to use this license as a starting point for your own “bespoke” license, you can! As I mention in the recording, I created my own variant of the Blue Oak license for one of my own projects. My main change was a strong requirement for downstream users to give credit to upstream contributors—not just when redistributing source code, but in all published software, books and websites created with the software!</p>\r\n<ul>\r\n<li><a href=\"https://thelocalyarn.com/cgi-bin/yarncode/doc/licensing/LICENSE.md\">The Local Yarn License 1.0.0</a> — This is the license as it currently sits in an experimental branch in my project’s Fossil repository</li>\r\n<li><a href=\"https://thelocalyarn.com/cgi-bin/yarncode/technote/8dfa234a1779782be090b36a6b1bcccfabd95b20\">Notes about my customizations</a> — Another tech note from the Fossil repo.</li>\r\n</ul>\r\n<p>Of course, when you make your own changes, you had better think hard about them, and if possible, get the advice of an Actual Lawyer who can discuss your particular situation.</p>\r\n',376,0,0,'CC-BY-SA','legal, licensing',0,0,1),
(2812,'2019-05-14','Is 5G mobile data a danger to your health?',484,'Apply Betteridge’s Law of Headlines to find out the answer','<p>This is mostly verbatim from my Fediverse post <a href=\"https://libranet.de/display/0b6b25a8-165c-9c7f-b55d-c7a077813050\" class=\"uri\">https://libranet.de/display/0b6b25a8-165c-9c7f-b55d-c7a077813050</a>, with a few minor edits.</p>\r\n<p>The anti-5G campaign has been cooking for many years now, and at the epicenter of it all are two men, Lennart Hardell and Rainer Nyberg. It’s a Swedish-Finnish phenomenon that is now really making the rounds and spreading internationally, as actual commercial deployment of 5G networks draws nearer.</p>\r\n<p>As a Swede, I apologize. These two do not represent the Swedish or Finnish cancer or radiation research community, and our media have given them far more space in the public discourse than their work merits.</p>\r\n<p>They are heavily quoted in networks of pseudoscience, including anti-vaccine sites, right-wing &quot;alternative facts&quot; sites and Strålskyddsstiftelsen (&quot;Swedish Radiation Protection Foundation&quot;), a private foundation created in 2012 with a deceptive name meant to invoke authority, which has had to be corrected on multiple occasions by the actual Swedish Radiation Safety Authority, Strålskyddsmyndigheten.</p>\r\n<p>Strålskyddsstiftelsen received the 2013 &quot;Misleader of the Year&quot; award from the main Swedish scientific skeptics\' society, Vetenskap och Folkbildning (&quot;Science and Public Education&quot;) for &quot;[their fearmongering propaganda and biased reporting on the health effects of mobile telephony use and wireless networks]&quot;.</p>\r\n<p><a href=\"https://www.vof.se/utmarkelser/tidigare-utmarkelser/aretas-forvillare-2013/\" class=\"uri\">https://www.vof.se/utmarkelser/tidigare-utmarkelser/aretas-forvillare-2013/</a> (in Swedish)</p>\r\n<p>These networks are part of a feedback loop where they get media attention, politicians pick up on their claims and use them to invoke the precautionary principle and get precautionary regulation in place, or judges rule based on the claims, which then gets quoted by these entities as evidence that they were right all along.</p>\r\n<p>They make it very hard to find factual information on whether millimeter-wavelength radiation actually has any different effect from the centimeter-wavelength radiation that we have been using for over two decades without any documented harmful effects, because wherever you look you just find these sites claiming that we have definitely had adverse health effects for the last two decades and the new frequency bands will definitely be far worse.</p>\r\n<p>When you dig deeper into the claims on these sites you find a handful of cherry-picked articles, leading back to the two men mentioned at the top, to studies with flawed methodology like self-reported surveys on mobile telephony use among cancer patients, or to the pseudoscience/media/politics/law feedback loop. And it’s all about centimeter waves, which simply have shown no conclusive sign of increasing brain cancers or any other adverse health effect related to the radiation. For every positive report made you can find one that reports brain cancer fell as we introduced mobile phones. There is a massive body of data, and if the signal were there, we would have seen it by now.</p>\r\n<p>I’m no cancer researcher, but neither is Rainer Nyberg, he’s a retired professor in pedagogy. He’s a concerned citizen. <a href=\"https://en.wikipedia.org/wiki/Lennart_Hardell\" class=\"uri\">https://en.wikipedia.org/wiki/Lennart_Hardell</a> is an actual oncologist and professor who has studied carcinogens, but his research results on the wireless/cancer connection have been dismissed as &quot;non-informative&quot;, &quot;post hoc&quot;, &quot;barely statistically significant&quot; and &quot;flawed&quot; by his peers. There is nothing there.</p>\r\n<p>We know that high-voltage 16.7 Hz fields increase the risk for leukemia in train drivers, but we don’t know why. I am open to the possibility that 20-50 GHz waves have different consequences from 2 GHz waves, but I’d have to hear it from a credible source.</p>\r\n<p>Straight up DNA mutation is out the window, and that’s one of the centerpoints of these campaigns. This is still frequencies below visual light, it’s not ionizing radiation. No plausible mechanism has been suggested, and there is no clear data on any adverse effects.</p>\r\n<p>We use millimeter waves for the full body scans in US airports. Surely the effects of those have been studied? The top search results go to truthaboutcancer and infowars and similar names I won’t even bother to click. I don’t want to read another article about how all cancer research after 1950 has been wrong, we should all just eat chalk to balance our acidity, and cancer is a fungus.</p>\r\n<p>Apart from the pseudoscience sites I found one paper on the first search results page, concluding that X-ray backscatter scanners have well-known risks, but radiation levels are far below safety standards, both for passengers and for security staff, and also below the background radiation exposure while flying, and millimeter-wave scanners, while an &quot;alarmingly small amount of information about its potential health effects&quot; is available, &quot;The established health effects associated with non-ionizing radiation are limited to thermal effects&quot; and &quot;these scanners operate at outputs well below those required to produce tissue heating&quot;, that is, we currently don’t know of a way millimeter waves might be harmful: <a href=\"https://www.sciencedirect.com/science/article/pii/S1687850714000168\" class=\"uri\">https://www.sciencedirect.com/science/article/pii/S1687850714000168</a> (<a href=\"https://doi.org/10.1016/j.jrras.2014.02.005\" class=\"uri\">https://doi.org/10.1016/j.jrras.2014.02.005</a>)</p>\r\n<p>For a guide on how to spot pseudoscience and how to read scientific papers, see ahuka’s excellent <a href=\"https://hackerpublicradio.org/eps.php?id=2695\">hpr2695: Problems with Studies</a>.</p>\r\n<p><a href=\"https://en.wikipedia.org/wiki/Betteridge%27s_Law_of_Headlines\">https://en.wikipedia.org/wiki/Betteridge%27s_Law_of_Headlines</a></p>',311,0,0,'CC-BY-SA','5g, health, radiation, pseudoscience',0,0,1),
(2818,'2019-05-22','Writing Web Game in Haskell - Science, part 1',2606,'Tuula explains types and data they used to model science in their Haskell game','<h2 id=\"background\">Background</h2>\r\n<p>This is rather large topic, so I split it in two episodes. Next one should follow in two weeks if everything goes as planned. First part is about modeling research, while second part concentrates on how things change over time.</p>\r\n<p>There’s three types of research: engineering, natural sciences and social sciences. Research costs points that are produced by various buildings.</p>\r\n<h2 id=\"implementation\">Implementation</h2>\r\n<p>There’s three database tables, which are defined below:</p>\r\n<pre><code>CurrentResearch\r\n    type Technology\r\n    progress Int\r\n    factionId FactionId\r\n\r\nAvailableResearch\r\n    type Technology\r\n    category TopResearchCategory\r\n    factionId FactionId\r\n\r\nCompletedResearch\r\n    type Technology\r\n    level Int\r\n    factionId FactionId\r\n    date Int</code></pre>\r\n<h2 id=\"data-types\">Data types</h2>\r\n<p><code>Technology</code> is enumeration of all possible technologies. Knowing these enable player to build specific buildings and space ships, enact various laws and so on. In the end this will be (hopefully) large list of technologies.</p>\r\n<pre><code>data Technology =\r\n    HighSensitivitySensors\r\n    | SideChannelSensors\r\n    | HighTensileMaterials\r\n    | SatelliteTechnology\r\n    | BawleyHulls\r\n    | SchoonerHulls\r\n    | CaravelHulls\r\n    ...\r\n    deriving (Show, Read, Eq, Enum, Bounded, Ord)</code></pre>\r\n<p>All research belong to one of the top categories that are shown below:</p>\r\n<pre><code>data TopResearchCategory =\r\n    Eng\r\n    | NatSci\r\n    | SocSci\r\n    deriving (Show, Read, Eq, Ord)</code></pre>\r\n<p><code>ResearchCategory</code> is more fine grained division of research. Each of the categories is further divided into sub-categories. Only <code>EngineeringSubField</code> is shown below, but other two are similarly divided.</p>\r\n<pre><code>data ResearchCategory =\r\n    Engineering EngineeringSubField\r\n    | NaturalScience NaturalScienceSubField\r\n    | SocialScience SocialScienceSubField\r\n    deriving (Show, Read, Eq)\r\n\r\ndata EngineeringSubField =\r\n    Industry\r\n    | Materials\r\n    | Propulsion\r\n    | FieldManipulation\r\n    deriving (Show, Read, Eq)</code></pre>\r\n<p><code>ResearchScore</code> is measure of how big some research is. It has type parameter <code>a</code> that is used to further quantify what kind of <code>ResearchScore</code> we’re talking about.</p>\r\n<pre><code>newtype ResearchScore a = ResearchScore { unResearchScore :: Int }\r\n    deriving (Show, Read, Eq, Ord, Num)</code></pre>\r\n<p><code>TotalResearchScore</code> is record of three different types of researches. I’m not sure if I should keep it as a record of three fields or if I should change it so that only one of those values can be present at any given time.</p>\r\n<pre><code>data TotalResearchScore a = TotalResearchScore\r\n    { totalResearchScoreEngineering :: ResearchScore EngineeringCost\r\n    , totalResearchScoreNatural :: ResearchScore NaturalScienceCost\r\n    , totalResearchScoreSocial :: ResearchScore SocialScienceCost\r\n    }\r\n    deriving (Show, Read, Eq)</code></pre>\r\n<p>Following singleton values are used with <code>ResearchScore</code> and <code>TotalResearchScore</code> to quantify what kind of value we’re talking about.</p>\r\n<pre><code>data EngineeringCost = EngineeringCost\r\n    deriving (Show, Read, Eq)\r\n\r\ndata NaturalScienceCost = NaturalScienceCost\r\n    deriving (Show, Read, Eq)\r\n\r\ndata SocialScienceCost = SocialScienceCost\r\n    deriving (Show, Read, Eq)\r\n\r\ndata ResearchCost = ResearchCost\r\n    deriving (Show, Read, Eq)\r\n\r\ndata ResearchProduction = ResearchProduction\r\n    deriving (Show, Read, Eq)\r\n\r\ndata ResearchLeft = ResearchLeft\r\n    deriving (Show, Read, Eq)</code></pre>\r\n<p>Finally there’s <code>Research</code>, which is a record that uses many of the types introduced earlier. It describes what <code>Technology</code> is unlocked upon completion, what’s the cost is and if there are any technologies that have to have been researched before this research can start. The tier of research isn’t currently used for anything, but I have vague plans what to do about it in the future.</p>\r\n<pre><code>data Research = Research\r\n    { researchName :: Text\r\n    , researchType :: Technology\r\n    , researchCategory :: ResearchCategory\r\n    , researchAntecedents :: [Technology]\r\n    , researchCost :: TotalResearchScore ResearchCost\r\n    , researchTier :: ResearchTier\r\n    }\r\n    deriving (Show, Read, Eq)</code></pre>\r\n<h2 id=\"tech-tree\">Tech tree</h2>\r\n<p>Putting all this together, we can define a list of <code>Research</code>. Since finding an entry from this list based on research type of it is such a common operation, we also define another data structure for this specific purpose. <code>Map</code> in other programming languages is often known as dictionary, associative array or hash map. It stores key-value - pairs. In our case <code>Technology</code> is used as key and <code>Research</code> as value. We define it based on the list previously defined:</p>\r\n<pre><code>techMap :: Map.Map Technology Research\r\ntechMap = Map.fromList $ (\\x -&gt; (researchType x, x)) &lt;$&gt; unTechTree techTree</code></pre>\r\n<p>Next time we’ll look into how to actually use all these types and data that were defined.</p>\r\n',364,107,0,'CC-BY-SA','Haskell',0,0,1),
(2811,'2019-05-13','Interview with Alan Pope',5387,'In this episode, Yannick talks with Alan Pope about snaps, snapcraft and all things related','<p>A few years ago, when you wanted to install a package on your Linux system, you had to grab the source code, and the nightmare began. But nowadays, this is over. You have deb files, and snaps, and flatpacks, and many other package formats available. On this episode, I was joined by Alan Pope, from Canonical, to talk about one of them in particular : snaps.</p>',370,78,0,'CC-BY-SA','ubuntu, snap, snapcraft, flatpack, linux, appimage, alan pope, popey',0,0,1),
(3066,'2020-05-04','HPR Community News for April 2020',2508,'Dave talks about shows released and comments posted in April 2020','<style>\ntable td.shrink {\n    white-space:nowrap\n}\n</style>\n\n<h2>New hosts</h2>\n<p>\nWelcome to our new host: <br />\n\n    <a href=\"https://hackerpublicradio.org/correspondents/0386.html\" target=\"_blank\">DanNixon</a>.\n</p>\n\n<h2>Last Month\'s Shows</h2>\n<table id=\"t01\">\n<tr>\n<th>Id</th>\n<th>Day</th>\n<th>Date</th>\n<th>Title</th>\n<th>Host</th>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3043\" target=\"_blank\">3043</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-04-01</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3043\" target=\"_blank\">How I record for HPR</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0318.html\" target=\"_blank\">Archer72</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3044\" target=\"_blank\">3044</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-04-02</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3044\" target=\"_blank\">mocp snooze tip</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0201.html\" target=\"_blank\">MrX</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3045\" target=\"_blank\">3045</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-04-03</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3045\" target=\"_blank\">OSS compliance with privacy by default and design</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3046\" target=\"_blank\">3046</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-04-06</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3046\" target=\"_blank\">HPR Community News for March 2020</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0159.html\" target=\"_blank\">HPR Volunteers</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3047\" target=\"_blank\">3047</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-04-07</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3047\" target=\"_blank\">The COVID-19 Work From Home Stream - Day 1</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3048\" target=\"_blank\">3048</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-04-08</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3048\" target=\"_blank\">Alternatives to toilet paper</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0078.html\" target=\"_blank\">klaatu</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3049\" target=\"_blank\">3049</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-04-09</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3049\" target=\"_blank\">What computers taught me about reality</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0078.html\" target=\"_blank\">klaatu</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3050\" target=\"_blank\">3050</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-04-10</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3050\" target=\"_blank\">Linux Inlaws S01E04 What\'s in a name</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3051\" target=\"_blank\">3051</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-04-13</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3051\" target=\"_blank\">The COVID-19 Work From Home Stream - Day 2</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3052\" target=\"_blank\">3052</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-04-14</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3052\" target=\"_blank\">Locating computers on a network</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3053\" target=\"_blank\">3053</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-04-15</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3053\" target=\"_blank\">AudioBookClub 17 - Blood Witness</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0157.html\" target=\"_blank\">HPR_AudioBookClub</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3054\" target=\"_blank\">3054</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-04-16</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3054\" target=\"_blank\">Coronavirus Thoughts</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3055\" target=\"_blank\">3055</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-04-17</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3055\" target=\"_blank\">Advice to new Fediverse administrators and developers</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3056\" target=\"_blank\">3056</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-04-20</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3056\" target=\"_blank\">Jitsi</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3057\" target=\"_blank\">3057</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-04-21</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3057\" target=\"_blank\">Formal verification with Coq</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0364.html\" target=\"_blank\">Tuula</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3058\" target=\"_blank\">3058</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-04-22</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3058\" target=\"_blank\">The COVID-19 Work From Home Stream - Day 3</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3059\" target=\"_blank\">3059</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-04-23</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3059\" target=\"_blank\">A quick intro to Snapcast</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0386.html\" target=\"_blank\">DanNixon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3060\" target=\"_blank\">3060</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-04-24</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3060\" target=\"_blank\">Running a local imap server</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3061\" target=\"_blank\">3061</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-04-27</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3061\" target=\"_blank\">Parental Controls With Mike Ivy</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3062\" target=\"_blank\">3062</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-04-28</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3062\" target=\"_blank\">Vassal: How to play board games while remote</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0311.html\" target=\"_blank\">clacke</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3063\" target=\"_blank\">3063</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-04-29</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3063\" target=\"_blank\">Pens, pencils, paper and ink - 1</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3064\" target=\"_blank\">3064</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-04-30</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3064\" target=\"_blank\">How I got started in Electronics</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0318.html\" target=\"_blank\">Archer72</a></td>\n</tr>\n</table>\n\n<h2>Comments this month</h2>\n\n<p>These are comments which have been made during the past month, either to shows released during the month or to past shows.\nThere are 24 comments in total.</p>\n<h3>Past shows</h3>\n<p>There are 4 comments on\n3 previous shows:</p>\n<ul>\n<li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3027#comments\" target=\"_blank\">hpr3027</a></strong>\n(2020-03-10) \"<em>What is quantum computing and why should we care?</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0379.html\" target=\"_blank\">mightbemike</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3027#1\" target=\"_blank\">Comment 1</a>:\nMongo on 2020-04-04:\n\"very interesting talk\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3032#comments\" target=\"_blank\">hpr3032</a></strong>\n(2020-03-17) \"<em>piCore on a Raspberry Pi 1 Model B</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0152.html\" target=\"_blank\">Claudio Miranda</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3032#2\" target=\"_blank\">Comment 2</a>:\nclacke on 2020-04-15:\n\"Re: Tiny Core maintainer name\"</li>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3032#3\" target=\"_blank\">Comment 3</a>:\nclacke on 2020-04-18:\n\"Ridiculously tiny really\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3034#comments\" target=\"_blank\">hpr3034</a></strong>\n(2020-03-19) \"<em>How to bridge Freenode IRC rooms to Matrix.org</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3034#2\" target=\"_blank\">Comment 2</a>:\nclacke on 2020-04-12:\n\"appservice-irc\"</li></ul><br/>\n</li></ul>\n<h3>This month\'s shows</h3>\n<p>There are 20 comments on 9 of this month\'s shows:</p>\n<ul><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3043#comments\" target=\"_blank\">hpr3043</a></strong>\n(2020-04-01) \"<em>How I record for HPR</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0318.html\" target=\"_blank\">Archer72</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3043#1\" target=\"_blank\">Comment 1</a>:\nthelovebug on 2020-04-02:\n\"Bass and Treble\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3046#comments\" target=\"_blank\">hpr3046</a></strong>\n(2020-04-06) \"<em>HPR Community News for March 2020</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0159.html\" target=\"_blank\">HPR Volunteers</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3046#1\" target=\"_blank\">Comment 1</a>:\nclacke on 2020-04-17:\n\"First-class ranting\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3048#comments\" target=\"_blank\">hpr3048</a></strong>\n(2020-04-08) \"<em>Alternatives to toilet paper</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0078.html\" target=\"_blank\">klaatu</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3048#1\" target=\"_blank\">Comment 1</a>:\nmcnalu on 2020-04-08:\n\"The affected episode\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3048#2\" target=\"_blank\">Comment 2</a>:\nBookewyrmm on 2020-04-09:\n\"A word of caution\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3048#3\" target=\"_blank\">Comment 3</a>:\nTuula on 2020-04-21:\n\"Speaking of romans\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3050#comments\" target=\"_blank\">hpr3050</a></strong>\n(2020-04-10) \"<em>Linux Inlaws S01E04 What\'s in a name</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3050#1\" target=\"_blank\">Comment 1</a>:\nAhuka on 2020-04-10:\n\"Great sketch!\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3051#comments\" target=\"_blank\">hpr3051</a></strong>\n(2020-04-13) \"<em>The COVID-19 Work From Home Stream - Day 2</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3051#1\" target=\"_blank\">Comment 1</a>:\nbrian in ohio on 2020-04-14:\n\"electoral college\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3052#comments\" target=\"_blank\">hpr3052</a></strong>\n(2020-04-14) \"<em>Locating computers on a network</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3052#1\" target=\"_blank\">Comment 1</a>:\nDave Morriss on 2020-04-22:\n\"Very useful, thanks\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3053#comments\" target=\"_blank\">hpr3053</a></strong>\n(2020-04-15) \"<em>AudioBookClub 17 - Blood Witness</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0157.html\" target=\"_blank\">HPR_AudioBookClub</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3053#1\" target=\"_blank\">Comment 1</a>:\nlostnbronx on 2020-04-08:\n\"Welcom back to the Audio Book Club!\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3054#comments\" target=\"_blank\">hpr3054</a></strong>\n(2020-04-16) \"<em>Coronavirus Thoughts</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3054#1\" target=\"_blank\">Comment 1</a>:\nbrian in ohio on 2020-04-18:\n\"politics\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3054#2\" target=\"_blank\">Comment 2</a>:\nTelford Tendys on 2020-04-23:\n\"Freedom, Governance and Pandemic\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3054#3\" target=\"_blank\">Comment 3</a>:\nbrian in ohio on 2020-04-24:\n\"clarification\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3054#4\" target=\"_blank\">Comment 4</a>:\nAhuka on 2020-04-24:\n\"Herd immunity\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3056#comments\" target=\"_blank\">hpr3056</a></strong>\n(2020-04-20) \"<em>Jitsi</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3056#1\" target=\"_blank\">Comment 1</a>:\nAhuka on 2020-04-20:\n\"Very timely\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3056#2\" target=\"_blank\">Comment 2</a>:\nharvhat on 2020-04-21:\n\"Why talk about Jitsi\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3056#3\" target=\"_blank\">Comment 3</a>:\njustme on 2020-04-21:\n\"I really enjoyed this episode\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3056#4\" target=\"_blank\">Comment 4</a>:\nMike Ray on 2020-04-21:\n\"Re: Why talk about jitsi?\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3056#5\" target=\"_blank\">Comment 5</a>:\nAhuka on 2020-04-23:\n\"Why listen?\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3056#6\" target=\"_blank\">Comment 6</a>:\nMike Ray on 2020-04-23:\n\"Re: Why listen?\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3056#7\" target=\"_blank\">Comment 7</a>:\ncrvs on 2020-04-30:\n\"Re: Why listen?\"</li></ul><br/>\n</li></ul>\n\n<h2>Mailing List discussions</h2>\n<p>\nPolicy decisions surrounding HPR are taken by the community as a whole. This\ndiscussion takes place on the <a href=\"https://hackerpublicradio.org/maillist\"\ntarget=\"_blank\">Mail List</a> which is open to all HPR listeners and\ncontributors. The discussions are open and available on the HPR server under\n<a href=\"https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/\">Mailman</a>.\n</p>\n<p>The threaded discussions this month can be found here:</p>\n<a href=\"https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/2020-April/thread.html\" target=\"_blank\">https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/2020-April/thread.html</a>\n\n\n<h2>Events Calendar</h2>\n<p>With the kind permission of <strong>LWN.net</strong> we are linking to\n<a href=\"https://lwn.net/Calendar/\" target=\"_blank\">The LWN.net Community Calendar</a>.</p>\n<p>Quoting the site:</p>\n<blockquote>This is the LWN.net community event calendar, where we track\nevents of interest to people using and developing Linux and free software.\nClicking on individual events will take you to the appropriate web\npage.</blockquote>\n\n<h2>Any other business</h2>\n<h3 id=\"tags-and-summaries\">Tags and Summaries</h3>\n<p>Thanks to the following contributors for sending in updates in the past month:<br />\n<b><a href=\"https://hackerpublicradio.org/correspondents/0225.html\">Dave Morriss</a>, <a href=\"https://hackerpublicradio.org/correspondents/0215.html\">Windigo</a></b></p>\n<p>Over the period tags and/or summaries have been added to 17 shows which were without them.</p>\n<p>If you would like to contribute to the tag/summary project visit the summary page at <a href=\"https://hackerpublicradio.org/report_missing_tags.php\" class=\"uri\">https://hackerpublicradio.org/report_missing_tags.php</a> and follow the instructions there.</p>\n\n\n',159,47,1,'CC-BY-SA','Community News',0,0,1),
(3086,'2020-06-01','HPR Community News for May 2020',3253,'Dave and Ken talk about shows released and comments posted in May 2020','<style>\ntable td.shrink {\n    white-space:nowrap\n}\n</style>\n\n<h2>New hosts</h2>\n<p>\nThere were no new hosts this month.\n</p>\n\n<h2>Last Month\'s Shows</h2>\n<table id=\"t01\">\n<tr>\n<th>Id</th>\n<th>Day</th>\n<th>Date</th>\n<th>Title</th>\n<th>Host</th>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3065\" target=\"_blank\">3065</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-05-01</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3065\" target=\"_blank\">The case for the unattributed message</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3066\" target=\"_blank\">3066</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-05-04</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3066\" target=\"_blank\">HPR Community News for April 2020</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0159.html\" target=\"_blank\">HPR Volunteers</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3067\" target=\"_blank\">3067</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-05-05</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3067\" target=\"_blank\">Getting my Python3 code working in Python2</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0201.html\" target=\"_blank\">MrX</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3068\" target=\"_blank\">3068</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-05-06</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3068\" target=\"_blank\">Keeping track of downloads in Elm</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0364.html\" target=\"_blank\">Tuula</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3069\" target=\"_blank\">3069</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-05-07</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3069\" target=\"_blank\">Linux Inlaws S01E05 Porn and Skynet</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3070\" target=\"_blank\">3070</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-05-08</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3070\" target=\"_blank\">making vim xdg compatible</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0385.html\" target=\"_blank\">crvs</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3071\" target=\"_blank\">3071</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-05-11</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3071\" target=\"_blank\">Bash snippet - quotes inside quoted strings</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3072\" target=\"_blank\">3072</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-05-12</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3072\" target=\"_blank\">The joy of pip-tools and pyenv-virtualenv</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0311.html\" target=\"_blank\">clacke</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3073\" target=\"_blank\">3073</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-05-13</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3073\" target=\"_blank\">Matchbox and Diecast Restoration</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0338.html\" target=\"_blank\">Tony Hughes AKA TonyH1212</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3074\" target=\"_blank\">3074</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-05-14</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3074\" target=\"_blank\">For your consideration - Escape Pod</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3075\" target=\"_blank\">3075</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-05-15</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3075\" target=\"_blank\">Federated Blogging with WriteFreely</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3076\" target=\"_blank\">3076</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-05-18</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3076\" target=\"_blank\">Keep calm and Virion</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3077\" target=\"_blank\">3077</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-05-19</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3077\" target=\"_blank\">Video conference Push to Talk</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0386.html\" target=\"_blank\">DanNixon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3078\" target=\"_blank\">3078</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-05-20</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3078\" target=\"_blank\">Coronavirus Update 2020-05-07</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3079\" target=\"_blank\">3079</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-05-21</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3079\" target=\"_blank\">Linux Inlaws S01E06 Porn and Trump</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3080\" target=\"_blank\">3080</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-05-22</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3080\" target=\"_blank\">Ansible ping</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3081\" target=\"_blank\">3081</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-05-25</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3081\" target=\"_blank\">Why do formal verification?</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0364.html\" target=\"_blank\">Tuula</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3082\" target=\"_blank\">3082</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-05-26</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3082\" target=\"_blank\">RFC 5005 Part 1 – Paged and archived feeds? Who cares?</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0311.html\" target=\"_blank\">clacke</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3083\" target=\"_blank\">3083</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-05-27</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3083\" target=\"_blank\">Mumbling while on lockdown</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3084\" target=\"_blank\">3084</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-05-28</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3084\" target=\"_blank\">AudioBookClub 18 - Star Trek: The Continuing Mission</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3085\" target=\"_blank\">3085</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-05-29</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3085\" target=\"_blank\">Architectures of Robust Openness</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n</table>\n\n<h2>Comments this month</h2>\n\n<p>These are comments which have been made during the past month, either to shows released during the month or to past shows.\nThere are 29 comments in total.</p>\n<h3>Past shows</h3>\n<p>There are 8 comments on\n4 previous shows:</p>\n<ul>\n<li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3013#comments\" target=\"_blank\">hpr3013</a></strong>\n(2020-02-19) \"<em>Bash Tips - 21</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3013#3\" target=\"_blank\">Comment 3</a>:\nnobody on 2020-05-22:\n\"awk\"</li>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3013#4\" target=\"_blank\">Comment 4</a>:\nDave Morriss on 2020-05-22:\n\"Response to \'nobody\' re awk\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3053#comments\" target=\"_blank\">hpr3053</a></strong>\n(2020-04-15) \"<em>AudioBookClub 17 - Blood Witness</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0157.html\" target=\"_blank\">HPR_AudioBookClub</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3053#2\" target=\"_blank\">Comment 2</a>:\nmordancy on 2020-05-28:\n\"Blood Witness\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3059#comments\" target=\"_blank\">hpr3059</a></strong>\n(2020-04-23) \"<em>A quick intro to Snapcast</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0386.html\" target=\"_blank\">DanNixon</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3059#1\" target=\"_blank\">Comment 1</a>:\nWindigo on 2020-05-01:\n\"Thanks for the introduction\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3063#comments\" target=\"_blank\">hpr3063</a></strong>\n(2020-04-29) \"<em>Pens, pencils, paper and ink - 1</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3063#1\" target=\"_blank\">Comment 1</a>:\nArcher72 on 2020-05-05:\n\"Fountain pens\"</li>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3063#2\" target=\"_blank\">Comment 2</a>:\nBookewyrmm on 2020-05-07:\n\"Pens, ink and paper\"</li>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3063#3\" target=\"_blank\">Comment 3</a>:\nDave Morriss on 2020-05-07:\n\"To Archer72\"</li>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3063#4\" target=\"_blank\">Comment 4</a>:\nDave Morriss on 2020-05-07:\n\"To Bookewyrmm\"</li></ul><br/>\n</li></ul>\n<h3>This month\'s shows</h3>\n<p>There are 21 comments on 11 of this month\'s shows:</p>\n<ul><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3065#comments\" target=\"_blank\">hpr3065</a></strong>\n(2020-05-01) \"<em>The case for the unattributed message</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3065#1\" target=\"_blank\">Comment 1</a>:\nbrian in ohio on 2020-05-01:\n\"enemies\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3066#comments\" target=\"_blank\">hpr3066</a></strong>\n(2020-05-04) \"<em>HPR Community News for April 2020</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0159.html\" target=\"_blank\">HPR Volunteers</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3066#1\" target=\"_blank\">Comment 1</a>:\nTuula on 2020-05-04:\n\"Thanks\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3066#2\" target=\"_blank\">Comment 2</a>:\nDave Morriss on 2020-05-05:\n\"No problem\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3066#3\" target=\"_blank\">Comment 3</a>:\nclacke on 2020-05-06:\n\"Blood type distribution\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3066#4\" target=\"_blank\">Comment 4</a>:\nAhuka on 2020-05-06:\n\"I loved the show\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3066#5\" target=\"_blank\">Comment 5</a>:\nDave Morriss on 2020-05-06:\n\"Re: Blood type distribution\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3066#6\" target=\"_blank\">Comment 6</a>:\nDave Morriss on 2020-05-06:\n\"Thanks Ahuka\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3069#comments\" target=\"_blank\">hpr3069</a></strong>\n(2020-05-07) \"<em>Linux Inlaws S01E05 Porn and Skynet</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3069#1\" target=\"_blank\">Comment 1</a>:\nBendy on 2020-05-12:\n\"skynet\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3071#comments\" target=\"_blank\">hpr3071</a></strong>\n(2020-05-11) \"<em>Bash snippet - quotes inside quoted strings</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3071#1\" target=\"_blank\">Comment 1</a>:\nnobody on 2020-05-22:\n\"Further simplifying\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3071#2\" target=\"_blank\">Comment 2</a>:\nDave Morriss on 2020-05-22:\n\"To \'nobody\' re ANSI-C quoting\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3072#comments\" target=\"_blank\">hpr3072</a></strong>\n(2020-05-12) \"<em>The joy of pip-tools and pyenv-virtualenv</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0311.html\" target=\"_blank\">clacke</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3072#1\" target=\"_blank\">Comment 1</a>:\nclacke on 2020-04-30:\n\"Errata: Ubuntu Python virtualenv works just fine\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3072#2\" target=\"_blank\">Comment 2</a>:\nTuula on 2020-05-12:\n\"Interesting and insightful\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3073#comments\" target=\"_blank\">hpr3073</a></strong>\n(2020-05-13) \"<em>Matchbox and Diecast Restoration</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0338.html\" target=\"_blank\">Tony Hughes AKA TonyH1212</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3073#1\" target=\"_blank\">Comment 1</a>:\nTuula on 2020-05-13:\n\"sounds good\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3073#2\" target=\"_blank\">Comment 2</a>:\nTony Hughes on 2020-05-14:\n\"Feedback from Tuula\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3075#comments\" target=\"_blank\">hpr3075</a></strong>\n(2020-05-15) \"<em>Federated Blogging with WriteFreely</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3075#1\" target=\"_blank\">Comment 1</a>:\nclacke on 2020-05-01:\n\"Federated link for talk on federated things\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3077#comments\" target=\"_blank\">hpr3077</a></strong>\n(2020-05-19) \"<em>Video conference Push to Talk</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0386.html\" target=\"_blank\">DanNixon</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3077#1\" target=\"_blank\">Comment 1</a>:\nKen Fallon on 2020-05-19:\n\"Brilliant Idea\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3077#2\" target=\"_blank\">Comment 2</a>:\njezra on 2020-05-19:\n\"an amazing mix of custom hardware and software\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3078#comments\" target=\"_blank\">hpr3078</a></strong>\n(2020-05-20) \"<em>Coronavirus Update 2020-05-07</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3078#1\" target=\"_blank\">Comment 1</a>:\nZen_floater2 on 2020-05-22:\n\"my magical forrest Atheist comments.\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3083#comments\" target=\"_blank\">hpr3083</a></strong>\n(2020-05-27) \"<em>Mumbling while on lockdown</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3083#1\" target=\"_blank\">Comment 1</a>:\nDanNixon on 2020-05-29:\n\"Groove based tape format\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3083#2\" target=\"_blank\">Comment 2</a>:\nMrX on 2020-05-31:\n\"Re Groove based tape format\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3084#comments\" target=\"_blank\">hpr3084</a></strong>\n(2020-05-28) \"<em>AudioBookClub 18 - Star Trek: The Continuing Mission</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0270.html\" target=\"_blank\">Thaj Sara</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3084#1\" target=\"_blank\">Comment 1</a>:\nAhuka on 2020-05-28:\n\"Missing Fifty\"</li></ul><br/>\n</li></ul>\n\n<h2>Mailing List discussions</h2>\n<p>\nPolicy decisions surrounding HPR are taken by the community as a whole. This\ndiscussion takes place on the <a href=\"https://hackerpublicradio.org/maillist\"\ntarget=\"_blank\">Mail List</a> which is open to all HPR listeners and\ncontributors. The discussions are open and available on the HPR server under\n<a href=\"https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/\">Mailman</a>.\n</p>\n<p>The threaded discussions this month can be found here:</p>\n<a href=\"https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/2020-May/thread.html\" target=\"_blank\">https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/2020-May/thread.html</a>\n\n\n<h2>Events Calendar</h2>\n<p>With the kind permission of <strong>LWN.net</strong> we are linking to\n<a href=\"https://lwn.net/Calendar/\" target=\"_blank\">The LWN.net Community Calendar</a>.</p>\n<p>Quoting the site:</p>\n<blockquote>This is the LWN.net community event calendar, where we track\nevents of interest to people using and developing Linux and free software.\nClicking on individual events will take you to the appropriate web\npage.</blockquote>\n\n<h2>Any other business</h2>\n<h3 id=\"tags-and-summaries\">Tags and Summaries</h3>\n<p>Thanks to the following contributor for sending in updates in the past month:<br />\n<b><a href=\"https://hackerpublicradio.org/correspondents/0225.html\">Dave Morriss</a></b></p>\n<p>Over the period tags and/or summaries have been added to 9 shows which were without them.</p>\n<p>If you would like to contribute to the tag/summary project visit the summary page at <a href=\"https://hackerpublicradio.org/report_missing_tags.php\" class=\"uri\">https://hackerpublicradio.org/report_missing_tags.php</a> and follow the instructions there.</p>\n\n\n',159,47,1,'CC-BY-SA','Community News',0,0,1),
(2813,'2019-05-15','Should we dump the linux Desktop.',1229,'Knightwise wonders if we should let go of the linux desktop environments and focus on cross-platform','<p>Knightwise wonders if we should let go of the linux desktop environments and focus on cross-platform applications instead. Please bring your torches and pitchforks.</p>',111,0,1,'CC-BY-SA','linux, desktop, rant',0,0,1),
(2814,'2019-05-16','Spectre and Meltdown and OpenBSD and our future',1251,'A discussion about CPU\'s and our future with them, where are we going?','<p>I discuss the entire Spectre and Meltdown issues and where we might go post an Intel world. My objective is to encourage others to leave Speculative processing backed by management engine based chips. SCATTER HUMANS!!! WE MUST LEAVE!!!!</p>\r\n',377,0,0,'CC-BY-SA','SCATTER HUMANS!!!',0,0,1),
(2815,'2019-05-17','Copy pasta',2300,'Copying and pasting on Linux: X selections, xsel, clipboard managers, GPM, screen, and more','<p>\r\nYou can copy and paste on Linux the same way you do on any other OS: Ctrl+C to copy and Ctrl+V to paste (or use the Edit menu, or a right-click menu).\r\n</p>\r\n\r\n<p>\r\nHowever, Linux doesn\'t limit you to just that.\r\nThe primary GUI environment of Linux (at the time of this recording) is X, and the <a href=\"https://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html\">Inter-Client Communication Conventions Manual</a> defines three <strong>X Selection</strong> states&#58; Primary, Secondary, and Clipboard.\r\nThe Secondary is rarely (if ever?) used, so I don\'t cover it here.\r\n</p>\r\n\r\n<h2>Primary</h2>\r\n\r\n<p>\r\nThe primary X Selection is anything literally selected at any given moment.\r\nIf you highlight a word in Firefox with your mouse, for instance, then it becomes the Primary Selection, and it is owned by Firefox.\r\nIf you press the Middle Mouse Button in any application, then that application asks the owner (Firefox, in this example) for the data contained in the Primary Selection.\r\nFirefox sends the data to that application so that it can paste it for you.\r\n</p>\r\n\r\n<p>\r\nA Primary selection remains the Primary Selection until it is overwritten by a new Primary Selection.\r\nIn other words, text needn\'t be highlighted to be retained in the Primary Selection slot.\r\n</p>\r\n\r\n\r\n<h2>Clipboard</h2>\r\n\r\n<p>\r\nThe Clipboard Selection is data that has explicitly been sent to the clipboard by a copy action.\r\nThis is usually a right-click &#62; Copy or a selection of Edit &#62; Copy.\r\nWhen another application is told to paste from the clipboard, it pastes data from the Clipboard Selection.\r\n</p>\r\n\r\n<h2>Both</h2>\r\n\r\n<p>\r\nYou can (and often do) have both a Primary Selection and a Clipboard selection.\r\nIf you press Ctrl+V, you get the contents of the Clipboard Selection.\r\nIf you press the middle mouse button, then you get the contents of the Primary Selection.\r\n</p>\r\n\r\n<h2>xsel</h2>\r\n\r\n<p>\r\nThe <code>xsel</code> command allows you to retrieve the contents of an X Selection.\r\n</p>\r\n\r\n<pre><code>\r\n$ xsel --primary\r\ndungeons\r\n$ xsel --clipboard\r\ndragons\r\n</code></pre>\r\n\r\n<h2>Clipboard managers</h2>\r\n\r\nClipboard managers such as Klipper, CopyQ, <a href=\"https://parcellite.sourceforge.net/\" target=\"_blank\">Parcellite</a>, and so on, provide a history for your clipboard.\r\nThey track the latest 10 (or so) items you have copied or selected.\r\nThey can be a little confusing, because they do tend to blur the line between the Primary Selection and the Clipboard Selection, but now that you know the technical difference, it shouldn\'t confuse you to see them both listed by a clipboard manager designed to conflate them.\r\n</p>\r\n\r\n<h2>GPM</h2>\r\n\r\n<p>\r\nGPM is a daemon allowing you to use your mouse without a GUI.\r\nAmong its features, it permits you to select text in a text console (TTY) and then paste it with the middle mouse button.\r\n</p>\r\n\r\n<h2>GNU Screen and Tmux</h2>\r\n\r\n<p>\r\nScreen and tmux are &#34;window managers for text consoles&#34;.\r\nI don\'t tend to use tmux as often as I should, having learnt GNU Screen long ago, so I\'m not familiar with the process of copying and pasting with tmux.\r\nFor Screen, you can copy text in this way:\r\n</p>\r\n\r\n<ol>\r\n<li><p>\r\nPress Ctrl+A to get out of insert mode.\r\n</p></li>\r\n<li><p>\r\nPress left-square_bracket to enter copy-mode\r\n</p></li>\r\n<li><p>\r\nMove your text to the position you want to start selecting and press Enter or Return\r\n</p></li>\r\n<li><p>\r\nArrow to the position at which you want to end your selection and press Enter or Return again\r\n</p></li>\r\n</ol>\r\n\r\n<p>\r\nTo paste your selection:\r\n</p>\r\n\r\n<ol>\r\n<li><p>\r\nPress Ctrl+A to get out of insert mode.\r\n</p></li>\r\n<li><p>\r\nPress right-square_bracket to paste\r\n</p></li>\r\n</ol>\r\n\r\n\r\n\r\n',78,0,0,'CC-BY-SA','copy,paste,xsel',0,0,1),
(2816,'2019-05-20','Gnu Awk - Part 14',1357,'Redirection of input and output - part 1','<h2 id=\"introduction\">Introduction</h2>\r\n<p>This is the fourteenth episode of the “<a href=\"https://hackerpublicradio.org/series/0094.html\" title=\"Learning Awk\">Learning Awk</a>” series which is being produced by <a href=\"https://hackerpublicradio.org/correspondents/0300.html\" title=\"b-yeezi\">b-yeezi</a> and myself.</p>\r\n<p>In this episode and the next I want to start looking at <em>redirection</em> within Awk programs. I had originally intended to cover the subject in one episode, but there is just too much.</p>\r\n<p>So, in the first episode I will be starting with <a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Redirection\" title=\"Redirecting output of `print` and `printf`\">output redirection</a> and then in the next episode will spend some time looking at the <code>getline</code> command used for <em>explicit input</em>, often with redirection.</p>\r\n<h2 id=\"long-notes\">Long notes</h2>\r\n<p>I have provided detailed notes as usual for this episode, and these can be <a href=\"https://hackerpublicradio.org/eps/hpr2816/full_shownotes.html\">viewed here</a>.</p>\r\n<h2 id=\"links\">Links</h2>\r\n<ul>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/html_node/index.html\"><em>GNU Awk User’s Guide</em></a>\r\n<ul>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Redirection\">Redirecting output of <code>print</code> and <code>printf</code></a></li>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Special-FD\">Special Files for Standard Preopened Data Streams</a></li>\r\n<li><a href=\"https://www.gnu.org/software/gawk/manual/gawk.html#Special-Files\">Special File names in gawk</a></li>\r\n</ul></li>\r\n</ul>\r\n<ul>\r\n<li>Previous shows in this series on HPR:\r\n<ul>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2114\">“<em>Gnu Awk - Part 1</em>”</a> - episode 2114</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2129\">“<em>Gnu Awk - Part 2</em>”</a> - episode 2129</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2143\">“<em>Gnu Awk - Part 3</em>”</a> - episode 2143</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2163\">“<em>Gnu Awk - Part 4</em>”</a> - episode 2163</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2184\">“<em>Gnu Awk - Part 5</em>”</a> - episode 2184</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2238\">“<em>Gnu Awk - Part 6</em>”</a> - episode 2238</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2330\">“<em>Gnu Awk - Part 7</em>”</a> - episode 2330</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2438\">“<em>Gnu Awk - Part 8</em>”</a> - episode 2438</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2476\">“<em>Gnu Awk - Part 9</em>”</a> - episode 2476</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2526\">“<em>Gnu Awk - Part 10</em>”</a> - episode 2526</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2554\">“<em>Gnu Awk - Part 11</em>”</a> - episode 2554</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2610\">“<em>Gnu Awk - Part 12</em>”</a> - episode 2610</li>\r\n<li><a href=\"https://hackerpublicradio.org/eps.php?id=2804\">“<em>Gnu Awk - Part 13</em>”</a> - episode 2804</li>\r\n</ul></li>\r\n<li>Resources:\r\n<ul>\r\n<li><a href=\"https://hackerpublicradio.org/eps/hpr2816/full_shownotes.epub\">ePub version of these notes</a></li>\r\n<li>Examples: <a href=\"https://hackerpublicradio.org/eps/hpr2816/awk14_fruit_data.txt\">awk14_fruit_data.txt</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2816/awk14_ex1.awk\">awk14_ex1.awk</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2816/awk14_ex2.awk\">awk14_ex2.awk</a>, <a href=\"https://hackerpublicradio.org/eps/hpr2816/awk14_ex3.awk\">awk14_ex3.awk</a></li>\r\n</ul></li>\r\n</ul>\r\n',225,94,1,'CC-BY-SA','Awk utility, Awk Language, gawk,redirection',0,0,1),
(2830,'2019-06-07','2018-2019 New Years Eve show part 1',12194,'The HPR community comes together to say happy new year and chat','<h2>Hacker Public Radio New Years Show episode 1</h2>\r\n<p>Welcome to the 7th Annual Hacker Public Radio show. It is December the 31st 2018 and the time is 10 hundred hours UTC.</p>\r\n<ul>\r\n<li>Ken introduces the New year show, gives some history and thanks Kevin Wisher and HonkeyMagoo for organising this.</li>\r\n<li>Wondering where Klaatu is,</li>\r\n<li>Fifty one fifty talks about his new isp<br /><a href=\"https://www.blazinghog.com\">https://www.blazinghog.com</a></li>\r\n<li>Ken GETS STUCK IN CAPS LOCK<br /> <a href=\"https://wiki.archlinux.org/index.php/Xorg/Keyboard_configuration\">https://wiki.archlinux.org/index.php/Xorg/Keyboard_configuration</a></li>\r\n<li>ISO8601 YYYY-MM-DD <a href=\"https://en.wikipedia.org/wiki/ISO_8601\">https://en.wikipedia.org/wiki/ISO_8601</a></li>\r\n<li><a href=\"https://www.hostelworld.com/hosteldetails.php/STF-IYHF-af-Chapman/Stockholm/32555\">https://www.hostelworld.com/hosteldetails.php/STF-IYHF-af-Chapman/Stockholm/32555</a></li>\r\n<li>Honkey is on his way to work</li>\r\n<li><pre>$ alias utc=\'/bin/date -u +%Y-%m-%d_%H-%M-%S%Z_%A\'</pre></li>\r\n<li><a href=\"https://www.youtube.com/watch?v=9PfdQod8HTw\">https://www.youtube.com/watch?v=9PfdQod8HTw</a> History Buffs: Tora! Tora! Tora!</li>\r\n<li>klaatu joins us, career at Red Hat, IBM takeover, teaching Linux to non-tech people<br /><a href=\"https://en.wikipedia.org/wiki/Dalton_Plan\">https://en.wikipedia.org/wiki/Dalton_Plan</a></li>\r\n<li>Computer musems<br /><a href=\"https://vonhagen.org/collection.html\">https://vonhagen.org/collection.html</a></li>\r\n<li>barcamp (yes related to foo)<br /><a href=\"https://en.wikipedia.org/wiki/BarCamp\">https://en.wikipedia.org/wiki/BarCamp</a></li>\r\n<li>Oggcamp<br /><a href=\"https://oggcamp.org/\">https://oggcamp.org/</a></li>\r\n<li>Mint Cast Podcast<br /><a href=\"https://mintcast.org/\">https://mintcast.org/</a></li>\r\n<li>Brexit<br /><a href=\"https://en.wikipedia.org/wiki/Brexit\">https://en.wikipedia.org/wiki/Brexit</a></li>\r\n</ul>\r\n<p>\"we should have bought stock\"</p>\r\n\r\n',159,121,1,'CC-BY-SA','hpr nye, new years eve, community',0,0,1),
(2817,'2019-05-21','Are you successful? Click to find out more!',281,'The answer may surprise you!','<p>Based on <a href=\"https://libranet.de/display/0b6b25a8-125c-a71f-c7ae-f1a686792961\" class=\"uri\">https://libranet.de/display/0b6b25a8-125c-a71f-c7ae-f1a686792961</a>.</p>\r\n<p>It’s pretty short, less than 4 minutes, but I think it’s important.</p>\r\n<p>Who defines whether you are successful, or whether your project is successful, and does it matter?</p>',311,0,0,'CC-BY-SA','success, self-care',0,0,1),
(2828,'2019-06-05','Writing Web Game in Haskell - Science, part 2',2734,'Tuula continues their explanation on simulating science in a game written in Haskell','<h2 id=\"intro\">Intro</h2>\r\n<p>Last time we looked how to model technology and research. This time we’ll do some actual research. I’m skipping over some of the details as the episode is long enough as it is. Hopefully it’s still possible to follow with the show notes.</p>\r\n<p>Main concepts that I’m mentioning: Technology allows usage of specific buildings, ship components and such. Research unlock technologies and may have antecedents that has to be completed before the research can be started. Research cost is measure of how expensive a research is in terms of research points, which are produced by different buildings.</p>\r\n<p>Earlier I modeled tech tree as Map that had Technology as keys and Research as values. I realized that this is suboptimal and will replace it at some point in the future.</p>\r\n<h2 id=\"server-api\">Server API</h2>\r\n<p>There’s three resources that client can connect to. First one is for retrieving list of available research, second one for manipulating current research and last one for retrieving info on how much research points is being produced.</p>\r\n<pre><code>/api/research/available     ApiAvailableResearchR       GET\r\n/api/research/current       ApiCurrentResearchR         GET POST DELETE\r\n/api/research/production    ApiResearchProductionR      GET</code></pre>\r\n<h2 id=\"simulation\">Simulation</h2>\r\n<p>Simulation of research is done by <code>handleFactionResearch</code>, which does simulation for one faction for a given date. After calculating current research point production and retrieving list of current research, function calculates progress of current researches. Unfinished ones are written back to database, while completed are moved into <code>completed_research</code> table. Final step is updating what research will be available in the next turn.</p>\r\n<pre><code>handleFactionResearch date faction = do\r\n    production &lt;- totalProduction $ entityKey faction\r\n    current &lt;- selectList [ CurrentResearchFactionId ==. entityKey faction ] []\r\n    let updated = updateProgress production &lt;$&gt; current\r\n    _ &lt;- updateUnfinished updated\r\n    _ &lt;- handleCompleted date updated $ entityKey faction\r\n    _ &lt;- updateAvailableResearch $ entityKey faction\r\n    return ()</code></pre>\r\n<h2 id=\"research-point-production\">Research point production</h2>\r\n<p>Research points are produced by buildings. So first step is to load all planets owned by the faction and buildings on those planets. Applying <code>researchOutput</code> function to each building yields a list of <code>TotalResearchScore</code>, which is then summed up by <code>mconcat</code>. We can use <code>mconcat</code> as <code>TotalResearchScore</code> is a monoid (I talked about these couple episodes ago).</p>\r\n<pre><code>totalProduction fId = do\r\n    pnbs &lt;- factionBuildings fId\r\n    let buildings = join $ fmap snd pnbs\r\n    return $ mconcat $ researchOutput . entityVal &lt;$&gt; buildings</code></pre>\r\n<p><code>researchOutput</code> function below uses pattern matching. Instead of writing one function definition and case expression inside of it, we’re writing multiple definitions. Each of them matches building of different type. First example is definition that is used for <code>ResearchComplex</code>, while second one is for <code>ParticleAccelerator</code>. Final case uses underscore to match anything and indicate that we’re not even interested on the particular value being matched. <code>mempty</code> is again from our monoid definition. It is empty or unit value of monoid, which in case of <code>TotalResearchScore</code> is zero points in all research categories.</p>\r\n<pre><code>researchOutput Building { buildingType = ResearchComplex } =\r\n    TotalResearchScore\r\n    { totalResearchScoreEngineering = ResearchScore 10\r\n    , totalResearchScoreNatural = ResearchScore 10\r\n    , totalResearchScoreSocial = ResearchScore 10\r\n    }\r\n\r\nresearchOutput Building { buildingType = ParticleAccelerator } =\r\n    TotalResearchScore\r\n    { totalResearchScoreEngineering = ResearchScore 15\r\n    , totalResearchScoreNatural = ResearchScore 15\r\n    , totalResearchScoreSocial = ResearchScore 0\r\n    }\r\n\r\nresearchOutput _ = mempty</code></pre>\r\n<h2 id=\"updating-progress\">Updating progress</h2>\r\n<p>Moving research forward is more complex looking function. There’s bunch of filtering and case expressions going on, but the idea is hopefully clear after a bit of explanation.</p>\r\n<p><code>updateProgress</code> takes two parameters, total production of research points and current research that is being modified. This assumes that there are only one of each categories of research going on at any given time. If there were more, we would have to divide research points between them by some logic. Function calculates effect of research points on current research and produces a new current research that is the end result.</p>\r\n<p>Perhaps the most interesting part is use of lenses. For example, line <code>entityValL . currentResearchProgressL +~ engResearch $ curr</code> means that <code>curr</code> (which is <code>Entity CurrentResearch</code>) is used as starting point. First we reach to data part of <code>Entity</code> and then we focus on <code>currentResearchProgress</code> and add <code>engResearch</code> to it. This results a completely new <code>Entity CurrentResearch</code> being constructed, which is otherwise identical with the original, but the <code>currentResearchProgress</code> has been modified. Without lenses we would have to do this destructuring and restructuring manually.</p>\r\n<pre><code>updateProgress :: TotalResearchScore ResearchProduction -&gt; Entity CurrentResearch -&gt; Entity CurrentResearch\r\nupdateProgress prod curr =\r\n    case researchCategory &lt;$&gt; research of\r\n        Just (Engineering _) -&gt;\r\n            entityValL . currentResearchProgressL +~ engResearch $ curr\r\n\r\n        Just (NaturalScience _) -&gt;\r\n            entityValL . currentResearchProgressL +~ natResearch $ curr\r\n\r\n        Just (SocialScience _) -&gt;\r\n            entityValL . currentResearchProgressL +~ socResearch $ curr\r\n\r\n        Nothing -&gt;\r\n            curr\r\n    where\r\n        research = Map.lookup (currentResearchType . entityVal $ curr) techMap\r\n        engResearch = unResearchScore $ totalResearchScoreEngineering prod\r\n        natResearch = unResearchScore $ totalResearchScoreNatural prod\r\n        socResearch = unResearchScore $ totalResearchScoreSocial prod</code></pre>\r\n<p>Writing unfinished research back to database is short function. First we find ones that hasn’t been finished by filtering with <code>(not . researchReady . entityVal)</code> and then we apply <code>replace</code> to write them back one by one.</p>\r\n<pre><code>updateUnfinished updated = do\r\n    let unfinished = filter (not . researchReady . entityVal) updated\r\n    mapM (\\x -&gt; replace (entityKey x) (entityVal x)) unfinished</code></pre>\r\n<p>Handling finished research starts by finding out which ones were actually completed by filtering with <code>(researchReady . entityVal)</code> and their research type with <code>currentResearchType . entityVal</code>. Rest of the function is all about database actions: creating entries into <code>completed_research</code> and adding news entries for each completed research, then removing entries from <code>current_research</code> and <code>available_research</code>.</p>\r\n<pre><code>handleCompleted date updated fId = do\r\n    let finished = filter (researchReady . entityVal) updated\r\n    let finishedTech = currentResearchType . entityVal &lt;$&gt; finished\r\n    insertMany_ $ currentToCompleted date . entityVal &lt;$&gt; finished\r\n    insertMany_ $ researchCompleted date fId . (currentResearchType . entityVal) &lt;$&gt; finished\r\n    deleteWhere [ CurrentResearchId &lt;-. fmap entityKey finished ]\r\n    deleteWhere [ AvailableResearchType &lt;-. finishedTech\r\n                , AvailableResearchFactionId ==. fId ]</code></pre>\r\n<h2 id=\"available-research\">Available research</h2>\r\n<p>Figuring out what researches will be available for the next turn takes several steps. I won’t be covering random numbers in detail, they’re interesting enough for an episode on their own. It’s enough to know that <code>g &lt;- liftIO getStdGen</code> gets us a new random number generator that is seeded by current time.</p>\r\n<p><code>updateAvailableResearch</code> starts by loading available research and current research for the faction and initializing a new random number generator. <code>g</code> can be used multiple times, but it’ll always return same sequence of numbers. Here it doesn’t matter, but in some cases it might. <code>getR</code> is helper function I wrote that uses random number generator to pick <code>n</code> entries from a given list. <code>n</code> in our case is hard coded to 3, but later on I’ll add possibility for player to research technologies that raise this limit. <code>newAvailableResearch</code> (we’ll look into its implementation closer just in a bit) produces a list of available research for specific research category. These lists are combined with <code>&lt;&gt;</code> operator and written into database with <code>rewriteAvailableResearch</code>.</p>\r\n<pre><code>updateAvailableResearch fId = do\r\n    available &lt;- selectList [ AvailableResearchFactionId ==. fId ] []\r\n    completed &lt;- selectList [ CompletedResearchFactionId ==. fId ] []\r\n    g &lt;- liftIO getStdGen\r\n    let maxAvailable = ResearchLimit 3\r\n    -- reusing same g should not have adverse effect here\r\n    let engCand = getR g (unResearchLimit maxAvailable) $ newAvailableResearch isEngineering maxAvailable available completed\r\n    let natCand = getR g (unResearchLimit maxAvailable) $ newAvailableResearch isNaturalScience maxAvailable available completed\r\n    let socCand = getR g (unResearchLimit maxAvailable) $ newAvailableResearch isSocialScience maxAvailable available completed\r\n    rewriteAvailableResearch fId $ engCand &lt;&gt; natCand &lt;&gt; socCand</code></pre>\r\n<p><code>newAvailableResearch</code> is in charge of figuring out what, if any, new research should be available in the next turn. In case where amount of currently available research is same or greater than research limit, empty list is returned, otherwise function calculates candidates and returns them. Logic for that is following:</p>\r\n<ul>\r\n<li>candidates are research of specific category of those that has been unlock and unresearched</li>\r\n<li>unlocked and unresearched are unlocked ones that are in list of known technology</li>\r\n<li>unlocked research are ones with antecedents available in tech tree</li>\r\n<li>known technology are ones in list of completed research</li>\r\n</ul>\r\n<p>and complete definition of the function is shown below:</p>\r\n<pre><code>newAvailableResearch selector limit available completed =\r\n    if ResearchLimit (length specificCategory) &gt;= limit\r\n        then []\r\n        else candidates\r\n    where\r\n        specificCategory = filter (availableResearchFilter selector) available\r\n        candidates = filter (selector . researchCategory) unlockedAndUnresearched\r\n        unlockedAndUnresearched = filter (\\x -&gt; researchType x `notElem` knownTech) unlockedResearch\r\n        unlockedResearch = filter (antecedentsAvailable knownTech) $ unTechTree techTree\r\n        knownTech = completedResearchType . entityVal &lt;$&gt; completed\r\n\r\n\r\navailableResearchFilter f x =\r\n    maybe False (f . researchCategory) res\r\n    where\r\n        res = Map.lookup (availableResearchType $ entityVal x) techMap</code></pre>\r\n<p>Final step of the simulation of research is to update database with new available research. <code>mkUniq</code> is helper function that removes duplicate elements from a list. It’s used in <code>rewriteAvailableResearch</code> function to make a list that contains all unique top research categories (engineering, natural sciences and social sciences). If the resulting list isn’t empty, we’ll use it to remove all available research for those top categories and insert new available research.</p>\r\n<pre><code>rewriteAvailableResearch fId res = do\r\n    let cats = mkUniq $ fmap (topCategory . researchCategory) res\r\n    unless (null cats) $ do\r\n        deleteWhere [ AvailableResearchFactionId ==. fId\r\n                    , AvailableResearchCategory &lt;-. cats ]\r\n        insertMany_ $ researchToAvailable fId &lt;$&gt; res</code></pre>\r\n<p>Now everything is ready for next round of simulation.</p>\r\n',364,107,0,'CC-BY-SA','haskell',0,0,1),
(2838,'2019-06-19','Why Haskell?',1900,'Tuula tries to answer Beeza\'s question on why would someone want to use Haskell','<p>I got really good comment on episode <a href=\"https://hackerpublicradio.org/eps.php?id=2778\">2778 - Functor and applicative in Haskell</a> from Beeza that I’m including below:</p>\r\n<blockquote>\r\n<p>I’ve been writing software for over 30 years but I find the syntax of Haskell anything but intuitive - in fact less so than any other programming language I have looked at. Thanks to your excellent show notes I can make sense of it but I have to say I would not like to have to develop a project using this language.</p>\r\n</blockquote>\r\n<blockquote>\r\n<p>Obviously I am missing the point as nobody would design a language with the intention of its being difficult to use. Perhaps you could produce another episode addressing the question “Why Haskell?”</p>\r\n</blockquote>\r\n<p>In this episode, I’m trying to answer to that from my point of view.</p>\r\n',364,107,0,'CC-BY-SA','haskell, response',0,0,1),
(2835,'2019-06-14','2018-2019 New Years Eve show part 2',9088,'The HPR community comes together to say happy new year and chat','<h2>Hacker Public Radio New Years Show episode 2</h2>\r\n<ul>\r\n<li>Claudio talks about doing IT for a school</li>\r\n<li>Pinebook discussion - complaints about keyboard, speakers, trackpad<br />\r\n<a href=\"https://www.pine64.org\">https://www.pine64.org</a></li>\r\n<li>Scanning photo negatives</li>\r\n<li>Camera discussion</li>\r\n<li>Firefly<br />\r\n<a href=\"https://www.imdb.com/title/tt0303461\">https://www.imdb.com/title/tt0303461</a></li>\r\n<li>Serenity<br />\r\n<a href=\"https://www.imdb.com/title/tt0379786\">https://www.imdb.com/title/tt0379786</a></li>\r\n<li>Babylon 5<br />\r\n<a href=\"https://www.imdb.com/title/tt0105946\">https://www.imdb.com/title/tt0105946</a></li>\r\n<li>POLYBIUS - The Video Game That Doesn\'t Exist<br />\r\n<a href=\"https://www.youtube.com/watch?v=_7X6Yeydgyg\">https://www.youtube.com/watch?v=_7X6Yeydgyg</a><br />\r\n<a href=\"https://en.wikipedia.org/wiki/Polybius\">https://en.wikipedia.org/wiki/Polybius</a></li>\r\n<li>Cicada 3301<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Cicada_3301\">https://en.wikipedia.org/wiki/Cicada_3301</a></li>\r\n<li>Ahoy you channel<br />\r\n<a href=\"https://www.youtube.com/channel/UCE1jXbVAGJQEORz9nZqb5bQ\">https://www.youtube.com/channel/UCE1jXbVAGJQEORz9nZqb5bQ</a></li>\r\n<li>Resilo Sync<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Resilio_Sync\">https://en.wikipedia.org/wiki/Resilio_Sync</a></li>\r\n<li>Mintcast<br />\r\n<a href=\"https://mintcast.org/\">https://mintcast.org/</a></li>\r\n<li>Zoom H2<br />\r\n<a href=\"https://www.zoom-na.com/products/field-video-recording/field-recording/h2-handy-recorder\">https://www.zoom-na.com/products/field-video-recording/field-recording/h2-handy-recorder</a></li>\r\n<li>LG Tone headsets<br />\r\n<a href=\"https://www.lg.com/us/bluetooth-headsets-headphones\">https://www.lg.com/us/bluetooth-headsets-headphones</a></li>\r\n<li>Urbanite XL<br />\r\n<a href=\"https://en-us.sennheiser.com/urbanite-xl\">https://en-us.sennheiser.com/urbanite-xl</a></li>\r\n<li>cmhobbs joins and asks for episode input.  will record winter field day 2019 from northwest arkansas.</li>\r\n\r\n<li>Book & audiobook</li>\r\n<li>Recommendations for books:<br />\r\n<ol>\r\n<li>Daemon by Daniel Suarez, <a href=\"https://daniel-suarez.com/\">https://daniel-suarez.com/</a></li>\r\n<li>Skyward by Brandon Sanderson, <a href=\"https://brandonsanderson.com/books/skyward/skyward/\">https://brandonsanderson.com/books/skyward/skyward/</a></li>\r\n</ol>\r\n</li>\r\n<li>Audiobook reading tips:<br />\r\n<ol>\r\n<li>To get into audiobooks, try listening to a book you\'ve read before</li>\r\n<li>Try increasing or decreasing the speed of the book</li>\r\n<li>Use the TTS feature of your eBook reader to create your own audiobooks</li>\r\n<li>Oddity of TTS mispronouncing words can be fun or frustrating</li>\r\n</ol>\r\n<li>Linux desktop upgrade fun</li>\r\n<li>MX Linux<br />\r\n<a href=\"https://mxlinux.org/\">https://mxlinux.org/</a></li>\r\n<li>AntiX Linux<br />\r\n<a href=\"https://antixlinux.com/\">https://antixlinux.com/</a></li>\r\n<li>exwm<br />\r\n<a href=\"https://github.com/ch11ng/exwm\">https://github.com/ch11ng/exwm</a></li>\r\n<li>ZFS on Linux<br />\r\n<a href=\"https://zfsonlinux.org/\">https://zfsonlinux.org/</a></li>\r\n<li>Dell venue 11 pro<br />\r\n<a href=-\"https://www.dell.com/en-us/work/shop/cty/venue-11-pro/spd/dell-venue-11-pro\">https://www.dell.com/en-us/work/shop/cty/venue-11-pro/spd/dell-venue-11-pro</a></li>\r\n<li>Acer aspire 1<br />\r\n<a href=\"https://www.acer.com/ac/en/US/content/series/aspire1\">https://www.acer.com/ac/en/US/content/series/aspire1</a></li>\r\n</ul>\r\n',159,121,0,'CC-BY-SA','HPR new years show, new years, community',0,0,1),
(2840,'2019-06-21','2018-2019 New Years Eve show part 3',7293,'The HPR community comes together to say happy new year and chat','<h2>Hacker Public Radio New Years Show episode 3</h2>\r\n<p>Welcome to the 7th Annual Hacker Public Radio New Years Show. 2018-2019</p>\r\n<ul>\r\n<li>Gaming PC vs Console</li>\r\n<li>Steam<br />\r\n<a href=\"https://store.steampowered.com/\">https://store.steampowered.com/</a></li>\r\n<li>Gaming on Linux with Proton<br />\r\n<a href=\"https://steamcommunity.com/games/221410/announcements/detail/1696055855739350561\">https://steamcommunity.com/games/221410/announcements/detail/1696055855739350561</a></li>\r\n<li>Good ol Games<br />\r\n<a href=\"https://www.gog.com/\">https://www.gog.com/</a></li>\r\n<li>Humble Bundle<br />\r\n<a href=\"https://www.humblebundle.com/\">https://www.humblebundle.com/</a></li>\r\n<li>God of War<br />\r\n<a href=\"https://godofwar.playstation.com/\">https://godofwar.playstation.com/</a></li>\r\n<li>The Witcher<br />\r\n<a href=\"https://thewitcher.com/en/\">https://thewitcher.com/en/</a></li>\r\n<li>Ghost of Tsushima<br />\r\n<a href=\"https://www.suckerpunch.com/category/games/ghost-of-tsushima/\">https://www.suckerpunch.com/category/games/ghost-of-tsushima/</a></li>\r\n<li>Plumble<br />\r\n<a href=\"https://play.google.com/store/apps/details?id=com.morlunk.mumbleclient.free&hl=en_US\">https://play.google.com/store/apps/details?id=com.morlunk.mumbleclient.free&hl=en_US</a></li>\r\n<li>mint cast<br />\r\n<a href=\"https://mintcast.org/\">https://mintcast.org/</a></li>\r\n<li>Free DOS<br />\r\n<a href=\"https://www.freedos.org/\">https://www.freedos.org/</a></li>\r\n<li>Compact flash<br />\r\n<a href=\"https://en.wikipedia.org/wiki/CompactFlash\">https://en.wikipedia.org/wiki/CompactFlash</a></li>\r\n<li>rtl-sdr<br />\r\n<a href=\"https://www.amazon.com/RTL-SDR-Blog-RTL2832U-Software-Defined/dp/B0129EBDS2\">https://www.amazon.com/RTL-SDR-Blog-RTL2832U-Software-Defined/dp/B0129EBDS2</a></li>\r\n<li>Cigarettes</li>\r\n<li>Taxing</li>\r\n<li>Alcohol</li>\r\n<li>Old Speckled Hen beer<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Old_Speckled_Hen\">https://en.wikipedia.org/wiki/Old_Speckled_Hen</a></li>\r\n<li>Motorcycles</li>\r\n<li>Harley Davidson<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Harley-Davidson\">https://en.wikipedia.org/wiki/Harley-Davidson</a></li>\r\n<li>Electric Cars</li>\r\n</ul>\r\n',159,121,0,'CC-BY-SA','HPR new years show, new years, community',0,0,1),
(2845,'2019-06-28','2018-2019 New Years Eve show part 4',10265,'The HPR community comes together to say happy new year and chat','<h2>Hacker Public Radio New Years Show episode 4</h2>\r\n<p>Welcome to the 7th Annual Hacker Public Radio New Years Show. 2018-2019</p>\r\n<ul>\r\n<li>3D Printing</li>\r\n<li>OSMC<br />\r\n<a href=\"https://osmc.tv/\">https://osmc.tv/</a></li>\r\n<li>Anet A8<br />\r\n<a href=\"https://3dprint.wiki/reprap/anet/a8\">https://3dprint.wiki/reprap/anet/a8</a></li>\r\n<li>Dell Venue 11 pro 7130<br />\r\n<ol>\r\n<li><a href=\"https://www.cnet.com/products/dell-venue-11-pro/specs/\">https://www.cnet.com/products/dell-venue-11-pro/specs/</a></li>\r\n<li><a href=\"https://www.studioteabag.com/science/dell-venue-pro-linux/DV11P/\">https://www.studioteabag.com/science/dell-venue-pro-linux/DV11P/</a></li>\r\n</ol>\r\n</li>\r\n<li>Drag vape<br />\r\n<a href=\"https://en.voopootech.com/drag-param\">https://en.voopootech.com/drag-param</a></li>\r\n<li>Gigabyte Brix<br />\r\n<a href=\"https://www.gigabyte.com/us/Mini-PcBarebone\">https://www.gigabyte.com/us/Mini-PcBarebone</a></li>\r\n<li>SDR talk</li>\r\n<li>DSP hack a day<br />\r\n<a href=\"https://hackaday.com/tag/dsp/\">https://hackaday.com/tag/dsp/</a></li>\r\n<li>Mastodon<br />\r\n<a href=\"https://joinmastodon.org/\">https://joinmastodon.org/</a></li>\r\n<li>hpr 2627 Home phone setup<br />\r\n<a href=\"https://hackerpublicradio.org/eps.php?id=2627\">https://hackerpublicradio.org/eps.php?id=2627</a></li>\r\n<li>Asterisk<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Asterisk_(PBX)\">https://en.wikipedia.org/wiki/Asterisk_(PBX)</a></li>\r\n<li>Hanging LED lights</li>\r\n<li>The Wall</li>\r\n<li>Clipper chip<br />\r\n<a href=\"https://en.wikipedia.org/wiki/Clipper_chip\">https://en.wikipedia.org/wiki/Clipper_chip</a></li>\r\n<li>Podcasting</li>\r\n<li>Time zones yet again</li>\r\n<li>Firearms</li>\r\n<li>President Trump</li>\r\n<li>Linux action news<br />\r\n<a href=\"https://linuxactionnews.com/\">https://linuxactionnews.com/</a></li>\r\n<li>Late night Linux<br />\r\n<a href=\"https://latenightlinux.com/\">https://latenightlinux.com/</a></li>\r\n<li>User error<br />\r\n<a href=\"https://www.jupiterbroadcasting.com/show/error/\">https://www.jupiterbroadcasting.com/show/error/</a></li>\r\n</ul>\r\n',159,121,1,'CC-BY-SA','HPR new years show, new years, community',0,0,1),
(2825,'2019-05-31','More text to speech trials',286,'A supplementary show to Jeroens episode 2792','<p>\r\nA supplementary show to Jeroens episode <a href=\"https://hackerpublicradio.org/eps.php?id=2792\">HPR2792 :: Playing around with text to speech synthesis on Linux</a>.\r\n</p>\r\n<p>\r\nI found two addional options. The first is <a href=\"https://mimic.mycroft.ai/\">mimic</a>\r\n</p>\r\n<pre>\r\n# dnf info mimic\r\nSummary      : Mycroft\'s TTS engine\r\nURL          : https://mimic.mycroft.ai/\r\nLicense      : BSD\r\nDescription  : Mimic is a fast, lightweight Text-to-speech engine developed by Mycroft A.I.\r\n             : and VocalID, based on Carnegie Mellon University’s FLITE software. Mimic takes\r\n             : in text and reads it out loud to create a high quality voice. Mimic\'s\r\n             : low-latency, small resource footprint, and good quality voices set it apart\r\n             : from other open source text-to-speech projects.\r\n</pre>\r\n\r\n<p>\r\nAnd the second is <a href=\"https://gtts.readthedocs.io/en/latest/index.html\">gTTS</a> which is a interface to the google TTS api.\r\n</p>\r\n',30,0,0,'CC-BY-SA','gTTS, Mimic, tts',0,0,1),
(2848,'2019-07-03','Random numbers in Haskell',1957,'Tuula talks how to generate random numbers (and other values) in Haskell','<p>There’s lots of random and similar sounding words in this episode. I hope you can still follow what I’m trying to explain, but I’m aware that it might be hard.</p>\r\n<p>Haskell functions are pure, meaning that they will always produce same values for same set of arguments. This might sound hard when you want to generate random numbers, but it turns out that the solution isn’t too tricky.</p>\r\n<p>First part to the puzzle is type class <code>RandomGen</code>:</p>\r\n<pre><code>class RandomGen g where\r\n    next :: g -&gt; (Int, g)\r\n    genRange :: g -&gt; (Int, Int)\r\n    split :: g -&gt; (g, g)</code></pre>\r\n<p><code>next</code> produces tuple, where first element is random <code>Int</code> and second element is new random generator. <code>genRange</code> returns tuple defining minimum and maximum values this generator will return. <code>split</code> produces tuple with two new random generators.</p>\r\n<p>Using <code>RandomGen</code> to produce random values of specific type or for specific range requires a bit of arithmetic. It’s easier to use <code>Random</code> that defines functions for that specific task:</p>\r\n<pre><code>class Random a where\r\n    randomR :: RandomGen g =&gt; (a, a) -&gt; g -&gt; (a, g)\r\n    random :: RandomGen g =&gt; g -&gt; (a, g)\r\n    randomRs :: RandomGen g =&gt; (a, a) -&gt; g -&gt; [a]\r\n    randoms :: RandomGen g =&gt; g -&gt; [a]\r\n    randomRIO :: (a, a) -&gt; IO a\r\n    randomIO :: IO a</code></pre>\r\n<ul>\r\n<li><code>randomR</code>, when given range and random generator, produces tuple with random number and new generator</li>\r\n<li><code>random</code>, is similar but doesn’t take range. Instead it will use minimum and maximum specific to that data type</li>\r\n<li><code>randomRs</code>, takes range and produces infinite list of random values within that range</li>\r\n<li><code>randoms</code>, simply produces infinite list of random values using range that is specific to datatype</li>\r\n<li><code>randomRIO</code> and <code>randomIO</code> are effectful versions that don’t need random generator, but use some default one</li>\r\n</ul>\r\n<p>In short, <code>RandomGen</code> is source of randomness and <code>Random</code> is datatype specific way of generating random values using random generator <code>RandomGen</code>.</p>\r\n<p>Final part of the puzzle is where to get <code>RandomGen</code>? One could initialize one manually, but then it wouldn’t be random. However, there’s function <code>getStdGen</code> that will seed <code>RandomGen</code> using OS default random number generator, current time or some other method. Since it has signature of <code>getStdGen :: IO StdGen</code>, one can only call it in IO monad.</p>\r\n<p>Functions that operate with IO can only be called from other IO functions. They can call pure functions, but pure functions can’t call them. So there’s two options: have the code that needs random numbers in effectful function or get <code>RandomGen</code> in effectful function and pass it to pure function.</p>\r\n<h2 id=\"example\">Example</h2>\r\n<pre><code>import System.Random\r\nimport Data.List\r\n\r\n-- | get n unique entries from given list in random order\r\n-- | if n &gt; length of list, all items of the list will be returned\r\ngetR :: RandomGen g =&gt; g -&gt; Int -&gt; [a] -&gt; [a]\r\ngetR g n xs =\r\n    fmap (xs !!) ids\r\n    where\r\n        ids = take (min n $ length xs) $ nub $ randomRs (0, length xs - 1) g\r\n\r\n-- | Returns 4 unique numbers between 1 and 10 (inclusive)\r\ntest :: IO [Int]\r\ntest = do\r\n    g &lt;- getStdGen\r\n    return $ getR g 4 [1..10]</code></pre>\r\n<h2 id=\"in-closing\">In closing</h2>\r\n<p>Pseudo randomness doesn’t require IO, only seeding the generator does. Simple computation that don’t require many calls to <code>random</code> are easy enough. If you need lots of random values, <a href=\"https://hackage.haskell.org/package/MonadRandom-0.4.1/docs/Control-Monad-Random-Class.html\"><code>MonadRandom</code></a> is better suited. It takes care of carrying implicit <code>RandomGen</code> along while your computation progresses.</p>\r\n<p>Best way to catch me nowadays is either email or fediverse where I’m <code>Tuula@mastodon.social</code></p>\r\n',364,107,0,'CC-BY-SA','haskell, random numbers',0,0,1),
(2820,'2019-05-24','29 - CERT Home Security Tips',1337,'What CERT recommends to mitigate security and privacy threats to your home network.','<p>The Computer Emergency Readiness Team of the US Department of Homeland Security issues a security bulletin, ST15-002, which has tips for home network security. In this episode we review these tips and why they make sense.</p>\r\n<h2 id=\"links\">Links:</h2>\r\n<ul>\r\n<li><a href=\"https://www.us-cert.gov/ncas/tips/ST15-002\" class=\"uri\">https://www.us-cert.gov/ncas/tips/ST15-002</a></li>\r\n<li><a href=\"https://www.zwilnik.com/\" class=\"uri\">https://www.zwilnik.com/</a></li>\r\n</ul>\r\n',198,74,0,'CC-BY-SA','Home Networks, Security',0,0,1),
(2821,'2019-05-27','Interviewing some exhibitors at the 2019 vcfe.org event',2784,'I interviewed some of the exhibitors at the recent vcfe.org event in Munich, Germany.','<p>I visited the vcfe.org event in Munich, Germany.</p>\r\n<p>Below you will find some urls for the projects that I came across.</p>\r\n<ul>\r\n<li>Steckschwein 6502 computer: <a href=\"https://steckschwein.de/\" class=\"uri\">https://steckschwein.de/</a></li>\r\n<li>Siemens Simatic S5 PLC: <a href=\"https://en.wikipedia.org/wiki/Simatic_S5_PLC\" class=\"uri\">https://en.wikipedia.org/wiki/Simatic_S5_PLC</a></li>\r\n<li>CP/M operating system: <a href=\"https://en.wikipedia.org/wiki/CP/M\" class=\"uri\">https://en.wikipedia.org/wiki/CP/M</a></li>\r\n<li>Old fashioned MUD game Nemesis: <a href=\"https://nemesis.de\" class=\"uri\">https://nemesis.de</a></li>\r\n<li>Eastern Germany Robotron hardware: <a href=\"https://en.wikipedia.org/wiki/VEB_Robotron\" class=\"uri\">https://en.wikipedia.org/wiki/VEB_Robotron</a></li>\r\n</ul>\r\n<p>If you like these things, the next exhibition will be in September in Berlin (you can find more info on <a href=\"https://vcfb.de/2019/\">vcfb.de</a>).</p>\r\n<p>Regards, Jeroen Baten</p>',369,78,0,'CC-BY-SA','vcfe, vintage, computers, exhibition, munich, germany',0,0,1),
(3111,'2020-07-06','HPR Community News for June 2020',3596,'Dave struggles to keep Ken on track as they talk about shows and comments in June 2020','<style>\ntable td.shrink {\n    white-space:nowrap\n}\n</style>\n\n<h2>New hosts</h2>\n<p>\nThere were no new hosts this month.\n</p>\n\n<h2>Last Month\'s Shows</h2>\n<table id=\"t01\">\n<tr>\n<th>Id</th>\n<th>Day</th>\n<th>Date</th>\n<th>Title</th>\n<th>Host</th>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3086\" target=\"_blank\">3086</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-06-01</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3086\" target=\"_blank\">HPR Community News for May 2020</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0159.html\" target=\"_blank\">HPR Volunteers</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3087\" target=\"_blank\">3087</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-06-02</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3087\" target=\"_blank\">Phonetic alphabet</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0078.html\" target=\"_blank\">klaatu</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3088\" target=\"_blank\">3088</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-06-03</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3088\" target=\"_blank\">Matchbox Restoration Part 2</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0338.html\" target=\"_blank\">Tony Hughes AKA TonyH1212</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3089\" target=\"_blank\">3089</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-06-04</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3089\" target=\"_blank\">For my Entertainment</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0318.html\" target=\"_blank\">Archer72</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3090\" target=\"_blank\">3090</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-06-05</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3090\" target=\"_blank\">Locating Computer on a Enterprise Network</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3091\" target=\"_blank\">3091</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-06-08</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3091\" target=\"_blank\">fuguserv</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0377.html\" target=\"_blank\">Zen_Floater2</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3092\" target=\"_blank\">3092</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-06-09</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3092\" target=\"_blank\">Pens, pencils, paper and ink - 2</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3093\" target=\"_blank\">3093</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-06-10</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3093\" target=\"_blank\">Response to Linux Inlaws S01E06 (hpr 3079) on NeXT</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0152.html\" target=\"_blank\">Claudio Miranda</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3094\" target=\"_blank\">3094</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-06-11</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3094\" target=\"_blank\">Holy crud! I have a kinesis advantage 2 keyboard!</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0115.html\" target=\"_blank\">sigflup</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3095\" target=\"_blank\">3095</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-06-12</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3095\" target=\"_blank\">Intro to GIMP</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3096\" target=\"_blank\">3096</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-06-15</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3096\" target=\"_blank\">Unscripted ramblings on a walk:  PC Building.</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0241.html\" target=\"_blank\">Christopher M. Hobbs</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3097\" target=\"_blank\">3097</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-06-16</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3097\" target=\"_blank\">Linux Inlaws S01E07 The Big Blue Button</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3098\" target=\"_blank\">3098</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-06-17</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3098\" target=\"_blank\">Matchbox Restoration Part 3</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0338.html\" target=\"_blank\">Tony Hughes AKA TonyH1212</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3099\" target=\"_blank\">3099</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-06-18</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3099\" target=\"_blank\">Linux Inlaws S01E08 The review of the review</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3100\" target=\"_blank\">3100</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-06-19</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3100\" target=\"_blank\">For your consideration - Makers Corner</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3101\" target=\"_blank\">3101</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-06-22</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3101\" target=\"_blank\">Metrics</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0268.html\" target=\"_blank\">Andrew Conway</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3102\" target=\"_blank\">3102</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-06-23</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3102\" target=\"_blank\">RFC 5005 Part 2 – Webcomics, subscribers and feed readers</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0311.html\" target=\"_blank\">clacke</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3103\" target=\"_blank\">3103</a></strong></td>\n<td>Wed</td>\n<td class=\"shrink\">2020-06-24</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3103\" target=\"_blank\">A warning about browser extensions and add-ons.</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3104\" target=\"_blank\">3104</a></strong></td>\n<td>Thu</td>\n<td class=\"shrink\">2020-06-25</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3104\" target=\"_blank\">HPR AudioBook Club 19 - Tincture: An Apocalyptic Proposition</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0157.html\" target=\"_blank\">HPR_AudioBookClub</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3105\" target=\"_blank\">3105</a></strong></td>\n<td>Fri</td>\n<td class=\"shrink\">2020-06-26</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3105\" target=\"_blank\">Akaso EK7000 Pro</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3106\" target=\"_blank\">3106</a></strong></td>\n<td>Mon</td>\n<td class=\"shrink\">2020-06-29</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3106\" target=\"_blank\">Linux Inlaws S01E09 Postgres</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a></td>\n</tr>\n<tr>\n<td><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3107\" target=\"_blank\">3107</a></strong></td>\n<td>Tue</td>\n<td class=\"shrink\">2020-06-30</td>\n<td><a href=\"https://hackerpublicradio.org/eps.php?id=3107\" target=\"_blank\">Generating comfortable passwords</a></td>\n<td><a href=\"https://hackerpublicradio.org/correspondents/0385.html\" target=\"_blank\">crvs</a></td>\n</tr>\n</table>\n\n<h2>Comments this month</h2>\n\n<p>These are comments which have been made during the past month, either to shows released during the month or to past shows.\nThere are 23 comments in total.</p>\n<h3>Past shows</h3>\n<p>There are 6 comments on\n5 previous shows:</p>\n<ul>\n<li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3056#comments\" target=\"_blank\">hpr3056</a></strong>\n(2020-04-20) \"<em>Jitsi</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3056#8\" target=\"_blank\">Comment 8</a>:\noperat0r on 2020-06-13:\n\"dERp\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3072#comments\" target=\"_blank\">hpr3072</a></strong>\n(2020-05-12) \"<em>The joy of pip-tools and pyenv-virtualenv</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0311.html\" target=\"_blank\">clacke</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3072#3\" target=\"_blank\">Comment 3</a>:\nclacke on 2020-06-02:\n\"The joy is real\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3079#comments\" target=\"_blank\">hpr3079</a></strong>\n(2020-05-21) \"<em>Linux Inlaws S01E06 Porn and Trump</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3079#1\" target=\"_blank\">Comment 1</a>:\nfrank on 2020-06-15:\n\"The sketch\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3082#comments\" target=\"_blank\">hpr3082</a></strong>\n(2020-05-26) \"<em>RFC 5005 Part 1 – Paged and archived feeds? Who cares?</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0311.html\" target=\"_blank\">clacke</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3082#1\" target=\"_blank\">Comment 1</a>:\nclacke on 2020-06-02:\n\"Atom \"tombstones\" RFC\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3083#comments\" target=\"_blank\">hpr3083</a></strong>\n(2020-05-27) \"<em>Mumbling while on lockdown</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0225.html\" target=\"_blank\">Dave Morriss</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3083#3\" target=\"_blank\">Comment 3</a>:\nWindigo on 2020-06-03:\n\"Modern Sheevaplug support\"</li>\n<li>\n<a href=\"https://hackerpublicradio.org/eps.php?id=3083#4\" target=\"_blank\">Comment 4</a>:\nDave Morriss on 2020-06-04:\n\"Re: Modern Sheevaplug support\"</li></ul><br/>\n</li></ul>\n<h3>This month\'s shows</h3>\n<p>There are 17 comments on 11 of this month\'s shows:</p>\n<ul><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3087#comments\" target=\"_blank\">hpr3087</a></strong>\n(2020-06-02) \"<em>Phonetic alphabet</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0078.html\" target=\"_blank\">klaatu</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3087#1\" target=\"_blank\">Comment 1</a>:\ncrvs on 2020-06-02:\n\"you forgot november\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3090#comments\" target=\"_blank\">hpr3090</a></strong>\n(2020-06-05) \"<em>Locating Computer on a Enterprise Network</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0036.html\" target=\"_blank\">operat0r</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3090#1\" target=\"_blank\">Comment 1</a>:\nb-yeezi on 2020-06-05:\n\"Thanks for reminding me\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3090#2\" target=\"_blank\">Comment 2</a>:\ncmhobbs on 2020-06-08:\n\"quality episode\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3091#comments\" target=\"_blank\">hpr3091</a></strong>\n(2020-06-08) \"<em>fuguserv</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0377.html\" target=\"_blank\">Zen_Floater2</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3091#1\" target=\"_blank\">Comment 1</a>:\nnorrist on 2020-06-08:\n\"read only router\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3091#2\" target=\"_blank\">Comment 2</a>:\nlZen_Floater1 on 2020-06-11:\n\"READ ONLY ROOTS\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3093#comments\" target=\"_blank\">hpr3093</a></strong>\n(2020-06-10) \"<em>Response to Linux Inlaws S01E06 (hpr 3079) on NeXT</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0152.html\" target=\"_blank\">Claudio Miranda</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3093#1\" target=\"_blank\">Comment 1</a>:\nmonochromec on 2020-05-27:\n\"The review of the review\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3094#comments\" target=\"_blank\">hpr3094</a></strong>\n(2020-06-11) \"<em>Holy crud! I have a kinesis advantage 2 keyboard!</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0115.html\" target=\"_blank\">sigflup</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3094#1\" target=\"_blank\">Comment 1</a>:\ncmhobbs on 2020-06-11:\n\"great keyboard\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3095#comments\" target=\"_blank\">hpr3095</a></strong>\n(2020-06-12) \"<em>Intro to GIMP</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0198.html\" target=\"_blank\">Ahuka</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3095#1\" target=\"_blank\">Comment 1</a>:\nbrian-in-ohio on 2020-06-14:\n\"the gimp\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3095#2\" target=\"_blank\">Comment 2</a>:\nAhuka on 2020-06-14:\n\"I\'m glad it helped\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3096#comments\" target=\"_blank\">hpr3096</a></strong>\n(2020-06-15) \"<em>Unscripted ramblings on a walk:  PC Building.</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0241.html\" target=\"_blank\">Christopher M. Hobbs</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3096#1\" target=\"_blank\">Comment 1</a>:\nMike Brehm on 2020-06-17:\n\"Productive walk\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3096#2\" target=\"_blank\">Comment 2</a>:\ncmhobbs on 2020-06-21:\n\"re: productive walk\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3099#comments\" target=\"_blank\">hpr3099</a></strong>\n(2020-06-18) \"<em>Linux Inlaws S01E08 The review of the review</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0384.html\" target=\"_blank\">monochromec</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3099#1\" target=\"_blank\">Comment 1</a>:\nClaudioM on 2020-06-18:\n\"All According to Plan! }:-)\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3100#comments\" target=\"_blank\">hpr3100</a></strong>\n(2020-06-19) \"<em>For your consideration - Makers Corner</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0030.html\" target=\"_blank\">Ken Fallon</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3100#1\" target=\"_blank\">Comment 1</a>:\nbrian-in-ohio on 2020-06-19:\n\"a book recommendation\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3101#comments\" target=\"_blank\">hpr3101</a></strong>\n(2020-06-22) \"<em>Metrics</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0268.html\" target=\"_blank\">Andrew Conway</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3101#1\" target=\"_blank\">Comment 1</a>:\nClinton Roy on 2020-06-22:\n\"Looking forward to further episodes.\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3101#2\" target=\"_blank\">Comment 2</a>:\nAhuka on 2020-06-22:\n\"Excellent!\"</li><li><a href=\"https://hackerpublicradio.org/eps.php?id=3101#3\" target=\"_blank\">Comment 3</a>:\nbrian-in-ohio on 2020-06-22:\n\"more episodes\"</li></ul><br/>\n</li><li><strong><a href=\"https://hackerpublicradio.org/eps.php?id=3107#comments\" target=\"_blank\">hpr3107</a></strong>\n(2020-06-30) \"<em>Generating comfortable passwords</em>\"\nby <a href=\"https://hackerpublicradio.org/correspondents/0385.html\" target=\"_blank\">crvs</a>.</li>\n<li style=\"list-style: none; display: inline\">\n<ul><li><a href=\"https://hackerpublicradio.org/eps.php?id=3107#1\" target=\"_blank\">Comment 1</a>:\nsigflup on 2020-06-30:\n\"Thanks\"</li></ul><br/>\n</li></ul>\n\n<h2>Mailing List discussions</h2>\n<p>\nPolicy decisions surrounding HPR are taken by the community as a whole. This\ndiscussion takes place on the <a href=\"https://hackerpublicradio.org/maillist\"\ntarget=\"_blank\">Mail List</a> which is open to all HPR listeners and\ncontributors. The discussions are open and available on the HPR server under\n<a href=\"https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/\">Mailman</a>.\n</p>\n<p>The threaded discussions this month can be found here:</p>\n<a href=\"https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/2020-June/thread.html\" target=\"_blank\">https://hackerpublicradio.org/pipermail/hpr_hackerpublicradio.org/2020-June/thread.html</a>\n\n\n<h2>Events Calendar</h2>\n<p>With the kind permission of <strong>LWN.net</strong> we are linking to\n<a href=\"https://lwn.net/Calendar/\" target=\"_blank\">The LWN.net Community Calendar</a>.</p>\n<p>Quoting the site:</p>\n<blockquote>This is the LWN.net community event calendar, where we track\nevents of interest to people using and developing Linux and free software.\nClicking on individual events will take you to the appropriate web\npage.</blockquote>\n\n<h2>Any other business</h2>\n<h3 id=\"error-feedback-from-show-notes\">Error feedback from show notes</h3>\n<p>Most of the shows we process require us to make some level of modifications to get them posted. This ranges from fixing tags to a complete rewrite of the shownotes, or verifying whether intros were actually added or not.</p>\n<p>Each modification that we make means that it requires more human intervention and prevents us from being able to completely automate the upload process. In addition there is a non trivial amount of time needed to \"fix\" these issues. This can range from a few minutes to an hour or more per show, and with 260 shows a year this mounts up.</p>\n<p>We normally don\'t contact hosts about these issues as it is usually quicker to fix the issues than composing emails, and waiting for the reply that may never come. For the most part our experience has been that hosts are more than willing to fix these issues if they are aware of them.</p>\n<p>As part of the ongoing steps toward automation, would hosts be open to the idea of getting a processing report once we have posted the show? This would list all the issues the test tools found and the steps that we needed to take to rectify them.</p>\n<h3 id=\"making-changes-to-shows-after-upload\">Making changes to shows after upload</h3>\n<p>Sometimes an error or omission in notes for an HPR episode isn\'t noticed until the show is posted to the site. In recent times a few hosts have sent in their changes by way of comments. This is not ideal:</p>\n<ol type=\"1\">\n<li>There\'s a limit on how much text a comment can hold</li>\n<li>The comment form has a nasty habit of stripping backslashes, so code corrections can be messed up</li>\n<li>We don\'t put comments on the show\'s page on <code>archive.org</code>, so such corrections will not be seen by people reading the notes there</li>\n</ol>\n<p>The HPR admins would prefer changes to be sent in the form of emails to <code>admin at hackerpublicradio.org</code>. They will then be applied to the show notes and the <code>archive.org</code> version updated in step.</p>\n<h3 id=\"tags-and-summaries\">Tags and Summaries</h3>\n<p>Thanks to the following contributor for sending in updates in the past month:<br />\n<b><a href=\"https://hackerpublicradio.org/correspondents/0215.html\">Windigo</a></b></p>\n<p>Over the period tags and/or summaries have been added to 10 shows which were without them.</p>\n<p>If you would like to contribute to the tag/summary project visit the summary page at <a href=\"https://hackerpublicradio.org/report_missing_tags.php\" class=\"uri\">https://hackerpublicradio.org/report_missing_tags.php</a> and follow the instructions there.</p>\n\n\n',159,47,1,'CC-BY-SA','Community News',0,0,1),
