[{"Id":11267,"Author":{"Name":"Ellis Morning","FirstName":"Ellis","ShortDescription":null,"DescriptionHtml":"\u003cb\u003eEllis Morning\u003c/b\u003e is a Computer Science graduate who fought in the trenches of Tech Support, occasionally crossing enemy lines into the Business Analyst and Project Management spheres of war. She\u0027s now a freelance writer and technical writer. Check out her highly-rated \u003ca href=\"https://swordandstarship.com/\" target=\"_blank\"\u003esci-fi/fantasy novels\u003c/a\u003e and find more humor, fiction, and blog posts at her \u003ca href=\"https://www.ellismorning.com\" target=\"_blank\"\u003ewebsite\u003c/a\u003e.","Slug":"ellis-morning","IsAdmin":true,"IsActive":true,"ImageUrl":"https://ellismorning.com/img/ellis2.jpeg"},"Status":"Published","SummaryHtml":"\u003cp\u003eFrom our \u003cb\u003eanonymous\u003c/b\u003e submitter:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eHaving reached the end of the road at a company increasingly swallowed up companies further east which you\u0026#39;d never believe were still afloat, I found myself headhunted for certain specialty software skills. I was reaching the final few years of my expected working span, so I jumped at the chance. The money was (to me at that time) spectacularly good, so I jumped into it.\u003c/p\u003e\n\u003c/blockquote\u003e","BodyHtml":"\u003cp\u003eFrom our \u003cb\u003eanonymous\u003c/b\u003e submitter:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eHaving reached the end of the road at a company increasingly swallowed up companies further east which you\u0026#39;d never believe were still afloat, I found myself headhunted for certain specialty software skills. I was reaching the final few years of my expected working span, so I jumped at the chance. The money was (to me at that time) spectacularly good, so I jumped into it.\u003c/p\u003e\n\u003cp style=\"float:right; padding-left:10px; padding-bottom:10px;\"\u003e\u003ca title=\"Steve Mendel, CC BY 3.0 \u0026lt;https://creativecommons.org/licenses/by/3.0\u0026gt;, via Wikimedia Commons\" href=\"https://commons.wikimedia.org/wiki/File:Time_Is_Life,_1080%C3%971920,_154.35_KB.jpg\"\u003e\u003cimg itemprop=\"image\" width=\"250\" alt=\"Time Is Life, 1080Ã—1920, 154.35 KB\" src=\"https://thumb.wikimedia.org/wikipedia/commons/thumb/7/72/Time_Is_Life%2C_1080%C3%971920%2C_154.35_KB.jpg/250px-Time_Is_Life%2C_1080%C3%971920%2C_154.35_KB.jpg?utm_source=commons.wikimedia.org\u0026amp;utm_campaign=index\u0026amp;utm_content=thumbnail\"/\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eIt started when my first day was spent by me being sent home for the weeks it was still going to take to onboard me. Not bad, engaged to wait, as it were, and the first 6 months was thus and so.\u003c/p\u003e\n\u003cp\u003eThe man who had interviewed me, call him Fred, was intelligent and urbane, and was a joy to meet. He and I clearly hit it off, and lo and behold I was in. It was he who gave me my first assignment, which was mathematical analysis of their core milk-cow program because they needed to find out what it did, and how it did it, so they could perhaps implement it in a more contemporary language.\u003c/p\u003e\n\u003cp\u003eSo I did that, and was just about to publish my findings with him, when Fred inconveniently dropped dead suddenly. In the what-are-we-going-to-do-now-our-key-man-is-no-more confusion, we contractors were forgotten.\u003c/p\u003e\n\u003cp\u003eFor the next 18 months or so (may have been more, may have been less) I was more or less ignored. I spent the time writing a development environment to work on any part of the program conveniently, all the while sitting next to a man who was constantly, forcefully and repetitiously speaking ill of the managers in his line structure. The ridiculously garrulous boss who inherited me thought little of me, and handed me the little work that came my way with active hostility. One or two good guys, but mostly a cabal of elderly men trying to preserve their little money-spinner as long as they could, and a johnny-come-lately trying to increase (and even introduce) automatic processes was less than welcome. During that time I spent quite some time on TDWTF, submitting a gem or two here and there.\u003c/p\u003e\n\u003cp\u003eNo surprise when they finally kicked my arse away. No love lost there. Now working my last couple of years to retirement as a postie.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eNo punchline here. I want you to know that \u003ca href=\"https://news.un.org/en/story/2026/04/1167356\"\u003edropping dead from work\u003c/a\u003e is all too real and can happen to anyone.\u003c/p\u003e","BodyAndAdHtml":"\u003cp\u003eFrom our \u003cb\u003eanonymous\u003c/b\u003e submitter:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eHaving reached the end of the road at a company increasingly swallowed up companies further east which you\u0026#39;d never believe were still afloat, I found myself headhunted for certain specialty software skills. I was reaching the final few years of my expected working span, so I jumped at the chance. The money was (to me at that time) spectacularly good, so I jumped into it.\u003c/p\u003e\n\u003cp style=\"float:right; padding-left:10px; padding-bottom:10px;\"\u003e\u003ca title=\"Steve Mendel, CC BY 3.0 \u0026lt;https://creativecommons.org/licenses/by/3.0\u0026gt;, via Wikimedia Commons\" href=\"https://commons.wikimedia.org/wiki/File:Time_Is_Life,_1080%C3%971920,_154.35_KB.jpg\"\u003e\u003cimg itemprop=\"image\" width=\"250\" alt=\"Time Is Life, 1080Ã—1920, 154.35 KB\" src=\"https://thumb.wikimedia.org/wikipedia/commons/thumb/7/72/Time_Is_Life%2C_1080%C3%971920%2C_154.35_KB.jpg/250px-Time_Is_Life%2C_1080%C3%971920%2C_154.35_KB.jpg?utm_source=commons.wikimedia.org\u0026amp;utm_campaign=index\u0026amp;utm_content=thumbnail\"/\u003e\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eIt started when my first day was spent by me being sent home for the weeks it was still going to take to onboard me. Not bad, engaged to wait, as it were, and the first 6 months was thus and so.\u003c/p\u003e\n\u003cp\u003eThe man who had interviewed me, call him Fred, was intelligent and urbane, and was a joy to meet. He and I clearly hit it off, and lo and behold I was in. It was he who gave me my first assignment, which was mathematical analysis of their core milk-cow program because they needed to find out what it did, and how it did it, so they could perhaps implement it in a more contemporary language.\u003c/p\u003e\n\u003cp\u003eSo I did that, and was just about to publish my findings with him, when Fred inconveniently dropped dead suddenly. In the what-are-we-going-to-do-now-our-key-man-is-no-more confusion, we contractors were forgotten.\u003c/p\u003e\n\u003cp\u003eFor the next 18 months or so (may have been more, may have been less) I was more or less ignored. I spent the time writing a development environment to work on any part of the program conveniently, all the while sitting next to a man who was constantly, forcefully and repetitiously speaking ill of the managers in his line structure. The ridiculously garrulous boss who inherited me thought little of me, and handed me the little work that came my way with active hostility. One or two good guys, but mostly a cabal of elderly men trying to preserve their little money-spinner as long as they could, and a johnny-come-lately trying to increase (and even introduce) automatic processes was less than welcome. During that time I spent quite some time on TDWTF, submitting a gem or two here and there.\u003c/p\u003e\n\u003cp\u003eNo surprise when they finally kicked my arse away. No love lost there. Now working my last couple of years to retirement as a postie.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eNo punchline here. I want you to know that \u003ca href=\"https://news.un.org/en/story/2026/04/1167356\"\u003edropping dead from work\u003c/a\u003e is all too real and can happen to anyone.\u003c/p\u003e\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/proget-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\tProGet’s got you covered with security and access controls on your NuGet feeds. \u003ca href=\"https://inedo.com/proget/private-nuget-server?utm_source=tdwtf\u0026amp;utm_medium=footer\u0026amp;utm_content=GotYouCoveredFooter\u0026amp;utm_campaign=Cyclops2020\"\u003eLearn more.\u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Title":"A Mortal Blow","RssTitle":"A Mortal Blow","CachedCommentCount":8,"LastCommentDate":"\/Date(1788894695350)\/","LastCommentDateDescription":"2026-09-08","DiscourseTopicId":null,"DiscourseTopicOpened":false,"PublishedDate":"\/Date(1788849000000)\/","ISODate":"2026-09-08","DisplayDate":"2026-09-08","Series":{"Slug":"feature-articles","Title":"Feature Articles","Description":"","CssClass":"featured"},"FooterAdHtml":"\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/proget-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\tProGet’s got you covered with security and access controls on your NuGet feeds. \u003ca href=\"https://inedo.com/proget/private-nuget-server?utm_source=tdwtf\u0026amp;utm_medium=footer\u0026amp;utm_content=GotYouCoveredFooter\u0026amp;utm_campaign=Cyclops2020\"\u003eLearn more.\u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Url":"https://thedailywtf.com/articles/a-mortal-blow","CommentsUrl":"https://thedailywtf.com/articles/comments/a-mortal-blow","Slug":"a-mortal-blow","TwitterUrl":"//www.twitter.com/home?status=https%3a%2f%2fthedailywtf.com%2farticles%2fa-mortal-blow+-+A+Mortal+Blow+-+The+Daily+WTF","FacebookUrl":"//www.facebook.com/sharer.php?u=https%3a%2f%2fthedailywtf.com%2farticles%2fa-mortal-blow\u0026t=A+Mortal+Blow+-+The+Daily+WTF","EmailUrl":"mailto:%20?subject=Check%20out%20this%20article%20on%20The%20Daily%20WTF...\u0026body=A%20Mortal%20Blow:%20https://thedailywtf.com/articles/a-mortal-blow","GooglePlusUrl":"//plus.google.com/share?url=https%3a%2f%2fthedailywtf.com%2farticles%2fa-mortal-blow","PreviousArticleId":11266,"PreviousArticleTitle":"Classic WTF: A Dumbain Specific Language","PreviousArticleSlug":"classic-wtf-a-dumbain-specific-language","PreviousArticleUrl":"//thedailywtf.com/articles/classic-wtf-a-dumbain-specific-language","NextArticleId":null,"NextArticleTitle":null,"NextArticleSlug":null,"NextArticleUrl":"//thedailywtf.com/articles/"},{"Id":11266,"Author":{"Name":"Remy Porter","FirstName":"Remy","ShortDescription":"Computers were a mistake, so I accidentally became a farmer? Editor-in-Chief for TDWTF.","DescriptionHtml":"\u003cp\u003eRemy is a veteran developer who writes software for farming robots. They pick tomatoes.\u003c/p\u003e\r\n\u003cp\u003eHe\u0027s often on stage, doing improv comedy, but insists that \u003cem\u003ehe\u003c/em\u003e isn\u0027t doing comedy- it\u0027s deadly serious. You\u0027re laughing at him, not with him. That, by the way, is usually true- you\u0027re laughing at him, not with him.\u003c/p\u003e","Slug":"remy-porter","IsAdmin":true,"IsActive":true,"ImageUrl":"https://s3.amazonaws.com/remy.jetpackshark.com/remy-thumb.jpg"},"Status":"Published","SummaryHtml":"\u003cblockquote\u003eIt\u0026#39;s a holiday here in the US, a celebration of labor, so we\u0026#39;re reaching back through the archives for a story about an attempt to be labor saving that was not successful. \u003ca href=\"https://thedailywtf.com/articles/a-dumbain-specific-language\"\u003eOriginal\u003c/a\u003e. --\u003cstrong\u003eRemy\u003c/strong\u003e\u003c/blockquote\u003e\n\n\u003cp\u003eI’ve had to write a few domain-specific-languages in the past. As per \u003ca href=\"https://twitter.com/RemyPorter/status/752913168624746497\"\u003eRemy’s Law of Requirements Gathering\u003c/a\u003e, it’s been mostly because the users needed an Excel-like formula language. \u003c!-- Although, more than once, it\u0027s been because I wanted to hack a macro system into a DSL for fun, as per my unfinished multiplayer CYOA engine written in Elixir --\u003e The danger of DSLs, of course, is that they’re often YAGNI in the extreme, or at least a sign that you don’t really understand your problem.\u003c/p\u003e\n\n\u003cp\u003eXML, coupled with schemas, is a tool for building data-focused DSLs. If you have some complex structure, you can convert each of its features into an XML attribute. For example, if you had a grammar that looked something like this:\u003c/p\u003e\n\u003cblockquote\u003e\u003c/blockquote\u003e","BodyHtml":"\u003cblockquote\u003eIt\u0026#39;s a holiday here in the US, a celebration of labor, so we\u0026#39;re reaching back through the archives for a story about an attempt to be labor saving that was not successful. \u003ca href=\"https://thedailywtf.com/articles/a-dumbain-specific-language\"\u003eOriginal\u003c/a\u003e. --\u003cstrong\u003eRemy\u003c/strong\u003e\u003c/blockquote\u003e\n\n\u003cp\u003eI’ve had to write a few domain-specific-languages in the past. As per \u003ca href=\"https://twitter.com/RemyPorter/status/752913168624746497\"\u003eRemy’s Law of Requirements Gathering\u003c/a\u003e, it’s been mostly because the users needed an Excel-like formula language. \u003c!-- Although, more than once, it\u0027s been because I wanted to hack a macro system into a DSL for fun, as per my unfinished multiplayer CYOA engine written in Elixir --\u003e The danger of DSLs, of course, is that they’re often YAGNI in the extreme, or at least a sign that you don’t really understand your problem.\u003c/p\u003e\n\n\u003cp\u003eXML, coupled with schemas, is a tool for building data-focused DSLs. If you have some complex structure, you can convert each of its features into an XML attribute. For example, if you had a grammar that looked something like this:\u003c/p\u003e\n\u003cblockquote\u003e\u003cpre\u003eThe Source specification obeys the following syntax\n\nsource = ( Feature1+Feature2+... \u0026#34;:\u0026#34; ) ? steps\n\nFeature1 = \u0026#34;local\u0026#34; | \u0026#34;global\u0026#34;\n\nFeature2 =\u0026#34;real\u0026#34; | \u0026#34;virtual\u0026#34; | \u0026#34;ComponentType.all\u0026#34;\n\nFeature3 =\u0026#34;self\u0026#34; | \u0026#34;ancestors\u0026#34; | \u0026#34;descendants\u0026#34; | \u0026#34;Hierarchy.all\u0026#34;\n\nFeature4 = \u0026#34;first\u0026#34; | \u0026#34;last\u0026#34; | \u0026#34;DayAllocation.all\u0026#34;\n\nIf features are specified, the order of features as given above has strictly to be followed.\n\nsteps = oneOrMoreNameSteps | zeroOrMoreNameSteps | componentSteps\n\noneOrMoreNameSteps = nameStep ( \u0026#34;.\u0026#34; nameStep ) *\n\nzeroOrMoreNameSteps = ( nameStep \u0026#34;.\u0026#34; ) *\n\nnameStep = \u0026#34;#\u0026#34; name\n\nname is a string of characters from \u0026#34;A\u0026#34;-\u0026#34;Z\u0026#34;, \u0026#34;a\u0026#34;-\u0026#34;z\u0026#34;, \u0026#34;0\u0026#34;-\u0026#34;9\u0026#34;, \u0026#34;-\u0026#34; and \u0026#34;_\u0026#34;. No umlauts allowed, one character is minimum.\n\ncomponentSteps is a list of valid values, see below.\n\nValid \u0026#39;componentSteps\u0026#39; are:\n\n- GlobalValue\n- Product\n- Product.Brand\n- Product.Accommodation\n- Product.Accommodation.SellingAccom\n- Product.Accommodation.SellingAccom.Board\n- Product.Accommodation.SellingAccom.Unit\n- Product.Accommodation.SellingAccom.Unit.SellingUnit\n- Product.OnewayFlight\n- Product.OnewayFlight.BookingClass\n- Product.ReturnFlight\n- Product.ReturnFlight.BookingClass\n- Product.ReturnFlight.Inbound\n- Product.ReturnFlight.Outbound\n- Product.\u003cspan onclick=\"cornify_add();return false;\" title=\"click me!\"\u003eAddon\u003c/span\u003e\u003cscript type=\"text/javascript\" src=\"//www.cornify.com/js/cornify.js\"\u003e\u003c/script\u003e\n- Product.Addon.Service\n- Product.Addon.ServiceFeature\n\nIn addition to that all subsequent steps from the paths above are permitted, that is \u0026#39;Board\u0026#39;, \n\u0026#39;Accommodation.SellingAccom\u0026#39; or \u0026#39;SellingAccom.Unit.SellingUnit\u0026#39;.\n\u0026#39;Accommodation.Unit\u0026#39; in the contrary is not permitted, as here some intermediate steps are missing.\u003c/pre\u003e\u003c/blockquote\u003e\n\n\u003cp\u003eYou could turn that grammar into an XML document by converting syntax elements to attributes and elements. You could do that, but \u003cstrong\u003eStella’s\u003c/strong\u003e predecessor did not do that. That of course, would have been \u003cem\u003ework\u003c/em\u003e, and they may have had to put some thought on how to relate their homebrew grammar to XSD rules, so instead they created an XML schema rule for \u003ccode\u003eSourceAttributeType\u003c/code\u003e that verifies that the data in the field is valid according to the grammar… using regular expressions. 1,310 characters of regular expressions.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"xml\"\u003e\u0026lt;xs:simpleType\u0026gt;\n    \u0026lt;xs:restriction base=\u0026#34;xs:string\u0026#34;\u0026gt;\n            \u0026lt;xs:pattern value=\u0026#34;(((Scope.)?(global|local|current)\\+?)?((((ComponentType.)?\n(real|virtual))|ComponentType.all)\\+?)?((((Hierarchy.)?(self|ancestors|descendants))|Hierarchy.all)\\+?)?\n((((DayAllocation.)?(first|last))|DayAllocation.all)\\+?)?:)?(#[A-Za-z0-9\\-_]+(\\.(#[A-Za-z0-9\\-_]+))*|(#[A-Za-z0-\n9\\-_]+\\.)*\n(ThisComponent|GlobalValue|Product|Product\\.Brand|Product\\.Accommodation|Product\\.Accommodation\\.SellingAccom|Prod\nuct\\.Accommodation\\.SellingAccom\\.Board|Product\\.Accommodation\\.SellingAccom\\.Unit|Product\\.Accommodation\\.Selling\nAccom\\.Unit\\.SellingUnit|Product\\.OnewayFlight|Product\\.OnewayFlight\\.BookingClass|Product\\.ReturnFlight|Product\\.\nReturnFlight\\.BookingClass|Product\\.ReturnFlight\\.Inbound|Product\\.ReturnFlight\\.Outbound|Product\\.Addon|Product\\.\nAddon\\.Service|Product\\.Addon\\.ServiceFeature|Brand|Accommodation|Accommodation\\.SellingAccom|Accommodation\\.Selli\nngAccom\\.Board|Accommodation\\.SellingAccom\\.Unit|Accommodation\\.SellingAccom\\.Unit\\.SellingUnit|OnewayFlight|Onewa\nyFlight\\.BookingClass|ReturnFlight|ReturnFlight\\.BookingClass|ReturnFlight\\.Inbound|ReturnFlight\\.Outbound|Addon|A\nddon\\.Service|Addon\\.ServiceFeature|SellingAccom|SellingAccom\\.Board|SellingAccom\\.Unit|SellingAccom\\.Unit\\.Sellin\ngUnit|BookingClass|Inbound|Outbound|Service|ServiceFeature|Board|Unit|Unit\\.SellingUnit|SellingUnit))\u0026#34;/\u0026gt;\n    \u0026lt;/xs:restriction\u0026gt;\n\u0026lt;/xs:simpleType\u0026gt;\n\u0026lt;/xs:union\u0026gt;\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eThere’s a bug in that regex that Stella needed to fix. As she put it: “Every time you evaluate it a few little kitties die because you shouldn’t use kitties to polish your car. I’m so, so sorry, little kitties…”\u003c/p\u003e\n\n\u003cp\u003eThe full, unexcerpted code is below, so… at least it has documentation. In two languages!\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"xml\"\u003e\u0026lt;xs:simpleType name=\u0026#34;SourceAttributeType\u0026#34;\u0026gt;\n                \u0026lt;xs:annotation\u0026gt;\n                        \u0026lt;xs:documentation xml:lang=\u0026#34;de\u0026#34;\u0026gt;\n                Die Source Angabe folgt folgender Syntax\n\n                        source = ( Eigenschaft1+Eigenschaft2+... \u0026#34;:\u0026#34; ) ? steps\n\n                        Eigenschaft1 = \u0026#34;local\u0026#34; | \u0026#34;global\u0026#34;\n\n                        Eigenschaft2 =\u0026#34;real\u0026#34; | \u0026#34;virtual\u0026#34; | \u0026#34;ComponentType.all\u0026#34;\n\n                        Eigenschaft3 =\u0026#34;self\u0026#34; | \u0026#34;ancestors\u0026#34; | \u0026#34;descendants\u0026#34; | \u0026#34;Hierarchy.all\u0026#34;\n\n                        Eigenschaft4 = \u0026#34;first\u0026#34; | \u0026#34;last\u0026#34; | \u0026#34;DayAllocation.all\u0026#34;\n\n                        Falls Eigenschaften angegeben werden muss zwingend die oben angegebene Reihenfolge der Eigenschaften eingehalten werden.\n\n                        steps = oneOrMoreNameSteps | zeroOrMoreNameSteps | componentSteps\n\n                        oneOrMoreNameSteps = nameStep ( \u0026#34;.\u0026#34; nameStep ) *\n\n                        zeroOrMoreNameSteps = ( nameStep \u0026#34;.\u0026#34; ) *\n\n                        nameStep = \u0026#34;#\u0026#34; name\n\n                        name ist eine Folge von Zeichen aus der Menge \u0026#34;A\u0026#34;-\u0026#34;Z\u0026#34;, \u0026#34;a\u0026#34;-\u0026#34;z\u0026#34;, \u0026#34;0\u0026#34;-\u0026#34;9\u0026#34;, \u0026#34;-\u0026#34; und \u0026#34;_\u0026#34;. Keine Umlaute. Mindestens ein Zeichen\n\n                        componentSteps ist eine Liste gültiger Werte, siehe im folgenden\n\n                Gültige \u0026#39;componentSteps\u0026#39; sind zunächst:\n\n                        - GlobalValue\n                        - Product\n                        - Product.Brand\n                        - Product.Accommodation\n                        - Product.Accommodation.SellingAccom\n                        - Product.Accommodation.SellingAccom.Board\n                        - Product.Accommodation.SellingAccom.Unit\n                        - Product.Accommodation.SellingAccom.Unit.SellingUnit\n                        - Product.OnewayFlight\n                        - Product.OnewayFlight.BookingClass\n                        - Product.ReturnFlight\n                        - Product.ReturnFlight.BookingClass\n                        - Product.ReturnFlight.Inbound\n                        - Product.ReturnFlight.Outbound\n                        - Product.Addon\n                        - Product.Addon.Service\n                        - Product.Addon.ServiceFeature\n\n                Desweiteren sind alle Unterschrittfolgen aus obigen Pfaden erlaubt, also \u0026#39;Board\u0026#39;, \u0026#39;Accommodation.SellingAccom\u0026#39; oder \u0026#39;SellingAccom.Unit.SellingUnit\u0026#39;.\n                \u0026#39;Accommodation.Unit\u0026#39; hingegen ist nicht erlaubt, da in diesem Fall einige Zwischenschritte fehlen.\n\n                                \u0026lt;/xs:documentation\u0026gt;\n                        \u0026lt;xs:documentation xml:lang=\u0026#34;en\u0026#34;\u0026gt;\n                                The Source specification obeys the following syntax\n\n                                source = ( Feature1+Feature2+... \u0026#34;:\u0026#34; ) ? steps\n\n                                Feature1 = \u0026#34;local\u0026#34; | \u0026#34;global\u0026#34;\n\n                                Feature2 =\u0026#34;real\u0026#34; | \u0026#34;virtual\u0026#34; | \u0026#34;ComponentType.all\u0026#34;\n\n                                Feature3 =\u0026#34;self\u0026#34; | \u0026#34;ancestors\u0026#34; | \u0026#34;descendants\u0026#34; | \u0026#34;Hierarchy.all\u0026#34;\n\n                                Feature4 = \u0026#34;first\u0026#34; | \u0026#34;last\u0026#34; | \u0026#34;DayAllocation.all\u0026#34;\n\n                                If features are specified, the order of features as given above has strictly to be followed.\n\n                                steps = oneOrMoreNameSteps | zeroOrMoreNameSteps | componentSteps\n\n                                oneOrMoreNameSteps = nameStep ( \u0026#34;.\u0026#34; nameStep ) *\n\n                                zeroOrMoreNameSteps = ( nameStep \u0026#34;.\u0026#34; ) *\n\n                                nameStep = \u0026#34;#\u0026#34; name\n\n                                name is a string of characters from \u0026#34;A\u0026#34;-\u0026#34;Z\u0026#34;, \u0026#34;a\u0026#34;-\u0026#34;z\u0026#34;, \u0026#34;0\u0026#34;-\u0026#34;9\u0026#34;, \u0026#34;-\u0026#34; and \u0026#34;_\u0026#34;. No umlauts allowed, one character is minimum.\n\n                                componentSteps is a list of valid values, see below.\n\n                                Valid \u0026#39;componentSteps\u0026#39; are:\n\n                                - GlobalValue\n                                - Product\n                                - Product.Brand\n                                - Product.Accommodation\n                                - Product.Accommodation.SellingAccom\n                                - Product.Accommodation.SellingAccom.Board\n                                - Product.Accommodation.SellingAccom.Unit\n                                - Product.Accommodation.SellingAccom.Unit.SellingUnit\n                                - Product.OnewayFlight\n                                - Product.OnewayFlight.BookingClass\n                                - Product.ReturnFlight\n                                - Product.ReturnFlight.BookingClass\n                                - Product.ReturnFlight.Inbound\n                                - Product.ReturnFlight.Outbound\n                                - Product.Addon\n                                - Product.Addon.Service\n                                - Product.Addon.ServiceFeature\n\n                                In addition to that all subsequent steps from the paths above are permitted, that is \u0026#39;Board\u0026#39;, \u0026#39;Accommodation.SellingAccom\u0026#39; or \u0026#39;SellingAccom.Unit.SellingUnit\u0026#39;.\n                                \u0026#39;Accommodation.Unit\u0026#39; in the contrary is not permitted, as here some intermediate steps are missing.\n\n                        \u0026lt;/xs:documentation\u0026gt;\n                \u0026lt;/xs:annotation\u0026gt;\n                \u0026lt;xs:union\u0026gt;\n                        \u0026lt;xs:simpleType\u0026gt;\n                                \u0026lt;xs:restriction base=\u0026#34;xs:string\u0026#34;\u0026gt;\n                                        \u0026lt;xs:pattern value=\u0026#34;(((Scope.)?(global|local|current)\\+?)?((((ComponentType.)?(real|virtual))|ComponentType.all)\\+?)?((((Hierarchy.)?(self|ancestors|descendants))|Hierarchy.all)\\+?)?((((DayAllocation.)?(first|last))|DayAllocation.all)\\+?)?:)?(#[A-Za-z0-9\\-_]+(\\.(#[A-Za-z0-9\\-_]+))*|(#[A-Za-z0-9\\-_]+\\.)*(ThisComponent|GlobalValue|Product|Product\\.Brand|Product\\.Accommodation|Product\\.Accommodation\\.SellingAccom|Product\\.Accommodation\\.SellingAccom\\.Board|Product\\.Accommodation\\.SellingAccom\\.Unit|Product\\.Accommodation\\.SellingAccom\\.Unit\\.SellingUnit|Product\\.OnewayFlight|Product\\.OnewayFlight\\.BookingClass|Product\\.ReturnFlight|Product\\.ReturnFlight\\.BookingClass|Product\\.ReturnFlight\\.Inbound|Product\\.ReturnFlight\\.Outbound|Product\\.Addon|Product\\.Addon\\.Service|Product\\.Addon\\.ServiceFeature|Brand|Accommodation|Accommodation\\.SellingAccom|Accommodation\\.SellingAccom\\.Board|Accommodation\\.SellingAccom\\.Unit|Accommodation\\.SellingAccom\\.Unit\\.SellingUnit|OnewayFlight|OnewayFlight\\.BookingClass|ReturnFlight|ReturnFlight\\.BookingClass|ReturnFlight\\.Inbound|ReturnFlight\\.Outbound|Addon|Addon\\.Service|Addon\\.ServiceFeature|SellingAccom|SellingAccom\\.Board|SellingAccom\\.Unit|SellingAccom\\.Unit\\.SellingUnit|BookingClass|Inbound|Outbound|Service|ServiceFeature|Board|Unit|Unit\\.SellingUnit|SellingUnit))\u0026#34;/\u0026gt;\n                                \u0026lt;/xs:restriction\u0026gt;\n                        \u0026lt;/xs:simpleType\u0026gt;\n                \u0026lt;/xs:union\u0026gt;\n\u0026lt;/xs:simpleType\u0026gt;\u003c/code\u003e\u003c/pre\u003e\n\u003c!-- Easy Reader Version: Something, something, Zalgo joke. --\u003e\n\u003clink rel=\"stylesheet\" href=\"//thedailywtf.com/images/highlight/styles/github.css\"/\u003e\n\u003cscript src=\"//thedailywtf.com/images/highlight/highlight.pack.js\"\u003e\u003c/script\u003e\n\u003cscript\u003ehljs.initHighlightingOnLoad();\u003c/script\u003e\n","BodyAndAdHtml":"\u003cblockquote\u003eIt\u0026#39;s a holiday here in the US, a celebration of labor, so we\u0026#39;re reaching back through the archives for a story about an attempt to be labor saving that was not successful. \u003ca href=\"https://thedailywtf.com/articles/a-dumbain-specific-language\"\u003eOriginal\u003c/a\u003e. --\u003cstrong\u003eRemy\u003c/strong\u003e\u003c/blockquote\u003e\n\n\u003cp\u003eI’ve had to write a few domain-specific-languages in the past. As per \u003ca href=\"https://twitter.com/RemyPorter/status/752913168624746497\"\u003eRemy’s Law of Requirements Gathering\u003c/a\u003e, it’s been mostly because the users needed an Excel-like formula language. \u003c!-- Although, more than once, it\u0027s been because I wanted to hack a macro system into a DSL for fun, as per my unfinished multiplayer CYOA engine written in Elixir --\u003e The danger of DSLs, of course, is that they’re often YAGNI in the extreme, or at least a sign that you don’t really understand your problem.\u003c/p\u003e\n\n\u003cp\u003eXML, coupled with schemas, is a tool for building data-focused DSLs. If you have some complex structure, you can convert each of its features into an XML attribute. For example, if you had a grammar that looked something like this:\u003c/p\u003e\n\u003cblockquote\u003e\u003cpre\u003eThe Source specification obeys the following syntax\n\nsource = ( Feature1+Feature2+... \u0026#34;:\u0026#34; ) ? steps\n\nFeature1 = \u0026#34;local\u0026#34; | \u0026#34;global\u0026#34;\n\nFeature2 =\u0026#34;real\u0026#34; | \u0026#34;virtual\u0026#34; | \u0026#34;ComponentType.all\u0026#34;\n\nFeature3 =\u0026#34;self\u0026#34; | \u0026#34;ancestors\u0026#34; | \u0026#34;descendants\u0026#34; | \u0026#34;Hierarchy.all\u0026#34;\n\nFeature4 = \u0026#34;first\u0026#34; | \u0026#34;last\u0026#34; | \u0026#34;DayAllocation.all\u0026#34;\n\nIf features are specified, the order of features as given above has strictly to be followed.\n\nsteps = oneOrMoreNameSteps | zeroOrMoreNameSteps | componentSteps\n\noneOrMoreNameSteps = nameStep ( \u0026#34;.\u0026#34; nameStep ) *\n\nzeroOrMoreNameSteps = ( nameStep \u0026#34;.\u0026#34; ) *\n\nnameStep = \u0026#34;#\u0026#34; name\n\nname is a string of characters from \u0026#34;A\u0026#34;-\u0026#34;Z\u0026#34;, \u0026#34;a\u0026#34;-\u0026#34;z\u0026#34;, \u0026#34;0\u0026#34;-\u0026#34;9\u0026#34;, \u0026#34;-\u0026#34; and \u0026#34;_\u0026#34;. No umlauts allowed, one character is minimum.\n\ncomponentSteps is a list of valid values, see below.\n\nValid \u0026#39;componentSteps\u0026#39; are:\n\n- GlobalValue\n- Product\n- Product.Brand\n- Product.Accommodation\n- Product.Accommodation.SellingAccom\n- Product.Accommodation.SellingAccom.Board\n- Product.Accommodation.SellingAccom.Unit\n- Product.Accommodation.SellingAccom.Unit.SellingUnit\n- Product.OnewayFlight\n- Product.OnewayFlight.BookingClass\n- Product.ReturnFlight\n- Product.ReturnFlight.BookingClass\n- Product.ReturnFlight.Inbound\n- Product.ReturnFlight.Outbound\n- Product.\u003cspan onclick=\"cornify_add();return false;\" title=\"click me!\"\u003eAddon\u003c/span\u003e\u003cscript type=\"text/javascript\" src=\"//www.cornify.com/js/cornify.js\"\u003e\u003c/script\u003e\n- Product.Addon.Service\n- Product.Addon.ServiceFeature\n\nIn addition to that all subsequent steps from the paths above are permitted, that is \u0026#39;Board\u0026#39;, \n\u0026#39;Accommodation.SellingAccom\u0026#39; or \u0026#39;SellingAccom.Unit.SellingUnit\u0026#39;.\n\u0026#39;Accommodation.Unit\u0026#39; in the contrary is not permitted, as here some intermediate steps are missing.\u003c/pre\u003e\u003c/blockquote\u003e\n\n\u003cp\u003eYou could turn that grammar into an XML document by converting syntax elements to attributes and elements. You could do that, but \u003cstrong\u003eStella’s\u003c/strong\u003e predecessor did not do that. That of course, would have been \u003cem\u003ework\u003c/em\u003e, and they may have had to put some thought on how to relate their homebrew grammar to XSD rules, so instead they created an XML schema rule for \u003ccode\u003eSourceAttributeType\u003c/code\u003e that verifies that the data in the field is valid according to the grammar… using regular expressions. 1,310 characters of regular expressions.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"xml\"\u003e\u0026lt;xs:simpleType\u0026gt;\n    \u0026lt;xs:restriction base=\u0026#34;xs:string\u0026#34;\u0026gt;\n            \u0026lt;xs:pattern value=\u0026#34;(((Scope.)?(global|local|current)\\+?)?((((ComponentType.)?\n(real|virtual))|ComponentType.all)\\+?)?((((Hierarchy.)?(self|ancestors|descendants))|Hierarchy.all)\\+?)?\n((((DayAllocation.)?(first|last))|DayAllocation.all)\\+?)?:)?(#[A-Za-z0-9\\-_]+(\\.(#[A-Za-z0-9\\-_]+))*|(#[A-Za-z0-\n9\\-_]+\\.)*\n(ThisComponent|GlobalValue|Product|Product\\.Brand|Product\\.Accommodation|Product\\.Accommodation\\.SellingAccom|Prod\nuct\\.Accommodation\\.SellingAccom\\.Board|Product\\.Accommodation\\.SellingAccom\\.Unit|Product\\.Accommodation\\.Selling\nAccom\\.Unit\\.SellingUnit|Product\\.OnewayFlight|Product\\.OnewayFlight\\.BookingClass|Product\\.ReturnFlight|Product\\.\nReturnFlight\\.BookingClass|Product\\.ReturnFlight\\.Inbound|Product\\.ReturnFlight\\.Outbound|Product\\.Addon|Product\\.\nAddon\\.Service|Product\\.Addon\\.ServiceFeature|Brand|Accommodation|Accommodation\\.SellingAccom|Accommodation\\.Selli\nngAccom\\.Board|Accommodation\\.SellingAccom\\.Unit|Accommodation\\.SellingAccom\\.Unit\\.SellingUnit|OnewayFlight|Onewa\nyFlight\\.BookingClass|ReturnFlight|ReturnFlight\\.BookingClass|ReturnFlight\\.Inbound|ReturnFlight\\.Outbound|Addon|A\nddon\\.Service|Addon\\.ServiceFeature|SellingAccom|SellingAccom\\.Board|SellingAccom\\.Unit|SellingAccom\\.Unit\\.Sellin\ngUnit|BookingClass|Inbound|Outbound|Service|ServiceFeature|Board|Unit|Unit\\.SellingUnit|SellingUnit))\u0026#34;/\u0026gt;\n    \u0026lt;/xs:restriction\u0026gt;\n\u0026lt;/xs:simpleType\u0026gt;\n\u0026lt;/xs:union\u0026gt;\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003eThere’s a bug in that regex that Stella needed to fix. As she put it: “Every time you evaluate it a few little kitties die because you shouldn’t use kitties to polish your car. I’m so, so sorry, little kitties…”\u003c/p\u003e\n\n\u003cp\u003eThe full, unexcerpted code is below, so… at least it has documentation. In two languages!\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"xml\"\u003e\u0026lt;xs:simpleType name=\u0026#34;SourceAttributeType\u0026#34;\u0026gt;\n                \u0026lt;xs:annotation\u0026gt;\n                        \u0026lt;xs:documentation xml:lang=\u0026#34;de\u0026#34;\u0026gt;\n                Die Source Angabe folgt folgender Syntax\n\n                        source = ( Eigenschaft1+Eigenschaft2+... \u0026#34;:\u0026#34; ) ? steps\n\n                        Eigenschaft1 = \u0026#34;local\u0026#34; | \u0026#34;global\u0026#34;\n\n                        Eigenschaft2 =\u0026#34;real\u0026#34; | \u0026#34;virtual\u0026#34; | \u0026#34;ComponentType.all\u0026#34;\n\n                        Eigenschaft3 =\u0026#34;self\u0026#34; | \u0026#34;ancestors\u0026#34; | \u0026#34;descendants\u0026#34; | \u0026#34;Hierarchy.all\u0026#34;\n\n                        Eigenschaft4 = \u0026#34;first\u0026#34; | \u0026#34;last\u0026#34; | \u0026#34;DayAllocation.all\u0026#34;\n\n                        Falls Eigenschaften angegeben werden muss zwingend die oben angegebene Reihenfolge der Eigenschaften eingehalten werden.\n\n                        steps = oneOrMoreNameSteps | zeroOrMoreNameSteps | componentSteps\n\n                        oneOrMoreNameSteps = nameStep ( \u0026#34;.\u0026#34; nameStep ) *\n\n                        zeroOrMoreNameSteps = ( nameStep \u0026#34;.\u0026#34; ) *\n\n                        nameStep = \u0026#34;#\u0026#34; name\n\n                        name ist eine Folge von Zeichen aus der Menge \u0026#34;A\u0026#34;-\u0026#34;Z\u0026#34;, \u0026#34;a\u0026#34;-\u0026#34;z\u0026#34;, \u0026#34;0\u0026#34;-\u0026#34;9\u0026#34;, \u0026#34;-\u0026#34; und \u0026#34;_\u0026#34;. Keine Umlaute. Mindestens ein Zeichen\n\n                        componentSteps ist eine Liste gültiger Werte, siehe im folgenden\n\n                Gültige \u0026#39;componentSteps\u0026#39; sind zunächst:\n\n                        - GlobalValue\n                        - Product\n                        - Product.Brand\n                        - Product.Accommodation\n                        - Product.Accommodation.SellingAccom\n                        - Product.Accommodation.SellingAccom.Board\n                        - Product.Accommodation.SellingAccom.Unit\n                        - Product.Accommodation.SellingAccom.Unit.SellingUnit\n                        - Product.OnewayFlight\n                        - Product.OnewayFlight.BookingClass\n                        - Product.ReturnFlight\n                        - Product.ReturnFlight.BookingClass\n                        - Product.ReturnFlight.Inbound\n                        - Product.ReturnFlight.Outbound\n                        - Product.Addon\n                        - Product.Addon.Service\n                        - Product.Addon.ServiceFeature\n\n                Desweiteren sind alle Unterschrittfolgen aus obigen Pfaden erlaubt, also \u0026#39;Board\u0026#39;, \u0026#39;Accommodation.SellingAccom\u0026#39; oder \u0026#39;SellingAccom.Unit.SellingUnit\u0026#39;.\n                \u0026#39;Accommodation.Unit\u0026#39; hingegen ist nicht erlaubt, da in diesem Fall einige Zwischenschritte fehlen.\n\n                                \u0026lt;/xs:documentation\u0026gt;\n                        \u0026lt;xs:documentation xml:lang=\u0026#34;en\u0026#34;\u0026gt;\n                                The Source specification obeys the following syntax\n\n                                source = ( Feature1+Feature2+... \u0026#34;:\u0026#34; ) ? steps\n\n                                Feature1 = \u0026#34;local\u0026#34; | \u0026#34;global\u0026#34;\n\n                                Feature2 =\u0026#34;real\u0026#34; | \u0026#34;virtual\u0026#34; | \u0026#34;ComponentType.all\u0026#34;\n\n                                Feature3 =\u0026#34;self\u0026#34; | \u0026#34;ancestors\u0026#34; | \u0026#34;descendants\u0026#34; | \u0026#34;Hierarchy.all\u0026#34;\n\n                                Feature4 = \u0026#34;first\u0026#34; | \u0026#34;last\u0026#34; | \u0026#34;DayAllocation.all\u0026#34;\n\n                                If features are specified, the order of features as given above has strictly to be followed.\n\n                                steps = oneOrMoreNameSteps | zeroOrMoreNameSteps | componentSteps\n\n                                oneOrMoreNameSteps = nameStep ( \u0026#34;.\u0026#34; nameStep ) *\n\n                                zeroOrMoreNameSteps = ( nameStep \u0026#34;.\u0026#34; ) *\n\n                                nameStep = \u0026#34;#\u0026#34; name\n\n                                name is a string of characters from \u0026#34;A\u0026#34;-\u0026#34;Z\u0026#34;, \u0026#34;a\u0026#34;-\u0026#34;z\u0026#34;, \u0026#34;0\u0026#34;-\u0026#34;9\u0026#34;, \u0026#34;-\u0026#34; and \u0026#34;_\u0026#34;. No umlauts allowed, one character is minimum.\n\n                                componentSteps is a list of valid values, see below.\n\n                                Valid \u0026#39;componentSteps\u0026#39; are:\n\n                                - GlobalValue\n                                - Product\n                                - Product.Brand\n                                - Product.Accommodation\n                                - Product.Accommodation.SellingAccom\n                                - Product.Accommodation.SellingAccom.Board\n                                - Product.Accommodation.SellingAccom.Unit\n                                - Product.Accommodation.SellingAccom.Unit.SellingUnit\n                                - Product.OnewayFlight\n                                - Product.OnewayFlight.BookingClass\n                                - Product.ReturnFlight\n                                - Product.ReturnFlight.BookingClass\n                                - Product.ReturnFlight.Inbound\n                                - Product.ReturnFlight.Outbound\n                                - Product.Addon\n                                - Product.Addon.Service\n                                - Product.Addon.ServiceFeature\n\n                                In addition to that all subsequent steps from the paths above are permitted, that is \u0026#39;Board\u0026#39;, \u0026#39;Accommodation.SellingAccom\u0026#39; or \u0026#39;SellingAccom.Unit.SellingUnit\u0026#39;.\n                                \u0026#39;Accommodation.Unit\u0026#39; in the contrary is not permitted, as here some intermediate steps are missing.\n\n                        \u0026lt;/xs:documentation\u0026gt;\n                \u0026lt;/xs:annotation\u0026gt;\n                \u0026lt;xs:union\u0026gt;\n                        \u0026lt;xs:simpleType\u0026gt;\n                                \u0026lt;xs:restriction base=\u0026#34;xs:string\u0026#34;\u0026gt;\n                                        \u0026lt;xs:pattern value=\u0026#34;(((Scope.)?(global|local|current)\\+?)?((((ComponentType.)?(real|virtual))|ComponentType.all)\\+?)?((((Hierarchy.)?(self|ancestors|descendants))|Hierarchy.all)\\+?)?((((DayAllocation.)?(first|last))|DayAllocation.all)\\+?)?:)?(#[A-Za-z0-9\\-_]+(\\.(#[A-Za-z0-9\\-_]+))*|(#[A-Za-z0-9\\-_]+\\.)*(ThisComponent|GlobalValue|Product|Product\\.Brand|Product\\.Accommodation|Product\\.Accommodation\\.SellingAccom|Product\\.Accommodation\\.SellingAccom\\.Board|Product\\.Accommodation\\.SellingAccom\\.Unit|Product\\.Accommodation\\.SellingAccom\\.Unit\\.SellingUnit|Product\\.OnewayFlight|Product\\.OnewayFlight\\.BookingClass|Product\\.ReturnFlight|Product\\.ReturnFlight\\.BookingClass|Product\\.ReturnFlight\\.Inbound|Product\\.ReturnFlight\\.Outbound|Product\\.Addon|Product\\.Addon\\.Service|Product\\.Addon\\.ServiceFeature|Brand|Accommodation|Accommodation\\.SellingAccom|Accommodation\\.SellingAccom\\.Board|Accommodation\\.SellingAccom\\.Unit|Accommodation\\.SellingAccom\\.Unit\\.SellingUnit|OnewayFlight|OnewayFlight\\.BookingClass|ReturnFlight|ReturnFlight\\.BookingClass|ReturnFlight\\.Inbound|ReturnFlight\\.Outbound|Addon|Addon\\.Service|Addon\\.ServiceFeature|SellingAccom|SellingAccom\\.Board|SellingAccom\\.Unit|SellingAccom\\.Unit\\.SellingUnit|BookingClass|Inbound|Outbound|Service|ServiceFeature|Board|Unit|Unit\\.SellingUnit|SellingUnit))\u0026#34;/\u0026gt;\n                                \u0026lt;/xs:restriction\u0026gt;\n                        \u0026lt;/xs:simpleType\u0026gt;\n                \u0026lt;/xs:union\u0026gt;\n\u0026lt;/xs:simpleType\u0026gt;\u003c/code\u003e\u003c/pre\u003e\n\u003c!-- Easy Reader Version: Something, something, Zalgo joke. --\u003e\n\u003clink rel=\"stylesheet\" href=\"//thedailywtf.com/images/highlight/styles/github.css\"/\u003e\n\u003cscript src=\"//thedailywtf.com/images/highlight/highlight.pack.js\"\u003e\u003c/script\u003e\n\u003cscript\u003ehljs.initHighlightingOnLoad();\u003c/script\u003e\n\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/buildmaster-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\t\u003ca href=\"https://inedo.com/BuildMaster?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eBuildMaster\u003c/a\u003e allows you to create a self-service release management platform that allows different teams to manage their applications. \u003ca href=\"https://inedo.com/BuildMaster/download?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eExplore how!\u003c/a\u003e \n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Title":"Classic WTF: A Dumbain Specific Language","RssTitle":"Best of…: Classic WTF: A Dumbain Specific Language","CachedCommentCount":10,"LastCommentDate":"\/Date(1788889531007)\/","LastCommentDateDescription":"2026-09-08","DiscourseTopicId":null,"DiscourseTopicOpened":false,"PublishedDate":"\/Date(1788762600000)\/","ISODate":"2026-09-07","DisplayDate":"2026-09-07","Series":{"Slug":"best-of","Title":"Best of…","Description":"Our \"best\" articles of years past.","CssClass":"soapbox"},"FooterAdHtml":"\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/buildmaster-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\t\u003ca href=\"https://inedo.com/BuildMaster?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eBuildMaster\u003c/a\u003e allows you to create a self-service release management platform that allows different teams to manage their applications. \u003ca href=\"https://inedo.com/BuildMaster/download?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eExplore how!\u003c/a\u003e \n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Url":"https://thedailywtf.com/articles/classic-wtf-a-dumbain-specific-language","CommentsUrl":"https://thedailywtf.com/articles/comments/classic-wtf-a-dumbain-specific-language","Slug":"classic-wtf-a-dumbain-specific-language","TwitterUrl":"//www.twitter.com/home?status=https%3a%2f%2fthedailywtf.com%2farticles%2fclassic-wtf-a-dumbain-specific-language+-+Classic+WTF%3a+A+Dumbain+Specific+Language+-+The+Daily+WTF","FacebookUrl":"//www.facebook.com/sharer.php?u=https%3a%2f%2fthedailywtf.com%2farticles%2fclassic-wtf-a-dumbain-specific-language\u0026t=Classic+WTF%3a+A+Dumbain+Specific+Language+-+The+Daily+WTF","EmailUrl":"mailto:%20?subject=Check%20out%20this%20article%20on%20The%20Daily%20WTF...\u0026body=Classic%20WTF:%20A%20Dumbain%20Specific%20Language:%20https://thedailywtf.com/articles/classic-wtf-a-dumbain-specific-language","GooglePlusUrl":"//plus.google.com/share?url=https%3a%2f%2fthedailywtf.com%2farticles%2fclassic-wtf-a-dumbain-specific-language","PreviousArticleId":11262,"PreviousArticleTitle":"Good Time","PreviousArticleSlug":"good-time","PreviousArticleUrl":"//thedailywtf.com/articles/good-time","NextArticleId":11267,"NextArticleTitle":"A Mortal Blow","NextArticleSlug":"a-mortal-blow","NextArticleUrl":"//thedailywtf.com/articles/a-mortal-blow"},{"Id":11262,"Author":{"Name":"Lyle Seaman","FirstName":"Lyle","ShortDescription":"networking, security infra and filesystems kernel hacker turned application programmer, SRE and engineering manager, Lyle traded tilting at windmills for viking at Vikings but couldn\u0027t catch any.","DescriptionHtml":null,"Slug":"lyle-seaman","IsAdmin":true,"IsActive":true,"ImageUrl":"/images/imageslws/viking.jpg"},"Status":"Published","SummaryHtml":"\u003cp\u003eAstute readers noticed last week that this editor (that is to say, me) had his own error\u0026#39;d failure to remember what day it was. Thank you for pointing it out promptly, and then proceeding to send in a bunch of examples of \u003cem\u003eother\u003c/em\u003e sites calendar failures.  Misery loves company!\u003c/p\u003e\n\n\u003cp\u003eTraveler\u0026#39;s travails, from\n\u003cstrong\u003eC_Chell\u003c/strong\u003e \n\u0026#34;Trying to complete the form on https://www.ihg.com to tell when\nI plan to arrive at the hotel, I can\u0026#39;t complete\nthe form because of this little time problem.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003c/blockquote\u003e","BodyHtml":"\u003cp\u003eAstute readers noticed last week that this editor (that is to say, me) had his own error\u0026#39;d failure to remember what day it was. Thank you for pointing it out promptly, and then proceeding to send in a bunch of examples of \u003cem\u003eother\u003c/em\u003e sites calendar failures.  Misery loves company!\u003c/p\u003e\n\n\u003cp\u003eTraveler\u0026#39;s travails, from\n\u003cstrong\u003eC_Chell\u003c/strong\u003e \n\u0026#34;Trying to complete the form on https://www.ihg.com to tell when\nI plan to arrive at the hotel, I can\u0026#39;t complete\nthe form because of this little time problem.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#06036a0253dc4d61b4bd648ab59c2dae\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"06036a0253dc4d61b4bd648ab59c2dae\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/06036a0253dc4d61b4bd648ab59c2dae.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\u0026#34;You Have -1 Month(s) To Order!\u0026#34; announces \n\u003cstrong\u003edragoncoder047\u003c/strong\u003e.\n\u0026#34;Ah, GradImages... the company that told all graduates that they\u0026#39;d\nget a free 5x7 but tried to charge me for\nit, then refused to honor my \u0026#34;unsubscribe\u0026#34; request and is\n*still* emailing me to this day... Can\u0026#39;t do date math?\nPar for the course.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#1820ae48b9df4a759ffbde45a8c715e0\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"1820ae48b9df4a759ffbde45a8c715e0\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/1820ae48b9df4a759ffbde45a8c715e0.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\u0026#34;Stansted Temporal UI design\u0026#34; shared by \n\u003cstrong\u003eMichael R.\u003c/strong\u003e\n\u0026#34;While waiting for a friend to arrive at Stansted I\nsee this. I better fire up the DeLorean to pick\nher up at 00:06 tomorrow.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#8fa526db89fe46d88d6d2597fe0fa3ae\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"8fa526db89fe46d88d6d2597fe0fa3ae\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/8fa526db89fe46d88d6d2597fe0fa3ae.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\u003cp\u003eWhile he was hunting through the website, \n\u003cstrong\u003eMichael R.\u003c/strong\u003e also found that\n\u0026#34;The Stansted airport website seems to suffer from Directional Confusion.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#89c37786ca724e82868eaab4f7285fcf\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"89c37786ca724e82868eaab4f7285fcf\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/89c37786ca724e82868eaab4f7285fcf.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003eNothing wrong with the calendar here, but \n\u003cstrong\u003eSlaoput\u003c/strong\u003e simply opposes mandatory existence. \n\u0026#34;I was filling out a form that said the Birthdate\nis optional, but when I hit submit I found out\nit was required. (I guess technically you have to be\nborn to fill out the form.)\u0026#34;\n\u003cbr/\u003e\u003cb\u003eNOT\u003c/b\u003e TO BE!\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#8bf00b3dc8ae4ca19481b42b9e63d0f4\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"8bf00b3dc8ae4ca19481b42b9e63d0f4\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/8bf00b3dc8ae4ca19481b42b9e63d0f4.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n","BodyAndAdHtml":"\u003cp\u003eAstute readers noticed last week that this editor (that is to say, me) had his own error\u0026#39;d failure to remember what day it was. Thank you for pointing it out promptly, and then proceeding to send in a bunch of examples of \u003cem\u003eother\u003c/em\u003e sites calendar failures.  Misery loves company!\u003c/p\u003e\n\n\u003cp\u003eTraveler\u0026#39;s travails, from\n\u003cstrong\u003eC_Chell\u003c/strong\u003e \n\u0026#34;Trying to complete the form on https://www.ihg.com to tell when\nI plan to arrive at the hotel, I can\u0026#39;t complete\nthe form because of this little time problem.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#06036a0253dc4d61b4bd648ab59c2dae\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"06036a0253dc4d61b4bd648ab59c2dae\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/06036a0253dc4d61b4bd648ab59c2dae.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\u0026#34;You Have -1 Month(s) To Order!\u0026#34; announces \n\u003cstrong\u003edragoncoder047\u003c/strong\u003e.\n\u0026#34;Ah, GradImages... the company that told all graduates that they\u0026#39;d\nget a free 5x7 but tried to charge me for\nit, then refused to honor my \u0026#34;unsubscribe\u0026#34; request and is\n*still* emailing me to this day... Can\u0026#39;t do date math?\nPar for the course.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#1820ae48b9df4a759ffbde45a8c715e0\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"1820ae48b9df4a759ffbde45a8c715e0\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/1820ae48b9df4a759ffbde45a8c715e0.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\u0026#34;Stansted Temporal UI design\u0026#34; shared by \n\u003cstrong\u003eMichael R.\u003c/strong\u003e\n\u0026#34;While waiting for a friend to arrive at Stansted I\nsee this. I better fire up the DeLorean to pick\nher up at 00:06 tomorrow.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#8fa526db89fe46d88d6d2597fe0fa3ae\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"8fa526db89fe46d88d6d2597fe0fa3ae\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/8fa526db89fe46d88d6d2597fe0fa3ae.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\u003cp\u003eWhile he was hunting through the website, \n\u003cstrong\u003eMichael R.\u003c/strong\u003e also found that\n\u0026#34;The Stansted airport website seems to suffer from Directional Confusion.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#89c37786ca724e82868eaab4f7285fcf\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"89c37786ca724e82868eaab4f7285fcf\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/89c37786ca724e82868eaab4f7285fcf.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003eNothing wrong with the calendar here, but \n\u003cstrong\u003eSlaoput\u003c/strong\u003e simply opposes mandatory existence. \n\u0026#34;I was filling out a form that said the Birthdate\nis optional, but when I hit submit I found out\nit was required. (I guess technically you have to be\nborn to fill out the form.)\u0026#34;\n\u003cbr/\u003e\u003cb\u003eNOT\u003c/b\u003e TO BE!\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#8bf00b3dc8ae4ca19481b42b9e63d0f4\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"8bf00b3dc8ae4ca19481b42b9e63d0f4\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/30/8bf00b3dc8ae4ca19481b42b9e63d0f4.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\u003cdiv\u003e\n\t[Advertisement] Picking up \u003cb\u003eNuGet\u003c/b\u003e is easy. Getting good at it takes time. \u003ca href=\"https://inedo.com/support/whitepapers/nuget-guide?utm_source=tdwtf\u0026amp;utm_medium=Footerad\u0026amp;utm_campaign=nuget\"\u003eDownload our guide to learn the best practice of NuGet for the Enterprise.\u003c/a\u003e\n\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e","Title":"Good Time","RssTitle":"Error\u0027d: Good Time","CachedCommentCount":15,"LastCommentDate":"\/Date(1788764159053)\/","LastCommentDateDescription":"2026-09-07","DiscourseTopicId":null,"DiscourseTopicOpened":false,"PublishedDate":"\/Date(1788503400000)\/","ISODate":"2026-09-04","DisplayDate":"2026-09-04","Series":{"Slug":"errord","Title":"Error\u0027d","Description":"Error\u0027d features fun error messages and other visual oddities from the world of IT.","CssClass":"errord"},"FooterAdHtml":"\u003cdiv\u003e\n\t[Advertisement] Picking up \u003cb\u003eNuGet\u003c/b\u003e is easy. Getting good at it takes time. \u003ca href=\"https://inedo.com/support/whitepapers/nuget-guide?utm_source=tdwtf\u0026amp;utm_medium=Footerad\u0026amp;utm_campaign=nuget\"\u003eDownload our guide to learn the best practice of NuGet for the Enterprise.\u003c/a\u003e\n\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e","Url":"https://thedailywtf.com/articles/good-time","CommentsUrl":"https://thedailywtf.com/articles/comments/good-time","Slug":"good-time","TwitterUrl":"//www.twitter.com/home?status=https%3a%2f%2fthedailywtf.com%2farticles%2fgood-time+-+Good+Time+-+The+Daily+WTF","FacebookUrl":"//www.facebook.com/sharer.php?u=https%3a%2f%2fthedailywtf.com%2farticles%2fgood-time\u0026t=Good+Time+-+The+Daily+WTF","EmailUrl":"mailto:%20?subject=Check%20out%20this%20article%20on%20The%20Daily%20WTF...\u0026body=Good%20Time:%20https://thedailywtf.com/articles/good-time","GooglePlusUrl":"//plus.google.com/share?url=https%3a%2f%2fthedailywtf.com%2farticles%2fgood-time","PreviousArticleId":11265,"PreviousArticleTitle":"Heating Up","PreviousArticleSlug":"heating-up","PreviousArticleUrl":"//thedailywtf.com/articles/heating-up","NextArticleId":11266,"NextArticleTitle":"Classic WTF: A Dumbain Specific Language","NextArticleSlug":"classic-wtf-a-dumbain-specific-language","NextArticleUrl":"//thedailywtf.com/articles/classic-wtf-a-dumbain-specific-language"},{"Id":11265,"Author":{"Name":"Remy Porter","FirstName":"Remy","ShortDescription":"Computers were a mistake, so I accidentally became a farmer? Editor-in-Chief for TDWTF.","DescriptionHtml":"\u003cp\u003eRemy is a veteran developer who writes software for farming robots. They pick tomatoes.\u003c/p\u003e\r\n\u003cp\u003eHe\u0027s often on stage, doing improv comedy, but insists that \u003cem\u003ehe\u003c/em\u003e isn\u0027t doing comedy- it\u0027s deadly serious. You\u0027re laughing at him, not with him. That, by the way, is usually true- you\u0027re laughing at him, not with him.\u003c/p\u003e","Slug":"remy-porter","IsAdmin":true,"IsActive":true,"ImageUrl":"https://s3.amazonaws.com/remy.jetpackshark.com/remy-thumb.jpg"},"Status":"Published","SummaryHtml":"\u003cp\u003eA common option for retrofitting heating and cooling into older homes is a mini-split, frequently tied to a heat pump. They\u0026#39;re (relatively) cheap to install, energy efficient, and can be added without substantial modifications to the home. They also, annoyingly, are mostly controlled via IR remotes, making them challenging to wire up to home automation or even a household thermostat.\u003c/p\u003e\n\u003cp\u003ePeople have made solutions, and today\u0026#39;s code comes from one of those solutions. Which, I want to stress, this code comes from an open source project for home automation, so it\u0026#39;s not \u003cem\u003ethe code\u003c/em\u003e that\u0026#39;s wrong, here. At first I thought it was, and had a moment of, \u0026#34;I\u0026#39;m not going to pick on some hobby project,\u0026#34; but then I realised the hobby project points at a deeper issue.\u003c/p\u003e\n","BodyHtml":"\u003cp\u003eA common option for retrofitting heating and cooling into older homes is a mini-split, frequently tied to a heat pump. They\u0026#39;re (relatively) cheap to install, energy efficient, and can be added without substantial modifications to the home. They also, annoyingly, are mostly controlled via IR remotes, making them challenging to wire up to home automation or even a household thermostat.\u003c/p\u003e\n\u003cp\u003ePeople have made solutions, and today\u0026#39;s code comes from one of those solutions. Which, I want to stress, this code comes from an open source project for home automation, so it\u0026#39;s not \u003cem\u003ethe code\u003c/em\u003e that\u0026#39;s wrong, here. At first I thought it was, and had a moment of, \u0026#34;I\u0026#39;m not going to pick on some hobby project,\u0026#34; but then I realised the hobby project points at a deeper issue.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-cpp\"\u003e\u003cspan class=\"hljs-comment\"\u003e// temperature helper these are direct mappings based on the remote\u003c/span\u003e\n\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003etoFahrenheit\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e(\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e fromCelsius)\u003c/span\u003e \u003c/span\u003e{\n    \u003cspan class=\"hljs-comment\"\u003e// Lookup table for specific mappings\u003c/span\u003e\n    \u003cspan class=\"hljs-type\"\u003econst\u003c/span\u003e std::map\u0026lt;\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e, \u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e\u0026gt; lookupTable = {\n        {\u003cspan class=\"hljs-number\"\u003e16.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e61\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e16.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e62\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e17.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e63\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e17.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e64\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e18.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e65\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e18.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e66\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e19.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e67\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e20.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e68\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e21.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e69\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e21.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e70\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e22.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e71\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e22.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e72\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e23.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e73\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e23.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e74\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e24.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e75\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e24.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e76\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e25.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e77\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e25.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e78\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e26.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e79\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e26.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e80\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e27.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e81\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e27.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e82\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e28.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e83\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e28.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e84\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e29.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e85\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e29.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e86\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e30.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e87\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e30.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e88\u003c/span\u003e}\n    };\n\n    \u003cspan class=\"hljs-comment\"\u003e// Check if the input is in the lookup table\u003c/span\u003e\n    \u003cspan class=\"hljs-keyword\"\u003eauto\u003c/span\u003e it = lookupTable.\u003cspan class=\"hljs-built_in\"\u003efind\u003c/span\u003e(fromCelsius);\n    \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (it != lookupTable.\u003cspan class=\"hljs-built_in\"\u003eend\u003c/span\u003e()) {\n        \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e it-\u0026gt;second;\n    }\n\n    \u003cspan class=\"hljs-comment\"\u003e// Default conversion and rounding to nearest integer\u003c/span\u003e\n    \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eroundf\u003c/span\u003e(fromCelsius * \u003cspan class=\"hljs-number\"\u003e1.8\u003c/span\u003e + \u003cspan class=\"hljs-number\"\u003e32.0\u003c/span\u003e);\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eOkay, I \u003cem\u003eam\u003c/em\u003e going to pick on their code a little bit; using \u003ccode\u003efloat\u003c/code\u003e as a key in a \u003ccode\u003emap\u003c/code\u003e is asking for trouble, because rounding errors are going to surprise you. But honestly, failing to find the key you\u0026#39;re looking for is \u003cem\u003ebetter\u003c/em\u003e than the opposite, since that actually does the correct thing. Because if you look carefully at the table, you\u0026#39;ll see that it\u0026#39;s \u003cem\u003ewrong\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003e18C, for example, should be 64F. Well, 64.4F, but we\u0026#39;re rounding to an integer. The choice here is to roughly map every 0.5C increase to a 1F increase, which is not the conversion factor. They try and correct- note how the table mostly steps by 0.5C, but skips 19.5C.\u003c/p\u003e\n\u003cp\u003eThe opposite direction is similarly bad:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-cpp\"\u003e\u003cspan class=\"hljs-comment\"\u003e// temperature helper these are direct mappings based on the remote\u003c/span\u003e\n\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003etoCelsius\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e(\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e fromFahrenheit)\u003c/span\u003e \u003c/span\u003e{\n    \u003cspan class=\"hljs-comment\"\u003e// Lookup table for specific mappings\u003c/span\u003e\n    \u003cspan class=\"hljs-type\"\u003econst\u003c/span\u003e std::map\u0026lt;\u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e, \u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e\u0026gt; lookupTable = {\n        {\u003cspan class=\"hljs-number\"\u003e61\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e16.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e62\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e16.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e63\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e17.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e64\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e17.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e65\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e18.0\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e66\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e18.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e67\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e19.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e68\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e20.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e69\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e21.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e70\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e21.5\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e71\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e22.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e72\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e22.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e73\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e23.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e74\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e23.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e75\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e24.0\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e76\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e24.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e77\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e25.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e78\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e25.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e79\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e26.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e80\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e26.5\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e81\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e27.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e82\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e27.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e83\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e28.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e84\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e28.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e85\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e29.0\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e86\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e29.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e87\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e30.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e88\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e30.5\u003c/span\u003e}\n    };\n\n    \u003cspan class=\"hljs-comment\"\u003e// Check if the input is in the lookup table\u003c/span\u003e\n    \u003cspan class=\"hljs-keyword\"\u003eauto\u003c/span\u003e it = lookupTable.\u003cspan class=\"hljs-built_in\"\u003efind\u003c/span\u003e(\u003cspan class=\"hljs-built_in\"\u003estatic_cast\u003c/span\u003e\u0026lt;\u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e\u0026gt;(fromFahrenheit));\n    \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (it != lookupTable.\u003cspan class=\"hljs-built_in\"\u003eend\u003c/span\u003e()) {\n        \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e it-\u0026gt;second;\n    }\n\n    \u003cspan class=\"hljs-comment\"\u003e// Default conversion and rounding to nearest 0.5\u003c/span\u003e\n    \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eroundf\u003c/span\u003e((fromFahrenheit - \u003cspan class=\"hljs-number\"\u003e32.0\u003c/span\u003e) / \u003cspan class=\"hljs-number\"\u003e1.8\u003c/span\u003e * \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e) / \u003cspan class=\"hljs-number\"\u003e2.0\u003c/span\u003e;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, we can be off by as much as a 1C, which is certainly a noticeable feeling.\u003c/p\u003e\n\u003cp\u003eAt first glance, I thought this was just a misguided attempt at optimizing the lookup. For common values, do a lookup instead of calculating because it\u0026#39;s faster. Seems like the kind of mistake a hobby project might make, and definitely not a WTF. But it\u0026#39;s the comment which corrects me: \u003ccode\u003ethese are direct mappings based on the remote\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eThese remotes usually have a display. So when you see on the remote that you\u0026#39;re trying to set the temperature to a comfortable 72F, the remote is actually sending 22.5C to the unit. That\u0026#39;s the actual temperature being sent.\u003c/p\u003e\n\u003cp\u003eNow, why on Earth does the remote behave this way? Well, I haven\u0026#39;t cracked one open to read off the part numbers, but I\u0026#39;m going to go out on a limb and guess that the microcontoller in the remote doesn\u0026#39;t handle floating point operations all that well. So it almost certainly does use a lookup table to decide what signal to send, and the lookup table is populated by \u0026#34;good enough\u0026#34; approximations of temperature conversions. There aren\u0026#39;t a \u003cem\u003elot\u003c/em\u003e of places that use Fahrenheit, so being \u0026#34;close enough\u0026#34; is a reasonable solution. If you want accurate temperatures, use SI units, not \u0026#34;freedom units\u0026#34;.\u003c/p\u003e\n\u003cp\u003eIn the end, I\u0026#39;d say that neither the hobby project, nor the remote control are the WTF here; locales that insist on using weird ass units are.\u003c/p\u003e\n\u003c!-- Easy Reader Version: Rankine is, of course, the most absurd version of this: keep the Fahrenheit scaling, but anchor at absolute zero, like Kelvin, though it\u0027s also worth reading up on the both the Newton scale and the Rømer scale, because \"coming up with a canonical temperature measurement\" was a hard thing to do in the early modern period! It was cutting edge science! Weird scales were a natural reaction to trying to find reproducible conditions. --\u003e\n\u003cstyle\u003e.comment { border: none }\u003c/style\u003e","BodyAndAdHtml":"\u003cp\u003eA common option for retrofitting heating and cooling into older homes is a mini-split, frequently tied to a heat pump. They\u0026#39;re (relatively) cheap to install, energy efficient, and can be added without substantial modifications to the home. They also, annoyingly, are mostly controlled via IR remotes, making them challenging to wire up to home automation or even a household thermostat.\u003c/p\u003e\n\u003cp\u003ePeople have made solutions, and today\u0026#39;s code comes from one of those solutions. Which, I want to stress, this code comes from an open source project for home automation, so it\u0026#39;s not \u003cem\u003ethe code\u003c/em\u003e that\u0026#39;s wrong, here. At first I thought it was, and had a moment of, \u0026#34;I\u0026#39;m not going to pick on some hobby project,\u0026#34; but then I realised the hobby project points at a deeper issue.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-cpp\"\u003e\u003cspan class=\"hljs-comment\"\u003e// temperature helper these are direct mappings based on the remote\u003c/span\u003e\n\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003etoFahrenheit\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e(\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e fromCelsius)\u003c/span\u003e \u003c/span\u003e{\n    \u003cspan class=\"hljs-comment\"\u003e// Lookup table for specific mappings\u003c/span\u003e\n    \u003cspan class=\"hljs-type\"\u003econst\u003c/span\u003e std::map\u0026lt;\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e, \u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e\u0026gt; lookupTable = {\n        {\u003cspan class=\"hljs-number\"\u003e16.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e61\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e16.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e62\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e17.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e63\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e17.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e64\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e18.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e65\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e18.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e66\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e19.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e67\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e20.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e68\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e21.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e69\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e21.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e70\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e22.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e71\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e22.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e72\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e23.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e73\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e23.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e74\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e24.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e75\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e24.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e76\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e25.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e77\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e25.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e78\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e26.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e79\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e26.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e80\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e27.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e81\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e27.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e82\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e28.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e83\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e28.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e84\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e29.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e85\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e29.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e86\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e30.0\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e87\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e30.5\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e88\u003c/span\u003e}\n    };\n\n    \u003cspan class=\"hljs-comment\"\u003e// Check if the input is in the lookup table\u003c/span\u003e\n    \u003cspan class=\"hljs-keyword\"\u003eauto\u003c/span\u003e it = lookupTable.\u003cspan class=\"hljs-built_in\"\u003efind\u003c/span\u003e(fromCelsius);\n    \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (it != lookupTable.\u003cspan class=\"hljs-built_in\"\u003eend\u003c/span\u003e()) {\n        \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e it-\u0026gt;second;\n    }\n\n    \u003cspan class=\"hljs-comment\"\u003e// Default conversion and rounding to nearest integer\u003c/span\u003e\n    \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eroundf\u003c/span\u003e(fromCelsius * \u003cspan class=\"hljs-number\"\u003e1.8\u003c/span\u003e + \u003cspan class=\"hljs-number\"\u003e32.0\u003c/span\u003e);\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eOkay, I \u003cem\u003eam\u003c/em\u003e going to pick on their code a little bit; using \u003ccode\u003efloat\u003c/code\u003e as a key in a \u003ccode\u003emap\u003c/code\u003e is asking for trouble, because rounding errors are going to surprise you. But honestly, failing to find the key you\u0026#39;re looking for is \u003cem\u003ebetter\u003c/em\u003e than the opposite, since that actually does the correct thing. Because if you look carefully at the table, you\u0026#39;ll see that it\u0026#39;s \u003cem\u003ewrong\u003c/em\u003e.\u003c/p\u003e\n\u003cp\u003e18C, for example, should be 64F. Well, 64.4F, but we\u0026#39;re rounding to an integer. The choice here is to roughly map every 0.5C increase to a 1F increase, which is not the conversion factor. They try and correct- note how the table mostly steps by 0.5C, but skips 19.5C.\u003c/p\u003e\n\u003cp\u003eThe opposite direction is similarly bad:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-cpp\"\u003e\u003cspan class=\"hljs-comment\"\u003e// temperature helper these are direct mappings based on the remote\u003c/span\u003e\n\u003cspan class=\"hljs-function\"\u003e\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e \u003cspan class=\"hljs-title\"\u003etoCelsius\u003c/span\u003e\u003cspan class=\"hljs-params\"\u003e(\u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e fromFahrenheit)\u003c/span\u003e \u003c/span\u003e{\n    \u003cspan class=\"hljs-comment\"\u003e// Lookup table for specific mappings\u003c/span\u003e\n    \u003cspan class=\"hljs-type\"\u003econst\u003c/span\u003e std::map\u0026lt;\u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e, \u003cspan class=\"hljs-type\"\u003efloat\u003c/span\u003e\u0026gt; lookupTable = {\n        {\u003cspan class=\"hljs-number\"\u003e61\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e16.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e62\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e16.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e63\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e17.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e64\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e17.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e65\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e18.0\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e66\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e18.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e67\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e19.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e68\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e20.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e69\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e21.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e70\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e21.5\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e71\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e22.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e72\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e22.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e73\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e23.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e74\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e23.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e75\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e24.0\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e76\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e24.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e77\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e25.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e78\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e25.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e79\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e26.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e80\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e26.5\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e81\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e27.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e82\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e27.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e83\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e28.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e84\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e28.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e85\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e29.0\u003c/span\u003e},\n        {\u003cspan class=\"hljs-number\"\u003e86\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e29.5\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e87\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e30.0\u003c/span\u003e}, {\u003cspan class=\"hljs-number\"\u003e88\u003c/span\u003e, \u003cspan class=\"hljs-number\"\u003e30.5\u003c/span\u003e}\n    };\n\n    \u003cspan class=\"hljs-comment\"\u003e// Check if the input is in the lookup table\u003c/span\u003e\n    \u003cspan class=\"hljs-keyword\"\u003eauto\u003c/span\u003e it = lookupTable.\u003cspan class=\"hljs-built_in\"\u003efind\u003c/span\u003e(\u003cspan class=\"hljs-built_in\"\u003estatic_cast\u003c/span\u003e\u0026lt;\u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e\u0026gt;(fromFahrenheit));\n    \u003cspan class=\"hljs-keyword\"\u003eif\u003c/span\u003e (it != lookupTable.\u003cspan class=\"hljs-built_in\"\u003eend\u003c/span\u003e()) {\n        \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e it-\u0026gt;second;\n    }\n\n    \u003cspan class=\"hljs-comment\"\u003e// Default conversion and rounding to nearest 0.5\u003c/span\u003e\n    \u003cspan class=\"hljs-keyword\"\u003ereturn\u003c/span\u003e \u003cspan class=\"hljs-built_in\"\u003eroundf\u003c/span\u003e((fromFahrenheit - \u003cspan class=\"hljs-number\"\u003e32.0\u003c/span\u003e) / \u003cspan class=\"hljs-number\"\u003e1.8\u003c/span\u003e * \u003cspan class=\"hljs-number\"\u003e2\u003c/span\u003e) / \u003cspan class=\"hljs-number\"\u003e2.0\u003c/span\u003e;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eHere, we can be off by as much as a 1C, which is certainly a noticeable feeling.\u003c/p\u003e\n\u003cp\u003eAt first glance, I thought this was just a misguided attempt at optimizing the lookup. For common values, do a lookup instead of calculating because it\u0026#39;s faster. Seems like the kind of mistake a hobby project might make, and definitely not a WTF. But it\u0026#39;s the comment which corrects me: \u003ccode\u003ethese are direct mappings based on the remote\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eThese remotes usually have a display. So when you see on the remote that you\u0026#39;re trying to set the temperature to a comfortable 72F, the remote is actually sending 22.5C to the unit. That\u0026#39;s the actual temperature being sent.\u003c/p\u003e\n\u003cp\u003eNow, why on Earth does the remote behave this way? Well, I haven\u0026#39;t cracked one open to read off the part numbers, but I\u0026#39;m going to go out on a limb and guess that the microcontoller in the remote doesn\u0026#39;t handle floating point operations all that well. So it almost certainly does use a lookup table to decide what signal to send, and the lookup table is populated by \u0026#34;good enough\u0026#34; approximations of temperature conversions. There aren\u0026#39;t a \u003cem\u003elot\u003c/em\u003e of places that use Fahrenheit, so being \u0026#34;close enough\u0026#34; is a reasonable solution. If you want accurate temperatures, use SI units, not \u0026#34;freedom units\u0026#34;.\u003c/p\u003e\n\u003cp\u003eIn the end, I\u0026#39;d say that neither the hobby project, nor the remote control are the WTF here; locales that insist on using weird ass units are.\u003c/p\u003e\n\u003c!-- Easy Reader Version: Rankine is, of course, the most absurd version of this: keep the Fahrenheit scaling, but anchor at absolute zero, like Kelvin, though it\u0027s also worth reading up on the both the Newton scale and the Rømer scale, because \"coming up with a canonical temperature measurement\" was a hard thing to do in the early modern period! It was cutting edge science! Weird scales were a natural reaction to trying to find reproducible conditions. --\u003e\n\u003cstyle\u003e.comment { border: none }\u003c/style\u003e\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/proget-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\tProGet’s got you covered with security and access controls on your NuGet feeds. \u003ca href=\"https://inedo.com/proget/private-nuget-server?utm_source=tdwtf\u0026amp;utm_medium=footer\u0026amp;utm_content=GotYouCoveredFooter\u0026amp;utm_campaign=Cyclops2020\"\u003eLearn more.\u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Title":"Heating Up","RssTitle":"CodeSOD: Heating Up","CachedCommentCount":36,"LastCommentDate":"\/Date(1788799589383)\/","LastCommentDateDescription":"2026-09-07","DiscourseTopicId":null,"DiscourseTopicOpened":false,"PublishedDate":"\/Date(1788417000000)\/","ISODate":"2026-09-03","DisplayDate":"2026-09-03","Series":{"Slug":"code-sod","Title":"CodeSOD","Description":"Code Snippet Of the Day (CodeSOD) features interesting and usually incorrect code snippets taken from actual production code in a commercial and/or open source software projects.","CssClass":"code"},"FooterAdHtml":"\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/proget-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\tProGet’s got you covered with security and access controls on your NuGet feeds. \u003ca href=\"https://inedo.com/proget/private-nuget-server?utm_source=tdwtf\u0026amp;utm_medium=footer\u0026amp;utm_content=GotYouCoveredFooter\u0026amp;utm_campaign=Cyclops2020\"\u003eLearn more.\u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Url":"https://thedailywtf.com/articles/heating-up","CommentsUrl":"https://thedailywtf.com/articles/comments/heating-up","Slug":"heating-up","TwitterUrl":"//www.twitter.com/home?status=https%3a%2f%2fthedailywtf.com%2farticles%2fheating-up+-+Heating+Up+-+The+Daily+WTF","FacebookUrl":"//www.facebook.com/sharer.php?u=https%3a%2f%2fthedailywtf.com%2farticles%2fheating-up\u0026t=Heating+Up+-+The+Daily+WTF","EmailUrl":"mailto:%20?subject=Check%20out%20this%20article%20on%20The%20Daily%20WTF...\u0026body=Heating%20Up:%20https://thedailywtf.com/articles/heating-up","GooglePlusUrl":"//plus.google.com/share?url=https%3a%2f%2fthedailywtf.com%2farticles%2fheating-up","PreviousArticleId":11264,"PreviousArticleTitle":"What You Measure","PreviousArticleSlug":"what-you-measure","PreviousArticleUrl":"//thedailywtf.com/articles/what-you-measure","NextArticleId":11262,"NextArticleTitle":"Good Time","NextArticleSlug":"good-time","NextArticleUrl":"//thedailywtf.com/articles/good-time"},{"Id":11264,"Author":{"Name":"Remy Porter","FirstName":"Remy","ShortDescription":"Computers were a mistake, so I accidentally became a farmer? Editor-in-Chief for TDWTF.","DescriptionHtml":"\u003cp\u003eRemy is a veteran developer who writes software for farming robots. They pick tomatoes.\u003c/p\u003e\r\n\u003cp\u003eHe\u0027s often on stage, doing improv comedy, but insists that \u003cem\u003ehe\u003c/em\u003e isn\u0027t doing comedy- it\u0027s deadly serious. You\u0027re laughing at him, not with him. That, by the way, is usually true- you\u0027re laughing at him, not with him.\u003c/p\u003e","Slug":"remy-porter","IsAdmin":true,"IsActive":true,"ImageUrl":"https://s3.amazonaws.com/remy.jetpackshark.com/remy-thumb.jpg"},"Status":"Published","SummaryHtml":"\u003cp\u003e\u003cstrong\u003eRachel\u003c/strong\u003e joined a new team which was proudly \u0026#34;metrics driven\u0026#34;. When she first met with her boss, Zane, he explained his thinking.\u003c/p\u003e\n\u003cp\u003e\u0026#34;We need to be data-driven to make good decisions, right? We\u0026#39;re a manufacturing company. We make widgets. At the end of the day, we need to make the most widgets for the lowest cost of goods sold. So we track that, and that feeds into every decision.\u0026#34;\u003c/p\u003e\n","BodyHtml":"\u003cp\u003e\u003cstrong\u003eRachel\u003c/strong\u003e joined a new team which was proudly \u0026#34;metrics driven\u0026#34;. When she first met with her boss, Zane, he explained his thinking.\u003c/p\u003e\n\u003cp\u003e\u0026#34;We need to be data-driven to make good decisions, right? We\u0026#39;re a manufacturing company. We make widgets. At the end of the day, we need to make the most widgets for the lowest cost of goods sold. So we track that, and that feeds into every decision.\u0026#34;\u003c/p\u003e\n\u003cp\u003eThe team oversaw an automated production line, which meant the software was a mix of robotics, embedded firmware, high-level web based monitoring tools, and thickets of dreaded PLC code. And because you can\u0026#39;t build an entire factory for test purposes, they only way they could test real-world scales with real-world data was to roll changes out to production. They could simulate, they could run tests on subsets of the system, but a change in the production line software couldn\u0026#39;t truly be validated until it rolled out into the real world.\u003c/p\u003e\n\u003cp\u003eRachel\u0026#39;s first task on the new team involved making some changes to their metrics dashboard. It was viewed as a good way to get her feet wet with the new team. As it turned out, the metrics dashboard was a Google Sheet, with a complex series of formulas that involved multi-level \u003ccode\u003eINDEX\u003c/code\u003e functions- essentially querying the spreadsheets like they were a database. Why not use an actual database? Oh, they did — six actually — but the company obeyed Remy\u0026#39;s Law of Requirements Gathering: \u0026#34;no matter what the requirements the users ask for, what they really wanted was Excel\u0026#34;. The database data was pulled into the spreadsheet for reporting.\u003c/p\u003e\n\u003cp\u003eNow, a complicated sheet pulling in data from not one, but six different databases, they must have a pretty complex model to explain how changes to their software would impact productivity. And since they needed to model the software to make predictions about how it\u0026#39;d behave in production, that model must be extremely useful.\u003c/p\u003e\n\u003cp\u003eOf course it wasn\u0026#39;t. The only metrics they tracked were output metrics, variations on \u0026#34;widgets produced per unit time\u0026#34;. There were some performance metrics, so you could maybe potentially identify \u0026#34;oh, our overall throughput dropped because unit 5 became a bottleneck and started taking 1.5 extra seconds per widget\u0026#34;, but nothing that actually helped you understand how the complex system made decisions. Or even \u003cem\u003ewhy\u003c/em\u003e unit 5 was taking longer.\u003c/p\u003e\n\u003cp\u003eFor example, there was an automated quality control scanner. It examined widgets as they came off the line, and rejected defective ones based on a computer vision algorithm. Did that subsystem record why it rejected a widget? No, it did not. The CV model was able to tag widgets with a defect category based on what it saw, but that information didn\u0026#39;t get recorded anywhere. In fact, it didn\u0026#39;t even record how \u003cem\u003emany\u003c/em\u003e widgets got rejected. The only way to know was to have an operator on the assembly line count widgets in the bin manually. Since that ate up a bunch of an operator\u0026#39;s time, it never happened unless the developers begged for it. And since the operator still couldn\u0026#39;t answer the question \u0026#34;why was this widget rejected\u0026#34;, it wasn\u0026#39;t all that useful anyway.\u003c/p\u003e\n\u003cp\u003eEvery change to the software was scored against the overall output metrics. This meant that when Rachel was ready to push out her first software change, something that would \u003cem\u003erecord how many widgets were rejected and why\u003c/em\u003e, whether or not it could be deployed was dependent on seeing the change improve, or at least not regress, the widgets-over-time scores. But the widgets-over-time were a noisy metric; it varied based on which operators were working any given shift, or based on supply chain constraints. Or sometimes, based on when one of the machines was last calibrated- theoretically something that happened on a set schedule, but really was up to the operators. This meant the first three times Rachel rolled her code out for a test run, the metrics regressed. Nothing she changed should have impacted the metrics, but the metrics regressed due to environmental issues.\u003c/p\u003e\n\u003cp\u003eThis meant making a simple change could take weeks, because you could only do final validation on the real system, which means you had to mark off a block of time for a test run, you could only run a handful of tests a day, and if metrics regressed you had to account for that before you could release the software for actual production use.\u003c/p\u003e\n\u003cp\u003eOver the first few months, Rachel added instrumentation to the code. Anything along the way to generating an output widget, she recorded. The hope was that once they had enough data, they could build a useful model of the system. Unfortunately, Zane had other ideas.\u003c/p\u003e\n\u003cp\u003e\u0026#34;So, you haven\u0026#39;t improved our metrics,\u0026#34; Zane said. \u0026#34;Which, I remind you, we\u0026#39;re a metrics driven organization. Every change needs to improve our metrics.\u0026#34;\u003c/p\u003e\n\u003cp\u003e\u0026#34;Sure, but I\u0026#39;m gathering more data so we have a better idea of what makes our metrics tick. We don\u0026#39;t know why our system does some of the things it does, because we don\u0026#39;t record any logging about the decisions it makes.\u0026#34;\u003c/p\u003e\n\u003cp\u003e\u0026#34;Right, but we already gather the key metrics.\u0026#34;\u003c/p\u003e\n\u003cp\u003e\u0026#34;But you don\u0026#39;t gather the data that tells you why those metrics are what they are!\u0026#34;\u003c/p\u003e\n\u003cp\u003e\u0026#34;Sure,\u0026#34; Zane said. \u0026#34;But those aren\u0026#39;t our key metrics.\u0026#34;\u003c/p\u003e\n\u003cp\u003eThat, unfortunately for Rachel, was where things landed. Understanding their complex system was a low priority. Pushing top-level metrics without understanding what fed into them, that was the priority. That didn\u0026#39;t mean Rachel was powerless: any time she made a change that she thought might help the top level metrics, she also made sure to add instrumentation that explained how that change behaved. It was the compromise that kept Zane happy: she released features that impacted the top-level metrics, but she also made the system more observable.\u003c/p\u003e","BodyAndAdHtml":"\u003cp\u003e\u003cstrong\u003eRachel\u003c/strong\u003e joined a new team which was proudly \u0026#34;metrics driven\u0026#34;. When she first met with her boss, Zane, he explained his thinking.\u003c/p\u003e\n\u003cp\u003e\u0026#34;We need to be data-driven to make good decisions, right? We\u0026#39;re a manufacturing company. We make widgets. At the end of the day, we need to make the most widgets for the lowest cost of goods sold. So we track that, and that feeds into every decision.\u0026#34;\u003c/p\u003e\n\u003cp\u003eThe team oversaw an automated production line, which meant the software was a mix of robotics, embedded firmware, high-level web based monitoring tools, and thickets of dreaded PLC code. And because you can\u0026#39;t build an entire factory for test purposes, they only way they could test real-world scales with real-world data was to roll changes out to production. They could simulate, they could run tests on subsets of the system, but a change in the production line software couldn\u0026#39;t truly be validated until it rolled out into the real world.\u003c/p\u003e\n\u003cp\u003eRachel\u0026#39;s first task on the new team involved making some changes to their metrics dashboard. It was viewed as a good way to get her feet wet with the new team. As it turned out, the metrics dashboard was a Google Sheet, with a complex series of formulas that involved multi-level \u003ccode\u003eINDEX\u003c/code\u003e functions- essentially querying the spreadsheets like they were a database. Why not use an actual database? Oh, they did — six actually — but the company obeyed Remy\u0026#39;s Law of Requirements Gathering: \u0026#34;no matter what the requirements the users ask for, what they really wanted was Excel\u0026#34;. The database data was pulled into the spreadsheet for reporting.\u003c/p\u003e\n\u003cp\u003eNow, a complicated sheet pulling in data from not one, but six different databases, they must have a pretty complex model to explain how changes to their software would impact productivity. And since they needed to model the software to make predictions about how it\u0026#39;d behave in production, that model must be extremely useful.\u003c/p\u003e\n\u003cp\u003eOf course it wasn\u0026#39;t. The only metrics they tracked were output metrics, variations on \u0026#34;widgets produced per unit time\u0026#34;. There were some performance metrics, so you could maybe potentially identify \u0026#34;oh, our overall throughput dropped because unit 5 became a bottleneck and started taking 1.5 extra seconds per widget\u0026#34;, but nothing that actually helped you understand how the complex system made decisions. Or even \u003cem\u003ewhy\u003c/em\u003e unit 5 was taking longer.\u003c/p\u003e\n\u003cp\u003eFor example, there was an automated quality control scanner. It examined widgets as they came off the line, and rejected defective ones based on a computer vision algorithm. Did that subsystem record why it rejected a widget? No, it did not. The CV model was able to tag widgets with a defect category based on what it saw, but that information didn\u0026#39;t get recorded anywhere. In fact, it didn\u0026#39;t even record how \u003cem\u003emany\u003c/em\u003e widgets got rejected. The only way to know was to have an operator on the assembly line count widgets in the bin manually. Since that ate up a bunch of an operator\u0026#39;s time, it never happened unless the developers begged for it. And since the operator still couldn\u0026#39;t answer the question \u0026#34;why was this widget rejected\u0026#34;, it wasn\u0026#39;t all that useful anyway.\u003c/p\u003e\n\u003cp\u003eEvery change to the software was scored against the overall output metrics. This meant that when Rachel was ready to push out her first software change, something that would \u003cem\u003erecord how many widgets were rejected and why\u003c/em\u003e, whether or not it could be deployed was dependent on seeing the change improve, or at least not regress, the widgets-over-time scores. But the widgets-over-time were a noisy metric; it varied based on which operators were working any given shift, or based on supply chain constraints. Or sometimes, based on when one of the machines was last calibrated- theoretically something that happened on a set schedule, but really was up to the operators. This meant the first three times Rachel rolled her code out for a test run, the metrics regressed. Nothing she changed should have impacted the metrics, but the metrics regressed due to environmental issues.\u003c/p\u003e\n\u003cp\u003eThis meant making a simple change could take weeks, because you could only do final validation on the real system, which means you had to mark off a block of time for a test run, you could only run a handful of tests a day, and if metrics regressed you had to account for that before you could release the software for actual production use.\u003c/p\u003e\n\u003cp\u003eOver the first few months, Rachel added instrumentation to the code. Anything along the way to generating an output widget, she recorded. The hope was that once they had enough data, they could build a useful model of the system. Unfortunately, Zane had other ideas.\u003c/p\u003e\n\u003cp\u003e\u0026#34;So, you haven\u0026#39;t improved our metrics,\u0026#34; Zane said. \u0026#34;Which, I remind you, we\u0026#39;re a metrics driven organization. Every change needs to improve our metrics.\u0026#34;\u003c/p\u003e\n\u003cp\u003e\u0026#34;Sure, but I\u0026#39;m gathering more data so we have a better idea of what makes our metrics tick. We don\u0026#39;t know why our system does some of the things it does, because we don\u0026#39;t record any logging about the decisions it makes.\u0026#34;\u003c/p\u003e\n\u003cp\u003e\u0026#34;Right, but we already gather the key metrics.\u0026#34;\u003c/p\u003e\n\u003cp\u003e\u0026#34;But you don\u0026#39;t gather the data that tells you why those metrics are what they are!\u0026#34;\u003c/p\u003e\n\u003cp\u003e\u0026#34;Sure,\u0026#34; Zane said. \u0026#34;But those aren\u0026#39;t our key metrics.\u0026#34;\u003c/p\u003e\n\u003cp\u003eThat, unfortunately for Rachel, was where things landed. Understanding their complex system was a low priority. Pushing top-level metrics without understanding what fed into them, that was the priority. That didn\u0026#39;t mean Rachel was powerless: any time she made a change that she thought might help the top level metrics, she also made sure to add instrumentation that explained how that change behaved. It was the compromise that kept Zane happy: she released features that impacted the top-level metrics, but she also made the system more observable.\u003c/p\u003e\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/buildmaster-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\t\u003ca href=\"https://inedo.com/BuildMaster?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eBuildMaster\u003c/a\u003e allows you to create a self-service release management platform that allows different teams to manage their applications. \u003ca href=\"https://inedo.com/BuildMaster/download?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eExplore how!\u003c/a\u003e \n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Title":"What You Measure","RssTitle":"What You Measure","CachedCommentCount":27,"LastCommentDate":"\/Date(1788768409600)\/","LastCommentDateDescription":"2026-09-07","DiscourseTopicId":null,"DiscourseTopicOpened":false,"PublishedDate":"\/Date(1788330600000)\/","ISODate":"2026-09-02","DisplayDate":"2026-09-02","Series":{"Slug":"feature-articles","Title":"Feature Articles","Description":"","CssClass":"featured"},"FooterAdHtml":"\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/buildmaster-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\t\u003ca href=\"https://inedo.com/BuildMaster?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eBuildMaster\u003c/a\u003e allows you to create a self-service release management platform that allows different teams to manage their applications. \u003ca href=\"https://inedo.com/BuildMaster/download?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eExplore how!\u003c/a\u003e \n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Url":"https://thedailywtf.com/articles/what-you-measure","CommentsUrl":"https://thedailywtf.com/articles/comments/what-you-measure","Slug":"what-you-measure","TwitterUrl":"//www.twitter.com/home?status=https%3a%2f%2fthedailywtf.com%2farticles%2fwhat-you-measure+-+What+You+Measure+-+The+Daily+WTF","FacebookUrl":"//www.facebook.com/sharer.php?u=https%3a%2f%2fthedailywtf.com%2farticles%2fwhat-you-measure\u0026t=What+You+Measure+-+The+Daily+WTF","EmailUrl":"mailto:%20?subject=Check%20out%20this%20article%20on%20The%20Daily%20WTF...\u0026body=What%20You%20Measure:%20https://thedailywtf.com/articles/what-you-measure","GooglePlusUrl":"//plus.google.com/share?url=https%3a%2f%2fthedailywtf.com%2farticles%2fwhat-you-measure","PreviousArticleId":11263,"PreviousArticleTitle":"So Much Room","PreviousArticleSlug":"so-much-room","PreviousArticleUrl":"//thedailywtf.com/articles/so-much-room","NextArticleId":11265,"NextArticleTitle":"Heating Up","NextArticleSlug":"heating-up","NextArticleUrl":"//thedailywtf.com/articles/heating-up"},{"Id":11263,"Author":{"Name":"Remy Porter","FirstName":"Remy","ShortDescription":"Computers were a mistake, so I accidentally became a farmer? Editor-in-Chief for TDWTF.","DescriptionHtml":"\u003cp\u003eRemy is a veteran developer who writes software for farming robots. They pick tomatoes.\u003c/p\u003e\r\n\u003cp\u003eHe\u0027s often on stage, doing improv comedy, but insists that \u003cem\u003ehe\u003c/em\u003e isn\u0027t doing comedy- it\u0027s deadly serious. You\u0027re laughing at him, not with him. That, by the way, is usually true- you\u0027re laughing at him, not with him.\u003c/p\u003e","Slug":"remy-porter","IsAdmin":true,"IsActive":true,"ImageUrl":"https://s3.amazonaws.com/remy.jetpackshark.com/remy-thumb.jpg"},"Status":"Published","SummaryHtml":"\u003cp\u003eToday\u0026#39;s representative comment ran out of room.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-java\"\u003e\u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e \u003cspan class=\"hljs-variable\"\u003emaxLen\u003c/span\u003e \u003cspan class=\"hljs-operator\"\u003e=\u003c/span\u003e getColumnSize(session, \u003cspan class=\"hljs-string\"\u003e\u0026#34;audit\u0026#34;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#34;text_value1\u0026#34;\u003c/span\u003e) - \u003cspan class=\"hljs-number\"\u003e16\u003c/span\u003e; \u003cspan class=\"hljs-comment\"\u003e// Leave some room for\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n","BodyHtml":"\u003cp\u003eToday\u0026#39;s representative comment ran out of room.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-java\"\u003e\u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e \u003cspan class=\"hljs-variable\"\u003emaxLen\u003c/span\u003e \u003cspan class=\"hljs-operator\"\u003e=\u003c/span\u003e getColumnSize(session, \u003cspan class=\"hljs-string\"\u003e\u0026#34;audit\u0026#34;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#34;text_value1\u0026#34;\u003c/span\u003e) - \u003cspan class=\"hljs-number\"\u003e16\u003c/span\u003e; \u003cspan class=\"hljs-comment\"\u003e// Leave some room for\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNo, it isn\u0026#39;t continued on the next line and just got trimmed out, except perhaps by a careless merge. This is the entire comment.\u003c/p\u003e\n\u003cp\u003eClearly, written by David Chase, the creator of \u0026#34;The Sopranos\u0026#34;.\u003c/p\u003e\n\u003cp\u003eThere are so many things we might be leaving room for. We could leave some room for dessert. Leave some room for activities. Leave some room for the holy spirit. Leave some room for improvisation.\u003c/p\u003e\n\u003c!-- Easy Reader Version: Leave some room for comments --\u003e","BodyAndAdHtml":"\u003cp\u003eToday\u0026#39;s representative comment ran out of room.\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-java\"\u003e\u003cspan class=\"hljs-type\"\u003eint\u003c/span\u003e \u003cspan class=\"hljs-variable\"\u003emaxLen\u003c/span\u003e \u003cspan class=\"hljs-operator\"\u003e=\u003c/span\u003e getColumnSize(session, \u003cspan class=\"hljs-string\"\u003e\u0026#34;audit\u0026#34;\u003c/span\u003e, \u003cspan class=\"hljs-string\"\u003e\u0026#34;text_value1\u0026#34;\u003c/span\u003e) - \u003cspan class=\"hljs-number\"\u003e16\u003c/span\u003e; \u003cspan class=\"hljs-comment\"\u003e// Leave some room for\u003c/span\u003e\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNo, it isn\u0026#39;t continued on the next line and just got trimmed out, except perhaps by a careless merge. This is the entire comment.\u003c/p\u003e\n\u003cp\u003eClearly, written by David Chase, the creator of \u0026#34;The Sopranos\u0026#34;.\u003c/p\u003e\n\u003cp\u003eThere are so many things we might be leaving room for. We could leave some room for dessert. Leave some room for activities. Leave some room for the holy spirit. Leave some room for improvisation.\u003c/p\u003e\n\u003c!-- Easy Reader Version: Leave some room for comments --\u003e\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/proget-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\tProGet’s got you covered with security and access controls on your NuGet feeds. \u003ca href=\"https://inedo.com/proget/private-nuget-server?utm_source=tdwtf\u0026amp;utm_medium=footer\u0026amp;utm_content=GotYouCoveredFooter\u0026amp;utm_campaign=Cyclops2020\"\u003eLearn more.\u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Title":"So Much Room","RssTitle":"Representative Line: So Much Room","CachedCommentCount":22,"LastCommentDate":"\/Date(1788515776167)\/","LastCommentDateDescription":"2026-09-04","DiscourseTopicId":null,"DiscourseTopicOpened":false,"PublishedDate":"\/Date(1788244200000)\/","ISODate":"2026-09-01","DisplayDate":"2026-09-01","Series":{"Slug":"representative-line","Title":"Representative Line","Description":"A single line of code from a large application that somehow manages to provide an almost endless insight into the pain that its maintainers face each day.","CssClass":"soapbox"},"FooterAdHtml":"\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/proget-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\tProGet’s got you covered with security and access controls on your NuGet feeds. \u003ca href=\"https://inedo.com/proget/private-nuget-server?utm_source=tdwtf\u0026amp;utm_medium=footer\u0026amp;utm_content=GotYouCoveredFooter\u0026amp;utm_campaign=Cyclops2020\"\u003eLearn more.\u003c/a\u003e\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Url":"https://thedailywtf.com/articles/so-much-room","CommentsUrl":"https://thedailywtf.com/articles/comments/so-much-room","Slug":"so-much-room","TwitterUrl":"//www.twitter.com/home?status=https%3a%2f%2fthedailywtf.com%2farticles%2fso-much-room+-+So+Much+Room+-+The+Daily+WTF","FacebookUrl":"//www.facebook.com/sharer.php?u=https%3a%2f%2fthedailywtf.com%2farticles%2fso-much-room\u0026t=So+Much+Room+-+The+Daily+WTF","EmailUrl":"mailto:%20?subject=Check%20out%20this%20article%20on%20The%20Daily%20WTF...\u0026body=So%20Much%20Room:%20https://thedailywtf.com/articles/so-much-room","GooglePlusUrl":"//plus.google.com/share?url=https%3a%2f%2fthedailywtf.com%2farticles%2fso-much-room","PreviousArticleId":11261,"PreviousArticleTitle":"Tales from the World Cup","PreviousArticleSlug":"tales-from-the-world-cup","PreviousArticleUrl":"//thedailywtf.com/articles/tales-from-the-world-cup","NextArticleId":11264,"NextArticleTitle":"What You Measure","NextArticleSlug":"what-you-measure","NextArticleUrl":"//thedailywtf.com/articles/what-you-measure"},{"Id":11261,"Author":{"Name":"Ellis Morning","FirstName":"Ellis","ShortDescription":null,"DescriptionHtml":"\u003cb\u003eEllis Morning\u003c/b\u003e is a Computer Science graduate who fought in the trenches of Tech Support, occasionally crossing enemy lines into the Business Analyst and Project Management spheres of war. She\u0027s now a freelance writer and technical writer. Check out her highly-rated \u003ca href=\"https://swordandstarship.com/\" target=\"_blank\"\u003esci-fi/fantasy novels\u003c/a\u003e and find more humor, fiction, and blog posts at her \u003ca href=\"https://www.ellismorning.com\" target=\"_blank\"\u003ewebsite\u003c/a\u003e.","Slug":"ellis-morning","IsAdmin":true,"IsActive":true,"ImageUrl":"https://ellismorning.com/img/ellis2.jpeg"},"Status":"Published","SummaryHtml":"\u003cp\u003eAll I can say in response to our \u003cb\u003eanonymous\u003c/b\u003e submitter\u0026#39;s story is, ALMOST?!\u003c/p\u003e\n\n\u003cblockquote\u003e\n\u003cp\u003eWith the World Cup being hosted in North America this year, I remembered this story that happened back in 2014. At the time I was working in Brazil, for a company that builds software systems for public services. And, with the World Cup being hosted there, in came the opportunity for local agencies to invest in modernization, with pretty much a blank check to get new services, so long as it was deployed before the end of the World Cup. And so the sales people did what they did best, and went around trying to upsell whoever would be willing to buy — no matter our actual capacity for developing the things.\u003c/p\u003e\n\n\u003c/blockquote\u003e","BodyHtml":"\u003cp\u003eAll I can say in response to our \u003cb\u003eanonymous\u003c/b\u003e submitter\u0026#39;s story is, ALMOST?!\u003c/p\u003e\n\n\u003cblockquote\u003e\n\u003cp\u003eWith the World Cup being hosted in North America this year, I remembered this story that happened back in 2014. At the time I was working in Brazil, for a company that builds software systems for public services. And, with the World Cup being hosted there, in came the opportunity for local agencies to invest in modernization, with pretty much a blank check to get new services, so long as it was deployed before the end of the World Cup. And so the sales people did what they did best, and went around trying to upsell whoever would be willing to buy — no matter our actual capacity for developing the things.\u003c/p\u003e\n\n\u003cp\u003eSo it was that I was pulled into this new fancy digital system for the police force of a state capital. However, we had only about 4 engineers available, and what they sold was a project estimated for a team of 20, to be delivered in 3 months, with no room for delay. And it wasn\u0026#39;t just our core C\u0026amp;D product, but this massive thing with customized public-facing websites, live tracking of the position of different police cars delivered to a tablet in each car, automated reporting, etc.\u003c/p\u003e\n\n\u003cp style=\"float:right; padding-left:10px; padding-bottom:10px;\"\u003e\u003ca title=\"Danilo Borges/copa2014.gov.br  LicenÃ§a Creative Commons AtribuiÃ§Ã£o 3.0 Brasil, CC BY 3.0 \u0026lt;https://creativecommons.org/licenses/by/3.0\u0026gt;, via Wikimedia Commons\" href=\"https://commons.wikimedia.org/wiki/File:Germany_and_Argentina_face_off_in_the_final_of_the_World_Cup_2014_-2014-07-13_(5).jpg\"\u003e\u003cimg itemprop=\"image\" width=\"300\" alt=\"Germany and Argentina face off in the final of the World Cup 2014 -2014-07-13 (5)\" src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Germany_and_Argentina_face_off_in_the_final_of_the_World_Cup_2014_-2014-07-13_%285%29.jpg/330px-Germany_and_Argentina_face_off_in_the_final_of_the_World_Cup_2014_-2014-07-13_%285%29.jpg?utm_source=commons.wikimedia.org\u0026amp;utm_campaign=index\u0026amp;utm_content=thumbnail\"/\u003e\u003c/a\u003e\u003c/p\u003e\n\n\u003cp\u003eFirst thing: We received a pile of 24 resumes, and were told to choose 16 of those. Maybe 3 were acceptable, but we had to waste 1 month hiring and onboarding 13 other people who were worse than useless. Classic man-month problem. We eventually had to tell management that nothing would be delivered this way, so they did the very best next thing: fly us to this other city, so we could work embedded there, in full crunch mode for the delivery. We pretty much worked 12+ hours a day, 7 days a week, for those next 2 weeks.\u003c/p\u003e\n\n\u003cp\u003eAnother situation: they wanted this system where people could take a photo of an incident in progress, and submit via this app + website, to be verified by an operator in real-time. We nicknamed it the \u0026#34;dick-pic encyclopedia.\u0026#34; Even worse, we only had the budget to run a single server, so this thing receiving public traffic would live in the same system that was tracking police car locations. Luckily they were convinced it was a bad idea so it was only ever online for a short period of time.\u003c/p\u003e\n\n\u003cp\u003eNext, was the police car tracking. This was done by a tablet installed in each car, which would be sending and receiving location information. But, 1 week before our deadline, we were hitting a serious bug: everything was working when we ran the tests ourselves, but the cops would report very weird bugs when testing it in the field. So we asked to do some field debugging, and I went on a ride-along. Things were working pretty much fine everywhere, so I asked to be taken to where he remembered seeing the tablets fail—to which the policeman just decides to drive off straight into one of the favelas around the city. I guess I can cross out \u0026#34;doing debugging in a police car passenger seat in a notoriously dangerous neighborhood\u0026#34; off my bucket list. Root cause: turns out cellphone connections would be pretty spotty in those areas, which we weren\u0026#39;t handling properly.\u003c/p\u003e\n\n\u003cp\u003eEither way, we delivered something on time that was severely below spec, and very much over-budget. Company tried to squirm out of paying overtime (was told that we would gain \u0026#34;prestige\u0026#34; by doing those extra hours), but I put my foot down and left that job shortly after. Last I heard they actually got sued for this and a bunch of similar projects, and almost went under.\u003c/p\u003e\n\u003c/blockquote\u003e","BodyAndAdHtml":"\u003cp\u003eAll I can say in response to our \u003cb\u003eanonymous\u003c/b\u003e submitter\u0026#39;s story is, ALMOST?!\u003c/p\u003e\n\n\u003cblockquote\u003e\n\u003cp\u003eWith the World Cup being hosted in North America this year, I remembered this story that happened back in 2014. At the time I was working in Brazil, for a company that builds software systems for public services. And, with the World Cup being hosted there, in came the opportunity for local agencies to invest in modernization, with pretty much a blank check to get new services, so long as it was deployed before the end of the World Cup. And so the sales people did what they did best, and went around trying to upsell whoever would be willing to buy — no matter our actual capacity for developing the things.\u003c/p\u003e\n\n\u003cp\u003eSo it was that I was pulled into this new fancy digital system for the police force of a state capital. However, we had only about 4 engineers available, and what they sold was a project estimated for a team of 20, to be delivered in 3 months, with no room for delay. And it wasn\u0026#39;t just our core C\u0026amp;D product, but this massive thing with customized public-facing websites, live tracking of the position of different police cars delivered to a tablet in each car, automated reporting, etc.\u003c/p\u003e\n\n\u003cp style=\"float:right; padding-left:10px; padding-bottom:10px;\"\u003e\u003ca title=\"Danilo Borges/copa2014.gov.br  LicenÃ§a Creative Commons AtribuiÃ§Ã£o 3.0 Brasil, CC BY 3.0 \u0026lt;https://creativecommons.org/licenses/by/3.0\u0026gt;, via Wikimedia Commons\" href=\"https://commons.wikimedia.org/wiki/File:Germany_and_Argentina_face_off_in_the_final_of_the_World_Cup_2014_-2014-07-13_(5).jpg\"\u003e\u003cimg itemprop=\"image\" width=\"300\" alt=\"Germany and Argentina face off in the final of the World Cup 2014 -2014-07-13 (5)\" src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/8/89/Germany_and_Argentina_face_off_in_the_final_of_the_World_Cup_2014_-2014-07-13_%285%29.jpg/330px-Germany_and_Argentina_face_off_in_the_final_of_the_World_Cup_2014_-2014-07-13_%285%29.jpg?utm_source=commons.wikimedia.org\u0026amp;utm_campaign=index\u0026amp;utm_content=thumbnail\"/\u003e\u003c/a\u003e\u003c/p\u003e\n\n\u003cp\u003eFirst thing: We received a pile of 24 resumes, and were told to choose 16 of those. Maybe 3 were acceptable, but we had to waste 1 month hiring and onboarding 13 other people who were worse than useless. Classic man-month problem. We eventually had to tell management that nothing would be delivered this way, so they did the very best next thing: fly us to this other city, so we could work embedded there, in full crunch mode for the delivery. We pretty much worked 12+ hours a day, 7 days a week, for those next 2 weeks.\u003c/p\u003e\n\n\u003cp\u003eAnother situation: they wanted this system where people could take a photo of an incident in progress, and submit via this app + website, to be verified by an operator in real-time. We nicknamed it the \u0026#34;dick-pic encyclopedia.\u0026#34; Even worse, we only had the budget to run a single server, so this thing receiving public traffic would live in the same system that was tracking police car locations. Luckily they were convinced it was a bad idea so it was only ever online for a short period of time.\u003c/p\u003e\n\n\u003cp\u003eNext, was the police car tracking. This was done by a tablet installed in each car, which would be sending and receiving location information. But, 1 week before our deadline, we were hitting a serious bug: everything was working when we ran the tests ourselves, but the cops would report very weird bugs when testing it in the field. So we asked to do some field debugging, and I went on a ride-along. Things were working pretty much fine everywhere, so I asked to be taken to where he remembered seeing the tablets fail—to which the policeman just decides to drive off straight into one of the favelas around the city. I guess I can cross out \u0026#34;doing debugging in a police car passenger seat in a notoriously dangerous neighborhood\u0026#34; off my bucket list. Root cause: turns out cellphone connections would be pretty spotty in those areas, which we weren\u0026#39;t handling properly.\u003c/p\u003e\n\n\u003cp\u003eEither way, we delivered something on time that was severely below spec, and very much over-budget. Company tried to squirm out of paying overtime (was told that we would gain \u0026#34;prestige\u0026#34; by doing those extra hours), but I put my foot down and left that job shortly after. Last I heard they actually got sued for this and a bunch of similar projects, and almost went under.\u003c/p\u003e\n\u003c/blockquote\u003e\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/buildmaster-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\t\u003ca href=\"https://inedo.com/BuildMaster?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eBuildMaster\u003c/a\u003e allows you to create a self-service release management platform that allows different teams to manage their applications. \u003ca href=\"https://inedo.com/BuildMaster/download?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eExplore how!\u003c/a\u003e \n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Title":"Tales from the World Cup","RssTitle":"Tales from the World Cup","CachedCommentCount":7,"LastCommentDate":"\/Date(1788245597167)\/","LastCommentDateDescription":"2026-09-01","DiscourseTopicId":null,"DiscourseTopicOpened":false,"PublishedDate":"\/Date(1788157800000)\/","ISODate":"2026-08-31","DisplayDate":"2026-08-31","Series":{"Slug":"feature-articles","Title":"Feature Articles","Description":"","CssClass":"featured"},"FooterAdHtml":"\u003cdiv\u003e\n\t\u003cimg src=\"https://thedailywtf.com/images/inedo/buildmaster-icon.png\" style=\"display:block; float: left; margin: 0 10px 10px 0;\"/\u003e [Advertisement] \n\t\u003ca href=\"https://inedo.com/BuildMaster?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eBuildMaster\u003c/a\u003e allows you to create a self-service release management platform that allows different teams to manage their applications. \u003ca href=\"https://inedo.com/BuildMaster/download?utm_source=tdwtf\u0026amp;utm_medium=footerad\u0026amp;utm_term=2018\u0026amp;utm_content=Self_Service\u0026amp;utm_campaign=Buildmaster_Footer\"\u003eExplore how!\u003c/a\u003e \n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e\n","Url":"https://thedailywtf.com/articles/tales-from-the-world-cup","CommentsUrl":"https://thedailywtf.com/articles/comments/tales-from-the-world-cup","Slug":"tales-from-the-world-cup","TwitterUrl":"//www.twitter.com/home?status=https%3a%2f%2fthedailywtf.com%2farticles%2ftales-from-the-world-cup+-+Tales+from+the+World+Cup+-+The+Daily+WTF","FacebookUrl":"//www.facebook.com/sharer.php?u=https%3a%2f%2fthedailywtf.com%2farticles%2ftales-from-the-world-cup\u0026t=Tales+from+the+World+Cup+-+The+Daily+WTF","EmailUrl":"mailto:%20?subject=Check%20out%20this%20article%20on%20The%20Daily%20WTF...\u0026body=Tales%20from%20the%20World%20Cup:%20https://thedailywtf.com/articles/tales-from-the-world-cup","GooglePlusUrl":"//plus.google.com/share?url=https%3a%2f%2fthedailywtf.com%2farticles%2ftales-from-the-world-cup","PreviousArticleId":11260,"PreviousArticleTitle":"Hello, New Mexico!","PreviousArticleSlug":"hello-new-mexico","PreviousArticleUrl":"//thedailywtf.com/articles/hello-new-mexico","NextArticleId":11263,"NextArticleTitle":"So Much Room","NextArticleSlug":"so-much-room","NextArticleUrl":"//thedailywtf.com/articles/so-much-room"},{"Id":11260,"Author":{"Name":"Lyle Seaman","FirstName":"Lyle","ShortDescription":"networking, security infra and filesystems kernel hacker turned application programmer, SRE and engineering manager, Lyle traded tilting at windmills for viking at Vikings but couldn\u0027t catch any.","DescriptionHtml":null,"Slug":"lyle-seaman","IsAdmin":true,"IsActive":true,"ImageUrl":"/images/imageslws/viking.jpg"},"Status":"Published","SummaryHtml":"\u003cp\u003e\n\u003cstrong\u003ePeter G.\u003c/strong\u003e shared with us yet another ordering bungled example of.\n\u0026#34;Should really say \u0026#34;please engage in an Easter egg hunt\nto find your language\u0026#34;.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#3ccdf44218264528b28550518f7d6aea\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"3ccdf44218264528b28550518f7d6aea\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/3ccdf44218264528b28550518f7d6aea.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003c/blockquote\u003e","BodyHtml":"\u003cp\u003e\n\u003cstrong\u003ePeter G.\u003c/strong\u003e shared with us yet another ordering bungled example of.\n\u0026#34;Should really say \u0026#34;please engage in an Easter egg hunt\nto find your language\u0026#34;.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#3ccdf44218264528b28550518f7d6aea\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"3ccdf44218264528b28550518f7d6aea\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/3ccdf44218264528b28550518f7d6aea.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\u0026#34;Google can\u0026#39;t count\u0026#34; claimed \n\u003cstrong\u003ePeter S.\u003c/strong\u003e.  It adds up.\n\u0026#34;Yet another proof that 0=1, this time from Google.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#2d284d0f696d48669a9c59251ecf9bc0\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"2d284d0f696d48669a9c59251ecf9bc0\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/2d284d0f696d48669a9c59251ecf9bc0.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\n\u003cp\u003e\u0026#34;Thanks, Microsoft\u0026#34; groused \n\u003cstrong\u003eIvan\u003c/strong\u003e\n\u0026#34;Ever since Microsoft ate university e-mail services worldwide and became\nresponsible for major free software mailing lists, quality of service\nhas been steadily dropping. In order to report delivery problems\nto Outlook, you need a Microsoft account. You\u0026#39;re prevented from\ncreating it at first because of \u0026#34;suspicious activity\u0026#34;. Once you\u0026#39;re\nin, the contact address is pre-filled for you with an\ninvalid email. Once you fix that in the web developer\ntoolbar, fuck you anyway! I think the form isn\u0026#39;t actually\nexpected to work; the fact that the request was submitted\nis an error. The only thing missing from the experience\nis the \u0026#34;beware of the leopard\u0026#34; sign.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#ae9ba09cc9474a2f89b8358201b0419a\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"ae9ba09cc9474a2f89b8358201b0419a\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/ae9ba09cc9474a2f89b8358201b0419a.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\u0026#34;Mango Math\u0026#34; needs a bit of money math for the rest of the world to understand.\n\u003cstrong\u003eMichael R.\u003c/strong\u003e muttered \n\u0026#34;I will buy it by the slice then.\u0026#34; The joke here is on the tip of my tongue.  Explainer: the new pence is one hundredth of the decimal pound. No shillings no more, decreps! At that ratio, 3p per slice of cheesecake would indeed be far less dear than four pounds for the whole thing, barring translucent slices. Alas, the reality is simply the boring fact that the price is 3p per gram.  Not as funny but I\u0026#39;m chuckling imagining Michael\u0026#39;s transparent serving of diet cheesecake. I\u0026#39;ll leave it up to you to decide if a gram really counts as an \u0026#34;item\u0026#34;. \n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#bd6d8a538f7a45b2a81f8b52d425b180\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"bd6d8a538f7a45b2a81f8b52d425b180\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/bd6d8a538f7a45b2a81f8b52d425b180.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\n\u003cstrong\u003eClint\u003c/strong\u003e clucked \n\u0026#34;Got this email from Bigbadtoystore. Lots of links available for\npreorder!\u0026#34; I think the talented website builders behind the New Mexico DOT have been busy.\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#d7efd5aabe754173a54fccb84c60b942\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"d7efd5aabe754173a54fccb84c60b942\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/d7efd5aabe754173a54fccb84c60b942.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n","BodyAndAdHtml":"\u003cp\u003e\n\u003cstrong\u003ePeter G.\u003c/strong\u003e shared with us yet another ordering bungled example of.\n\u0026#34;Should really say \u0026#34;please engage in an Easter egg hunt\nto find your language\u0026#34;.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#3ccdf44218264528b28550518f7d6aea\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"3ccdf44218264528b28550518f7d6aea\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/3ccdf44218264528b28550518f7d6aea.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\u0026#34;Google can\u0026#39;t count\u0026#34; claimed \n\u003cstrong\u003ePeter S.\u003c/strong\u003e.  It adds up.\n\u0026#34;Yet another proof that 0=1, this time from Google.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#2d284d0f696d48669a9c59251ecf9bc0\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"2d284d0f696d48669a9c59251ecf9bc0\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/2d284d0f696d48669a9c59251ecf9bc0.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\n\u003cp\u003e\u0026#34;Thanks, Microsoft\u0026#34; groused \n\u003cstrong\u003eIvan\u003c/strong\u003e\n\u0026#34;Ever since Microsoft ate university e-mail services worldwide and became\nresponsible for major free software mailing lists, quality of service\nhas been steadily dropping. In order to report delivery problems\nto Outlook, you need a Microsoft account. You\u0026#39;re prevented from\ncreating it at first because of \u0026#34;suspicious activity\u0026#34;. Once you\u0026#39;re\nin, the contact address is pre-filled for you with an\ninvalid email. Once you fix that in the web developer\ntoolbar, fuck you anyway! I think the form isn\u0026#39;t actually\nexpected to work; the fact that the request was submitted\nis an error. The only thing missing from the experience\nis the \u0026#34;beware of the leopard\u0026#34; sign.\u0026#34;\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#ae9ba09cc9474a2f89b8358201b0419a\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"ae9ba09cc9474a2f89b8358201b0419a\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/ae9ba09cc9474a2f89b8358201b0419a.png\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\u0026#34;Mango Math\u0026#34; needs a bit of money math for the rest of the world to understand.\n\u003cstrong\u003eMichael R.\u003c/strong\u003e muttered \n\u0026#34;I will buy it by the slice then.\u0026#34; The joke here is on the tip of my tongue.  Explainer: the new pence is one hundredth of the decimal pound. No shillings no more, decreps! At that ratio, 3p per slice of cheesecake would indeed be far less dear than four pounds for the whole thing, barring translucent slices. Alas, the reality is simply the boring fact that the price is 3p per gram.  Not as funny but I\u0026#39;m chuckling imagining Michael\u0026#39;s transparent serving of diet cheesecake. I\u0026#39;ll leave it up to you to decide if a gram really counts as an \u0026#34;item\u0026#34;. \n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#bd6d8a538f7a45b2a81f8b52d425b180\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"bd6d8a538f7a45b2a81f8b52d425b180\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/bd6d8a538f7a45b2a81f8b52d425b180.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\n\u003cp\u003e\n\u003cstrong\u003eClint\u003c/strong\u003e clucked \n\u0026#34;Got this email from Bigbadtoystore. Lots of links available for\npreorder!\u0026#34; I think the talented website builders behind the New Mexico DOT have been busy.\n\u003c/p\u003e\u003cblockquote\u003e\u003cp\u003e\u003ca href=\"#d7efd5aabe754173a54fccb84c60b942\"\u003e\u003cimg itemprop=\"image\" border=\"0\" alt=\"d7efd5aabe754173a54fccb84c60b942\" src=\"https://d3hvi6t161kfmf.cloudfront.net/images/2026/08/27/d7efd5aabe754173a54fccb84c60b942.jpeg\"/\u003e\u003c/a\u003e\u003c/p\u003e\u003cp\u003e \u003c/p\u003e\u003c/blockquote\u003e\n\n\u003cdiv\u003e\n\t[Advertisement] Picking up \u003cb\u003eNuGet\u003c/b\u003e is easy. Getting good at it takes time. \u003ca href=\"https://inedo.com/support/whitepapers/nuget-guide?utm_source=tdwtf\u0026amp;utm_medium=Footerad\u0026amp;utm_campaign=nuget\"\u003eDownload our guide to learn the best practice of NuGet for the Enterprise.\u003c/a\u003e\n\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e","Title":"Hello, New Mexico!","RssTitle":"Error\u0027d: Hello, New Mexico!","CachedCommentCount":26,"LastCommentDate":"\/Date(1788262058847)\/","LastCommentDateDescription":"2026-09-01","DiscourseTopicId":null,"DiscourseTopicOpened":false,"PublishedDate":"\/Date(1787898600000)\/","ISODate":"2026-08-28","DisplayDate":"2026-08-28","Series":{"Slug":"errord","Title":"Error\u0027d","Description":"Error\u0027d features fun error messages and other visual oddities from the world of IT.","CssClass":"errord"},"FooterAdHtml":"\u003cdiv\u003e\n\t[Advertisement] Picking up \u003cb\u003eNuGet\u003c/b\u003e is easy. Getting good at it takes time. \u003ca href=\"https://inedo.com/support/whitepapers/nuget-guide?utm_source=tdwtf\u0026amp;utm_medium=Footerad\u0026amp;utm_campaign=nuget\"\u003eDownload our guide to learn the best practice of NuGet for the Enterprise.\u003c/a\u003e\n\n\u003c/div\u003e\n\u003cdiv style=\"clear: left;\"\u003e \u003c/div\u003e","Url":"https://thedailywtf.com/articles/hello-new-mexico","CommentsUrl":"https://thedailywtf.com/articles/comments/hello-new-mexico","Slug":"hello-new-mexico","TwitterUrl":"//www.twitter.com/home?status=https%3a%2f%2fthedailywtf.com%2farticles%2fhello-new-mexico+-+Hello%2c+New+Mexico!+-+The+Daily+WTF","FacebookUrl":"//www.facebook.com/sharer.php?u=https%3a%2f%2fthedailywtf.com%2farticles%2fhello-new-mexico\u0026t=Hello%2c+New+Mexico!+-+The+Daily+WTF","EmailUrl":"mailto:%20?subject=Check%20out%20this%20article%20on%20The%20Daily%20WTF...\u0026body=Hello,%20New%20Mexico!:%20https://thedailywtf.com/articles/hello-new-mexico","GooglePlusUrl":"//plus.google.com/share?url=https%3a%2f%2fthedailywtf.com%2farticles%2fhello-new-mexico","PreviousArticleId":11259,"PreviousArticleTitle":"The Big Family","PreviousArticleSlug":"the-big-family","PreviousArticleUrl":"//thedailywtf.com/articles/the-big-family","NextArticleId":11261,"NextArticleTitle":"Tales from the World Cup","NextArticleSlug":"tales-from-the-world-cup","NextArticleUrl":"//thedailywtf.com/articles/tales-from-the-world-cup"}]