The Brutalism Post, Part 2: What Brutalism is Not

Why open a series about Brutalism by discussing what is not Brutalism? The answer is simple: of all of the terms in the history of architecture, Brutalism is perhaps the most misused and misunderstood by the general public. 

Pictured: Citizens Bank Tower, 1958-66. Not Brutalism (it’s just plain ol’ International Style modernism). Source

The main issue here, as we will discuss later, is not that people are ignorant for using the wrong definition of the word Brutalism, but that the word Brutalism has come to mean or refer to a variety of architectural phenomena that are linked to one another via overarching similarities, the most important being an expanded set of buildings that elicit a specific emotional response in the viewer.  

“Brutalism”, a specific architectural movement with its own ideology and history, has come to encompass a wide range of colloquial meanings. Some of these meanings are common misconceptions that reflect a need for broader architectural education (the purpose of this series), and some of these meanings reflect a deeper, more philosophical, interrogation into how we perceive and discuss architecture and the complex emotions it arouses within us, exposing a need for new means of communicating a common architectural sentiment

Let’s start with the most common misuse of the term. 

Brutalism is not: every single building made primarily of reinforced concrete. 

Blame this one on the dictionary. The term Brutalism, while being derived from the French term beton brut, meaning raw concrete, does not apply to all buildings made from reinforced concrete. Developed in the 1870s, reinforced concrete is one of the most commonly used building materials in the world. Because of its inexpensive price, its structural integrity, and its ability to be cast into a variety of shapes and forms, many buildings were - and continue to be - made from it. 

Let’s look at three examples of buildings I have found labeled “brutalist” in various places. 

Not Brutalism: (from left to right): Tadao Ando, Vitra Conference Center (1993) Photo by Wojtek Gurak (CC BY NC 2.0); Le Corbusier, Villa Savoye (1929) Photo by Scarlet Green (CC BY 2.0); Albert Kahn, Highland Park Ford Factory (1910) Photo by Thomas Hawk (CC BY NC 2.0)

All of these buildings are constructed primarily from reinforced concrete. As you can see, they are all very, very different from one another. In these three cases, the key piece of information discrediting these buildings as being Brutalist is when they were built. Brutalism was a specific architectural movement from spanning a defined period of time (1940s-late 1970s). Buildings constructed outside of this time window are rather unlikely to be Brutalist

Let’s look at why these buildings might be mislabeled brutalist. 

Our first example is the Vitra Conference Center by Tadao Ando, which was built in 1993. Even though 1993 is far outside the time frame that brutalism spanned, this building has many characteristics that are “brutalistic,” specifically its extensive use of unpainted reinforced concrete, its heavy, geometric massing, and its intense visual weight. Ando’s architecture falls under the term “critical regionalism” - which is best understood as being modern in form (but not in dogma), with a heightened focus on the surrounding ecology and landscape as well as other geographical, cultural, and social contexts.  

The Villa Savoye by Le Corbusier, finished in 1929, is one of the most iconic 20th century houses and works of modernist architecture in the world. This house, though made of reinforced concrete, belongs to the movement known as the International Style, which was developed in Western Europe after World War I, is known for its rejection of ornament, flat surfaces (especially roofs), extensive use of glass, and visually lightweight and repetitive forms. While the International Style makes use of concrete, it differs from Brutalism in its visual lightness - the Villa Savoye seems to float effortlessly above the landscape - very unlike Brutalist architecture, which is characterized by its massive scale, hulking forms and visual heaviness. 

The Highland Park Ford Plant, built in 1910 by noted factory architect Albert Kahn, was once the premiere factory building in America, helping to advance not only the Fordist system, but the city of Detroit, Michigan as being the automobile capital of the world. It is a touchstone of factory design, notable for its pioneering use of the assembly line to facilitate mass production, a concept that remains central to factory design today. Although made of reinforced concrete, the Highland Park plant is not a brutalist building. It frequently is mischaracterized as being brutalist because of its massive side, imposing features, and the close association that has developed between brutalist architecture and urban exploration photography (More on this later). 

TL;DR: All brutalist buildings are made of reinforced concrete (or heavy masonry), but not all reinforced concrete buildings are brutalist. Moving on.

Brutalism is not a catch-all term for Late Modernist architecture

Architecture got so weird and complicated in the period from the 1960s through the early 1980s that it inspired the architectural theorist Charles Jencks to create the first of several delightful and mind-bending charts to try and categorize it: 

Yeah. 

What is Late Modernism? The concise definition is that it is an umbrella term encompassing the various architectural movements that transpired after International Style/Mid-Century Modernism but before Postmodernism. (For more on what Late Modernism is and why you should care, see my post from 2016.) Brutalism elides with Late Modernism, but not all Late Modern buildings are Brutalist. Because Brutalism is contemporaneous with Late Modernism, the distinction can be confusing. Often the case is that Late Modern buildings that are described as ‘Brutalist’ should be recategorized or reassigned to a different, equally obscure and hyper-specific architectural sub-movement happening around the same time. This might seem nitpicky, but look on the bright side: now you get to correct your friends. 

Late Modernism encompassed a lot of smaller architectural movements, most, but not all of them ending in -ism. Some, like Brutalism and High Tech, are more well known; others, like Metabolism, Structuralism, Critical Realism, and Neo-expressionism, not so much. Some buildings don’t fit into any of these categories and must (frustratingly) be referred to as simply “Late Modern” or “Transitional” (referring to the transition from Modernism to Postmodernism.) 

Here are three Late Modern buildings that are not Brutalist:

Left: Richard Rogers, Lloyd’s Building (1986) Photo by Lloyd’s Insurance (CC BY 2.5); Top Right: Kisho Kurakawa Nakagin Capsule Tower (1972) Photo by scarletgreen (CC BY 2.0); Bottom Right: Herman Hertzberger, Centraal Baheer (1972) Photo by Apdency (CC BY-SA 3.0) 

Lloyd’s Building, the headquarters of Lloyd’s of London, located in, unsurprisingly, London, was designed by Richard Rogers and completed in 1986. Despite the relative lack of reinforced concrete, the building is frequently categorized as being Brutalist. The fact that it lacks reinforced concrete as a defining architectural feature is all one needs to eliminate Lloyd’s from the Brutalism category - why it is put there in the first place we will discuss more in depth in the next section of this post. Lloyd’s - along with most of Rogers’ work - is part of the architectural movement known as “High Tech” because it is, well, High Tech. 

High Tech buildings are the apogee of the modernist mindset in terms of glorifying the functions of a building and the technological elements of structural engineering. They take what are usually internal systems such as structural frames, circulation systems (such as stairs and elevators) and services (electrical, plumbing, etc) and integrate them into their external architectural form. (Lloyd’s is colloquially known by Londoners as the “inside out building”). High Tech was relatively short lived because it turns out that when you decorate the outside of your building with its internal services, when winter comes, your water pipes, exposed to the elements, tend to freeze. 

The Nakagin Capsule Tower, built in 1972 by Japanese architect Kisho Kurakawa (one of my favorite architects ever who more people should know about), is one of the buildings most commonly labeled as Brutalist. This building illustrates the gray area that arises when one uses vague aesthetic attributes (concrete, visually heavy, geometric massing) to designate a building as Brutalist instead of the actual history and context of the building in question. The Nakagin Capsule Tower belongs to a different (if coexistent) architectural movement that, frankly is a lot weirder than Brutalism: Metabolism. Take the formal concept of organic biological growth and systems and combine it with the urbanistic concept of megastructures (an entire city contained in a single continuous structure or via several interconnecting structures) and you get Metabolism. Because of the practical issues with building an entire city within a single building, Metabolism lived mostly on paper, however a few built examples were executed, the most famous being the Nakagin Capsule Tower. 

The Centraal Baheer office building was built by Dutch architect Herman Hertzberger in 1972. Like the Nakagin Capsule Tower, it satisfies many of the aesthetic signifiers commonly attributed to Brutalism: it’s made of reinforced concrete, composed of large geometric massing, and it’s visually heavy. Also like the Nakagin Capsule Tower, it belongs to a different, coexisting architectural movement, primarily developed by the Dutch, called Structuralism. Structuralism is a complex set of architectural ideologies developed in the 1960s and 70s, centered around a few key concepts: the rationalist idea that people’s behavior can be directly changed (or manipulated) via design; designing built structures that correspond in form to social structures; an emphasis on cultural and geographical context; an urbanism and design approach based, like Metabolism, on a biological growth analogy (called Aesthetics of Number); the integration of a variety of uses and programs within the same overall structure; and, finally, the aim to architecturally reconcile the needs of both “high” and “low” culture. 

Brutalism, Metabolism, and Structuralism arose from a similar origin, and are ideologically more alike than different, something we will talk about in the next installment of this series. 

Brutalism is not a feeling. 

But also, it kind of is. It is, as the folks say, “a big mood.” A large reason why buildings are incorrectly labeled Brutalist is because they bring forth a very specific emotional response to architecture shared by many people across the world. Some of the buildings that cause people to feel this complex and nuanced set of emotional and aesthetic reactions are, in fact, Brutalist, but many are not. To me, what this demonstrates, is a broader need for architectural education and discourse that goes beyond the most common system for classifying architecture: stylistic labels. 

To talk about this, we’ll bring back Lloyd’s Building, Kahn’s factory and present it alongside a few other examples. 

Left to Right: John M Johanson, Stage Center Oklahoma City (1979) Photographer unknown; Yuri Platonov, Russian Academy of Sciences (1968) Photo by Raita (CC BY 2.0); Boris Magasto, Haludovo Hotel, Krk, Croatia (1972) Photographer unknown; Kevin Roche, The Pyramids (1972) Photo by jikatu (CC BY SA 2.0)

All of these buildings (and all of the photographs of these buildings) are very different from one another, and yet, they have all been classified mistakenly as being “Brutalism.” The only real link between them is emotion. 

Like many folks in the late aughts/early 2010s, I nurtured my then-juvenile love of architecture through spending hours lurking in the Skyscraper City forums looking at thread after thread of pictures of 20th century architecture. Why? Because those images made me feel powerful emotions that I still find difficult to put into words. 

When talking about Brutalism as a feeling, perhaps the closest idea comes from the English philosopher Edmund Burke in his 1756 treatise “A Philosophical Enquiry into the Origin of our Ideas of the Sublime and Beautiful”. I am, of course, talking about the sublime. The Burkean sublime is emotionally complex. To quote Burke directly: 

“Whatever is fitted in any sort to excite the ideas of pain, and danger, that is to say, whatever is in any sort terrible, or is conversant about terrible objects, or operates in a manner analogous to terror, is a source of the sublime; that is, it is productive of the strongest emotion which the mind is capable of feeling.”

But the sublime isn’t just negative. It overwhelms us with its awesome power and in this moment, “the mind is so entirely filled with its object, that it cannot entertain another.” Burke’s concept of the sublime was initially applied to such things as the ocean or the Alps - natural features that are so large, massive, and inherently dangerous that they put us in a state of awe-inspiring disbelief - and yet, and despite their mass and their danger, they give us feelings of deep pleasure and joy

To the people (including myself) who love Brutalism - it does engender feelings of unknowing, of mystery, and sometimes, especially when said Brutalist building is in disrepair or photographed at a particularly menacing angle, of fear or grief. It shares this, rather than a stylistic label, with the buildings featured in this post. 

Because of Brutalism’s association with the State, such as in the case of the former Soviet Bloc, East Germany, the welfare state in England, or its use in governmental buildings around the world, lingering political sentiments can also contribute to this complex mix of emotions - whether one longs for the halcyon days of eras past or fears them as being domineering or totalitarian. It can also cause people to associate buildings that are not Brutalist with buildings that are because they share a same political history. Similar to how the post-industrial society left behind a trail of industrial ruins along the American Rust Belt, so too has neoliberalism gutted and left for dead the monuments of these modernist utopias. 

An actual Brutalist building: Paul Rudolph, Endo Laboratories Headquarters (1964). Photo via Library of Congress

Brutalist or not, these are enigmatic buildings - their forms are strange and unusual, alien even; their contents and even their purposes remain mysterious. Their siting makes them seem either imposing relative to their surroundings or isolated and alone. There is something dark and lonely, sad and longing about them. They are beautiful, partially because of their striking, form-bending architecture, and partially because they once lived different lives in times so unlike ours. 

If you like this post, and want to see more like it, consider supporting me on Patreon! 

There is a whole new slate of Patreon rewards, including Good House of the Week, Crowdcast streaming, and bonus essays!

Not into recurring donations or bonus content? Consider the tip jar! Or, Check out the McMansion Hell Store! Proceeds from the store help protect great buildings from the wrecking ball. 

Copyright Disclaimer: All photographs are used in this post under fair use for the purposes of education, satire, and parody, consistent with 17 USC §107. Manipulated photos are considered derivative work and are Copyright © 2019 McMansion Hell. Please email kate@mcmansionhell.com before using these images on another site. (am v chill about this)

important announcement

i met the lawyer to my foyer
the nub to my roofline
the car to my carhole…
what i’m trying to say is i’m engaged now

edit: we will not be buying a mcmansion for obvious reasons but if you’re feeling the love tonight, you can donate a coffee to the kate wagner & partner tiny and modest wedding fund: www.ko-fi.com/mcmansionhell ! 

(i’m a writer and he’s a high school math teacher so we could use all the help we can get.)

50 States of McMansion Hell: Campbell County, Wyoming

Howdy, folks! It’s time for us to go home, (big, ugly) home on the range. That’s right: It’s time for Wyoming. Now, when I think Wyoming, I think of rolling hills, ranches, incredible landscapes, and also that book about cowgirls that Dick Cheney’s wife wrote.

On that note:

This beautiful 5 bed/4.5 bath 6,000 square foot house was built in 2002. It can be all yours for around $700,000 USD.

Let’s mosey on down through this here estate.

Divorce Lawyer Foyer/Living Room

Now, I’ve been an architecture enthusiast for about a decade of my short, two and a half decade life and never have I seen something as both absurd and patently useless as whatever the hell that thing separating the foyer and the living room is. Does it have a structural purpose? No. Does it have an aesthetic purpose? Also no.

Kitchen

(Running for president voice) “Folks, when I become president, I assure you that the injustice - the absolute tyranny -  that is the island stovetop/wall oven combo will finally–” (crowd cheering) “– and I mean finally, be put deep into the ground where it belongs.”

Dining Room

The aged bronze chandeliers must have been on ultra clearance. Personally, as someone who loves a good deal, I cannot shame them for this.

Master Bedroom

What I can’t determine is what they were going for with the sponge paint on the walls. My closest approximation is tree bark, in which case what we see before us in fact is deeply offensive to the trees, who are innocent and don’t deserved to be involved in any of this.

Master Bathroom

I don’t care how nostalgic we as a culture get for the late nineties/early aughts, sponge paint should never come back. One, it’s sponge paint. Two, it is ridiculously labor intensive and frankly we could all be spending our last few years on this still-habitable earth doing something more worthwhile with our time, such as going outside or falling in love or destroying our brains on the internet.

You are seriously not ready for this

When making this picture I realized I desperately need to log off.

Bathroom 2

Computer, enhance.

Ok but you can’t even read that in the shower. If you’re that desperate for prophetic, non-digital bathroom reading material, buy a bottle of Dr. Bronners or, like, a copy of War and Peace.

Basement

Poor Little Julie. :(

Well, that wraps up our interior. Now, for the final frontier, on the frontier:

Rear Exterior

Somehow this house looks more like it’s made out of cardboard than the many, many houses on this blog that also look like they’re made out of cardboard.

Anyways, that does it for Wyoming! Stay tuned for next week’s Brutalism Post, Part II: What Brutalism is Not. Have a great weekend, folks.

If you like this post, and want to see more like it, consider supporting me on Patreon, ESPECIALLY if you also like donoteat01′s content on YouTube, because we will be doing a livestream collab on Patreon on August 25th, 2019 from 8-10PM EST!!!

There is a whole new slate of Patreon rewards, including Good House of the Week, Crowdcast streaming, and bonus essays!

Not into recurring donations or bonus content? Consider the tip jar! Or,Check out the McMansion Hell Store ! 100% of the proceeds from the McMansion Hell store go to charity!

Copyright Disclaimer: All photographs are used in this post under fair use for the purposes of education, satire, and parody, consistent with 17 USC §107. Manipulated photos are considered derivative work and are Copyright © 2019 McMansion Hell. Please email kate@mcmansionhell.com before using these images on another site. (am v chill about this)

Kate Wagner - McMansion Hell Live at Motorco!

Kate Wagner - McMansion Hell Live at Motorco!:

Howdy folks! If you’re in the NC area next Tuesday, come and see me talk about McMansions as well as do a live house roast at Motorco in Durham. The ticket sales go to fund NC Modernist Houses, a nonprofit that works to preserve the heritage of architectural modernism in North Carolina. 

When: Tuesday, July 23, 6pm

Where: Motorco, 723 Rigsbee Avenue, Durham

Tickets: Advance - $29
At the door - $39
VIP - $99
(you get to throw axes at pictures of McMansions with me afterward lol)

See y’all there! 

The Brutalism Post, Part One: Introduction

This is part one of a five-part post about Brutalism. 

University of Massachusetts at Dartmouth campus by Paul Rudolph. Photo via Library of Congress

No style of architecture so passionately divides even the most good-natured and level-headed people as Brutalism. The discourse surrounding Brutalism being “good” or “bad” is fierce and polemical. The “for” crowd lobbies on both aesthetic grounds – posting pictures of incredible and obscure structures and saying “I mean LOOK at this” – as well as political ones, citing in particular, how Brutalism was used to house thousands of people during the postwar period. 

On the other hand, the “against” crowd brings up the failed urbanism of Le Corbusier that gave us the freeways and slum clearance that split and displaced entire swaths of city fabric, proclaiming that only architects or architecture enthusiasts like Brutalism, and that this is a testament to how out of touch they are with everyday people. “If you had to live or work in these buildings,” they say, “you’d feel differently.” 

Unité d'Habitation by Le Corbusier. Photo by Thomas Nemeskeri, via Flickr (CC BY-NC-ND 2.0) 

I’ve been a spectator to this debate since I first lurked in the Skyscraper City forums as a high school freshman, ten years ago, when Brutalism itself sparked the interest in architecture that brings me here today. I have, as they say, heard both sides, and when asked to pick one, my response is unsatisfying. Though my personal aesthetic tastes fall on the side of “Brutalism is good,” I think the actual answer is  it’s deeply, deeply complicated. 

Still, what is it about Brutalism that makes it so divisive? Why does a short-lived substyle of modern architecture elicit such vehement passion in so many people? What does it even mean for a style of architecture to be “good” or “bad”? You can see why I’m drawn to finally sitting down and penning this series, which has been simmering at the back of my mind since I started McMansion Hell three years ago. (By the way, Happy Birthday to this blog!!!) 

Brutalism has a special way of inspiring us to ask big and difficult questions about architecture. “Is Brutalism good?” is really a question of “is any kind of architecture good?” - is architecture itself good? And what do we mean by good? Are we talking about mere aesthetic merits? Or is it more whether or not a given work of architecture satisfies the purpose for which it was built? Can architecture be morally good? Is there a right or wrong way to make, or interpret, a building? 

Ferrier Estate, a now-demolished social housing complex in South London. Photo by Tim Slessor via Flickr (CC BY-NC 2.0)  

I have bad news for you: the answers to all of these questions are complicated, nuanced, and unsatisfying. In today’s polemical and deeply divided world of woke and cancelled, nuance has gotten a bad rap, having been frequently misused by those acting in bad faith to create blurred lines in situations where answers to questions of morality are, in reality, crystal clear. This is not my intention here. 

For centuries, the philosophical discipline of aesthetics has tried in vain to articulate some kind of clearly defined standard by which we can delineate whether or not a work of art is good, bad, moral or amoral. Architecture makes this even more complicated because unlike literature, painting, music, or art, we have to live, work, and exist in architecture. Not only does the question of whether or not we can separate the art from the artist exist in architecture, so to do questions of whether or not we can separate the building from the politics, from the culture, from the time period, from the urbanism, from the socioeconomic system, from the entire contents of everyday life in which it exists. 

Orange County Government Center, Perspective Drawing, by Paul Rudolph. Photo via the Library of Congress.

Existential questions aside, there are other reasons to write about Brutalism. First, while we’ve been hemming and hawing about it online, we’ve lost priceless examples of the style to either demolition or cannibalistic renovation, including Paul Rudolph’s elegant Orange County Government Center, Bertrand Goldberg’s dynamic Prentice Women’s Hospital in Chicago, and the iconic Trinity Square, Gateshead complex, famous for the role it played in the movie Get Carter. My hope is that by bringing up the nuances of Brutalism before a broad and diverse audience, other buildings on the chopping block might be spared. 

On an even broader note, I think Brutalism is worth writing about simply because a lot of people are rightly confused as to what it even is.  The common practice of identifying Brutalism by the presence of a material - reinforced concrete - too broadly defines a style that belongs to a specific era and architectural praxis. There are so many buildings and styles called Brutalist that are not Brutalist that I’ve devoted the first two installments of this series to the subject “What Brutalism Is Not,” followed, of course, by “What is Brutalism?” The goal is that these two essays will be educational and interesting (with the added bonus of providing the reader with an arsenal of information that will make them as insufferable at dinner parties as I am.)

The third part in this series is devoted to the people of Brutalism - the architects, politicians, planners, writers, and philosophers, who signed their names to an architectural movement that spanned the globe. Finally, the last installment gathers all this information together and answers the question we’ve all been waiting for: is Brutalism good? 

The Kyoto International Conference Center, designed by Sachio Otani. Photo by Chris Guy, via Flickr. (CC BY-NC-ND 2.0) 

This is a series on Brutalism, but Brutalism itself demands a level of inquiry that goes beyond defining a style. Really, this is a series about architecture, and its relationship to the world in which it exists. Architects, as workers, artists, and ideologues, may dream up a building on paper and, with the help of laborers, erect it in the material world, but this is only the first part of the story. The rest is written by us, the people who interact with architecture as shelter; as monetary, cultural, and political capital; as labor; as an art; and, most broadly, as that which makes up the backdrop of our beautiful, complicated human lives. 

If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including Good House of the Week, Crowdcast streaming, and bonus essays!

Not into recurring donations or bonus content? Consider the tip jar! Or,Check out the McMansion Hell Store ! 100% of the proceeds from the McMansion Hell store go to charity!

Copyright Disclaimer: All photographs are used in this post under fair use for the purposes of education, satire, and parody, consistent with 17 USC §107. Manipulated photos are considered derivative work and are Copyright © 2019 McMansion Hell. Please email kate@mcmansionhell.com before using these images on another site. (am v chill about this)

50 States of McMansion Hell: Top 10 Waukesha County, Wisconsin McMansions

Howdy Folks! We’re continuing our out-of-order-for-dramatic-effect tour of the 50 States of McMansion Hell today with perhaps one of the most underrated McMansion counties in the country: Waukesha County, Wisconsin. These houses were so bizarre it was hard to choose just one to do a takedown of. So, without further ado… 

#10: Doom McGloom

This 2002 estate, thanks to the clever machinations of whoever took these photographs, looks less like an enticing investment property and more like a prime candidate for the Chernobyl ripoff set in America that has 2 stars and is only available on Amazon Prime. 

#9: Headquarters of Tree-Haters Anonymous

This 2004 manse is $1.4 million dollars and yet its creators couldn’t afford more than a single (invasive!) tree. I don’t know what kind of sociopath wakes up in the morning and actively hates everything taller than a malnourished shrub. Whoever they are, this is certainly the house for them. 

#8: Roofer’s Paradise 

A post-recession 2011 McMansion, this house clearly didn’t learn anything from the recent past. With many McMansions, I can conceive of ways to improve them to make them better. With this house, I simply do not know how to rectify its main problem: it’s, like, 90% roof. In my head I refer to houses like this as “turtle houses” but frankly this does a disservice to the noble turtle. 

#7: Haunted Geometry

This house was built in 2014, a time when people should definitely have known better. Its inclusion in this list is solely due to the absolutely bizarre geometry of its roof, a kind of geometry formerly unknown to mathematics until this time. Bonus points for the continued animosity to trees found in the wealthy populous of this county. 

#6: McEscher

Nothing about this house makes sense. I’m serious. I’ve looked at it from several different angles and have yet to perceive any coherent spatial logic to how it comes together. This is house is an SCP. It’s an X-Files case. House of Leaves was actually based on this house. It’s an Escherian nightmare. 0/10 would not go inside even if you paid me. 

#5: Obligatory Beigehaus

You know when a bad stand up comedian tells a joke that just keeps going way too long? The audience is like, okay, we get it, you need therapy, but he (and it’s always a he) just keeps going on and on. Well, this is the house equivalent of that. 

#4: House of Lumps

Whoever built this house was utterly incapable of picturing in their minds eye what a house should look like. The very conception of a house is foreign to them. They have never seen a children’s book with houses in it. They probably didn’t even have a childhood. 

#3: Play-doh Playhouse

This house made it so far in the countdown because it is, frankly, weird. I don’t know why it is painted the color of jaundice, or why they have transformed every gable into a hollow cavity longing for death. Lots of things are happening here, though none of them could appropriately be called “architecture.”

#2: Farmhouse Freak

Let your eyes glaze over as you look at this “farmhouse” - the more you look at it the less sense it makes. What are they farming, you ask? Why, turf grass of course! Bonus points for this image in which the house appears through a haze of ozone or something. 

And now, the moment you’ve been waiting for…

#1: Corinthian Catastrophe

It’s one thing to have oversized Corinthian columns on your absurd McManse, but it’s a whole new level of extra to spray paint the capitals gold. This house takes all the elements found in the other houses (treeless sociopathy, turret lust, garish mismatched windows, foam) and ramps it up to 11, which is why it earns the number one slot in the county. Also, as a bonus, I find it incredibly funny that they embossed the letter “C” everywhere. I guess whoever buys it either has to have a name starting with C or has their work cut out for them. The C represents the grade they got in home design class. 

Anyways, that’s it for Wisconsin, folks! Stay tuned for a special essay on whether or not brutalism is good, as well as the next installment of the 50 States: Wyoming. Have a great weekend. 

If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including Good House of the Week, Crowdcast streaming, and bonus essays!

Not into recurring donations or bonus content? Consider the tip jar! Or,Check out the McMansion Hell Store ! 100% of the proceeds from the McMansion Hell store go to charity!

Copyright Disclaimer: All photographs are used in this post under fair use for the purposes of education, satire, and parody, consistent with 17 USC §107. Manipulated photos are considered derivative work and are Copyright © 2019 McMansion Hell. Please email kate@mcmansionhell.com before using these images on another site. (am v chill about this)

McMansion Hell Cross Stitch Patterns

Howdy folks! My internet has been funny this week, thus, I had a lot of time to myself with no internet which invariably leads to…crafting. I made some McMansion Hell-themed cross stitch patterns in MacStitch and wanted to share them with all of you in case there are other folks out there who love to stitch. 

These pictures are just the previews - to download the full patterns, click here

Happy Stitching! See you soon with Wisconsin’s McMansion! 

Why Marie Kondo’s method is ideal for my ADHD

Why Marie Kondo’s method is ideal for my ADHD:

I got to write about how Marie Kondo helped with my ADHD! 

Frank Lloyd Wright Quarterly | Frank Lloyd Wright Foundation

Frank Lloyd Wright Quarterly | Frank Lloyd Wright Foundation:

Art by Ellen Surrey

Howdy! The lovely folks at the Frank Lloyd Wright Foundation let me take the reigns as guest-editor for the new edition of their quarterly, about FLW and pop culture! It was a great opportunity for me to revisit my love of Wright’s work, to invite some of my favorite architecture writers around to share their talents, and to draw arrows and text on top of a very famous and handsome building instead of the ugliest and dumbest houses imaginable. 

Topics include why FLW’s work and life remain so influential after all these years; a reverse McMansion Hell roast of Taliesin West, and a look at FLW in tv (including GoT!!), movies, and the entire genre of science fiction. (There’s also some really cute drawings of FLW sitting on the Iron Throne, cavorting with robots, etc.)

Stay tuned for the next installment of this blog, which will drop Thursday! 

I wasted a whole day making this chart for architects and so now you have to see it too

I wasted a whole day making this chart for architects and so now you have to see it too

interior design is my passion

interior design is my passion

Kate Wagneri made a website for myself (kate wagner)

i made a website for myself (kate wagner)

Top 5 Worst McMansions in SpaceHowdy folks! If you thought suburban sprawl couldn’t extend any...

Top 5 Worst McMansions in Space

Howdy folks! If you thought suburban sprawl couldn’t extend any further, encroaching and devouring everything in its path, you’re right! That’s why, in co-operation with a variety of shady Silicon Valley start-ups, property speculators and developers are now taking bold new steps in order to expand the iron grip of real estate by entering… the space market! The offerings have been slim, so far, but remain ever promising for readers of this website. Let’s take a look!

#5: 6341 Crater Drive, Moon

Hoping to cash in on a moon real estate boom, this lovely 6000 square foot “ranch” is located a mere 30 miles from the famous “Moon Landing” site. Tall ceilings abound, convenient for those who have to live in low gravity. Also includes granite countertops, and “bathrooms” to remind you of Earth’s luxuries. Only $500,000,000, HOA not included. 

#4: 443 Black Hole Lane, Jellyfish Nebula

Another sprawling rancher, this time drifting endlessly into the abyss somewhere near the Jellyfish Nebula. At 6349 square feet, there’s plenty of space for you to ponder the loneliness that is the universe and the ever-present fear that you may never see your family on Earth again. Before you change your mind, wait til you see that master bath, folks!

#3: 553 Discovery Place, Mars

This amazing 6 bedroom 11 bath Space Chateau is a great investment opportunity for those smart investors that want to cash in on the Mars craze and stay ahead of Elon Musk! Designed to blend into the harsh Mars terrain, this 7,530 sqft house is perfect for the land grabbing space colonizing enthusiast and faux royalty alike. 

#2: 11 Apollo Court, Moon

Did seeing Apollo 11 in IMAX get your moon juices flowing? Well do I have a house for you! If you like a good view, forget the hilly expanses of California, or the breezy seaside vibes of Florida - you can see it all from this elegant 7845 sqft Moon Estate featuring no-maintenance plastic landscaping, a 3-rover garage, and large, diverse windows allowing for nonstop views. This house is great for entertaining, but if someone knocks on your door DO NOT ANSWER IT and REPORT TO THE NEAREST AUTHORITIES. 

#1: 733 Starry Boulevard, Carina Nebula

This incredible 6 bedroom, 8 bathroom home features large, sweeping views of the ever-expanding universe in which all of us are unfortunately trapped like puny flies in a dish of olive oil. If you like elegant stonework, tall ceilings, and the tranquil silence afforded by the vacuum of space, than this Tudor European Estate complete with satellite is perfect for your discerning tastes. 

McMansion Hell would like to thank recent architecture school graduate Sean Maciel (@seanmaciel on Twitter) for creating locating via space real estate networks the images used in this post. 

If you like this post, and want to see more like it, consider supporting me on Patreon!

There is a whole new slate of Patreon rewards, including Good House of the Week, Crowdcast streaming, and bonus essays!

Not into recurring donations or bonus content? Consider the tip jar! Or,Check out the McMansion Hell Store ! 100% of the proceeds from the McMansion Hell store go to charity!

Copyright Disclaimer: All photographs are used in this post under fair use for the purposes of education, satire, and parody, consistent with 17 USC §107. Manipulated photos are considered derivative work and are Copyright © 2019 McMansion Hell. Please email kate@mcmansionhell.com before using these images on another site. (am v chill about this)

we did it folks

we did it folks

Ada Louise Huxtable (1921-2013)

Ada Louise Huxtable (1921-2013):

I wrote about the life and timelessness of the architecture critic Ada Louise Huxtable for The Architectural Review. 

Griffin vs. Cloud9 / 2019 World Championship - Group A / Post-Match Discussion

By /u/G2Minion

submitted by /u/G2Minion to r/leagueoflegends
[link] [comments]

The way the veins of the leaf align on the creases of the hand

By /u/admiralwan

The way the veins of the leaf align on the creases of the hand submitted by /u/admiralwan to r/oddlysatisfying
[link] [comments]

🔥 Wild horses enjoy the ocean

By /u/Dlatrex

🔥 Wild horses enjoy the ocean submitted by /u/Dlatrex to r/NatureIsFuckingLit
[link] [comments]

“You either love it or you hate it” starterpack

By /u/orangeinjustice

“You either love it or you hate it” starterpack submitted by /u/orangeinjustice to r/starterpacks
[link] [comments]

Found this gem recently

By /u/SugmaNuts

Found this gem recently submitted by /u/SugmaNuts to r/insanepeoplefacebook
[link] [comments]

Thats hot

By /u/weiloh

Thats hot submitted by /u/weiloh to r/BikiniBottomTwitter
[link] [comments]

What's a fun little fact about yourself?

By /u/TwetBeg

submitted by /u/TwetBeg to r/AskReddit
[link] [comments]

The first all-female spacewalk happens today

By /u/NoKidsItsCruel

submitted by /u/NoKidsItsCruel to r/news
[link] [comments]

'Dad stop the burning, I beg you': Horrifying footage reveals badly-burned Kurdish children in Syria amid claims Turkey is using banned weapons such as napalm and white phosphorus

By /u/JamburaStudio

submitted by /u/JamburaStudio to r/worldnews
[link] [comments]

blursed chinese fries

By /u/KMeowRooter

blursed chinese fries submitted by /u/KMeowRooter to r/blursedimages
[link] [comments]

This is what happens if you play with a yo-yo too much (I'm not kidding this is the hand of a professional yo-yo player)

By /u/SadTension5

This is what happens if you play with a yo-yo too much (I'm not kidding this is the hand of a professional yo-yo player) submitted by /u/SadTension5 to r/Wellthatsucks
[link] [comments]

Exclusive: China cancels release of Tarantino's 'Once Upon a Time in Hollywood'

By /u/Senile_Sapien

Exclusive: China cancels release of Tarantino's 'Once Upon a Time in Hollywood' submitted by /u/Senile_Sapien to r/movies
[link] [comments]

Qatar now so hot it has started air-conditioning the outdoors - Giant coolers in public areas accelerating climate crisis further by using electricity from fossil fuels

By /u/ManiaforBeatles

submitted by /u/ManiaforBeatles to r/worldnews
[link] [comments]

TIFU by quoting Thanos while arguing with my GF

By /u/AdoptedByThanos

Trowaway account for privacy, this happened yesterday and I don't know how to make it up.

My girlfriend and I met at university 4 years ago, and we both graduated some time ago. Since then we've both been looking for work, but the research is more difficult than we thought, and until yesterday neither of us had managed to get a job. Yesterday my girlfriend received a positive answer to one of her applications, for a job located 430 kilometers from our hometown. She was very happy and that's how she told me to come to her house to tell me some good news about the research. So expecting some good news, I took a detour to buy her sushi because we both love it, and I arrived at her house early in the evening, and that's when she tells me that in two weeks she's going to go more than 400 kilometers from our city, and that I now have to look in the same area as her. I totally lost my mind when she told me that. I explain that I understand that the research is complicated, but that it was no reason to look at work across the country, and that I had no desire to leave my family and friends because my life is in my hometown. The situation then became very tense, she told me that I am selfish and that I have to learn to move away, that even if there is no urgency, it is important to find a job quickly so as not to remain inactive. I then offered her a long-distance relationship for a few months because I really don't want to leave, and she could come back as soon as she found a job in our city. And that, guys, she took it really hard, I've never seen her so upset in my life. She then gave me an ultimatum: either I follow her or we stop our relationship, and she asks me if I'm really ready to leave her to stay with my family and friends. Maybe some people can see it, but this is the moment I fucked up.

I still don't know why my brain betrayed me like that, but the only answer I could find was : "Perhaps, maybe it is a small price to pay for salvation". I could have made long rants to show her that I love her, that I care about her. I could have found arguments so that we could solve the situation, as any person in a relationship for 4 years would do. But no, my fucking stupidity made me quote a purple guy. She looked at me with an empty look for several seconds, I realized how much I fucked up, but nothing came from my mouth. She just asks me to leave her house, and since yesterday she speak to me or answer my calls and messages. I sent her a very long message of apology, adding that I hope we will be able to resolve the situation, but still no answer.

I am now staring my Thanos funko pop thinking how much this guy may have ruined part of my life.

TLDR : GF finds a job far away from our city and I doesn't want to leave my life to live this far. She asks me if I'm really ready to leave her just to stay in my city and my only answer was "Maybe it is a small price to pay for salvation".

submitted by /u/AdoptedByThanos to r/tifu
[link] [comments]

Greta Thunberg’s 13-year-old sister is struggling with the 'systematic bullying, hatred and harassment' her family is facing

By /u/andrzej1220

Greta Thunberg’s 13-year-old sister is struggling with the 'systematic bullying, hatred and harassment' her family is facing submitted by /u/andrzej1220 to r/europe
[link] [comments]

Error'd: Encoded for YOUR Benefit

By Mark Bowytz

"Oracle makes it easy! Just dereference this pointer to view your failed invoice," wrote Jeremy W.

 

"Oh no! It's too late for Computing. They weren't able to fend off evolving threats in time!" writes David B.

 

Jean R. wrote, "Well, thank you Google for this handy tip! I'm sure it is helpful for any cyborg out there that might want to do some mental arithmetic."

 

"While this Microsoft mouse is light on CPU and storage, it makes up for it by being so small and lightweight!" Dave L. writes.

 

Andrzej wrote, "Ah yes, undefined, undefined, and undefined...truly some of my favorite artists. WAAAAY better than null."

 

Bob E. writes, "Keep this up and it'll be free Ham and Cheese Benedicts for everyone!"

 

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

CodeSOD: A Context for Logging

By Remy Porter

When logging in Java, especially frameworks like Spring, making sure the logging statement has access to the full context of the operation in flight is important. Instead of spamming piles of logging statements in your business logic, you can use a “mapped diagnostic context” to cache useful bits of information during an operation, such that any logging statement can access it.

One of the tools for this is the “Mapped Data Context”, MDC. Essentially, it’s very much like a great big hash map that happens to be thread-local and is meant to be used by the logging framework. It’s a global-ish variable, but without the worst side effects of being global.

And you know people just love to use global variables.

Lothar was trying to figure out some weird requests coming out of an API, and needed to know where certain session ID values were coming from. There are a lot of “correct” ways to store session information in your Java Spring applications, and he assumed that was how they were storing those things. Lothar was wrong.

He provided this anonymized/generalized example of how pretty much every one of their REST request methods looked:

 @Override
   public Wtf getWtf(String wtfId) {

    Map<String, Object> params = new HashMap<>();
    params.put("wtfId", wtfId);
    params.put("sessId", MDC.get(MDC_LABEL_SESSION_ID));
    params.put(MDC_LABEL_SESSION_ID, MDC.get(MDC_LABEL_SESSION_ID));

    UriComponents uriComponents = UriComponentsBuilder
            .fromUriString("https://thedailywtf.com")
            .buildAndExpand(params);
    String urlString = uriComponents.toUriString();
        ResponseEntity<byte[]> responseEntity = restTemplate.getForEntity(urlString, byte[].class);
  }

Throughout their application, they (ab)used their logging framework as a thread-local storage system for passing user session data around.

Sure, the code was stupid, but the worst part about this code was that it worked. It did everything it needed to do, and it also meant that all of their log messages had rich context which made it easier to diagnose issues.

If it’s stupid and it works, that means you ship it.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

CodeSOD: The Replacements

By Remy Porter

Nobody wants to have a Bobby Tables moment in their database. So we need to to sanitize our inputs. Ted C noticed a bunch of stored procedures which contained lines like this:

  @scrubbed = fn_ScrubInput(fn_ScrubInput(@input))

Obviously, they wanted to be super careful, and make sure their inputs were clean. But it got Ted curious, so he checked out how the function was implemented. The function body had one line, the RETURN line, which looked like this:

  RETURN REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@input, '"', '"'), 
'*', '\*'),'~', '\~'), '@', '\@'), '#', 
'\#'), '$','\$'),'%','\%'),'^','\^'),
'&','\&'),'(','\('),')','\)'),
'_','\_'),'+','\+'),'=','\='),'>',
'\>'),'<','\<'),'?','\?'),'/',
'\/')

Whitespace added.

Ted REPLACE REPLACE REPLACEd this with a call to the built-in STRING_ESCAPE function, which handled the escaping they needed.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

CodeSOD: Cast Away

By Remy Porter

The accountants at Gary's company had a problem: sometimes, when they wanted to check the price to ship a carton of product, that price was zero. No one had, as of yet, actually shipped product for free, but they needed to understand why certain cartons were showing up as having zero cost.

The table which tracks this, CartonFee, has three fields: ID, Carton, and Cost. Carton names are unique, and things like 12x3x6, or Box1, or even Large box. So, given a carton name, it should be pretty easy to update the cost, yes? The stored procedure which does this, spQuickBooks_UpdateCartonCost should be pretty simple.

ALTER PROCEDURE [dbo].[spQuickBooks_UpdateCartonCost] @Carton varchar(100), @Fee decimal(6,2) AS BEGIN DECLARE @Cost decimal(8,3) = LEFT(CAST(CAST((CAST(@Fee AS NUMERIC(36,3))/140) * 100 AS NUMERIC(36,3)) AS VARCHAR), LEN(CAST(CAST((CAST(@Fee AS NUMERIC(36,3))/140) * 100 AS NUMERIC(36,3)) AS VARCHAR)) - 1) + CASE WHEN RIGHT(LEFT(CAST(CAST((CAST(@Fee AS NUMERIC(36,3))/140) * 100 AS NUMERIC(36,4)) AS VARCHAR), LEN(CAST(CAST((CAST(@Fee AS NUMERIC(36,3))/140) * 100 AS NUMERIC(36,4)) AS VARCHAR)) - 1), 1) > 5 THEN '5' ELSE '0' END IF NOT EXISTS (SELECT 1 FROM CartonFee WHERE Carton = @Carton) BEGIN INSERT INTO CartonFee VALUES (@Carton, @Cost) END ELSE BEGIN UPDATE CartonFee SET Cost = @Cost WHERE Carton = @Carton END END

Just stare at that chain of casts for a moment. It teeters on the verge of making sense, calls to LEFT and RIGHT and multiplying by 100- we're just doing string munging to round off, that must be what's going on. If I count the parentheses, and really sit down and sketch this out, I can figure out what's going on, it must make sense, right?

And then you spot the /140. Divide by 140. Why? Why that very specific number? Is it a secret code? Is it a signal to the Illuminated Seers of Bavaria such that they know the stars are right and they may leave Aghartha to sit upon the Throne of the World? After all, 1 + 4 + 0 is five, and as we know, the law of fives is never wrong.

As it turns out, this stored procedure wasn't the problem. While it looks like it's responsible for updating the cost field, it's never actually called anywhere. It was, at one point, but it caused so much confusion that the users just started updating the table by hand. Somebody thought they'd get clever and use an UPDATE statement and messed up.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

CodeSOD: I See What Happened

By Remy Porter

Graham picked up a ticket regarding their password system. It seemed that several users had tried to put in a perfectly valid password, according to the rules, but it was rejected.

Graham's first step was to attempt to replicate on his own, but couldn't do it. So he followed up with one of the end users, and got them to reveal the password they had tried to use. That allowed him to trigger the bug, so he dug into the debugger to find the root cause.

private static final String UPPERCASE_LETTERS = "ABDEFGHIJKLMNOPQRSTUVWXYZ"; private int countMatches(String string, String charList) { int count = 0; for (char c : charList.toCharArray()) { count += StringUtils.countMatches(string, String.valueOf(c)); } return count; }

This isn't a great solution, but it at least works. Well, it "works" if you are able to remember how to recite the alphabet. If you look closely, you can tell that there are no pirate on their development team, because while pirates are fond of the letter "R", their first love will always be the "C".

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

Error'd: The WTF Experience

By Mark Bowytz

"As it turns out, they've actually been singing Purple Haze before the start of all of those sportsball games," Adam writes.

 

Andrew C. writes, "When you buy from 'Best Pool Supplies', make no mistake...you're going to pay for that level of quality."

 

Jared wrote, "Pulling invalid data is forgiveable, but using a loop is not."

 

"VMware ESXi seems a little confused about how power state transitions work," writes Paul N.

 

"At first I was annoyed I didn't get the job, but now I really want to go in for free and fix their systems for them!" Mark wrote.

 

Peter M. writes, "Oh yes, Verizon! I am very excited! ...I'm just having a difficult time defining why."

 

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!

CodeSOD: Parse, Parse Again

By Remy Porter

Sometimes, a block of terrible code exists for a good reason. Usually, it exists because someone was lazy or incompetent, which while not a good reason, at least makes sense. Sometimes, it exists for a stupid reason.

Janet’s company recently bought another company, and now the new company had to be integrated into their IT operations. One of the little, tiny, minuscule known-issues in the new company’s system was that their logging was mis-configured. Instead of putting a new-line after each logging message, it put only a single space.

That tiny problem was a little bit larger, as each log message was a JSON object. The whole point of logging out a single JSON document per line was that it would be easy to parse/understand the log messages, but since they were all on a single line, it was impossible to just do that.

The developers at the acquired company were left with a choice: they could fix the glitch in the logging system so that it output a newline after each message, or they could just live with this. For some reason, they decided to live with it, and they came up with this solution for parsing the log files:

def parse(string):
  obs = []
  j = ""
  for c in string.split():
    j += c
    try:
      obs.append(json.loads(j))
      j = ""
    except ValueError:
      pass
 
  return obs

This splits the string on spaces. Then, for each substring, it tries to parse it as a JSON object. If it succeeds, great. If it throws an exception, append the next substring to this one, and then try parsing again. Repeat until we’ve built a valid JSON document, than clear out the accumulator and repeat the process for all the rest of the messages. Eventually, return all the log messages parsed as JSON.

As a fun side effect, .split is going to throw the spaces away, so when they j += c, if your log message looked like:

{"type": "Error", "message": "Unable to parse JSON document"}

After parsing that into JSON, the message becomes UnabletoparseJSONdocument.

But at least they didn’t have to solve than newline bug.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

Coded Smorgasbord: Driven to Substraction

By Remy Porter

Deon (previously) has some good news. His contract at Initrode is over, and he’s on his way out the door. But before he goes, he wants to share more of his pain with us.

You may remember that the StringManager class had a bunch of data type conversions to numbers and dates. Well guess what, there’s also a DateManager class, which is another 1600 lines of methods to handle dates.

As you might expect, there are a pile of re-invented conversion and parsing methods which do the same thing as the built-in methods. But there’s also utility methods to help us handle date-related operations.

		public static int subStractFromCurrentDate(System.DateTime dateTimeParm) 
		{
			//get now
			System.DateTime now = System.DateTime.Now;
			//now compare days
			int daysDifference  = now.Day - dateTimeParm.Day;
			return daysDifference ;
		}

Fun fact: the Day property returns the day of the month. So this method might “subStract”, but if these two dates fall in different months, we’re going to get unexpected results.

One of the smaller string formatters included is this one:

		public static string formatEnglishDate (System.DateTime inputDateTime) 
		{
			Hashtable _monthsInEnglishByMonthNumber = new Hashtable();
			_monthsInEnglishByMonthNumber[1] = "January";
			_monthsInEnglishByMonthNumber[2] = "February";
			_monthsInEnglishByMonthNumber[3] = "March";
			_monthsInEnglishByMonthNumber[4] = "April";
			_monthsInEnglishByMonthNumber[5] = "May";
			_monthsInEnglishByMonthNumber[6] = "June";
			_monthsInEnglishByMonthNumber[7] = "July";
			_monthsInEnglishByMonthNumber[8] = "August";
			_monthsInEnglishByMonthNumber[9] = "September";
			_monthsInEnglishByMonthNumber[10] = "October";
			_monthsInEnglishByMonthNumber[11] = "November";
			_monthsInEnglishByMonthNumber[12] = "December";

			StringBuilder _dateBldr = new StringBuilder();
			_dateBldr.Append(_monthsInEnglishByMonthNumber[inputDateTime.Month].ToString());
			_dateBldr.Append(" ");
			_dateBldr.Append(inputDateTime.Day.ToString());
			_dateBldr.Append(", ");
			_dateBldr.Append(inputDateTime.Year.ToString());

			return _dateBldr.ToString();
		}

Among all the bad things implied here, I really like that they used a Hashtable as an array.

        public static bool  currentDateIsFirstBusinessDateOfTheMonth 
                            (
                                Hashtable inputHolidayHash
                            )
        {
            /*
             * If current date is not a business date, then it cannot
             * be the first business date of the month.
             */
            DateTime _currentDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            _currentDate =
                new DateTime(2010, 5, 6);
            if (
                    _currentDate.DayOfWeek == DayOfWeek.Saturday
                    ||
                    _currentDate.DayOfWeek == DayOfWeek.Sunday
                    ||
                    inputHolidayHash[_currentDate] != null
                )
                return false;

            /*
             * If current date is a business date, and if it is also
             * the first calendar date of the month, then the
             * current date is the first business date of the month.
             */

            DateTime _firstDayOfTheMonth =
                _currentDate.AddDays(1 - _currentDate.Day);
            if (_firstDayOfTheMonth == _currentDate)
                return true;

            /*
             * If current date is a business date, but is not the 1st calendar
             * date of the month, and, if, in stepping back day by day 
             * from the current date,  we encounter a business day before 
             * encountering the last calendar day of the preceding month, then the 
             * current date is NOT the first business date of the month.
            */
            DateTime _tempDate = _currentDate.AddDays(-1);
            while (_tempDate >= _firstDayOfTheMonth)
            {
                if (
                        _tempDate.DayOfWeek != DayOfWeek.Saturday
                        &&
                        _tempDate.DayOfWeek != DayOfWeek.Sunday
                        &&
                        inputHolidayHash[_tempDate] == null
                    )
                    return false;
                _tempDate = _tempDate.AddDays(-1);
            }
            /*
             * * If current date is a business date, but is not the 1st calendar
             * date,and, if, in stepping back day by day from the current date, 
             * we encounter no business day before encountering the 
             * 1st calendar day of the month, then the current date 
             * IS the first business date of the month.
            */
            return true;
        }

This one has loads of comments, and honestly, I still have no idea what it’s doing. If it’s checking the current day, why does it need to cycle through other days? Why even ask that question, because clearly while debugging they hard-coded a testing date (new DateTime(2010, 5, 6)) and just left that in there.

I’m not the only one getting confused. Check out this comment:


        //@??
        public static DateTime givenPeriodEndDateFindLastBusinessDateInPeriod
                                (
                                    DateTime inputPeriodEndDate
                                    , Hashtable inputHolidayHash
                                )
        {
          ...
        }

And if you’re missing good old StringManager, don’t worry, we use it here:

    /**
		 * @description format date
		 * */
		public static string formatYYYYMMDD (System.DateTime inputDateTime) 
		{
			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(inputDateTime.Year.ToString());
			_bldr.Append(initrode.utilities.StringManager.Fill(inputDateTime.Month.ToString(),
															"0",       // Zero-Fill
															true,	   // Fill from left
															2));        // String length

			_bldr.Append(initrode.utilities.StringManager.Fill(inputDateTime.Day.ToString(),
															"0",       // Zero-Fill
															true,	   // Fill from left
															2));       // String length
			return _bldr.ToString();
		}

And all of this is from just about the first third of the code. I’m trying to keep to shorter methods before posting the whole blob of ugly. So with that in mind, what if you wanted to compare dates?

		public static DateComparison date1ComparedToDate2(DateTime inputDate1, 
															DateTime inputDate2)
		{
			if (inputDate1.Year > inputDate2.Year) return DateComparison.gt;
			if (inputDate1.Year < inputDate2.Year) return DateComparison.lt;
			if (inputDate1.DayOfYear > inputDate2.DayOfYear) return DateComparison.gt;
			if (inputDate1.DayOfYear < inputDate2.DayOfYear) return DateComparison.lt;
			return DateComparison.eq;
		
		}

Oh yeah, not only do we break the dates up into parts to compare them, we also have a custom enumerated type to represent the result of the comparison. And it’s not just dates, we do it with times, too.

		public static DateComparison timestamp1ComparedToTimestamp2(DateTime inputTimestamp1, 
																	DateTime inputTimestamp2)
		{
			if (inputTimestamp1.Year > inputTimestamp2.Year) return DateComparison.gt;
			if (inputTimestamp1.Year < inputTimestamp2.Year) return DateComparison.lt;
			if (inputTimestamp1.DayOfYear > inputTimestamp2.DayOfYear) return DateComparison.gt;
			if (inputTimestamp1.DayOfYear < inputTimestamp2.DayOfYear) return DateComparison.lt;
			if (inputTimestamp1.Hour > inputTimestamp2.Hour) return DateComparison.gt;
			if (inputTimestamp1.Hour < inputTimestamp2.Hour) return DateComparison.lt;
			if (inputTimestamp1.Minute > inputTimestamp2.Minute) return DateComparison.gt;
			if (inputTimestamp1.Minute < inputTimestamp2.Minute) return DateComparison.lt;
			if (inputTimestamp1.Second > inputTimestamp2.Second) return DateComparison.gt;
			if (inputTimestamp1.Second < inputTimestamp2.Second) return DateComparison.lt;
			if (inputTimestamp1.Millisecond > inputTimestamp2.Millisecond) return DateComparison.gt;
			if (inputTimestamp1.Millisecond < inputTimestamp2.Millisecond) return DateComparison.lt;
			return DateComparison.eq;
		
		}

Initrode has a bright future with this product. Deon adds:

The contractor who is replacing me has rolled his own piece of software to try and replace Entity Framework because his version is “better” despite being written around a decade ago, so I’m sure he’ll fit right in.

The future’s so bright I’ve gotta wear shades.

Here’s the full block, if you want to suffer through that:

/*
  Changes Log:

  @01 - 01/23/2009 - {some initials were here} - Improve performance of approval screens.
*/
using System;
using System.Collections;
using System.Globalization; 
using System.Text;

namespace initrode.utilities
{
	/// <summary>
	/// Summary description for DateManager.
	/// </summary>
	public class DateManager
	{
		public enum	DateComparison {gt = 1, eq = 0, lt = -1}
        public enum DateTimeParts
        {
            dateOnly
            , dateAndTime
            , dateTimeAndAMOrPM
        }
						
		/*
			* @description return the days difference from today date
			* @parm int amount of days in the past
			* @return int the amount of days difference
			* 
			**/
		public static int subStractFromCurrentDate(System.DateTime dateTimeParm) 
		{
			//get now
			System.DateTime now = System.DateTime.Now;
			//now compare days
			int daysDifference  = now.Day - dateTimeParm.Day;
			return daysDifference ;
		}
		/**
		 * @description format date
		 * */
		public static string format (System.DateTime dateTime, string format) 
		{
			string dateFormat;
			dateFormat = dateTime.ToString(format,DateTimeFormatInfo.InvariantInfo);
			return dateFormat;
		}
        public static DateTime  convertDateStringInSlashedFormatToDateTime
                                (
                                    string inputDateStringInSlashedFormat
                                )
        {
            inputDateStringInSlashedFormat =
                initrode.utilities.StringManager.StripWhitespace
                (
                    inputDateStringInSlashedFormat
                );
            ArrayList _dateParts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    inputDateStringInSlashedFormat
                    ,@"/"
                );
            if (_dateParts.Count != 3) return new DateTime(1900, 1, 1);

            string _monthString =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _dateParts[0].ToString()
                );
            if (
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        _monthString
                    ) == false
                )
                new DateTime(1900, 1, 1);

            string _dayString =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _dateParts[1].ToString()
                );
            if (
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        _dayString
                    ) == false
                )
                new DateTime(1900, 1, 1);

            string _yearString =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _dateParts[2].ToString()
                );
            if (
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        _yearString
                    ) == false
                )
                new DateTime(1900, 1, 1);
            return new DateTime
                        (
                            Convert.ToInt32
                            (
                                _yearString
                            )
                            , Convert.ToInt32
                            (
                                _monthString
                            )
                            , Convert.ToInt32
                            (
                                _dayString
                            )
                        );
        }            
		/**
		 * @description format date
		 * */
		public static string formatEnglishDate (System.DateTime inputDateTime) 
		{
			Hashtable _monthsInEnglishByMonthNumber = new Hashtable();
			_monthsInEnglishByMonthNumber[1] = "January";
			_monthsInEnglishByMonthNumber[2] = "February";
			_monthsInEnglishByMonthNumber[3] = "March";
			_monthsInEnglishByMonthNumber[4] = "April";
			_monthsInEnglishByMonthNumber[5] = "May";
			_monthsInEnglishByMonthNumber[6] = "June";
			_monthsInEnglishByMonthNumber[7] = "July";
			_monthsInEnglishByMonthNumber[8] = "August";
			_monthsInEnglishByMonthNumber[9] = "September";
			_monthsInEnglishByMonthNumber[10] = "October";
			_monthsInEnglishByMonthNumber[11] = "November";
			_monthsInEnglishByMonthNumber[12] = "December";

			StringBuilder _dateBldr = new StringBuilder();
			_dateBldr.Append(_monthsInEnglishByMonthNumber[inputDateTime.Month].ToString());
			_dateBldr.Append(" ");
			_dateBldr.Append(inputDateTime.Day.ToString());
			_dateBldr.Append(", ");
			_dateBldr.Append(inputDateTime.Year.ToString());

			return _dateBldr.ToString();
		}
        public static bool currentDateIsFirstSaturdayOfTheMonth()
        {
            /*
             * If current date is not a business date, then it cannot
             * be the first business date of the month.
             */
            DateTime _currentDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            if (
                    _currentDate.DayOfWeek == DayOfWeek.Saturday
                    &&
                    _currentDate.Day <= 7
                )
                return true;

            return false;
        }

        public static bool  currentDateIsFirstBusinessDateOfTheMonth 
                            (
                                Hashtable inputHolidayHash
                            )
        {
            /*
             * If current date is not a business date, then it cannot
             * be the first business date of the month.
             */
            DateTime _currentDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            _currentDate =
                new DateTime(2010, 5, 6);
            if (
                    _currentDate.DayOfWeek == DayOfWeek.Saturday
                    ||
                    _currentDate.DayOfWeek == DayOfWeek.Sunday
                    ||
                    inputHolidayHash[_currentDate] != null
                )
                return false;

            /*
             * If current date is a business date, and if it is also
             * the first calendar date of the month, then the
             * current date is the first business date of the month.
             */

            DateTime _firstDayOfTheMonth =
                _currentDate.AddDays(1 - _currentDate.Day);
            if (_firstDayOfTheMonth == _currentDate)
                return true;

            /*
             * If current date is a business date, but is not the 1st calendar
             * date of the month, and, if, in stepping back day by day 
             * from the current date,  we encounter a business day before 
             * encountering the last calendar day of the preceding month, then the 
             * current date is NOT the first business date of the month.
            */
            DateTime _tempDate = _currentDate.AddDays(-1);
            while (_tempDate >= _firstDayOfTheMonth)
            {
                if (
                        _tempDate.DayOfWeek != DayOfWeek.Saturday
                        &&
                        _tempDate.DayOfWeek != DayOfWeek.Sunday
                        &&
                        inputHolidayHash[_tempDate] == null
                    )
                    return false;
                _tempDate = _tempDate.AddDays(-1);
            }
            /*
             * * If current date is a business date, but is not the 1st calendar
             * date,and, if, in stepping back day by day from the current date, 
             * we encounter no business day before encountering the 
             * 1st calendar day of the month, then the current date 
             * IS the first business date of the month.
            */
            return true;
        }
        //@??
        public static DateTime givenPeriodEndDateFindLastBusinessDateInPeriod
                                (
                                    DateTime inputPeriodEndDate
                                    , Hashtable inputHolidayHash
                                )
        {
            if (inputHolidayHash[inputPeriodEndDate] == null)
                return inputPeriodEndDate;
            DateTime _tempDate = inputPeriodEndDate.AddDays(-1);

            while (
                        (
                            _tempDate.DayOfWeek == DayOfWeek.Saturday
                            ||
                            _tempDate.DayOfWeek == DayOfWeek.Sunday
                        )
                        ||
                        inputHolidayHash[_tempDate] != null
                    )
            {
                _tempDate = _tempDate.AddDays(-1);
            }
            return _tempDate;
        }

		/**
		 * @description format date
		 * */
        public static string convertDateTimeToSQLDate
                                (
                                    DateTime inputDateTime
                                )
        {
            StringBuilder _sqlDateBldr =
                new StringBuilder();
            _sqlDateBldr.AppendFormat
            (
                "{0}/{1}/{2}"
                ,inputDateTime.Month.ToString()
                ,inputDateTime.Day.ToString()
                ,inputDateTime.Year.ToString()
            );
            return _sqlDateBldr.ToString();
        }
        /**
         * @description format date
         * */
        public static string convertDateTimeToDB2Timestamp
                                (
                                    DateTime inputDateTime
                                )
        {
            StringBuilder _sqlDateBldr =
                new StringBuilder();
            _sqlDateBldr.AppendFormat
            (
                "{0}-{1}-{2}.{3}:{4}:{5}.{6}"
                , inputDateTime.Year.ToString()
                ,   initrode.utilities.StringManager.Fill
                    (
                        inputDateTime.Month.ToString()
                        ,"0"
                        ,true  //boolFromLeft
                        ,2
                    )
                ,   initrode.utilities.StringManager.Fill
                    (
                        inputDateTime.Day.ToString()
                        ,"0"
                        ,true  //boolFromLeft
                        ,2
                    )
                , initrode.utilities.StringManager.Fill
                    (
                        inputDateTime.Hour.ToString()
                        ,"0"
                        ,true  //boolFromLeft
                        ,2
                    )
                , initrode.utilities.StringManager.Fill
                    (
                        inputDateTime.Minute.ToString()
                        ,"0"
                        ,true  //boolFromLeft
                        ,2
                    )
                ,   initrode.utilities.StringManager.Fill
                    (
                        inputDateTime.Second.ToString()
                        , "0"
                        , true  //boolFromLeft
                        , 2
                    )
                ,   initrode.utilities.StringManager.Fill
                    (
                        inputDateTime.Millisecond.ToString()
                        , "0"
                        , true  //boolFromLeft
                        , 2
                    )
            );
            return _sqlDateBldr.ToString();
        }

		/**
		 * @description format date
		 * */
		public static string formatYYYYMMDD (System.DateTime inputDateTime) 
		{
			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(inputDateTime.Year.ToString());
			_bldr.Append(initrode.utilities.StringManager.Fill(inputDateTime.Month.ToString(),
															"0",       // Zero-Fill
															true,	   // Fill from left
															2));        // String length

			_bldr.Append(initrode.utilities.StringManager.Fill(inputDateTime.Day.ToString(),
															"0",       // Zero-Fill
															true,	   // Fill from left
															2));       // String length
			return _bldr.ToString();
		}
		//@01
		public static DateTime givenDateGetPeriodStartDate(DateTime inputDate1)
		{
			if (inputDate1.Day > 15) return new DateTime(inputDate1.Year,inputDate1.Month,16);
			return new DateTime(inputDate1.Year,inputDate1.Month,1);
		}
		//@01
		public static DateTime givenDateGetPeriodEndDate(DateTime inputDate1)
		{
			if (inputDate1.Day < 16) return new DateTime(inputDate1.Year,inputDate1.Month,15);
			inputDate1 = inputDate1.AddMonths(1);
			inputDate1 = new DateTime(inputDate1.Year,inputDate1.Month,1).AddDays(-1);
			return inputDate1;
		}

		/**
		 * @description add days to a date
		 * */
		public static DateTime addDays (DateTime dateTime, int days) 
		{
			DateTime newDate = dateTime.AddDays(days);
			return newDate;
		}
		/** 
		 * @description get first day of the  month from mm-dd-yyyy formatted string
		 * **/
		public static DateTime getFirstDayofTheMonthFromMM_DD_YYYYFormattedString(
									string inputDateTimeInMM_DD_YYYYFormatString) 
		{
			if (initrode.utilities.StringManager.IsValidDateInMM_DD_YYYYFormat(inputDateTimeInMM_DD_YYYYFormatString) == false)
			{
				return initrode.utilities.DateManager.getFirstDayofTheCurrentMonth();
			}
			return initrode.utilities.DateManager.getFirstDayofTheMonth(Convert.ToDateTime(inputDateTimeInMM_DD_YYYYFormatString));
		}


		/** 
		 * @description get first day of the  month
		 * **/
		public static DateTime getFirstDayofTheMonth(System.DateTime inputDateTime) 
		{
			return new DateTime(inputDateTime.Year,
								inputDateTime.Month,
								1);
		}

        public static DateTime  convertTimestampOrDateInAnyStringFormatToDateTime
                                (
                                    string inputTimestampOrDateInAnyStringFormat
                                )
        {
            DateTime _returnDateTime = 
                new DateTime(1900, 1, 1);
            ArrayList _splitDateTimeParts = new ArrayList();
            inputTimestampOrDateInAnyStringFormat =
                initrode.utilities.StringManager.StripWhitespaceFromEnds
                (
                    inputTimestampOrDateInAnyStringFormat
                );
            DateTimeParts _myDateTimeParts = DateTimeParts.dateOnly;
            string _timeParts = "";
            string _amOrPMParts = "";
            if (inputTimestampOrDateInAnyStringFormat.Contains(" "))
            {
                _splitDateTimeParts =
                    initrode.utilities.StringManager.splitIntoArrayList
                    (
                        inputTimestampOrDateInAnyStringFormat
                        , " "
                    );
            }
            else
            {
                _splitDateTimeParts.Add
                (
                    inputTimestampOrDateInAnyStringFormat
                );
            }
            DateTime _dateOnly = new DateTime(1900, 1, 1);
            switch (_splitDateTimeParts.Count)
            {
                case 1:
                    _myDateTimeParts = DateTimeParts.dateOnly;
                    _dateOnly =
                        initrode.utilities.DateManager.convertDateInAnyStringFormatIntoDateTime
                        (
                            inputTimestampOrDateInAnyStringFormat
                        );
                    break;
                case 2:
                    _myDateTimeParts = DateTimeParts.dateAndTime;
                    _dateOnly =
                        initrode.utilities.DateManager.convertDateInAnyStringFormatIntoDateTime
                        (
                            _splitDateTimeParts[0].ToString()
                        );
                    _timeParts =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _splitDateTimeParts[1].ToString()
                        );
                    break;
                case 3:
                    _myDateTimeParts = DateTimeParts.dateTimeAndAMOrPM;
                    _dateOnly =
                        initrode.utilities.DateManager.convertDateInAnyStringFormatIntoDateTime
                        (
                            _splitDateTimeParts[0].ToString()
                        );
                    _timeParts =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _splitDateTimeParts[1].ToString()
                        );
                    _amOrPMParts =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _splitDateTimeParts[2].ToString()
                        ).ToUpper();

                    break;
                default:
                    return _returnDateTime;
            }
            if (_myDateTimeParts == DateTimeParts.dateOnly) return _dateOnly;
            if (_dateOnly == new DateTime(1900, 1, 1)) return _returnDateTime;

            if (
                    _myDateTimeParts == DateTimeParts.dateTimeAndAMOrPM
                    &&
                    _amOrPMParts.CompareTo("AM") != 0
                    &&
                    _amOrPMParts.CompareTo("PM") != 0
                ) return _returnDateTime;
                
            switch (_myDateTimeParts)
            {
                case DateTimeParts.dateAndTime:
                return  initrode.utilities.DateManager.convertTimeInStringFormatAlongWithDateOnlyDateTimeIntoDateTime
                        (
                            _timeParts //string inputStrTime
                            , false //bool inputAMOrPMFormat
                            , "" //string inputAMOrPM
                            , _dateOnly //DateTime inputDateOnlyDateTime
                        );
                case DateTimeParts.dateTimeAndAMOrPM:
                return initrode.utilities.DateManager.convertTimeInStringFormatAlongWithDateOnlyDateTimeIntoDateTime
                        (
                            _timeParts //string inputStrTime
                            , true //bool inputAMOrPMFormat
                            , _amOrPMParts //string inputAMOrPM
                            , _dateOnly //DateTime inputDateOnlyDateTime
                        );
            }
            return _returnDateTime;
        }
        public static DateTime convertTimeInStringFormatAlongWithDateOnlyDateTimeIntoDateTime
                                (
                                    string inputStrTime
                                    ,bool inputAMOrPMFormat
                                    ,string inputAMOrPM
                                    ,DateTime inputDateOnlyDateTime
                                )
        {
            DateTime _returnDateTime = inputDateOnlyDateTime;
            if (inputStrTime.Contains(":") == false) return _returnDateTime;

            int _intMillisecondsPart = 0;
            if (inputStrTime.Contains(".") == true)
            {
                ArrayList _millisecondsAndTimeParts =
                    initrode.utilities.StringManager.splitIntoArrayList
                    (
                        inputStrTime
                        ,@"."
                    );
                if (_millisecondsAndTimeParts.Count != 2) return _returnDateTime;
                string _strMillisecondsPart =
                    initrode.utilities.StringManager.StripWhitespace
                    (
                        _millisecondsAndTimeParts[1].ToString()
                    );
                if (initrode.utilities.StringManager.IsValidNumber(_strMillisecondsPart) == true)
                    _intMillisecondsPart =
                        Convert.ToInt32
                        (
                            _strMillisecondsPart
                        );
                inputStrTime =
                    initrode.utilities.StringManager.StripWhitespace
                    (
                        _millisecondsAndTimeParts[0].ToString()
                    );
            }
            ArrayList _timeParts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    inputStrTime
                    ,":"
                );
            if (_timeParts.Count != 3) return _returnDateTime;


            string _strHoursPart =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _timeParts[0].ToString()
                );
            string _strMinutesPart =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _timeParts[1].ToString()
                );
            string _strSecondsPart =
                initrode.utilities.StringManager.StripWhitespace
                (
                    _timeParts[2].ToString()
                );
            if (
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        _strHoursPart
                    ) == false
                    ||
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        _strMinutesPart
                    ) == false
                    ||
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        _strSecondsPart
                    ) == false
                ) return _returnDateTime;

            int _intHoursPart =
                Convert.ToInt32
                (
                    _strHoursPart
                );
            int _intMinutesPart =
                Convert.ToInt32
                (
                    _strMinutesPart
                );
            int _intSecondsPart =
                Convert.ToInt32
                (
                    _strSecondsPart
                );

            if (_intHoursPart > 23) return _returnDateTime;
            if (inputAMOrPMFormat == true)
            {
                if (_intHoursPart > 12) return _returnDateTime;
            }
            if (_intMinutesPart > 59) return _returnDateTime;
            if (_intSecondsPart > 59) return _returnDateTime;

            if (inputAMOrPMFormat == true)
            {
                if (inputAMOrPM.CompareTo("PM") == 0)
                {
                    _intHoursPart += 12;
                }
                else if (
                            inputAMOrPM.CompareTo("AM") == 0
                            &&
                            _intHoursPart == 12
                            &&
                            _intMinutesPart == 0
                            &&
                            _intSecondsPart == 0
                            &&
                            _intMillisecondsPart == 0
                        )
                {
                    return new DateTime
                                (
                                    inputDateOnlyDateTime.Year
                                    , inputDateOnlyDateTime.Month
                                    , inputDateOnlyDateTime.Day
                                );
                }
            }
            _returnDateTime =
                new DateTime
                    (
                        inputDateOnlyDateTime.Year
                        , inputDateOnlyDateTime.Month
                        , inputDateOnlyDateTime.Day
                        , _intHoursPart
                        , _intMinutesPart
                        , _intSecondsPart
                        , _intMillisecondsPart
                    );
            return _returnDateTime;
        }
        public static DateTime convertDateInAnyStringFormatIntoDateTime
                                (
                                    string inputDateInAnyStringFormat   
                                )
        {
            DateTime _returnDateTime = new DateTime(1900, 1, 1);
            inputDateInAnyStringFormat =
                initrode.utilities.StringManager.StripWhitespace
                (
                    inputDateInAnyStringFormat
                );
            ArrayList _dateParts = new ArrayList();
            string _strMonth = "";
            string _strDay = "";
            string _strYear = "";
            if (inputDateInAnyStringFormat.Contains("/") == true)
            {
                _dateParts =
                    initrode.utilities.StringManager.splitIntoArrayList
                    (
                        inputDateInAnyStringFormat
                        ,@"/"
                    );
                if (_dateParts.Count != 3) return _returnDateTime;
                _strMonth =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _dateParts[0].ToString()
                        );
                _strDay =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _dateParts[1].ToString()
                        );
                _strYear =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _dateParts[2].ToString()
                        );
                return initrode.utilities.DateManager.convertDateTimeStringPartsIntoDateTime
                        (
                            _strMonth
                            ,_strDay
                            ,_strYear
                        );
            }
            if (inputDateInAnyStringFormat.Contains("-") == true)
            {
                _dateParts =
                    initrode.utilities.StringManager.splitIntoArrayList
                    (
                        inputDateInAnyStringFormat
                        , @"-"
                    );
                if (_dateParts.Count != 3) return _returnDateTime;
                _strYear =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _dateParts[0].ToString()
                        );
                _strMonth =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _dateParts[1].ToString()
                        );
                _strDay =
                        initrode.utilities.StringManager.StripWhitespace
                        (
                            _dateParts[2].ToString()
                        );
                return initrode.utilities.DateManager.convertDateTimeStringPartsIntoDateTime
                        (
                            _strMonth
                            , _strDay
                            , _strYear
                        );
            }
            if (inputDateInAnyStringFormat.Length == 8)
            {
                _strYear =
                    inputDateInAnyStringFormat.Substring(0, 4);
                _strMonth =
                    inputDateInAnyStringFormat.Substring(4, 2);
                _strDay =
                    inputDateInAnyStringFormat.Substring(6, 2);
                return initrode.utilities.DateManager.convertDateTimeStringPartsIntoDateTime
                        (
                            _strMonth
                            , _strDay
                            , _strYear
                        );
            }
            if (inputDateInAnyStringFormat.Length == 6)
            {
                _strYear =
                    inputDateInAnyStringFormat.Substring(0, 2);
                _strMonth =
                    inputDateInAnyStringFormat.Substring(2, 2);
                _strDay =
                    inputDateInAnyStringFormat.Substring(4, 2);
                return initrode.utilities.DateManager.convertDateTimeStringPartsIntoDateTime
                        (
                            _strMonth
                            , _strDay
                            , _strYear
                        );
            }
            return _returnDateTime;
        }
        public static DateTime convertDateTimeStringPartsIntoDateTime
                                (
                                    string inputStrMonth
                                    , string inputStrDay
                                    , string inputStrYear
                                )
        {
            DateTime _returnDateTime = new DateTime(1900, 1, 1);
            if (
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        inputStrMonth
                    ) == false
                    ||
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        inputStrDay
                    ) == false
                    ||
                    initrode.utilities.StringManager.IsValidNumber
                    (
                        inputStrYear
                    ) == false
                ) return _returnDateTime;

            int _intYear =
                Convert.ToInt32
                (
                    inputStrYear
                );
            if (_intYear <= 100)
            {
                if (_intYear >= 90)
                {
                    _intYear += 1900;
                }
                else
                {
                    _intYear += 2000;
                }
            }
            inputStrYear = _intYear.ToString();

            inputStrMonth = 
                initrode.utilities.StringManager.Fill
                (
                    inputStrMonth
                    ,"0"
                    ,true //fromLeft
                    ,2
                );

            inputStrDay = 
                initrode.utilities.StringManager.Fill
                (
                    inputStrDay
                    ,"0"
                    ,true //fromLeft
                    ,2
                );

            if (
                    initrode.utilities.StringManager.IsValidDate
                    (
                        inputStrMonth
                        ,inputStrDay
                        ,inputStrYear
                    ) == false
                ) return _returnDateTime;

            _returnDateTime =
                new DateTime
                    (
                        Convert.ToInt32
                        (
                            inputStrYear
                        )
                        ,   Convert.ToInt32
                            (
                                inputStrMonth
                            )
                        , Convert.ToInt32
                            (
                                inputStrDay
                            )
                    );
            return _returnDateTime;
        }
        public static DateTime convertDateIn_MM_Slash_DD_Slash_YYYY_FormatToDateTime
                                (
                                    string inputDateIn_MM_Slash_DD_Slash_YYYY_Format
                                )
        {
            if (initrode.utilities.StringManager.IsValidDateInMM_DD_YYYYFormat(inputDateIn_MM_Slash_DD_Slash_YYYY_Format) == false)
                return Convert.ToDateTime("1/1/1900");
            ArrayList _dateParts =
                initrode.utilities.StringManager.splitIntoArrayList
                (
                    inputDateIn_MM_Slash_DD_Slash_YYYY_Format
                    ,"/"
                );
            string _mm = _dateParts[0].ToString();
            if (_mm.Substring(0, 1).CompareTo("0") == 0)
                _mm = _mm.Substring(1, 1);
            string _dd = _dateParts[1].ToString();
            if (_dd.Substring(0, 1).CompareTo("0") == 0)
                _dd = _dd.Substring(1, 1);
            string _yyyy = _dateParts[2].ToString();

            return new DateTime
                        (
                                Convert.ToInt32
                                (
                                    _yyyy
                                )
                            ,   Convert.ToInt32
                                (
                                    _mm
                                )
                            ,   Convert.ToInt32
                                (
                                    _dd
                                )
                        );
        }
        public static bool  isInputtedDateTheLastBusinessDateOfTheMonth
                            (
                                DateTime inputDateTime
                                , Hashtable inputHolidayHash
                            )
        {
            inputDateTime =
                new DateTime
                    (
                        inputDateTime.Year
                        , inputDateTime.Month
                        , inputDateTime.Day
                    );

            DateTime _lastBusinessDate =
                initrode.utilities.DateManager.getLastBusinessDateOfMonthForInputtedDate
                (
                    inputDateTime
                    ,inputHolidayHash
                );
            if (
                    inputDateTime.Year == _lastBusinessDate.Year
                    && inputDateTime.Month == _lastBusinessDate.Month
                    && inputDateTime.Day == _lastBusinessDate.Day
                )
                return true;
            return false;
        }

        public static DateTime  getLastBusinessDateOfMonthForInputtedDate
                                (
                                    DateTime inputDateTime
                                    , Hashtable inputHolidayHash
                                )
        {
            inputDateTime = 
                new DateTime
                    (
                        inputDateTime.Year
                        ,inputDateTime.Month
                        ,inputDateTime.Day
                    );
            DateTime _lastBusinessDate;
            if (
                    initrode.utilities.DateManager.isInputtedDateABusinessDate
                    (
                        inputDateTime
                        , inputHolidayHash
                    ) == true
                )
                _lastBusinessDate =
                    inputDateTime;
            else
                _lastBusinessDate =
                    initrode.utilities.DateManager.getNextBusinessDateFromInputtedDate
                    (
                        inputDateTime
                        , inputHolidayHash
                    );
            if (_lastBusinessDate.Month != inputDateTime.Month)
            {
                if (
                        initrode.utilities.DateManager.isInputtedDateABusinessDate
                        (
                            inputDateTime
                            , inputHolidayHash
                        ) == true
                    )
                    return inputDateTime;
                else
                    return
                        initrode.utilities.DateManager.getPreviousBusinessDateFromInputtedDate
                        (
                            inputDateTime
                            , inputHolidayHash
                        );
            } 
            DateTime _nextBusinessDate =
                initrode.utilities.DateManager.getNextBusinessDateFromInputtedDate
                (
                    _lastBusinessDate
                    , inputHolidayHash
                );
            while (_nextBusinessDate.Month == inputDateTime.Month)
            {
                _lastBusinessDate =
                    _nextBusinessDate;

                _nextBusinessDate =
                    initrode.utilities.DateManager.getNextBusinessDateFromInputtedDate
                    (
                        _lastBusinessDate
                        , inputHolidayHash
                    );
            }
            return _lastBusinessDate;
        }
        public static DateTime  getPreviousBusinessDateFromInputtedDate
                                (
                                    DateTime inputDateTime
                                    , Hashtable inputHolidayHash
                                )
        {
            DateTime _dateWithTimeOmitted =
                new DateTime
                    (
                        inputDateTime.Year
                        , inputDateTime.Month
                        , inputDateTime.Day
                    );
            _dateWithTimeOmitted =
                _dateWithTimeOmitted.AddDays(-1);
            while (
                        initrode.utilities.DateManager.isInputtedDateABusinessDate
                        (
                            _dateWithTimeOmitted
                            , inputHolidayHash
                        ) == false
                    )
            {
                _dateWithTimeOmitted =
                    _dateWithTimeOmitted.AddDays(-1);
            }
            return _dateWithTimeOmitted;
        }

        public static DateTime  getNextBusinessDateFromInputtedDate
                                (
                                    DateTime inputDateTime
                                    , Hashtable inputHolidayHash
                                )
        {
            DateTime _dateWithTimeOmitted =
                new DateTime
                    (
                        inputDateTime.Year
                        , inputDateTime.Month
                        , inputDateTime.Day
                    );
            _dateWithTimeOmitted.AddDays(1);
            while   (
                        initrode.utilities.DateManager.isInputtedDateABusinessDate
                        (
                            _dateWithTimeOmitted
                            ,inputHolidayHash
                        ) == false
                    )
            {
                _dateWithTimeOmitted.AddDays(1);
            }
            return _dateWithTimeOmitted;
        }

        public static bool      isInputtedDateABusinessDate
                                (
                                    DateTime inputDateTime
                                    ,Hashtable inputHolidayHash
                                )
        {
            DateTime _dateWithTimeOmitted =
                new DateTime
                    (
                        inputDateTime.Year
                        ,inputDateTime.Month
                        ,inputDateTime.Day
                    );
            if (_dateWithTimeOmitted.DayOfWeek == DayOfWeek.Saturday
                || _dateWithTimeOmitted.DayOfWeek == DayOfWeek.Sunday)
                return false;
            foreach (DateTime _holidayDate in inputHolidayHash.Keys)
            {
                if (
                        _holidayDate.Year == inputDateTime.Year
                        && _holidayDate.Month == inputDateTime.Month
                        && _holidayDate.Day == inputDateTime.Day
                    )
                {
                    return false;
                }
            }
            return true;
        }
        public static string    convertDateTimeToMMDDYYYY_WithoutSlashesOrDashes
                                (
                                    DateTime inputDateTime
                                )
        {
            StringBuilder _dateBldr =
                new StringBuilder();
            _dateBldr.AppendFormat
            (
                "{0}{1}{2}"
                , initrode.utilities.StringManager.Fill
                (
                    inputDateTime.Month.ToString()
                    , "0"
                    , true //from left
                    , 2
                )
                ,initrode.utilities.StringManager.Fill
                (
                    inputDateTime.Day.ToString()
                    , "0"
                    , true //from left
                    , 2
                )
                ,inputDateTime.Year.ToString()
            );
            return _dateBldr.ToString();
        }
        public static DateTime  convertMMDDYYYY_WithoutSlashesOrDashesToDateTime
                                (
                                    string inputMMDDYYYY
                                )
        {
            inputMMDDYYYY = 
                initrode.utilities.StringManager.StripWhitespace
                (
                    inputMMDDYYYY
                );
            StringBuilder _mmSlashddSlashyyyyBldr =
                new StringBuilder();
            _mmSlashddSlashyyyyBldr.AppendFormat
            (
                "{0}/{1}/{2}"
                ,inputMMDDYYYY.Substring(0,2)
                ,inputMMDDYYYY.Substring(2,2)
                ,inputMMDDYYYY.Substring(4,4)
            );
            if (
                    initrode.utilities.StringManager.IsValidDateInMM_DD_YYYYFormat
                    (
                        _mmSlashddSlashyyyyBldr.ToString()
                    ) == false
                )
                return new DateTime(1900, 1, 1);
            DateTime _returnDateTime =
                new DateTime
                    (
                        Convert.ToInt32
                        (
                            inputMMDDYYYY.Substring(4, 4)
                        )
                        , Convert.ToInt32
                        (
                            inputMMDDYYYY.Substring(0, 2)
                        )
                        , Convert.ToInt32
                        (
                            inputMMDDYYYY.Substring(2, 2)
                        )
                    );
            return _returnDateTime;
        }

		public static DateTime	convertDateInYYYYMMDDFormatToDateTime
								(
									string inputDateInYYYYMMDDFormat
								)
		{
			if (initrode.utilities.StringManager.IsValidDateInYYYYMMDDFormat(inputDateInYYYYMMDDFormat) == false) 
                return Convert.ToDateTime("1/1/1900");
			return new	DateTime
						(
							Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(0,4))
							,Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(4,2))
							,Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(6,2))
						);
		}
		public static DateTime	getNextPeriodStartDateFromGivenDate
								(
									DateTime inputDate
								)
		{
			if (inputDate.Day == 1) return inputDate;
			if (inputDate.Day == 16) return inputDate;
			if (inputDate.Day <= 15) return inputDate.AddDays(16 - inputDate.Day);
			return inputDate.AddMonths(1).AddDays(1 - inputDate.Day);
		}
		public static DateTime	getNextPeriodEndDateFromGivenPeriodStartDate
								(
									DateTime inputPeriodStartDate
								)
		{
			if (inputPeriodStartDate.Day == 1) return inputPeriodStartDate.AddDays(15 - inputPeriodStartDate.Day);
			return inputPeriodStartDate.AddMonths(1).AddDays(0 - inputPeriodStartDate.Day);
		}

		public static DateTime	convertDateInYYYYMMDDFormatAndTimeInHHColonMIColonSSFormatToDateTime
								(
									string inputDateInYYYYMMDDFormat,
									string inputTimeInHHColonMIColonSSFormat
								)
		{
			inputDateInYYYYMMDDFormat = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputDateInYYYYMMDDFormat);
			inputTimeInHHColonMIColonSSFormat = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputTimeInHHColonMIColonSSFormat);
			if (inputDateInYYYYMMDDFormat.Length != 8 ||
				initrode.utilities.StringManager.IsValidDateInYYYYMMDDFormat(inputDateInYYYYMMDDFormat) == false) return new DateTime(1900,1,1);
		
			if (inputTimeInHHColonMIColonSSFormat.Length != 8 ||
				initrode.utilities.StringManager.IsValidTimeInHHColonMIColonSSFormat(inputTimeInHHColonMIColonSSFormat) == false)
					return new	DateTime 
								(
									Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(0,4)),
									Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(4,2)),
									Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(6,2))
								);

			return new	DateTime 
						( 
							Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(0,4)),
							Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(4,2)),
							Convert.ToInt32(inputDateInYYYYMMDDFormat.Substring(6,2)),
							Convert.ToInt32(inputTimeInHHColonMIColonSSFormat.Substring(0,2)),
							Convert.ToInt32(inputTimeInHHColonMIColonSSFormat.Substring(3,2)),
							Convert.ToInt32(inputTimeInHHColonMIColonSSFormat.Substring(6,2))
						);
		
		}
        public static bool validateTimestampInODBCCanonicalFormat
                           (
                              string inputTimestampInODBCCanonicalFormat
                           )
        {
            if (inputTimestampInODBCCanonicalFormat.Length != 23)
                return false;

            if (initrode.utilities.StringManager.IsValidNumber(inputTimestampInODBCCanonicalFormat.Substring(0, 4)) == false
                || initrode.utilities.StringManager.IsValidNumber(inputTimestampInODBCCanonicalFormat.Substring(5, 2)) == false
                || initrode.utilities.StringManager.IsValidNumber(inputTimestampInODBCCanonicalFormat.Substring(8, 2)) == false
                || initrode.utilities.StringManager.IsValidNumber(inputTimestampInODBCCanonicalFormat.Substring(11, 2)) == false
                || initrode.utilities.StringManager.IsValidNumber(inputTimestampInODBCCanonicalFormat.Substring(14, 2)) == false
                || initrode.utilities.StringManager.IsValidNumber(inputTimestampInODBCCanonicalFormat.Substring(17, 2)) == false
                || initrode.utilities.StringManager.IsValidNumber(inputTimestampInODBCCanonicalFormat.Substring(20, 3)) == false)
                return false;

            string _yyyy =
                inputTimestampInODBCCanonicalFormat.Substring(0, 4);
            string _mm =
                inputTimestampInODBCCanonicalFormat.Substring(5, 2);
            string _dd =
                inputTimestampInODBCCanonicalFormat.Substring(8, 2);
            if (initrode.utilities.StringManager.IsValidDate
                (
                    _mm
                    ,_dd
                    ,_yyyy
                ) == false)
                return false;

            StringBuilder _timeBldr =
                new StringBuilder();
            _timeBldr.Append
            (
                inputTimestampInODBCCanonicalFormat.Substring(11, 2)
            );
            _timeBldr.Append
            (
                ":"
            );
            _timeBldr.Append
            (
                inputTimestampInODBCCanonicalFormat.Substring(14, 2)
            );
            _timeBldr.Append
            (
                ":"
            );
            _timeBldr.Append
            (
                inputTimestampInODBCCanonicalFormat.Substring(17, 2)
            );
            if (initrode.utilities.StringManager.IsValidTimeInHHColonMIColonSSFormat
                (
                    _timeBldr.ToString()
                ) == false)
                return false;
            return true;
        }
        public static DateTime  convertTimestampInODBCCanonicalFormatToDateTime
                                (
                                    string inputTimestampInODBCCanonicalFormat
                                )
        {
            if (validateTimestampInODBCCanonicalFormat
                    (
                        inputTimestampInODBCCanonicalFormat
                     ) == false)
                return new DateTime(1900, 1, 1);

            int _yyyy = 
                Convert.ToInt32(inputTimestampInODBCCanonicalFormat.Substring(0,4));
            int _mm = 
                Convert.ToInt32(inputTimestampInODBCCanonicalFormat.Substring(5,2));
            int _dd = 
                Convert.ToInt32(inputTimestampInODBCCanonicalFormat.Substring(8,2));

            int _hh =
                Convert.ToInt32(inputTimestampInODBCCanonicalFormat.Substring(11, 2));
            int _mi =
                Convert.ToInt32(inputTimestampInODBCCanonicalFormat.Substring(14, 2));
            int _ss =
                Convert.ToInt32(inputTimestampInODBCCanonicalFormat.Substring(17, 2));
            int _ms =
                Convert.ToInt32(inputTimestampInODBCCanonicalFormat.Substring(20, 3));
            return new DateTime
                        (
                            _yyyy
                            , _mm
                            , _dd
                            , _hh
                            , _mi
                            , _ss
                            , _ms
                         );   
        }

		/** 
		 * 
		 * @description get first day of the current month
		 * **/
		public static DateTime getFirstDayofTheCurrentMonth() 
		{
			return initrode.utilities.DateManager.getFirstDayofTheMonth(System.DateTime.Now);
		}

        public static DateTime convertDateTimeToDate
                                (
                                    DateTime inputTimestamp
                                )
        {
            DateTime _returnDate =
                new DateTime
                    (
                        inputTimestamp.Year
                        ,inputTimestamp.Month
                        ,inputTimestamp.Day
                    );
            return _returnDate;
        }
		/**
		 * @description get the last day of the month
		 * */
							   	
		public static DateTime getLastDayOfTheMonth( System.DateTime inputDateTime) 
		{
			return initrode.utilities.DateManager.getFirstDayofNextMonth(inputDateTime).AddDays(-1);
		}
		/** 
		 * @description get last day of the current month
		 * **/
		public static DateTime getLastDayofTheCurrentMonth() 
		{
			return initrode.utilities.DateManager.getLastDayOfTheMonth(DateTime.Now);
		}

		/** 
		 * Convert the DateTime value to YYYYMMDD format
		 * **/
		public static string convertDateTimeToYYYYMMDDFormat(DateTime inputDateTime)
		{
			StringBuilder _dateBldr = new StringBuilder();
			_dateBldr.Append(inputDateTime.Year.ToString());
			_dateBldr.Append(initrode.utilities.StringManager.Fill(inputDateTime.Month.ToString(),"0",true,2));
			_dateBldr.Append(initrode.utilities.StringManager.Fill(inputDateTime.Day.ToString(),"0",true,2));
			return _dateBldr.ToString();
		}
		/** 
		 * Convert the DateTime value to MM, DD, YYYY character parts
		 * **/
		public static void convertDateTimeToMM_DD_YYYYStringParts(DateTime inputDateTime,
																	out string outputMM,
																	out string outputDD,
																	out string outputYYYY)
		{
			string _date_in_MM_DD_YYYY_Format = 
				convertDateTimeToMM_DD_YYYYFormat(inputDateTime);
			outputMM = "";
			outputDD = "";
			outputYYYY = "";

			outputMM = _date_in_MM_DD_YYYY_Format.Substring(0,2);
			outputDD = _date_in_MM_DD_YYYY_Format.Substring(3,2);
			outputYYYY = _date_in_MM_DD_YYYY_Format.Substring(6,4);
		}
		/** 
		 * Convert the DateTime value to MM_DD_YYYY format.
		 * **/
		public static DateTime convertMM_DD_YYYYFormatToDateTime(string inputDateInMM_DD_YYYYFormat)
		{
			inputDateInMM_DD_YYYYFormat = initrode.utilities.StringManager.StripWhitespaceFromEnds(inputDateInMM_DD_YYYYFormat);
			if (initrode.utilities.StringManager.IsValidDateInMM_DD_YYYYFormat(inputDateInMM_DD_YYYYFormat) == false) return new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
			int _intMM = Convert.ToInt32(inputDateInMM_DD_YYYYFormat.Substring(0,2));
			int _intDD = Convert.ToInt32(inputDateInMM_DD_YYYYFormat.Substring(3,2));
			int _intYYYY = Convert.ToInt32(inputDateInMM_DD_YYYYFormat.Substring(6,4));
			return new DateTime(_intYYYY,_intMM, _intDD);
		}
        public static int calculateMonthsDifferenceBetweenTwoDates
                            (
                                DateTime inputOlderDate
                                , DateTime inputNewerDate
                            )
        {
            DateTime _tempDate = inputOlderDate;
            int _numberOfMonthsDifference = 0;
            while (_tempDate < inputNewerDate)
            {
                _tempDate = _tempDate.AddMonths(1);
                if (_tempDate < inputNewerDate)
                    _numberOfMonthsDifference++;
            }
            return _numberOfMonthsDifference;
        }

		/** 
		 * Convert the DateTime value to MM_DD_YYYY format.
		 * **/
		public static string convertTimestampToStringFormat(DateTime inputDateTime)
		{
			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(initrode.utilities.StringManager.Fill(	
												inputDateTime.Month.ToString(),
												"0",
												true,           //Fill from left
												2));
			_bldr.Append("/");
			_bldr.Append(initrode.utilities.StringManager.Fill(	
												inputDateTime.Day.ToString(),
												"0",
												true,           //Fill from left
												2));
			_bldr.Append("/");
			_bldr.Append(inputDateTime.Year.ToString());
			_bldr.Append(" ");
			_bldr.Append(initrode.utilities.StringManager.Fill(	
												inputDateTime.Hour.ToString(),
												"0",
												true,           //Fill from left
												2));
			_bldr.Append(":");
			_bldr.Append(initrode.utilities.StringManager.Fill(	
												inputDateTime.Minute.ToString(),
												"0",
												true,           //Fill from left
												2));
			_bldr.Append(":");
			_bldr.Append(initrode.utilities.StringManager.Fill(	
												inputDateTime.Second.ToString(),
												"0",
												true,           //Fill from left
												2));
			_bldr.Append(".");
			_bldr.Append(initrode.utilities.StringManager.Fill(	
												inputDateTime.Millisecond.ToString(),
												"0",
												true,           //Fill from left
												3));

			return _bldr.ToString();
		}

		/** 
		 * Convert the DateTime value to MM_DD_YYYY format.
		 * **/
		public static string convertDateTimeToMM_DD_YYYYFormat(DateTime inputDateTime)
		{
			StringBuilder _bldr = new StringBuilder();
			_bldr.Append(initrode.utilities.StringManager.Fill(	
												inputDateTime.Month.ToString(),
												"0",
												true,           //Fill from left
												2));
			_bldr.Append("/");
			_bldr.Append(initrode.utilities.StringManager.Fill(	
												inputDateTime.Day.ToString(),
												"0",
												true,           //Fill from left
												2));
			_bldr.Append("/");
			_bldr.Append(inputDateTime.Year.ToString());
			return _bldr.ToString();
		}

		/** 
		 * @description get first day of the next  month
		 * **/
		public static DateTime getFirstDayofNextMonth(DateTime inputDateTime) 
		{
			return  initrode.utilities.DateManager.getFirstDayofTheMonth(inputDateTime).AddMonths(1);
		}


		/** 
		 * @description get first day of the next  month
		 * **/
		public static DateTime getFirstDayofNextMonth() 
		{
			return  getFirstDayofNextMonth(DateTime.Now); 
		}

		/** 
		 * @description add days to a date
		 * **/
		public static DateTime daysFromTheFirst(int days, System.DateTime date)
		{
			DateTime nextDate = date.AddDays(days); //calculate  1 day of next month
			return nextDate;
		}
		/** 
		 * 
		 * @description get first day of the current year
		 * **/
		public static DateTime getFirstDayofTheCurrentYear() 
		{
			return initrode.utilities.DateManager.getFirstDayofTheInputtedDatesYear(System.DateTime.Now);
		}
		/** 
		 * 
		 * @description get last day of the current year
		 * **/
		public static DateTime getLastDayofTheCurrentYear() 
		{
			return initrode.utilities.DateManager.getFirstDayofTheCurrentYear().AddYears(1).AddDays(-1);
		}

		/** 
		 * 
		 * @description get first day of the inputted year
		 * **/
		public static DateTime getFirstDayofTheInputtedDatesYear(System.DateTime inputDateTime) 
		{
			return new DateTime(inputDateTime.Year,1,1);
		}
		/** 
		 * 
		 * @description get last day of the inputted year
		 * **/
		public static DateTime getLastDayofTheInputtedDatesYear(System.DateTime inputDateTime) 
		{
			return new DateTime(inputDateTime.Year,12,31);
		}

		public static DateComparison timestamp1ComparedToTimestamp2(DateTime inputTimestamp1, 
																	DateTime inputTimestamp2)
		{
			if (inputTimestamp1.Year > inputTimestamp2.Year) return DateComparison.gt;
			if (inputTimestamp1.Year < inputTimestamp2.Year) return DateComparison.lt;
			if (inputTimestamp1.DayOfYear > inputTimestamp2.DayOfYear) return DateComparison.gt;
			if (inputTimestamp1.DayOfYear < inputTimestamp2.DayOfYear) return DateComparison.lt;
			if (inputTimestamp1.Hour > inputTimestamp2.Hour) return DateComparison.gt;
			if (inputTimestamp1.Hour < inputTimestamp2.Hour) return DateComparison.lt;
			if (inputTimestamp1.Minute > inputTimestamp2.Minute) return DateComparison.gt;
			if (inputTimestamp1.Minute < inputTimestamp2.Minute) return DateComparison.lt;
			if (inputTimestamp1.Second > inputTimestamp2.Second) return DateComparison.gt;
			if (inputTimestamp1.Second < inputTimestamp2.Second) return DateComparison.lt;
			if (inputTimestamp1.Millisecond > inputTimestamp2.Millisecond) return DateComparison.gt;
			if (inputTimestamp1.Millisecond < inputTimestamp2.Millisecond) return DateComparison.lt;
			return DateComparison.eq;
		
		}

		public static DateComparison date1ComparedToDate2(DateTime inputDate1, 
															DateTime inputDate2)
		{
			if (inputDate1.Year > inputDate2.Year) return DateComparison.gt;
			if (inputDate1.Year < inputDate2.Year) return DateComparison.lt;
			if (inputDate1.DayOfYear > inputDate2.DayOfYear) return DateComparison.gt;
			if (inputDate1.DayOfYear < inputDate2.DayOfYear) return DateComparison.lt;
			return DateComparison.eq;
		
		}

		/** 
		 * 
		 * @description get first day of the first Future Period
		 * **/
		public static DateTime getTheDateBeforeTheFirstFuturePeriod() 
		{
			// If date is less than the 16th, the 15th is the date.

			DateTime _date = DateTime.Now;
			if (_date.Day < 16)
			{
				return _date.AddDays(15 - _date.Day);
			}

			// If date is greater than the 16th, the 1st of the following month is
			// the first date of the first future period.

			return _date.AddDays(1 - _date.Day).AddMonths(1).AddDays(-1);
		}
	}
}
[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

CodeSOD: Compiled Correctly

By Remy Porter

Properly used, version history can easily help you track down and identify the source of a bug. Improperly used, it still can. As previously established, the chief architect Dana works with has some issues with source control.

Dana works on a large, complex embedded system. “Suddenly”, her team started to spot huge piles of memory corruption problems. Something was misbehaving, but it was hard to see exactly what.

They ported Valgrind to their platform, just so they could try and figure out what was going wrong. Eventually, they tracked the problem down to a pair of objects.

In the flow of the code, the correct path was that object A, which we’ll call Monster would be allocated. Then a second object would be allocated. Somehow, Monster instances were corrupting the memory of the second object.

How does an object allocated earlier corrupt the memory of an object allocated later? Well, “before” and “after” have different meaning when your code is multi-threaded, which this was. Worse, the Monster class was katamari of functionality rolled up across thousands of lines of code. Obviously, there had to be a race condition- but a quick glance at all the Monster methods showed that they were using a mutex to avoid the race condition.

Or were they? Dana looked more closely. One of the methods called during the initialization process, doSomething, was marked const. In C++, that should mean that the method doesn’t change any property values. But if it doesn’t change any property values, how can it lock the mutex?

This is where walking through the commit history tells a story. “Fortunately” this was before Jerry learned you could amend a commit, so each step of his attempts to get the code to compile are recorded for posterity.

The chain of commits started with one labeled “Add Feature $X”, and our doSomething method looked like this.

  void doSomething() const {
      Mutex::ScopedLock lock(mutex);
      // Dozens of lines of code
  }

Now, the intent here was to create a ScopedLock object based off a mutex property. But that required the mutex property to change, which violated const, which meant this didn’t even compile.

Which brings up our next commit, labeled “Fix compile failure”:

  void doSomething() const {
      Mutex::ScopedLock lock(mutex) const;
      // Dozens of lines of code
  }

Surprisingly, just slapping the const declaration on the variable initialization didn’t do anything. The next commit, also helpfully labeled “Fix compile failure”:

  void doSomething() const {
      Mutex::ScopedLock lock(const mutex);
      // Dozens of lines of code
  }

Again, this didn’t work. Which brings us to the last “Fix compile failure” commit in this chain:

  void doSomething() const {
      Mutex::ScopedLock lock(const Mutex mutex);
      // Dozens of lines of code
  }

By randomly adding and subtracting symbols, Jerry was able to finally write a function which compiles. Unfortunately, it also doesn’t work, because this time, the line of code is a function declaration for a function with no implementation. It takes a mutex as a parameter, and returns a lock on that mutex. Since the declaration has no implementation, if we ever tried to call this in doSomething, we’d get an error, but we don’t, because this was always meant to be a constructor.

The end result is that nothing gets locked. Thus, the race condition means that sometimes, two threads contend with each other and corrupt memory. Dana was able to fix this method, but the root cause was only fixed when Jerry left Initech to be a CTO elsewhere.

[Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!

CodeSOD: Generically Bad

By Remy Porter

The first two major releases of the .NET Framework, 1.0 and 1.1 were… not good. It's so long ago now that they're easily forgotten, but it's important to remember that a lot of core language features weren't in the framework until .NET 2.0.

Like generics. Generics haven't always been part of the language, but they've been in the language since 2006. The hope would be that, in the course of 13 years, developers would learn to use this feature.

Russell F (recently) has a co-worker who is still working on it.

public static DataTable ClassRegionDToDatatable<POSInvoiceRegionD>(string tableName) where POSInvoiceRegionD : class { Type classType = typeof(POSInvoiceRegionD); DataTable result = new DataTable(tableName); foreach (PropertyInfo property in classType.GetProperties()) { DataColumn column = new DataColumn(); column.ColumnName = property.Name; column.DataType = property.PropertyType; result.Columns.Add(column); } return result; } public static DataTable ClassRegionFToDatatable<POSInvoiceRegionF>(string tableName) where POSInvoiceRegionF : class { Type classType = typeof(POSInvoiceRegionF); DataTable result = new DataTable(tableName); foreach (PropertyInfo property in classType.GetProperties()) { DataColumn column = new DataColumn(); column.ColumnName = property.Name; column.DataType = property.PropertyType; result.Columns.Add(column); } return result; } public static DataTable ClassRegionGToDatatable<POSInvoiceRegionG>(string tableName) where POSInvoiceRegionG : class { Type classType = typeof(POSInvoiceRegionG); DataTable result = new DataTable(tableName); foreach (PropertyInfo property in classType.GetProperties()) { DataColumn column = new DataColumn(); column.ColumnName = property.Name; column.DataType = property.PropertyType; result.Columns.Add(column); } return result; } public static DataTable ClassRegionKToDatatable<POSInvoiceRegionK>(string tableName) where POSInvoiceRegionK : class { Type classType = typeof(POSInvoiceRegionK); DataTable result = new DataTable(tableName); foreach (PropertyInfo property in classType.GetProperties()) { DataColumn column = new DataColumn(); column.ColumnName = property.Name; column.DataType = property.PropertyType; result.Columns.Add(column); } return result; }

Now, the core idea behind generics is that code which is generic doesn't particularly care about what data-type it's working on. A generic list handles inserts and other list operations without thinking about what it's actually touching.

So, right off the bat, the fact that we have a pile of generic methods which all contain the same code is a simple hint that something's gone terribly wrong.

In this case, each of these methods takes a type parameter (which happens, in this case, to be named just like one of the actual classes we use), and then generates an empty DataTable with the columns configured to match the class. So, for example, you might do:

DataTable d = POSInvoiceRegionUtils.ClassRegionDToDatatable<POSInvoiceRegionD>("the_d");

Of course, because these methods are all generic and accept type parameters, you could just as easily…

DataTable d = POSInvoiceRegionUtils.ClassRegionKToDatatable<POSInvoiceRegionD>("the_d");

Not that such a counterintuitive thing ever happens. By the way, did you notice how these regions are named with letters? And you know how the alphabet has 26 of them? Well, while they're not using all 26 letters, there are a lot more regions than illustrated here, and they all get the same ClassRegion{x}ToDatatable implementation.

So yes, we could boil all of these implementations down into one. Then again, should we? GetProperties is one of .NET's reflection methods, which lets us examine the definition of class objects. Using it isn't wrong, but it's always suspicious. Perhaps we don't need any of this code? Without more information, it's hard to say, but Russell adds:

I'm going to leave aside the question of whether this is something that should be done at all to focus on the fact that it's being done in a really bizarre way.

I'm not sure about "bizarre", but wrong? Definitely. Definitely wrong.

[Advertisement] Ensure your software is built only once and then deployed consistently across environments, by packaging your applications and components. Learn how today!

Error'd: An Error Storm of Monstrous Proportions

By Mark Bowytz

"Move over NOAA, Google News shows us, unfortunately after the fact that The Daily Beast is the TRUEST hurricane prognosticator," Alejandro D. writes.

 

"Um...So, these are so my car can listen to music, wirelessly, because its mirrors are its...er...ears??" Paul writes.

 

Jyri B. wrote, "You know, it's really nice to see that the Eurovision people are embracing all the European languages."

 

"Wow! Maltese looks like a tough language to learn. Glad I don't have to know it. Thank YOU Google Translate!" Peter K. writes.

 

"At Gamestop, you can pre-order figurines of all your favoirte characters from MSI!" wrote Chris A.

 

Mikkel H. writes, "I don't want to hear about timezone issues. The only thing possible that happened here was that my FedEx package was teleported from Beijing to Anchorage and back again."

 

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

The Windows Update

By Remy Porter

Every change breaks someones workflow.

A few years ago, Ian started at one of the many investment banks based out of London. This particular bank was quite proud of how they integrated “the latest technology” into all their processes, “favoring the bleeding edge,” and “are always focusing on Agile methods, and cross-functional collaboration.”

That last bit is why every software developer was on a tech support rotation. Every two weeks, they’d have to spend a day sitting with the end users, watching them work. Ostensibly, by seeing how the software was actually used, the developers would have a better sense of the users’ needs. In practice, they mostly showed people how to delete emails or recover files from the recycling bin.

Unfortunately, these end users also directly or indirectly controlled the bank’s budgeting process, so keeping them happy was a big part of ensuring continued employment. Not just service, but service with a smile- or else.

Ian’s problem customer was Jacob. Jacob had been with the bank at least thirty years, and still longed for the days of lunchtime brandy and casual sexual harassment. He did not like computers. He did not like the people who serviced his computer. He did not like it when a web page displayed incorrectly, and he especially did not like it when you explained that you couldn’t edit the web page you didn’t own, and couldn’t tell Microsoft to change Internet Explorer to work with that particular website.

“I understand you smart technical kids are just a cost of doing business,” Jacob would often say, “but your budget is out of control. Something must be done!”

Various IT projects proceeded apace. Jacob continued to try and cut their budget. And then the Windows 7 rollout happened.

This was a massive effort. They had been on Windows XP. A variety of intranet and proprietary applications didn’t work on Windows 7, and needed to be upgraded. Even with those upgrades, everyone knew that there would be more problems. These big changes never came without unexpected side effects.

The day Jacob got Windows 7 imaged onto his computer also happened to be the day Ian was on helldesk duty. Ian got a frantic email:

My screen is broken! Everything is wrong! COME TO MY DESK RIGHT NOW, YOUNG MAN

Ian had already prepared, and went right ahead and changed Jacob’s desktop settings so that they as closely mimicked Windows XP as possible.

“That’s all fine and good,” Jacob said, “but it’s still broken.”

Ian looked at the computer. Nothing was broken. “What… what exactly is the problem?”

“Internet Explorer is broken!”

Ian double clicked the IE icon. The browser launched just fine, and pulled up the company home page.

“No! Close that window, and look at the desktop!”

Ian did so, waiting for Jacob to explain the problem. Jacob waited for Ian to see the problem. They both sat there, waiting, no one willing to move until the other had gone.

Jacob broke first. “The icon is wrong!”

Ah, yes, the big-blue-E of Windows XP had been replaced by the big-blue-E of Windows 7.

“This is unacceptable!” Jacob said.

Ian had already been here for most of the morning, so a few more minutes made no difference. He fired up image search, grabbed the first image which was an XP era IE icon, and then set that as the icon on the desktop.

Jacob squinted. “Nope. No, I don't like that. It’s too smooth.”

Of course. Ian had grabbed the first image, which was much higher resolution than the original icon file. “I… see. Give me a minute.”

Ian went back to his desk, resized the image, threw it on a network share, went back to Jacob’s desk, and changed the icon.

“There we are,” Jacob said. “At least someone on your team knows how to support their users. It’s not just about making changes willy-nilly, you know. Good work!”

That was the first and only honest compliment Jacob ever gave Ian. Two years later, Ian moved on to a new job, leaving Jacob with his old IE icon, sitting at the same desk he’d been since before the Internet was even a “thing”.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

CodeSOD: An Updated Version

By Remy Porter

Some folks were perplexed by the fact that Microsoft skipped Windows 9 and went straight to Windows 10. The urban legend is that so many old applications checked which version of Windows was running by doing something like version.startsWith("Windows 9") to see if they were on 95 or 98, that Microsoft risked breaking otherwise working code if they released Windows 9.

But gone are those days of doing string munging to check which version of an OS we’re running on. We’ve got much better ways to check what features and functionality are available without having to parse strings out, right?

John D found some TypeScript code in a Ionic app that needs to adapt to different versions of iOS:

private iOS13Device(): boolean {
		// fix for ios 13 pan end issue
		if (
			this.isIOS13Device === undefined &&
			this.deviceService.isiOS &&
			this.deviceInfoService.deviceInfo &&
			this.deviceInfoService.deviceInfo.osVersion &&
			this.deviceInfoService.deviceInfo.osVersion.indexOf('_') &&
			this.deviceInfoService.deviceInfo.osVersion.split('_') &&
			this.deviceInfoService.deviceInfo.osVersion.split('_')[0] &&
			this.deviceInfoService.deviceInfo.osVersion.split('_')[0] === '11'
		) {
			this.isIOS13Device = true;
			return this.isIOS13Device;
		} else {
			this.isIOS13Device = false;
			return this.isIOS13Device;
		}
	}

Well, at least they’re caching the result.

Also, I’m no expert on iOS device strings, but this seems to imply that an iOS13Device (an OS which just came out recently) reports its OS version number as a string starting with 11. Maybe that’s correct, but in either case, that seems like a bonus WTF.

[Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!

When Unique Isn't Unique

By Jane Bailey

Palm III 24

Gather 'round, young'uns, for a tale from the Dark Ages of mobile programming: the days before the iPhone launched. Despite what Apple might have you believe, the iPhone wasn't the first portable computing device. Today's submitter, Jack, was working for a company that streamed music to these non-iPhone devices, such as the Palm Treo or the Samsung Blackjack. As launch day approached for the new client for Windows Mobile 6, our submitter realized that he'd yet to try the client on a non-phone device (called a PDA, for those of you too young to recall). So he tracked down an HP iPaq on eBay just so he could verify that it worked on a device without the phone API.

The device arrived a few days out from launch, after QA had already approved the build on other devices. It should've been a quick test: sideload the app, stream a few tracks, log in, log out. But when Jack opened the app for the first time on the new device, it was already logged into someone's account! He closed it and relaunched, only to find himself in a different, also inappropriate account. What on earth?!

The only thing Jack could find in common between the users he was logged in as was that they were running the same model of PDA. That was the crucial key to resolving the issue. To distinguish which device was making the calls to the streaming service, Jack used a call in Windows Mobile that would return a unique ID for each mobile device. In most devices, it would base this identifier on the IMEI, ensuring uniqueness—but not on the HP iPaq. All HP devices could automatically log into the account of the most recently used iPaq, providing the user logged out and back in, as it would generate a recent-user record with the device ID.

Jack had read the documentation many times, and it always stated that the ID was guaranteed to be unique. Either HP had a different definition of "unique" than anyone else, or they had a major security bug!

Jack emailed HP, but they had no plans to fix the issue, so he had to whip up an alternate method of generating a UUID in the case that the user was on this device. The launch had to be pushed back to accommodate it, but the hole was plugged, and life went on as usual.

[Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!

CodeSOD: Butting In

By Remy Porter

Initech is a large, international corporation. Any time you're doing business at a global scale, you're going to need to contend with a language barrier sooner or later. This makes employees who are multilingual valuable.

Dana recently joined Initech, and in the first week, was warned about Jerry. Jerry was the "chief" "architect" and team "lead", and was one of those special, valuable employees who spoke three languages. Correction, "spoke" needs scare quotes too, because Jerry was incomprehensible in every language he spoke, including his native tongue.

Jerry's emails were stuff of legend around the office. Punctuation was included, not to structure sentences, but as a kind of decoration, just to spice up his communiques. Capitalization was applied at random. Sentences weren't there to communicate a single thought or idea, but to express fragments of half considered dreams.

Despite being the "chief architect", Jerry's code was about as clear as his emails. His class definitions were rambling stretches of unrelated functionality, piled together into a ball of mud. Splattered through it all were blocks of commented out functionality. And 99.9% of his commits to master had syntax errors.

Why did his commits always have syntax errors? Jerry had never seen fit to install a C++ compiler on his machine, and instead pushed to master and let their CI system compile and find all his syntax errors. He'd then amend the commit to fix the errors, and woe betide anyone else working in the repo, because he'd next git push --force the amended commit. Then he'd fix the new round of syntax errors.

Their organization did have an official code review standard, but since no one understood any of Jerry's code, and Jerry was the "chief", Jerry reviewed his own code.

So, let's talk about enumerated types. A common practice in C++ enums is to include an extra value in the enum, just to make it easy to discover the size of the enum, like so:

enum Color { COLOR_RED, COLOR_BLACK, COLOR_BLUE, COLOR_SIZE }

COLOR_SIZE isn't actually a color value, but it tells you how many color values there are. This can be useful when working with a large team, as it's a sort of form of documentation. It also allows patterns like, `for (int i = 0; i < COLOR_SIZE; i++)…`. Of course, it only works when everyone follows the same convention.

Jerry couldn't remember the convention. So, in his native language, he invented a new one: he'd end all his enums with a _END instead of _SIZE. But Jerry also couldn't remember what the English word for "end" was. So he went off to Google Translate, and got an English translation.

Then he wrote code. Lots of code. No one got to review this code. Jerry touched everything, without worrying about what any other developer was doing.

This meant that before long, every enum in the system looked like this:

enum Color { COLOR_RED, COLOR_BLACK, COLOR_BLUE, COLOR_BUTT }

Eventually, Jerry left Initech. He'd found a position where he could be a CTO of a well-funded startup. The very same day, Dana submitted her largest pull request ever, where she removed every single one of Jerry's butts.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

Return to the Vaucluse, 2019

By Jon North (noreply@blogger.com)


One of our first ports of call when we began regular visits to France over 25 years ago was to the southern Rhône valley, the south of the Drôme département (south that is, of our old twin town, Die).  This September we were back in the Vaucluse for a short overnight stay on my birthday.  The photo above is from the road approaching the Domaine de Coyeux, high above Beaumes de Venise, with Mont Ventoux in the distance.  Try as I might I could not convey the height and scale of this well-known obstacle in many Tours de France, but it is often there in views of the area.

When we first visited in the mid-1990s the only way to approach Coyeux was via an unmade road, snaking across the top of the Dentelles de Montmirail, itself already a worrying distance from civilisation.  We've visited the Domaine de Durban, on the road towards Coyeux, quite often over the years, but now that track is closed and the road to Coyeux snakes up the hillside like a Tour de France special, until you arrive on the high plateau with the lace-like rocks that give the Dentelles their name, at closer quarters.

On the way to the Domaine de Coyeux
When we first came in the 90s, Beaumes de Venise was well-known for its sweet muscat wines, as it still is, but in the past 20 years sweet wines have become less popular and the reds from this village have become increasingly good and, compared with the neighbouring Gigondas or Vacqueyras, let along Châteauneuf du Pape, very good value.  Coyeux is noted this year in the Guide Hachette for an excellent red, Praestans, which fulfilled our expectations when we tasted it.  We also fell for dry white and rosé wines from Muscat grapes - a very worthwhile visit with views to match.
   

             

All the white and rosé wines we tried at Coyeux were made from muscat petit grains grapes, the same as are used to make the fortified Muscat de Beaumes de Venise.  When we firt came, dry wines were only made when the harvest was plentiful enough.  Now, dry white wines are increasingly normal, and I was surprised to discover rosé made from the same grape (this is not really surprising - the skins are reddish though the juice is 'white', so leaving ths skins in contact with the juice for a short time makes a nice pale rosé).  Mary is always pleased to find dry muscat, and the Coyeux rosé and white were both excellent.  We also have more and more dry muscat around us in Lunel, and one of our best winemakers tells us he decreases the sugar content of even his sweet wines year by year as people's tastes change.

As we often do when travelling in France, we chose to stay in a Logis de France hotel - almost always with good restaurants attached.  This one in Sablet, the Domaine de Cabasse, lived up to the usual good standards and is as its name suggests also attached to a wine domaine.  However, with so many good wines around we didn't buy here this time - just drank some of their good red with our meal.  The pool was also a welcome attraction in the afternoon heat.





The hotel is among the vines midway between the small sleepy villages of Sablet and Séguret.  
As you emerge onto the little road, across the fields you can see two huge buildings typical of the caves coopératives you come across right across the south of France, but if possible even bigger.  This I guessed, rightly, was the Gravillas Coop which we were aiming for after our night in the hotel.  It has a good reputation, and a Rosé in particular which got outstanding marks in the latest Guide Hachette.  The previous afternoon we'd stopped in another small sleepy village, Violès, on the plain between the Rhône and the Dentelles.  There we visited a charming family-run domaine, the Bastide Saint Vincent, another Hachette recommendation, whose red Florentin is a splendid example of the newish 'Plan de Dieu' (plain of God, I guess) Côtes du Rhône Villages appellation.



               
 The story of our link to Violès also goes right back to our twinning visits 25 years ago.  At that time our local organic shop in Derbyshire had branched out into wines, and had a nice red Côtes du Rhône and we decided to see if we could find the producer.  At that time Violès was even more of a backwater than it is now - small, dusty and not really used to tourists, but we found the winemaker, bought some wine and had a meal in the little restaurant at the village crossroads.  The raising of quality and acquisition of the plan de Dieu tag has brought new fortune to Violès, which now has more commerce, several well-set-up winemakers and a beautiful new public library among other things.  All very enouraging

To finish here are a few photos of the area, taken on the top of the Dentelles but a little further south and west around the Domaine de Durban, with some better views of Mont Ventoux too




Our dog Camel

By noreply@blogger.com (Jon North)

Over 250 years the English poet Christopher Smart wrote the poem For I will consider my cat Jeffrey.  Now we think constantly 'for we will consider our dog Camel', the new friend at 74 rue de la Brechette following Evie's sad death last autumn.  Her replacement is several times her size!!


Last week we went to Figeac, 3-4 hours' drive west of Lunel, to collect our new companion, a 10-year-old male dog called Camel.  He had lived for 4 years in the refuge in the remote hilltop locality Nayrac a couple of km outside Figeac on the river Lot.  The refuge is operated (since the late 80s) by  MASAQ, the Mouvement Associatif pour la Sauvegarde des Animaux du Quercy, a very caring and committed group which seems to be struggling to cope with demand - the 100+ dogs have to be housed, fed and walked by volunteers and they are completely full up on the cat side, and the refuge has shelter and some limited facilities, but little warmth or protection for the many animals in the woodland setting surrounded by rubbish processing plants at the end of a long winding dead end road.

Camel is a placid, friendly animal, underweight and in need of more walks and more food, carefully controlled to allow for his rather shrunken stomach, and now just starting to get used to our warm dry house!  He was chipped and checked by their vet before we could collect him and sign the adoption papers, and given a thorough check by our own vet the day after he arrived.  But if he seems bemused to find himself in our home it isn't surprising - he'll still be getting used to being warm.

Figeac itself is a really nice little town with a really lovely medieval centre which we explored despite the annoying closure of the Tourist Office for staff training!  But going to the Mairie instead to get a town plan was a bonus, because the young woman at the desk turned out to be a volunteer at the refuge and of course knew one of their longest-staying residents!  She and we were very glad to say hello before we went to find him.

Here is an album of photos of Camel in his first few days with us.

Road trip

By noreply@blogger.com (Jon North)

Interrupting my enjoyable accounts of meetings with family and friends in England, a trawl around out 3500 km plus round trip to England from the S of France.

We decided to drive because we thought of taking French wine to our family.  In the process we kept some Burgundy for ourselves from our favourite Jacob vineyards - crémant, Chambolle Musigny and some white Hautes Côtes de Beaune matured in Acacia barrels which is less easily available so we were lucky to find it!  Sadly, on our return through France we could not find a chance to revisit Echevronne but we'll be back, no doubt.

Perhaps the highlights of the route and the roads we travelled were or will be the Millau viaduct which will more or less welcome us back into the Languedoc when we return home down the A75 tomorrow, and the quiet journey from north of London up the A5 towards Staffordshire as we started our visit in December.  the Narrow Boat pub on the Grand Union Canal has been an enjoyable stopping place over the years.  We returned south on the A5 but sadly the pub was not yet open for coffee as we passed.

But the most surprising pleasure is the moment on the M25 near Rickmansworth when it passes neatly under the Chalfont Viaduct - as the Atlasobscura website relates "Those impressive Edwardians thoughtfully left enough room between the arches of this grand 1906 railway viaduct for an eight-lane motorway to pass through".  I can't help thinking the motorway designers had to back off a considerable distance to line up the M25 through those excellent brick arches.

Our almost daily journeys from near Burton to Wirksworth, between the houses of our sons, gave us time to refine our route - the picturesque but windy one via Ashbourne was rapidly replaced by the smoother but still enjoyable route via the A38 and A50, quicker and less demanding!

We have learnt to pace ourselves, shorter stages with hotel stops, but still on these short winter days the end of each day is a challenge as streams of headlights approach us in the gathering darkenss as we attempt to decipher the directions to the next hotel.  And even welcome sunshine in France today presented problems as we negotiated ring roads and roundabouts.  But we enjoyed the sights we could spare time to see - Chartres cathedral against the skyline, and a sliver of crescent moon as we drove towards Orléans.

The car ferry is a gentle respite on the route, and the Channel Tunnel is so quickly over in a car that you scarcely remember it before you are on the road again.  But on short winter days perhaps the tunnel is a better bet, leaving more daylight hours to drive safely in.  Changing sides of the road no longer presents too many challenges - I always feel that the signage and road markings are clues enought to which side of the Channel and of the road you are currently on.  And we saw no gilets jaunes at all on the way up,though several stood by their roadside fires and did not bother us as we passed Dieppe, Evreux and Dreux on the way down.

An anniversary and other Christmas moments

By noreply@blogger.com (Jon North)

Our 40th wedding anniversary was in October, but since we could not meet the family then we arranged a meal together just after Christmas.  It was lovely to have all our sons and their families with us for an evening of Italian treats in Oakerthorpe, where the Peacock pub has been rebranded Pesto at the Peacock!


We shared our time over the festive period between the homes of Jeff & Fi and Sam and family, enjoying several exchanges of presents, walking around the Staffordshire countryside and taking occasional trips to shops in Burton and Ashbourne, as well as catching up on tv and sleep!

Jeff & Fi's cottage across the fields
 






Some Christmas moments at Marebrook

By noreply@blogger.com (Jon North)

More photos from our stay at Jeff & Fi's









Waiting for Christmas in Staffs and Derbys

By noreply@blogger.com (Jon North)

Our days leading up to Christmas this year have been spent with the usual mix of shopping, wrapping, watching telly and spending time with our family.  This is a little photo diary of our first few days in rural Staffordshire.

  




 




Christmas trip part 2 - to the Midlands

By noreply@blogger.com (Jon North)

NB photos of Staffs taken on an earlier winter visit
 I'm writing in the early morning of Saturday 22 Dec in a cosy cottage near Burton-on-Trent, home our son and daughter-in-law Jeff & Fi, and our temporary resting place in England.  We've driven nearly 1500 km to get here with amazingly little difficulty - not only avoiding hold-ups in France but making the journey from Kent to London and then on to Staffs smoothly on quiet roads.  All the more amazing on the brink of a holiday weekend when all reports are of heavy traffic and jams.  They all seem to have happened after we passed!

Our short stay in London with old friends Ruth & Claus was comfortable and warm in every sense.  We had a chance to wander in Highgate village and introduced two sets of friends from different parts of our lives over lunch - if there was a common thread beyond a general enjoyment of culture it was the appreciation of good wine: we'd brought with us wine Gaynor & Ed had bought in Bordeaux during our summer visit there together, and we enjoyed both good Bordeaux red and delicious Chablis with lunch.  I keep straying in this blog into the territory of the wine one!

Highgate scenes

So we set our yesterday from London, aiming for the A5.  This lust be one of the least diverted of the old Roman Roads in the country, once you get onto it north of St Albans.  Of course it has new bits like the Milton Keynes bypass that Romans would have found it hard to imagine (even without the concrete cows) but mostly it passes through delightful undulating rural landscapes all the way to Leicestershire where we turned off towards Burton.  On the way up we stopped for some lunch at a really good raodside pub, the Narrow Boat at Weedon (now we discovered with Motel-like rooms fringing the car park).  We visited this quite often on our trips to and from Derbyshire some years ago.  The grounds are right next to the Grand Union Canal and it's altogether a good place to visit.  We arrived at Jeff & Fi's at 3 pm and enjoyed a cosy evening with a blazing stove, good wine(!) including some excellent Aldi organic prosecco we'd discovered on our last visit and some beautiful pinot noir we'd brought from the Limoux vineyard of Jean-Louis Denois.  A good start to our holiday.

Christmas in England - arrival

By noreply@blogger.com (Jon North)

With the uncertainties of Brexit on the horizon, this seems like a more than usually important time to visit our family in England, and we are really looking forward to being with Jeff & Fi, Sam, Sas, Heather and Ben and also seeing Ed, Isla and Karen for a while.  Lots to look forward as I sit in our Folkestone hotel which was a nightmare to find in the wet and dark, but it all felt better after a drink in the bar!

The past two days started early, very early, as we drove up a dark and almost deserted A9 from Lunel to our overnight stop in Burgundy, not quite knowing if the gilets jaunes would add to the uncertainty of Brexit.  Weekend reports were not encouraging - we read of fires on and by motorways and toll booths, a whole section of the A7 from Avignon to Valence closed, numerous entrances and exits closed as our own local ones had been on and off for the past few weeks.  We started out full of anxiety, just hoping that after the weekend the demonstrators would all heed to colder damper weather and go home.  

All sorts of thoughts have crowded in on us as we've driven 1,000+ km up France.  We drove without seeing a single gilet jaune. Tant mieux, and of course there are fewer in the north than in the south, fewer in midweek than at weekends, fewer now than there were 2 months ago. But we were reminded that until recently a frequent electronic message on motorways here used to be 'respect the men in yellow’, and today it says something like ‘agents anticipés’. Does not trip off the tongue as the other used to, but no danger of mistaking workmen for protestors, at least in the wording of messages!  

One final thought about these demonstrations - we read in a local paper in Burgundy that local groups of gilets jaunes are hoping to form associations so that they can be eligible for grants from public authorities!!  So people who began by demonstrating against too high taxes are now hoping some taxation will be spent on their groups.  In fact, merssages are mixed - some want lower taxes; others want to preserve services which are being cut.  On top of that, some have destroyed lots of things, motorway toll booths and sometimes the roads themselves with fire.  Vinci (one of the motorway companies) reckons they will need to spend millions repairing things.  Not easy to square with keeping up tax-funded services.  But enough, we don't understand everything and no doubt there are important causes to be fought.  The rest of this will be, more pleasantly, concerned with our doings.

Our first port of call in Burgundy was our friends Jean-Michel and Christine Jacob, whose wine will accompany us to England and (some of it) back home.  It's always a pleasure to see them again, but their story really belongs in my wine blog where I've often written of them (here for example), so suffice it to say that we were warmly received and delighted with the wines we found and could take away, as we hope our family and friends will be!  We had a good simple lunch in Beaune, a pleasure to revisit this lovely town, and then sought our our hotel.


lunch in Beaune - Mary appears twice thanks to the mirror next to our table!
The hill of Corton from our hotel terrace
We'd chosen a Logis hotel in Ladoix Serrigny, on the south-eastern flank of the famed Hill of Corton (origin of grand crû wines which we did not seek out this time, both red and, unusually north of Beaune, white (Corton Charemagne).  It was a simple but comfy overnight stop and we set out at leisure for the north today.  The roads were quiet, the weather mostly dry and often bright, and the middle stretch in particular as we approached Troyes across the Fôret d'Orient was full of the amazing variations of colour and texture of winter scenery, branches, fields and hedgerows.  The last stretch past Reims and on up to the coast is long and less interesting to look at, but we made the Tunnel hours ahead of the time we'd planned and so crossed into wet Kent and our first night on English soil, looking forward to seeing people as we travel north tomorrow and after.

September wine fairs

By Jon North (noreply@blogger.com)

The French 'rentrée' is also the start of an interesting period for wine enthusiasts - the season of wine fairs in supermarkets.  In all, these span nearly 6 weeks, and these days the wines are not only good value but also carefully selected.  As with medal competitions, you always have to bear in mind that makers who already have a good market for their wines need not participate, but with the aid of review articles you can usually buy good wines at good prices.  Since the best bargains are usually snapped up early, the secret is to arrive at the supermarket at opening time on day 1. 

I did this several times in September, partly for our wine tasting circle here in Lunel and partly to find wines as presents.  The wines I bought are listed below, but first a few notes on the different places I visited and on some of my choices.  I was aided by the comprehensive article in the Revue in August, which highlighted a dozen or so top picks from each chain.

The earliest wine fairs are in the cut-price supermarkets - Lidl, Aldi, Netto and Leader Price.  One could add BioCoop but their wine fair sas so chaotic that they could not even agree on a start date, so lost out as I arrived early on the first day of each.  That’s what you have to do to snap up the best bargains.  Lidl is the most impressive, with three aisles dedicated to a huge range of French and a few foreign wines.  As you can see, I found plenty of choice even without the usual array of Bordeaux reds.  Rhône reds and a nice Touraine white were my picks here.

For the rest, the budget stores ranged from the chaotic Netto (lucky to find any of the wines listed beforehand) to the interesting but slightly disorganised Leader Price and the very nicely organised Aldi, whose range I’ll explore more next year.  Although the major supermarkets’ fairs start later in September, or into October, I managed to find one of my star buys in Intermarché and (as I have done often in previous years) some good buys in Leclerc.

Two personal stories link to my wine fair visits this year.  The first is a red from the flat lands between Orange and the Dentelles de Montmirail in the southern Rhône, from the village of Violès.  When we first discovered this it followed a purchase from the organic shop Beanos in Matlock Bath, which we used a lot during our time in Derbyshire.  At that time Violès was on the bottome rung of the Côtes du Rhône, a sleepy village en route to more celebrated places like Vacqueyras, Gigondas and Beaumes de Venise.  Since then the village has acquired Côtes du Rhône Villages status itself, and the Tour des Abbesses we found in Inter was one of the best reds we’ve come across recently for  everyday drinking.  I seek it out when I visit Intermarché stores in the Cevennes, but I doubt it will be sin stock for much longer.

Second, one of the highlights of my visit to Aldi was the Bonnezeaux from a well-known producer, Château de Fesles.  The sweet chenin blanc wines from this area (the Layon valley south of Angers) are exceptional and long-lasting, one of the few white appellations outside exalted Burgundies to keep more than a few years.  But is is for this very reason that makers divest themselves of wines 15 years old or more.  We first discovered this in the 1990s when we bought 1979 Bonnezeaux from the very same producer from 3D wines, who introduced us to some of our favourite makers elsewhere.  Because these wines last so long, makers hold onto stocks but in the end have to sell them to make room in their cellars, and we profit.  This Bonnezeaux was not a great wine, but a delicious wine to drink now all the same, and it will keep a few years yet.

By the way, a late purchase not on my list below is a Savennières, another Anjou wine but this time dry but equally longlasting.  Sadly the bottle we bought from Leclerc will not be tested for longevity because we finished it between us at lunchtime today, but there is another lurking and I’ll be getting back to Leclerc in the vain hope that there may still be some left - utterly delicious.

Here is my list of purchases, 7 whites first, the rest red.


Saint Véran Louis Dailly 2017 Leader Price 8.04 €
Macon Villages Cave d'Azé 2017 Netto 4.99 €
Touraine Sauvignon Caves Gilles Gobin 2017 Lidl 3.99 €
Menetou Salon Patient Cottat 2017 Intermarché 9.95 €
Sancerre Les Fossiles, dom Roblin 2017 Intermarché 13.75 €
Alsace Riesling Rittimann Celliers de Romarin 2016 Aldi 5.99 €
Bonnezeaux Château de Fesles (50 cl) 2001 Aldi 13.99 €
CdR Villages Dom de Tavans 2017 Leader Price 5.87 €
Cahors Malbec du Clos 2015 Leader Price 5.33 €
J L Baldès
Saint Joseph Dom de Blacieux 2017 Lidl 9.99 €
Vacqueyras Terroir des Dentelles 2016 Lidl 6.99 €
SCA Rhonéa, Beaumes de Venise
Juliénas Collin-Bourisset 2017 Lidl 5.99 €
Vinsobres Dom Croze-Brunet 2016 Lidl 5.49 €
Côtes du Rhône Vill. Dom la Tour des Abbesses, Plan de Dieu 2017 Intermarché 4.49 €
Gaillac Gd réserve de Labastide de Lévis 2016 Aldi 3.99 €

Visiting the Val du Séran

By Jon North (noreply@blogger.com)

We come to the Ain almost every year to play and sing music at Val du Séran, a huge converted farm building in the lovely countryside between the Bugey area and the upper Rhône.  It's quite isolated, surrounded by green hills with some of the cows that produce milk for Comté cheese, and with more distant views of the pre-Alpine mountains.  But apart from the stimulating guidance of our host Stéphane and the marvellous cooking of his wife Chantal, we always enjoy the wines they choose to accompany our evening meals, usually showing a sure touch  in matching food and wine.

This year, for example we've had a Bordeaux Clairet accompanying tarragon chicken.  We came across this on our trip to Bordeaux earlier this year - a light-coloured red wine (like a dark rosé) usually made from merlot grapes.  Then, a Californian cabernet sauvignon full of sweet vanilla fruit in a style which is definitely not French, a really good match with a scented but mild beef curry; a smooth Fitou (from the area south of Narbonne, not far from us) with a veal and ginger dish; a beautiful red Côte du Rhône  with barbecued rissoles made from a Croatian recipe; and a Fleurie (one of the Beaujolais crûs, usually regarded as relatively light and floral) with a pork mignon served with a haricot purée.  A couple more nights of this before we return to our own less diverse choices at home.

When we come to this area, we also enjoy the local wines, particularly the white Roussette de Savoie and Seyssel, made from local grape varieties Altesse and Molette.  These are lively flavourful wines which work well as apéritifs, as Mary proves most evenings after a full day of cello playing.  AT Stéphane's recommendation we visit the maker Bernard Aimé in the village of Corbonod near the town of Seyssel itelf and close to the river Rhône which is very picturesque in this area.

We have good lunches here of salads, cheese and fruit, but (unlike our home habit) no alcohol at lunchtime so that the music is not marred by sleepiness or lack of attention!  But the evenings are a time to relax and feast, as you can see!

Living with pain

By noreply@blogger.com (Jon North)

The past year for me has seen a slow ratcheting up of pain from sciatica.  Before that I would not have believed its all-consuming force.  Even so, I am well aware that I am lucky not to have worse, and the exercise of trying to stay positive is both constructive and interesting.  When we arrived in France Mary spent months with severe tendinitis in a shoulder which she would otherwise have used to bow her cello - upsetting and frustrating but ultimately thank goodness cured.  Since then we have both had joint pain, and sod's law says that at our age this is usually in a place linked to your most creative and important activity.

Treating pain is a complex obstacle course full of blind alleys and treatments which have worked for other people, enthusiastically advocated, but they seem to have no effect when you try them yourself.  Ultimately painkillers are OK, but they kill more than the pain you are trying to treat, and if they do not upset the digestive system or attack the stomach lining they are more or less addictive.  I take them anyway, and they work at least for periods of time.  'Alternative' treatments work if you believe in them, and I tend not to which makes me a poor patient!

With the sciatica I have also been through the gamut of steroid treatments which are very good for a day or three, then just stop working, back to agonising mornings.  Surgery is something I've had with one knee replacement, with mixed results though I can walk - it is like having a posh new hinge on a door, but someone forgot to oil it properly.  Since sciatica involves eroded discs in the spine it is another level of complexity and risk altogether, and I'll go some distance to avoid it despite our appreciation of the talents of Supervet Noel Fitzpatrick.  The animals he treats are after all much less heavy than I am!

But exercise and physical treatment are another matter.  I enjoy cycling, and riding my bike around our lovely flat town or using my exercise bike at home are both constant parts of my life.  The pain goes down, and either I can read and listen to music, or enjoy passing scenery, whhile I finish a session or ride with less.

I've just got back from my latest session with a physiotherapist.  I have had several of these over the past 5 years or so, before and after knee surgery, and my expectations were low.  I'm not the only person, patient or doctor, who recognises the description of being left hitched to a machine (pulley, electrodes, whatever) for 20 minutes while your therapist attends to 2 or 3 other clients.  An hour in a treatment room with only 10 minutes' direct treatment is not uncommon.

I'm not writing to moan about bad examples of physiotherapists because this time I think I have finally found a good one.  A young man who spent 29 mins of the allotted half hour with me, pushed and pulled me both to check my limits and push them a bit, and most importantly left me with exercises I should be doing several times a day at home.  To be fair to the last man he proposed something similar, but not very well explained.  I know now what stretching I need to do and how often, and I'll do it even though my rubber mat on the floor is less convenient and comfortable than his therapy couch.

I'll see him regularly over the next 6 weeks or so.  But in the end the answer is going to be in my own hands, or legs maybe - profiting from my enjoyment of cycling outdoors and in, putting together the advice of my GP, the rheumatologist, an osteopath who tweaked my vertebrae once, and my new physiotherapist that the best treatment is going to be more exercise.  And overcoming my innate laziness to get down on the floor and do the spinal stretches every day.

Incidentally, I was puzzled about the link between the term rheumatology, all things connected with rheumatism, arthritish and pains generally in joints and muscles, and the original French/Latin root rhume meaning cold or sniffles.  Apparently ancient medicine regarded these painful conditions as linked to watery humours - who knew?  The Oxford Dictionary certainly did and does!

At the same time I remember all the time that other people (family, friends and those I meet around the place) have more serious difficulties.  I was reminded of this again this morning seeing others arriving at the physio centre as I left to ride my bike home in the sunshine.

Reading

By noreply@blogger.com (Jon North)

Well here I am again, the inconstant blogger.  I have more time to write just now, and more time to read, so this will be about reading, and specifically in praise of the Kindle.  I've nothing against other brands but I'm not the BBC so need not display impartiality and I have little experience of other electronic readers.

I am a librarian and booklover, so of course I understand and share many people's feelings that Real Books are still of value.  Some would say they are far better - Mary usually reads them, and I often do, but often I turn to my Kindle and here's why.

First of all, I read in bed.  A heavy book can be difficult to manage, and if like me you often read when your partner is asleep, a Kindle is light enough to hold in one hand and its inbuilt light is a boon.

Secondly, and I appreciate this as a librarian, you can search text.  As I get older I often lose track of the names of people and places, and find it helpful to check back to the first or a previous reference.  Who was that?  When did the place crop up or what did the person do?  On a Kindle I can check quickly back and resume reading.

Thirdly, in my frequent need to read in a foreign language (my French is improving, but slowly) if I come across a word I don't remember or have never seen before I can quickly check its meaning through the built-in dictionary.  This is a real boon, and there is a way of noting newly discovered words in a vocabulary builder which, after a while, is a good read on its own!

Fourthly I get my daily paper first thing in the morning.  Paper copies are among the most famously cluttering things in many households I have known, often piled high in garages and spare rooms when their owners cannot bear to throw them out 'in case', but they are scarcely ever re-read after a day or two.  The online papers are not there for ever but for a couple of weeks you can search, then clip and store things that interest you.

People who cling fiercely to books and never read electronic text talk of the feel and form of a real book.  I share some of this feeling, especially having worked with older out of print books, but I realise that these become fragile and should finally be conserved and consulted via scanned copies or they will be damaged beyond repair.

I don't think I shall ever stop liking having books around, but they take space and collect dust - logically a Kindle is more environmentally friendly option, and it's amazing to think that there can be scores, hundreds, of books available in one small device, more easily stored and downloaded at will.  And as travelling with heavy books is ever harder, a single device with months of good reading in it is a welcome asset.

Thinking back to our holiday in the Caucasus

By noreply@blogger.com (Jon North)


I have been wondering, thinking more or less non-stop, and dreaming as well, how to round up our extraordinary fortnight beyond the Black Sea and on the boundary between Europe and Asia.  We went knowing so little, and we have found out so much about these extraordinary small countries in the mountainous triangle between the Russian, Turkish and Iranian great powers.

We visited Armenia and Georgia, for only a week each, and could hardly have contemplated visiting Azerbaijan which is the third of the trio because its relations with Armenia are so poor.  Indeed, on a trip north and wesst around Armenia we were advised to avoid the road near the western border in case of snipers.  Since our return we have reflected as much on the shared history of the countries we visited as on the differences which struck us most forcibly during our visit.

It was only as we started to read good guidebooks (we'd especially recommend the Bradt Guide to Armenia by Deirdre Holding, and the Georgia companion by Tim Burford (Bradt also) is not bad either), and then discovered a wonderful history and contemporary survey The Caucasus: an introduction by Thomas de Waal, that we began to understand the interwoven complexities of this fascinating area.

The Genocide Memorial in Yerevan
Armenia, our first port of call and now a landlocked country of only 3+ million people, was perhaps historically the most significant, having for centuries stretched from the eastern Mediterranean through Turkey across almost the whole of the area now divided between Armenia, Georgia and Azerbaijan.  Its current identity is marked by loss - loss of territory to the Turks (who now claim the sacred Mount Ararat once the centre of the Armenian highlands from which the ethnic group originates), loss of people to the awful genocide of the early 20th century, and loss of stability in the face of war (still smouldering with Azerbaijan over the disputed territory of Nagorny Karabach) and of natural disaster in the shape of earthquakes, since the area is on a geological fault line.   One town, Spitak, the size of Lunel was almost destroyed in 1988 and most of its inhabitants killed.  The damage was still all too evident, with temporary homes in containers and railway carriages, as we travelled through the area.

Our second week in Georgia was primarily to meet again our friends Leo and Marika, whom we'd hosted in Wirksworth in the early 2000s.  We added organised tours to fill our time during the week when they had to work.  We had a quaint but comfortable hotel in the old town of Tblisi, whence we could walk around the centre and visit museums and churches, and even attend a marionette show in the charming puppet theatre (in Georgian but with English surtitles, a very entertaining folk tale that ended up with the principal characters in Paris!).
Pirosmani's Doctor on a donkey

Karen Hakobyan's instruments
Highlights of our visit included artistic visits to the beautiful small museum in Yerevan dedicated to the well-known film director Sergei Parjanov - we loved it and went back to take in more detail before leaving Armenia - and the beautiful small gallery of the artist Niko Pirosmani in Signagi.  We also met Karen Hakobyan, a maker of traditional musical instruments including the duduk, in Yerevan - a real inspiration, and I have an alto shvi, a traditional fipple flute, as a lasting memento.  The instruments are made of stained apricot wood, the traditional material.

The separate identities of the two countries were really only crystallised under Tsarist and particularly Soviet influence, one effect of which was to precipitate huge population shifts to create 3 ethnically distinct countries (it would have been diffficult if not impossible to visit Azerbaijan even if we had had time).  I read that at one time in the 19th century almost no ethnic Armenians lived in present-day Armenia, huge numbers residing in what is now Iran and many also living in Georgia (our Armenian driver Ashot, for example, was brought up in Tblisi).

But communist rule (and particularly the longs shadows of Stalin and Beria) served to sow distrust between ethnic groups which separated like oil and water.  Armenia now has a population 98% ethnically Armenian, and although Tblisi has a more cosmopolitan feel (with a mosque where Shia and Sunni worship together and Christian churches of all the various traditions), there is a feeling of bravado and of Georgian national pride as strong in its way as the Armenian one.

The distrust, and the story of the south Caucasus, revolves round ethnic and cultural minorities, not only in Nagorny Kharabakh where de facto Armenian control has left a seemingly permanent impasse between the opposed positions of Azerbaijan and Armenia that have resisted repeated international conferences all over the world and which makes any reconciliation between Armenia and Turkey even more difficult than the genocide left it, but in the north of Georgia where two autonomous regions, Abkhazia and South Ossetia,, have been set up with Russian support.  The history of these two areas is long and complicated, but it has left most Georgians with a deep distrust of Russia and a strong preference for territorial integrity.  This in turn means they support Azerbaijan in claiming back Nagorny Kharabakh which sets Georgia at odds with Armenia, although luckily the antipathy is not extgreme so you can still travel as we did from one to the other, and Armenian commerce has access to the Black sea through the southern province of Georgia where there is still a high Armenian population that has resisted ethnic cleansing.

Traditional bread-making in Garni, Armenia
Two final things for now.  First food and drink.  We had excellent food throughout, with lots of fresh fruits, vegetables and salads particularly in Armenia and some lovely soups in Georgia as well as the ubiquitous and stomach-lining khachapuri, variations on warm flat bread filled with cheese, one delicious variant of which has an egg lightly poached on top.  The Armenian wine industry is less developed than the Georgian but both use indigenous grape varieities to good effect, particulalry the red Areni (centred round a village of that name in the south) in Armenia and some good dry whites in Georgia.  But Georgia also prides itself on good sweet red and white wines made from late-picked grapes.  And then there is Armenian brandy, reputedly Churchill's favourite tipple, and the ubiquitous vodka which testifies to the strength of the Soviet influence.

Drink at the Botanic Gardens, Tblisi
Roadside food stall in Tblisi old town
Wine tasting at Château Mukhrani west of Tblisi
Second, Stalin.  An odd note to finish on, maybe, and our Georgian friends doubted if we really needed to visit the museum in Gori which he himself established.  The little town still retains his statue in hte centre, and his childhoold house is preserved under a kind of huge bus shelter.  He adopted the last Tsar's railway carriage to get around, more or less without modification.  But we were helped by a suitably irreverent English-speaking guide, himself a native of Gori.  Above all this was a reminder (in a world where Brexit and Trump remind us how near the surface divisive extremism can be) that the fragile free countries we visited are there partly as a result of Stalin who, for better or worse, permitted the development of separate states with separate identities, and partly despite the cruel bloodshed that has surrounded them throughout their history and virtually until the present.

View over Tblisi to the mountains north-west of the city
Perhaps the most powerful influences that have shaped them and allowed them to survive and develop, though, are the mountains - the High Caucasus to the north which so hampered easy Russian access to the southern countries, the mountains between Turkey and Armenia which while sacred to the latter are also a brake on easy passage, and the mountains within the countries which have allowed separatist enclaves to survive.  It also makes for lovely scenery for us tourists, even if there is a risk of the early snow we ran into twice in our fortnight.

The larger Mount Ararat with Khor Virap monastery in the foreground
Mount Ararat from the 7th century circular cathedral of Zvartnots south of Yerevan


A week in Georgia

By noreply@blogger.com (Jon North)


 I had hoped to write this sooner, but getting back home I had to catch up on life in France, so this has been the first chance I've had to publish this post about our second week away.

It was of course the original reason for our Caucasus trip - to visit the couple of Georgian friends Leo and Marika whom we had hosted while Leo was a postgraduate architecture student in Nottingham.  But they both have to work, so having spent a weekend with them we joined up with the guide Eva (also seen here) and driver Ilya for a few days' tours to places outside the capital.  The weather turned wet and cold until our last day, which spoiled a lot of views, but we still saw a lot.

Our hotel in the Old Town was comfortable and convenient for walking around the tourist centre of Tblisi, which we did often during our week's stay.  The travel agent had arranged daytime trips during the week, but over the weekend Leo drove us east to an area, Khakheti, which produces most of the country's wine.  We visited monasteries and a town wine festival, and also a gallery including works by Pirosmani, one of the country's most popular modern artists who liked his wine as you can see).

                                   

                          

We spent the week, while Marika and Leo were at work, exploring the area west of Tblisi, including the old capital of Georgia and its cathedral, a monatery overlooking a lake and a snowy mountain pass, then later the château Mukhari, a winery of some quality.

Probably the outstanding visit of the week was to Mtskheta, the old capital of Georgia, which is just west of Tblisi at the confluence of 2 rivers.  The 6th century Jvari monastery is on a promontory overlooking the rivers, and the 11th century cathedral of Mtskheta just below.  Both were impressive - photos to finish this brief post, and more to come as I reflect on the complex, intertwined history and culture of the two countries we visited over this memorable fortnight.


 




















A week in Armenia 14-20 October 2016

By noreply@blogger.com (Jon North)

We'd thought of visiting our friends in Georgia for a few years, and Mary finally made the arrangements this summer as we celebrate 40 years together.  She found a travel agent in Montpellier which does Asian tours including an Armenian trip with an extension into Georgia, and since the season is nearly over they offered us an individual fortnight's holiday for 2.  This week we were in Armenia, and next we'll be in Georgia whence we fly home to France.

So this is a bit about our first week.  The best story is told through photos, but although I can easily put these on Facebook from this tablet, getting them into a blog will be much easier once I'm home with my laptop.  For now, some verbal impressions.  We travelled to Yerevan via Vienna, arriving in the early hours of Friday last.  Our guide Marietta and driver Ashot met us at the airport and have accompanied daily with friendly and professional care - they usually leave us evenings to recover, but this evening they've invited us for a farewell meal before they both accompany us to the airport at 5 tomorrow morning.

We have spent most of the time based in Yerevan, a sprawling mixture of Soviet blocks, shacks, building sites and splendid modern plazas and developments, home to around a million people, with very busy roads, and few bikes or motor bikes.  Roads outside the capital, and even back roads in Yerevan, are mostly in a poor state, and Ashot has needed all his skill to keep us out of most of the potholes in his Mercedes minibus.

Marietta, who is proud of her French, is even prouder of her country and people.  In fact, many people we met were anxious to get our opinion and approval of Armenia.  We had little real knowledge of it before we came, and only found a really good guidebook (in the Bradt guides series - http://www.bradtguides.com/destinations/europe/armenia.html) after our arrival, but we rapidly realised that this small nation with its quirky and unique alphabet derives its intense national pride from its history, up to the present day, of defining itself in the melting pot of the Caucasus, between the powerful political jaws of Russia and Turkey and as a Christian country under pressure from Muslim neighbours.

We have visited Christian heritage in many monasteries and saw incredible and ancient remains including countless lovely carvings, and we witnessed briefly the Sunday mass and beautiful singing at the cathedral.  We discovered local traditions - musical instruments like the doudouk, bread making - and extraordinary artists like Sergei Paradjanov.  We have been to wine and brandy tastings and learnt about local grape varieties.  And we have eaten good food, based hugely around fresh fruit and veg and salads and cooked vegetables prepared in countless ways, interesting local cheeses, creams and yoghurts, plus nice meat especially in stuffings for vine leaves.  And drunk a lot of good coffee.

We have ventured out of Yerevan to do all this on day excursions, mostly on day excursions but once on a 2-day trip via the huge lake Sevan north near the Azeri and Georgian borders, a journey plagued by rain then snow which forced us to alter our route, all of which Ashot handled well despite dropping temperatures.  On that trip we were reminded of the latest catastrophic earthquake in the north-west - Armenia lies on a tectonic fault-line.  Tragedies near the epicentre were heightened by poor Soviet-era building standards so that whole buildings collapsed killing thousands.

Such tragedies, and wars, pale into insignificance beside the 1915 genocide which has occupied our minds increasingly towards the end of our visit.  Wikipedia and the official genocide memorial website give much valuable information but nothing quite prepares you for the terrible graphic reality of the museum exhibition witnessing to the enforced death of over a million Armenians expelled from their homes and neighbourhoods.

I could go on but it will suffice to finish with our own testimony to a friendly and hospitable people despite, perhaps partly because of the tragedies and economic hardship they have suffered and despite the difficulties many still face.  We are happy to do our small part to make this place and these people better-known.

Why is the NHS listening to the siren voices of the vape manufacturers? | Victoria Coren Mitchell

By Victoria Coren Mitchell

The calls to make e-cigarettes free on prescription are outrageous when an actual cure for smoking is available

Public Health England has called for e-cigarettes to be made available on the NHS. This makes me so angry that I want to have a fag, although the last one I had was on 27 September 2014.

Ah well. I’ll settle for eating another packet of Minstrels and typing furiously.

Continue reading...

The checkout free shop is a wonderful idea, a machine will never judge you | Victoria Coren Mitchell

By Victoria Coren Mitchell

When we no longer have to impress the cashier – or fellow shoppers – we can buy what we like

Are you frightened of the rising machines? I try not to be. Machines are the future and being horrified by the future is so terribly ageing. Banging on about the misery of automated switchboards, the insecurity of online banking or the impersonality of email puts 20 years on you immediately, like racism or natural light. I try to avoid such things.

So, for me, it’s all “Good news, my local post office has shut down!”, “Ooh, you need a ‘registered account’ to buy cinema tickets, I couldn’t be happier!” and “Hurray! A leaked NHS England report says 111 calls will soon be diverted to a ‘diagnosis app’ instead of a person!”

Continue reading...

I did lose a pair of trousers once but they weren’t worth £1m, Boris | Victoria Coren Mitchell

By Victoria Coren Mitchell

The bankrupt tennis star’s admission that he has mislaid his trophies resonates with all of us who know we put that thing somewhere…

A s I sat with Boris Becker in the Riviera sunshine, each of us clutching a cigarette in one hand and a doughnut in the other, I thought: “This is my kind of sportsman.”

I didn’t know Boris Becker very well but I liked him enormously. Clearly, we both enjoyed the taste of a sugary butt on a spring afternoon. Also, we both loved a hand of cards; we were in Monte Carlo for a €10,000 poker tournament. I always found him approachable, friendly, unpretentious and nice to be around.

Continue reading...

Comparing unlike with unlike – it’s Whitehall’s secret new parlour game | Victoria Coren Mitchell

By Victoria Coren Mitchell

If the culture minister says that ambassadors should be paid more than BBC editors, we should next ask him how to choose between Victoria Beckham and a leopard

Well done Peston On Sunday, last week, for having three interview guests and triggering major news stories with each of them. That’s an amazing hit rate.

First guest Jeremy Corbyn hit the headlines for suggesting that the UK doesn’t really have a special relationship with America. Third guest Miriam Margolyes said “fuck” live on air. And the middle guest, shiny new culture secretary Matt Hancock, said that editors at the BBC should not be paid more than ambassadors.

Continue reading...

Molly tries to shuffle the pack | Victoria Coren Mitchell

By Victoria Coren Mitchell

The more things change the more they stay the same – even in a film about a strong woman

Can Hollywood fix itself? Is that already happening? Let’s go to the cinema together and find out.

It’ll have to be my local Everyman – a genteel chain where they transmit a lot of productions live from the National Theatre and sell yoghurt-coated nuts instead of Minstrels. Might not be your cup of tea. On the plus side, you can also get a cup of tea. It has to be that venue, because the trip has already happened.

Continue reading...

My Christmas present to you

By Victoria Coren Mitchell

Hate gift guides? Here’s an alternative to all those that insult you with dull ideas

The gift guides are out again! Regular readers will know how infuriated I am by those Christmas gift guides. Pages and pages of newsprint, all given over to the advice that we should consider buying our relatives a pair of socks or a bottle of wine.

Adding insult to insult, they invariably divide these “ideas” into relatives (“A lipstick for your wife! A book for your mum! A bottle of wine for Grandpa!”) just to make sure that nobody shops beyond the boundaries of age and gender stereotype. Not only must we buy the same old stuff every year, we must make the same old assumptions. Women love clothes. Kids love sweets. Men love golf calendars.

Continue reading...

Ed Sheeran versus the super-idiots | Victoria Coren Mitchell

By Victoria Coren Mitchell

Attacking the singer’s charity efforts takes a rare type of stupidity. But guess what...

According to a Dropbox survey published last week, most people believe that “only 68% of their work colleagues” are capable of the job.

This is a staggering figure. Why so high? Nobody’s capable of the job. Nobody’s capable of anything.

Related: Ed Sheeran Comic Relief film branded 'poverty porn' by aid watchdog

Continue reading...

Michael Gove, where did our love go? | Victoria Coren Mitchell

By Victoria Coren Mitchell

The environment secretary has shown a flash of his old character but I can’t forgive his betrayal

Did you wake up on Thursday morning expecting to feel a wave of affection for Michael Gove? I didn’t. I’m not sure anyone did. Possibly not even Mrs Gove, who wrote a very interesting joke in her Daily Mail column the day before.

“Kevin Spacey and Harvey Weinstein are reportedly languishing in rehab at an upmarket sex addiction clinic in Arizona,” it began. “No sex for eight weeks, apparently – although quite why they needed to fly to the desert for that is beyond me. Most of us find getting married does the trick.”

Continue reading...

Why are the police copping flak? | Victoria Coren Mitchell

By Victoria Coren Mitchell

Don’t damn officers for a Halloween prank – law and order should show it has bit of heart

It is possible that I have many things in common with Fenland police. You can’t do Only Connect for as long as I have without knowing that one thing can always be linked to another. Four things can be a challenge, but a simple pair, such as Fenland police and me… off the top of my head: we both like to wear blue, we’ve both dealt with a lot of drunks and neither of us has managed to stamp out hare-coursing in the county of Cambridgeshire.

And here’s another: we both tweeted pictures of ourselves dressed up for Halloween.

Continue reading...

Casinos gamble on their credibility | Victoria Coren Mitchell

By Victoria Coren Mitchell

If you’re too smart for gaming houses they’ll find a way to stop you - but more fool them

It is rare to see Phil Ivey, the greatest poker player of our time, losing seriously. This man is a genius. He can get inside other people’s heads.

The first time I played poker against him, I think he found me a little unsettling. People do, the first time. In Phil’s case, I don’t think it’s just that I was female – which is what throws most people – but that I was female and making jokes.

Continue reading...

Faster, higher, twerkier? | Victoria Coren Mitchell

By Victoria Coren Mitchell

Why stop at pole dancing at the Olympics? Let’s have groping and mud wrestling as well

The news that pole dancing has been formally recognised as a sport – and will now be considered for possible inclusion in the Olympics – fills me with delight.

Regular readers may be surprised. You might imagine I would feel weary and suspicious at this development. You might imagine I’d roll my eyes and ask: “What next? A simultaneous men’s event – how many bills can you shove in her bra as she writhes?”

Continue reading...

I’m really not a petrolhead... | Victoria Coren Mitchell

By Victoria Coren Mitchell

... but the thought of driverless cars and the surrender of freedom fill me with gloom

God bless the women of Saudi Arabia and their excitement about a royal decree allowing them to hold driving licences at last.

As we sit in traffic jams, fuming about inexplicable delays and unending roadworks, terrible radio playlists, the utter monotony and hell of it all, we should think of our sisters in the desert who see only the freedom, power and joy.

Continue reading...

Putting Granny online? No thanks| Victoria Coren Mitchell

By Victoria Coren Mitchell

I’m all for doing something for old people. But don’t ask me to put family snaps on the web

Today is National Grandparents’ Day. AgeUK is asking people to tweet, Instagram, hashtag (and other words your granny would not have understood) a photograph of their beloved ancestors, marked #grandpics, with a suggested donation of £5 with every photograph.

They asked me directly to do this. I said no. F*** em, I said.

Continue reading...

Oh, do let’s be beastly to the Nazis | Victoria Coren Mitchell

By Victoria Coren Mitchell

Nobody thinks Paul Hollywood is an actual Nazi; we should let him dress how he likes

A Nazi goes into a pub.

Hang on… that’s not a Nazi! It’s the well-known baker and TV personality Paul Hollywood!

Continue reading...

High street betting must clean up its act | Victoria Coren Mitchell

By Victoria Coren Mitchell

My column about the evils of fixed-odd betting terminals brought almost universal agreement but a few voiced their dissent. Let me answer my critics

Since my column last week about fixed-odds betting terminals, I’ve been getting hundreds of messages a day. Ninety-five percent of them agree with my view that these high-stakes modern slot machines should be restricted. I don’t think I’ve ever written a column that encountered more assent – or less dissent – apart from the one about “funeral crashers” who skulked around misleading the bereaved in hope of free booze. Not many people came out in support of those guys.

But FOBT machines are equal to the funeral crashers in their rapacious appetites, and inspired almost as little praise. The unanimity of the response was heartening and baffling at the same time: left-wingers and right-wingers, Labour MPs and Tory MPs, betting-shop workers, betting-shop punters and people who have never been in a betting shop; old and young, the addicts and the free; all united in agreement that the machines should be capped.

Continue reading...

Weekly Update 161

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

It's my first conference back in Australia since probably about May and I'm experiencing a rare luxury - not flying! I'm sticking to driving some big distances just to get a break from the tyranny that is check-in, security and airport lounges. Seriously, it was beginning to do my head

Weekly Update 160

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Australia! Geez it's nice to sit amongst the gum trees and listen to the birds, even if it's right in the middle of some fairly miserable weather. I'll continue to be here for the foreseeable future too, at least in one state or another. But being back here hasn't stopped

Weekly Update 159

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Well, this will be the last weekly update done overseas for some time as I count down the return to beaches, sunshine and fantastic coffee (yes, I'm confident saying that even whilst in Italy!) It's been a non-stop trip with an attempt of a bit of downtime at the end

Weekly Update 158

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

It's been a bit of intense country-hopping since the last update so this one is a consolidated "this week in tweets" version. I actually found it kind of interesting going back through the noteworthy incidents of the week in lieu of having original content of my own, see what you

Weekly Update 157

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Hungary! And that's about as much intro as I'm going to do on that because this is going out super later and I'm writing this at the end of a very long day. Only other thing I'll mention is the audio - the Instamic failed to record again so it's

Banks, Arbitrary Password Restrictions and Why They Don't Matter

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Allow me to be controversial for a moment: arbitrary password restrictions on banks such as short max lengths and disallowed characters don't matter. Also, allow me to argue with myself for a moment: banks shouldn't have these restrictions in place anyway.

I want to put forward cases for both arguments

Weekly Update 156

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Turns out it's actually a sunny day in Oslo today, although it's the last one I'll see here for quite some time before heading off to Denmark then other European things for the remainder of this trip. I'm talking a little about those events (all listed on my events page

Weekly Update 155

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

From the emerging spring to the impending autumn, I'm back in Oslo at the beginning of another series of European events that'll take me across Norway, Denmark, Hungary and Switzerland. This week's update comes from under the glow of a warm outdoor heater at ridiculous o'clock as my sleep cycle

Weekly Update 154

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

How's that for a setting in this week's video? 🌴 First day of spring here which aligned with a father's day on the water:

Back on business as

Weekly Update 153

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Australia! Sunshine, good coffee and back in the water on the tail end of "winter". I'm pretty late doing this week's video as the time has disappeared rather quickly and I'm making the most of it before the next round of events. Be that as it may, there's a bunch

Weekly Update 152

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

I made it out of Vegas! That was a rather intense 8 days and if I'm honest, returning to the relative tranquillity of Oslo has been lovely (not to mention the massive uptick in coffee quality). But just as the US to Europe jet lag passes, it's time to head

Extended Validation Certificates are (Really, Really) Dead

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Almost one year ago now, I declared extended validation certificates dead. The entity name had just been removed from Safari on iOS, it was about to be removed from Safari on Mojave and there were indications that Chrome would remove it from the desktop in the future (they already weren't

Weekly Update 151

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Well that's Vegas done. 8 days of absolutely non-stop events that's now pretty much robbed me of my voice but hey, I got a flying cow! Scott and I both spent BSides, Black Hat and DEF CON doing "hallway con" or in other words, wandering around just meeting people. The

Weekly Update 150

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Vegas! I'm a bit late with this week's update but I thought I'd catch up with Scott Helme and do the video together. We're talking about the events in Vegas, the ongoing Project Svalbard process, some very screwy messaging about certificates from Sectigo and the Irish government coming on board

Welcoming the Irish Government to Have I Been Pwned

By Troy Hunt

Presently sponsored by: Varonis. Free Video Course: 7 Hidden Office 365 Security Settings You Can Only Unlock with PowerShell

Over the last year and a bit I've been working to make more data in HIBP freely available to governments around the world that want to monitor their own exposure in data breaches. Like the rest of us, governments regularly rely on services that fall victim to attacks resulting in

It is fixed-term tenancies that are from a bygone era. They are costly, stigmatising and unnecessary

By Aileen Evans

Following the suggestion that lifetime tenancies are “from a bygone era”, Aileen Evans argues that they make more practical and business sense than fixed-term contracts

Enfield to increase affordable housing to 50% on first phase of its £6bn Meridian Water scheme

By James Wilmore

A London council has committed to 50% affordable housing on the first phase of a troubled £6bn flagship regeneration scheme.

London council launches heat pump pilot following climate emergency declaration

By Lucie Heath

A London borough will retrofit a high-rise block with ground source heat pumps in an effort to cut residents’ bills and meet climate change targets.

Dispatches from the Scottish National Party Conference 2019

By Lucie Heath

Inside Housing spent the first half of this week at the Scottish National Party’s Annual Conference. At an important crossroads for the housing sector in Scotland, Lucie Heath rounds up some of the key talking points from the event in Aberdeen

Abuse victims must be allocated 5% of all London’s new social homes, says charity

By James Wilmore

Five per cent of all new social homes built in London each year should be allocated for women and children made homeless through abuse, a charity has said. 

Developers face ‘surprising’ biodiversity net gain target on new schemes

By James Wilmore

New laws will force developers to deliver a net biodiversity gain of “at least” 10% on housing schemes as part of the government’s Environment Bill.

Inside Housing chief executive salary survey 2019: gender pay gap closes to 2%

By Jack Simpson

The pay gap between female and male chief executives of the country’s largest housing associations has been drastically cut, with women being paid on average just over 2% less than their male counterparts, exclusive research by Inside Housing reveals.

Morning Briefing: scepticism of Grenfell land study findings

By Lucie Heath

An MP and a community group have expressed scepticism about the findings of a government study that found “no increased risk to health” from potentially contaminated land surrounding Grenfell Tower, and other housing news

Housing association gives interim boss permanent role after governance upgrade

By James Wilmore

Leeds & Yorkshire Housing Association (LYHA) has installed its interim chief executive in the job permanently, less than a month after regaining the top regulatory grading for governance. 

The CEO salary gap may have shifted but there is still much work to be done

By Martin Hilditch

A narrowing of the CEO pay gap shouldn’t disguise the work that still needs to be done to make the sector more equal, writes Martin Hilditch

18 October digital edition of Inside Housing out now

By Inside Housing

The 18 October digital edition of Inside Housing is now available to subscribers

The new kid on the block: we meet the housing secretary Robert Jenrick

By Jack Simpson

Robert Jenrick’s rise to the cabinet has come in double-quick time. Three months into his new role, Jack Simpson sits down with the housing secretary to see how he is settling in.

Morning Briefing: tenants win London segregated garden battle

By James Wilmore

Council tenants on a London estate have won their fight to use gardens reserved for owners of multimillion pound flats.

PWLB rate rise is ‘credit negative’ for councils, warns Moody’s

By Nathaniel Barker

The Treasury’s decision to increase Public Works Loan Board (PWLB) interest rates is “credit negative” for local authorities, credit rating agency Moody’s has warned.

Is regulation the answer to improving the housing sector’s record on diversity?

By Raj Patel and Pritti Allen

Regulatory attention to diversity in the sector has fallen in recent years. Raj Patel and Pritti Allen ask: is it time for it to be stepped up?

Maids Moreton: Ben Field jailed for author's murder

Benjamin Field, 28, seduced 69-year-old Peter Farquhar into changing his will before killing him.

Like Visual Studio Code and your data lives in SQL Server? Microsoft has something for you

By Richard Speed

SQL Object Explorer, SQLCMD and more IntelliCode arrive for VS Code

Microsoft's determination to foist on the world ever more ways of connecting to SQL Server has continued unabated with a major update of the mssql extension for the ubiquitous Visual Studio Code.…

Harry Dunn: Parents ask police to charge crash death suspect

Harry Dunn's family say US officials are "ruthlessly" protecting Anne Sacoolas from facing justice.

Honesty Cards: Burnley's Ashley Westwood & Ashley Barnes spill the beans

Ashley Westwood and Ashley Barnes reveal who does the best impression of Burnley boss Sean Dyche in the Clarets' dressing room, in this week's Honesty Cards.

Dozens killed in Afghanistan mosque bombing

The attack, in eastern Nangarhar province, targeted worshippers during Friday prayers.

Brexit: Johnson in race to win support for deal

No 10 is trying to persuade MPs to back the PM's deal ahead of a vote in the Commons on Saturday.

El Chapo: Mexican police free drug lord's son as Culiacán battle erupts

Security forces and cartel gunmen clash after drug lord Joaquín "El Chapo" Guzmán's son is discovered.

Brexit: What to expect from Parliament's Saturday sitting

The weekend sitting of Parliament will see MPs vote on Boris Johnson's Brexit deal.

Yahoo! Groups' closure and a tale of Oftel: Die-hard users 'informally' included telcos

By Kat Hall

Ofcom: Ahem. Just check our website

The tossing away of user-generated content on Yahoo!'s long-running Groups site on Wednesday was not just bad news for all the hardcore users who are about to lose all their precious things stored there. Many were quick to point at telcos, who were using Yahoo! Groups to manage phone number assignments.…

Catalonia protests and general strike paralyse Barcelona

The Supreme Court decision to jail nine separatist leaders has enraged demonstrators in Catalonia.

Nasa astronauts Christina Koch and Jessica Meir in all-women spacewalk

Two female astronauts are making history with the first ever all-women spacewalk.

Reading Chick-fil-A outlet to close in LGBT rights row

The Oracle shopping centre decides "not to extend the lease" of the popular US fast-food chain.

El Clasico: Barcelona v Real Madrid postponed because of fears over civil unrest

This month's El Clasico between Barcelona and Real Madrid is postponed because of fears of civil unrest.

Soup up your serverless smarts with our practical hands-on workshops: Sign up now and we'll see you next month

By Team Register

Serverless Computing London takes you deep into Lambda, Azure, and more

Event  If you’re looking for a thorough grounding in serverless computing, or just want to kick your existing experiments into a higher gear, why not join our workshop day at Serverless Computing London next month.…

Brexit deal: What does it mean?

Boris Johnson has agreed a new Brexit deal with the EU - but what does it mean and will Parliament pass it?

2018 Central Park Squirrel Census in Datasette

2018 Central Park Squirrel Census in Datasette

The Squirrel Census project released their data! 3,000 squirrel observations in Central Park, each with fur color and latitude and longitude and behavioral observations. I love this data so much. I've loaded it into a Datasette running on Glitch.

Via @simonw

5 Tools to Track and Tweak WordPress Performance

By Ben Lloyd

In the ultra-competitive online world, every millisecond counts. If a page takes too long to load, impatient visitors will go elsewhere. To help retain audience and boost sales, website owners invest heavily in tools and tweaks to squeeze every bit of performance out of their WordPress-based websites. Here’s our selection of five tools typically used […]

The post 5 Tools to Track and Tweak WordPress Performance appeared first on Pingdom Royal.

Tour d'Orwell: The River Orwell

Continuing my Orwell-themed peregrination, a certain Eric Blair took his pen name "George Orwell" because of his love for a certain river just south of Ipswich, Suffolk. With sheepdog trials being undertaken in the field underneath, even the concrete Orwell Bridge looked pretty majestic from the garden centre — cum — food hall.

μPlot

μPlot

"An exceptionally fast, tiny time series chart. [...] from a cold start it can create an interactive chart containing 150,000 data points in 40ms. [...] at < 10 KB, it's likely the smallest and fastest time series plotter that doesn't make use of WebGL shaders or WASM"

Via @mikeal

Weeknotes: PG&E outages, and Open Source works!

My big focus this week was the PG&E outages project. I'm really pleased with how this turned out: the San Francisco Chronicle used data from it for their excellent PG&E outage interactive (mixing in data on wind conditions) and it earned a bunch of interest on Twitter and some discussion on Hacker News.

I gave a talk about the project on Thursday for the Online News Association Silicon Valley meetup and made connections with a bunch of interesting journalists from around the Bay Area.

Open Source works!

A highlight of last week was that a bunch of my projects gained new functionality through open source contributions!

Dogsheep

I started a very basic website for my Dogsheep personal analytics project.

I also started running various Dogsheep tools via cron on my personal Dogsheep server, to keep that set of databases automatically updated with my latest activity on various services.

Most excitingly, Tobias Kunze built the first indepedent Dogsheep-style tool: goodreads-to-sqlite!

As the name suggests, it imports your data from Goodreads into a SQLite database. It inspired me to create a Goodreads account which I will be using to track my book reading activity from now on.

Tobias wrote a fantastic blog post introducing the tool which includes some neat example queries and graphs.

In other Dogsheep news, I added an issue-comments command to github-to-sqlite for fetching all issue comments in a repo. My goal is to evolve that tool to the point where it can import all relevant data from all of my repositories and give me a single Datasette-powered dashboard for keeping track of everything in one place.

goodreads-to-sqlite

goodreads-to-sqlite

This is so cool! Tobias Kunze built a Python CLI tool to import your Goodreads data into a SQLite database, inspired by github-to-sqlite and my various other Dogsheep tools. It's the first Dogsheep style tool I've seen that wasn't built by me - and Tobias' write-up includes some neat examples of queries you can run against your Goodreads data. I've now started using Goodreads and I'm importing my books into my own private Dogsheep Datasette instance.

Via @rixxtr

Tracking PG&E outages by scraping to a git repo

PG&E have cut off power to several million people in northern California, supposedly as a precaution against wildfires.

As it happens, I've been scraping and recording PG&E's outage data every 10 minutes for the past 4+ months. This data got really interesting over the past two days!

The original data lives in a GitHub repo (more importantly in the commit history of that repo).

Reading JSON in a Git repo isn't particularly productive, so this afternoon I figured out how to transform that data into a SQLite database and publish it with Datasette.

The result is pge-outages.simonwillison.net

The data model: outages and snapshots

The three key tables to understand are outages, snapshots and outage_snapshots.

PG&E assign an outage ID to every outage - where an outage is usually something that affects a few dozen customers. I store these in the outages table.

Every 10 minutes I grab a snapshot of their full JSON file, which reports every single outage that is currently ongoing. I store a record of when I grabbed that snapshot in the snapshots table.

The most interesting table is outage_snapshots. Every time I see an outage in the JSON feed, I record a new copy of its data as an outage_snapshot row. This allows me to reconstruct the full history of any outage, in 10 minute increments.

Here are all of the outages that were represented in snapshot 1269 - captured at 4:10pm Pacific Time today.

I can run select sum(estCustAffected) from outage_snapshots where snapshot = 1269 (try it here) to count up the total PG&E estimate of the number of affected customers - it's 545,706!

I've installed datasette-vega which means I can render graphs. Here's my first attempt at a graph showing the number of estimated customers affected over time.

(I don't know why there's a dip towards the end of the graph).

I also defined a SQL view which shows all of the outages from the most recently captured snapshot (usually within the past 10 minutes if the PG&E website hasn't gone down) and renders them using datasette-cluster-map.

Things to be aware of

There are a huge amount of unanswered questions about this data. I've just been looking at PG&E's JSON and making guesses about what things like estCustAffected means. Without official documentation we can only guess as to how accurate this data is, or how it should be interpreted.

Some things to question:

How it works

I originally wrote the scraper back in October 2017 during the North Bay fires, and moved it to run on Circle CI based on my work building a commit history of San Francisco's trees.

It's pretty simple: every 10 minutes a Circle CI job runs which scrapes the JSON feed that powers the PG&E website's outage map.

The JSON is then committed to my pge-outages GitHub repository, over-writing the existing pge-outages.json file. There's some code that attempts to generate a human-readable commit message, but the historic data itself is saved in the commit history of that single file.

Building the Datasette

The hardest part of this project was figuring out how to turn a GitHub commit history of changes to a JSON file into a SQLite database for use with Datasette.

After a bunch of prototyping in a Jupyter notebook, I ended up with the schema described above.

The code that generates the database can be found in build_database.py. I used GitPython to read data from the git repository and my sqlite-utils library to create and update the database.

Deployment

Since this is a large database that changes every ten minutes, I couldn't use the usual datasette publish trick of packaging it up and re-deploying it to a serverless host (Cloud Run or Heroku or Zeit Now) every time it updates.

Instead, I'm running it on a VPS instance. I ended up trying out Digital Ocean for this, after an enjoyable Twitter conversation about good options for stateful (as opposed to stateless) hosting.

Next steps

I'm putting this out there and sharing it with the California News Nerd community in the hope that people can find interesting stories in there and help firm up my methodology - or take what I've done and spin up much more interesting forks of it.

If you build something interesting with this please let me know, via email (swillison is my Gmail) or on Twitter.

Tour d'Orwell: Southwold

I recently read that that during 1929 George Orwell returned to his family home in the Suffolk town of Southwold but when I further learned that he had acquired a motorbike during this time to explore the surrounding villages I could not resist visiting myself on such a transport mode.

Orwell would end up writing his first novel here ("Burmese Days") followed by his first passable one ("A Clergyman's Daughter") but unfortunately the local bookshop was only to have the former in stock. He moved back to London in 1934 to work in a bookshop in Hampstead, now a «Le Pain Quotidien».

If you are thinking of visiting, Southwold has some lovely quaint beach huts, a brewery and the officially signposted A1120 "Scenic Route" I took on the way out was neither as picturesque nor as fun to ride as the A1066

How To Check Website Status

By Ben Lloyd

Website status checks should be a routine part of any IT maintenance schedule. Corporate websites are often hosted externally, but this doesn’t mean they should be excluded from the checklist of applications and servers needing to be monitored. But what’s website status, and how do you check it properly? Website Status – What You Need […]

The post How To Check Website Status appeared first on Pingdom Royal.

SQL Murder Mystery in Datasette

SQL Murder Mystery in Datasette

"A crime has taken place and the detective needs your help. The detective gave you the  crime scene report, but you somehow lost it. You vaguely remember that the crime  was a murder that occurred sometime on ​Jan.15, 2018 and that it took place in SQL  City. Start by retrieving the corresponding crime scene report from the police  department’s database." - Really fun game to help exercise your skills with SQL by the NU Knight Lab. I loaded their SQLite database into Datasette so you can play in your browser.

Via @knightlab

Weeknotes: Dogsheep

Having figured out my Stanford schedule, this week I started getting back into the habit of writing some code.

Dogsheep

Dogsheep is the collective name I've given to a suite of tools I'm building around the concept of personal analytics.

I generate a lot of data, and while much of it ends up in the silos of the internet giants, thanks to the GDPR most of those silos now feature an "export a copy of your data" button.

Wouldn't it be cool if you could convert that data into a SQLite database and then use Datasette to run queries against it?

So that's what I'm doing! The tools I've built so far include:

My biggest achievement this week is that my own personal Dogsheep is no longer vaporware! I got a Datasette instance running on a AWS Lightsail VPS (using the systemd recipe from this ticket) and started loading in copies of my data.

Securing this instance well is important. In addition to running it behind datasette-auth-github I've followed up on a long-term ambition of deploying something protected by client certificates. If your browser doesn't have the required certificate installed it gets rejected by nginx before it's even proxied through to Datasette.

I have the certificate successfully installed on my iPhone and my laptop browsers. Setting this all up wasn't particularly straight-forward - I ended up following this excellent tutorial by Nathan Wittstock for the nginx part of it, then randomly Googling for tips on installing the certificate in Firefox and on my iPhone.

I think there's a great opportunity for tooling that makes this much easier. Adding that to my maybe-someday pile.

datasette-auth-github asset caching

Dogsheep is a great opportunity for eating my own dogfood. I've been having a lot of fun using it to explore my data... but I noticed that there was a suspicous delay every time I clicked a link. Datasette is mostly JavaScript-free but usually it responds so fast (~100ms or less) that clicking around feels "app-like" - but here I was really feeling the delay, often of more than a second.

I fired up the Firefox Network inspector and quickly spotted what was happening. I have the datasette-vega plugin installed so I can create charts, and that weighs in at nearly 1MB of JavaScript. According to Firefox my browser was loading that entire 1M file from scratch for every page load!

The culprit there turned out to be my datasette-auth-github plugin.

As detailed in issue #6, the ASGI middleware adds a cache-control: private header to every HTTP response - to make sure authentication-required content isn't accidentally cached by any intermediary proxies (I originally designed Datasette to run effectively behind Varnish and Cloudflare).

This was applied to everything... including the static JavaScript and CSS served up by the plugin!

To fix this, I shipped a new release of datasette-auth-github with a cacheable_prefixes setting, which defaults to /-/static/ and /-/static-plugins/ when run as a Datasette plugin. See issue 47 for details.

Areas of research

Connection pooling

My most significant ongoing project for Datasette right now concerns database connection pooling.

For Datasette Library I want to be able to support potentially hundreds of attached databases, and Datasette Edit calls for the ability to use a writable (as opposed to read-only) connection.

This means I need to get smarter about database connections, and last week I finally made some solid progress on figuring out more advanced connection pooling. Still more work to go but I'm finally feeling unblocked on this after sweating over it for a couple of months without writing any code.

I also added a /-/threads page to Datasette (demo) to make it easier to understand the threads being run by the application.

Recursive CTEs in SQLite

twitter-to-sqlite generates a tweets table with both id and in_reply_to_status_id (nullable) columns.

SQLite supports recursive CTEs, documented here. In theory, this means it should be possible to write SQL queries that analyze Twitter threads - showing me the tweets that are at the bottom of the longest reply chain, for example.

I was feeling lazy and asked if anyone knew how to do that on Twitter. Robin Houston, Matthew Somerville and Piers Cawley all chipped in with useful tips, which I've collected in this gist.

I particularly enjoyed learning how Piers uses recursive SQL queries to help run his bakery.

logging

I finally made some progress on getting my head around the Python standard library logging module, a long-time nemesis.

The breakthrough was to sit down and actually read the source code - which helped me understand that the entire point of the library is to be a globally configured logging system that makes careful use of threading primitives to ensure you can log without worrying about concurrency.

I've been worrying about that aspect of logging for years, so it's reassuring to see that Vinay Sajip has that comprehensively covered already.

Easier installation for Datasette

I want journalists to be able to install Datasette. I don't want to have to talk them through installing xcode to install homebrew to install Python 3 first!

Raffaele Messuti did some great work investigating pyinstaller for this a while ago. I started a conversation on Twitter a few days ago after investigating pex (neat but not quite what I want, since users still have to install Python). From that thread I got some interesting further leads:

Next step: actively try some of these out and see what I can do with them.

My longer term goal is to package Datasette up with Electron and make it available as a regular Windows and OS X application, for people who aren't comfortable using the command-line directly.

Books

I've been mostly working through required reading for my Stanford courses. Strategic Communication in particular has some excellent text books:

twitter-to-sqlite 0.6, with track and follow

twitter-to-sqlite 0.6, with track and follow

I shipped a new release of my twitter-to-sqlite command-line tool this evening. It now includes experimental features for subscribing to the Twitter streaming API: you can track keywords or follow users and matching Tweets will be written to a SQLite database in real-time as they come in through the API. Since Datasette supports mutable databases now you can run Datasette against the database and run queries against the tweets as they are inserted into the tables.

Streamlit: Turn Python Scripts into Beautiful ML Tools

Streamlit: Turn Python Scripts into Beautiful ML Tools

A really interesting new tool / application development framework. Streamlit is designed to help machine learning engineers build usable web frontends for their work. It does this by providing a simple, productive Python environment which lets you declaratively build up a sort-of Notebook style interface for your code. It includes the ability to insert a DataFrame, geospatial map rendering, chart or image into the application with a single Python function call. It's hard to describe how it works, but the tutorial and demo worked really well for me: "pip install streamlit" and then "streamlit hello" to get a full-featured demo in a browser, then you can run through the tutorial to start building a real interactive application in a few dozen lines of code.

Via Hacker News

Get your own Pocket OAuth token

Get your own Pocket OAuth token

I hate it when APIs make you jump through extensive hoops just to get an access token for pulling data directly from your own personal account. I've been playing with the Pocket API today and it has a pretty complex OAuth flow, so I built a tiny Flask app on Glitch which helps go through the steps to get an API token for your own personal Pocket account.

Via Source code for your-pocket-oauth-token.glitch.me

Client-Side Certificate Authentication with nginx

Client-Side Certificate Authentication with nginx

I'm intrigued by client-side browser certificates, which allow you to lock down a website such that only browsers with a specific certificate installed can access them. They work on both laptops and mobile phones. I followed the steps in this tutorial and managed to get an nginx instance running which only allows connections from my personal laptop and iPhone.

Comparison of X Window Managers

Comments

Microsoft’s visual data explorer SandDance open sourced

Comments

Life Sciences Data Business Analyst

Comments

Mozilla Intends to Deprecate OpenSearch

Comments

Rules for Developing Safety Critical Code [pdf]

Comments

Intel Shooting Star Drones

Comments

Really Fixing Getrandom()

Comments

Options for Saving Yahoo Groups Content

Comments

What nobody tells you about documentation

Comments

My Favourite Git Commit

Comments

Microchip Adds RISC-V Cores to PolarFire FPGAs

Comments

Machine learning in UK financial services

Comments

We moved our servers to Iceland

Comments

Knuth – Estimating the Efficiency of Backtrack Programs(1975) [pdf]

Comments

California fault capable of producing a magnitude 8 earthquake has begun moving

Comments

Montgomery Brewster's 'None of the Above' would walk this election.

By Jackart (noreply@blogger.com)

It's actually quite liberating to follow politics without a team to shout for. I remain a Conservative by inclination. I like free markets, economic liberalism and so forth even if the Conservative manifesto doesn't seem to all that much, Tories, if not their leadership, are mainly for these things. I am also a social liberal, I remain committed to an open and tolerant society. However the Liberal Democrats risk becoming the Church of England does Politics, being stuffed with the kind of dry, shabby inadequate who can't quite get over his (self) loathing of homosexuality. I dislike May. I think she's a narrow-minded provincial bigot who's been promoted way, way above her level of competence. She is however the best of the two candidates for Prime Minister. 

Let's not pretend Corbyn was doing other than palling around with the IRA in the 1980s because the glamour of "anti-imperialist" terrorists excited him. He has always supported whoever was fighting the UK at the time, and doesn't deserve to be an MP, let alone to reverse those letters. Labour's clown-car economics is only marginally less risible than the Tories offer, this time round. The difference is Labour actually believe their silliness, and they're led by a traitor. 

If you live in Scotland, this election is about independence. If you live in NI, then this election is about the tribal headcount. If you live elsewhere this election is whether you want an incompetent nanny-state provincial Tory or an antediluvian Socialist to deliver Brexit. It's a shabby, and dispiriting affair. If you can't work out how to vote, you can always vote for Montgomery Brewster. None of the above is appealing. But if you feel you MUST vote, then I have prepared a handy flow-chart to help you.

If you despise politicians, you get despicable politicians.
This shabby parade of also-rans from which we have to choose on today (without any actual choice on the main, nay only, issue of the day) is the logic of calling decent, capable people like Blair, Cameron and Major "war criminals" and "Traitors", for decades. It pollutes the language for when you actually get some of these things on the offer.
No worthwhile people will put up with the scrutiny and abuse heaped daily on politicians. So you get the kind of bore for whom the scrutiny isn't an issue. They've never done anything interesting in the their lives. At least David Cameron dropped some E and went to a rave or two as a youth. What does Theresa May, who spent her twenties complaining about the promotion of lesbianism in schools, know of fun? As for Corbyn, he looks like the kind of man for whom a perfect saturday night is treatise on Marx (so long as it contains nothing he doesn't already know and agree with) with some lovely mineral water. He is the Labour man Orwell warned you about.

I'll be voting Tory. Why? My local headbanging Leadsomite hard-brexiter has stood down after his colossal act of vandalism, to be replaced by a man with whom I seem to agree.
My expectations are of a  Tory majority around 75, on a low turnout, and they will have half a dozen seats in Scotland.  The Liberal Democrats will take Vauxhall and Twickenham, losing in Sheffield Hallam (the "were you up for...?" moment as Clegg loses his seat), but holding Orkney and Shetland against the SNP, remaining about where they are now overall. Or that's where my betting is at the moment.
What do I want to see happen? I'd like to see May remain PM but in a hung parliament, reliant on Northern Irish politicians for her majority because let's face it, she deserves nothing better.
A rubbish show all round but at least I can enjoy it, whoever loses.

Whales are more Important to Climate change than Donald Trump.

By Jackart (noreply@blogger.com)

Donald Trump has pulled the USA out of the Paris Climate accord. And I don't think this matters all that much. For a start, the USA's emissions are falling. Mostly this is because coal is being replaced by Natural Gas, but also because people are driving less, in smaller vehicles with ever more efficient engines. The motors driving the west's steady fall in carbon emissions are economic and technological, not political.

Next to the steady decline in carbon emissions from the west, is set the Vast increase in emissions in recent decades from Asia. But this represents billions of people using no net carbon energy, tending crops using animal muscle and burning biomass (and occasionally starving to death) Just a few decades ago, to my meeting an indian chap on Holiday in Stockholm with his family and chatting about cricket while we tried to decipher the train times. The rise of the middle class in India and China is a huge flowering of human potential, even if it comes with soluble environmental problems.

Anyway, the level of Co2 in the atmosphere is rising, and this is changing the climate. Reducing emissions is a noble aim, but it must not get in the way of developing economies' economic growth. Fortunately, the solution is already with us. Renewable technology is improving. Cars are getting more efficient, and perhaps moving away from fossil fuel (at least directly). And this process will happen in india and China more quickly than in the west beacaue adopting what will be soon proven and cheap technology will enable them to miss whole generations of poluting technologies.

Which brings us to the great cetaceans. The southern ocean is the world's biggest habitat, with the world's shortest food chain, at the top of which sits the largest animal that has ever existed on earth. Phytoplancton bloom, and are eaten by zooplankton, which are eaten by fish larvae and Krill, which are eaten buy just about everything else. The biggest eaters of Krill are the baleen whales which turn five tons of Krill into Iron-rich shit every day. Sperm whales meanwhile are diving to the abysal deep turning several tons of squid into Iron-rich scat, moving nutrients from the deep to the surface. The limiting nutrient at the bottom of the food-chain is iron, so whale faeces fertilise the ocean, and enable more phytoplanckton to grow which absorb Co2 from  the air, much of which falls to the bottom of the ocean as marine snow, and eventually become rock.

But we killed the whales, and when we stopped doing so, they didn't recover as quickly as we hoped. We didn't just kill the Apex predators, in doing so, humanity reduced the Southern ocean's ecosystem's capacity to create life, and absorb Carbon. The southerm ocean may have settled at a lower equilibrium of Iron circulation. The Atlantic on the other hand, which gets tons of Iron from the african deserts every time the wind blows, has seen whale stocks recover better.

Which is why I want to see more research into Iron seeding the ocean, which may give a leg up to Balaenoptera musculus, as well as possibly solving climate change. Climate change is a problem. But while Trump's petulent gesture doesn't help us solve it, nor does it make the problem any harder. Politicians simply matter less than a whale taking a dump.

Why the Blue Passport Matters.

By Jackart (noreply@blogger.com)

People have spent the day on Twitter saying "why does the colour of a passport matter"? While the Daily Express is cheering the return of the Blue Passport to the rafters. For most people capable of abstract thought, this is a mystifying detail, the importance of which to their opponents is utterly baffling. Of course, I am a remain "ultra". But I did swim in the same intellectual Milieu as the Brexity-Trumpkins for decades and know many serious Brexiters personally. Having spend decades rationalising the EU-obsessed madness of the Tory right as a harmless eccentricity that they don't really mean, I do have, with hindsight, some understanding what these creatures think.



Why does the passport matter?

For the Tory Brexiter, the underlying issue is Sovereignty. They object violently, strenuously and on principle to ANYTHING that comes "above" the Crown in Parliament. The jurisdiction of the ECJ is for them, an insult to the courts and other institutions of the UK. The idea is offensive that any law-making organisation, especially one that Jacques Delors told the trades unions is basically for stopping the Tories Torying, could be "supreme" over parliament.

Of course the ECJ mainly deals in trade disputes and represents an international court to settle international issues and ensure consistent interpretation of EU law. It isn't "making the law of the land" and nor is it a "supreme" court in a meaningful way as far as the average citizen is concerned because it doesn't deal with those issues. If you're up in front of the Magistrate for punching a rotter, you're not going to be able to appeal all the way to the ECJ. Criminal law stops with the nation. Appeals of bad people going up to the European court of Human Rights on seemingly spurious grounds get funnelled into this narrative (shhh, I know), so the impression is obtained that "Crazy Euro-Judges" are "over-ruling parliament", and demanding prisoners can vote or should be allowed hacksaws to avoid trampling on "Human Rights" or whatever the tabloid outrage du jour may be. This then reinforces the narrative that the EU is "anti-democratic" and "makes all our laws". And once you have this narrative, flawed as it is, it's jolly easy to amass an awful lot of corroborating "evidence" because the Tabloids spent 30 years deliberately feeding it.

Sovereignty vs Influence; there is a trade-off. The UK, broadly, wrote the Financial services legislation for the entire continent. In return, the Continent got access to the only truly global city in Europe. The French did this for farming and got the CAP, while the Germans got the Eurozone's interest rates and got to destroy Southern Europe. The EU which contains (rather like the UK and trade negotiators) no-one who CAN write decent financial services legislation legislation, because most of those people are British. Thanks to Brexit, the quality of the legislation on financial services will go down, both in the UK which will be compelled to have regulatory equivalence to keep banks' access to the single market and the EU. The UK will have become a rule-taker rather than a rule maker. I fail to see how this reclaims "Sovereignty". The organisational source of the legislation will remain unchanged, but we loose any ability to influence, let alone write it. Multiply this catastrophe across an economy and you see why the "sovereignty" argument against EU law is, on any rational basis, stupid.

The parliament, the very existence of which takes on the aspect of a supranational government in waiting, rather than a simple means to have democratic oversight of an organisation which employs fewer people than Manchester city council, distributes about 1% of GDP and writes trade law. This unwarranted grandiosity once again suits both the Brussels apparatchiks, and the simian oiks of UKIP whom the British public sent to Brussels as a mark of the National contempt for the institution. The parliament is, to my mind is a risible little potempkin affair, barely worth considering,

So there's the error. Back to the passport.

The International Civil Aviation Organisation sets the dimensions, so the writing was on the wall for the old British hardback passport, fabulous though it was, it didn't really fit in the back pocket of your trousers.  However once you believe that the EU tentacles are slowly creeping into institutions to turn you into a province of the "EUSSR", then you start to see this everywhere. The EU is foolish to seek the trappings of a national Government before they had built a demos, and absent any desire for it from the people. Symbols matter. The UK doesn't have an ID card. So when Brits talk about nationality they might say "Australian passport-holder" rather than "Australian citizen". I am not sure if any other nationalities use this formulation. The passport is slightly more than a document. No? Try losing one abroad.

The EU resolution on Passports is here. For anyone who thinks the EU "made" the UK have a Maroon passport, here's EU Croatia's. .



The EU suggested the Colour be harmonised and the words "European Union" be put First. At the top. Above the crown, First. Symbolising, perhaps inadvertently that the EU was more important than the nations. And there you have it. And no-one working on it thought to object. Changing the colour of the passport was a key symbolic gesture that irritated many people, and reinforced an utterly false narrative, to no end or benefit to anyone. There is simply no need for European Union passports to be uniformly coloured. It merely satisfies the bureaucrats' desire for order. And it is my belief that it is this symbolic bureaucratic exercise in territory marking by the EU that revealed, and still reveals, a fundamental disconnect between the Brussels Panjandrums, the people of the EU and the British in particular. The Eurocrats want a Federal Europe with the EU as a Government. The Nations, broadly supported by their governments don't, and have resisted any attempt.

The EU hasn't made Britain less "sovereign". All EU law, necessary to trade with as little friction as possible, is of the type that by whom it is written doesn't matter. With trading standards does it really matter WHAT they are, just that they're as universal and consistently applied? I don't need to tell you that it was never illegal to display prices of potatoes in Lbs and Oz, just that you HAD to display the price in KG and g too, in case any Frenchmen walking through the market didn't know how many Lbs are in a KG. I don't care who writes the regulations for the import of Duck eggs, just that it's done.

But there it is. The Brexiters shooting with the accuracy of a semi-trained recruit who's just dropped LSD at every figment of their fevered imagination, egged on by equally deluded fantasists who still think they're creating a Federal United States of Europe. These two groups of lunatics needed each other. And so, the passport, with 'European Union' at the top was barely noticed on the continent, but seemed to some Brits as evidence the EU was after their democracy, their identity and their Freedom. However stupid this belief is, a Blue passport could've been delivered cheaply as a quick Tabloid-Friendly win for Cameron and such was the narrow margin, it would have probably been enough.

Rosencrantz and Guildenstern are Dead.

By Jackart (noreply@blogger.com)


Wednesday saw my 40th Birthday, and to celebrate I went to see Tom Stoppard's brilliant Rosencrantz and Guildenstern are Dead at the Old Vic with a Chum. While Daniel Radcliffe & Joshua Maguire lead, the show is stolen by a magisterial performance by David Haig as The Player, a sort of luvvie-pimp-cum-impresario who holds the whole play, in its absurdity, together.


The play is Hamlet, seen from the point of view of two minor characters, Rosencrantz and Guildenstern, old friends of Hamlet's. The hapless pair spend the play wondering what they're doing and why, having been recalled to Elsinore by Claudius to find out why Hamlet's being such a dick, moping about and talking gibberish to himself ("to be, or not to be..." etc). They are eventually betrayed by their friend, who suspects them of working for his uncle which they are, sort of.

The play is therefore a meditation on the futility of existence, and the limitations of people's personal agency. Most people get on with their lives, as bit parts in a greater drama, not really sure as to the direction of events, or even of the past. After all, what have Rosencrantz and Guildenstern got to go on, but what can be gleaned from a few words of Shakespeare's, as metaphor for everyone's flawed and self-serving memory. Any interrogator or detective will tell you about the reliability of eye-witnesses and the difficulty of establishing the truth.

From everyone's point of view then, even when we're at the centre of events, most of the action is happening offstage. There will have been some point at which you could have said "no", but you missed it. Then you die.

If you can get tickets, do so.

Minimum Wages, Immigration, Culture and Education.

By Jackart (noreply@blogger.com)

Net migration to the UK has run at hundreds of thousands a year for decades, of which about a quarter since 2004 has been "A8 countries", Poland, the Baltic states, Czech Republic, Slovakia, Slovenia and Hungary, another quarter from 'Core EU' and the rest from non-EU countries, mainly India, Pakistan and West Africa. 13% of the population of the UK was born overseas, of whom over 2/3rds are non-EU migrants. This is an unprecedented migration to the rich world from the poor, and It's not clear from this EU migration is the underlying problem. The Poles will integrate fast, and leave imprints on the culture like a higher incidence of catholicism, bigos (a stew of meat and Sauerkraut) and some hard-to-spell surnames. They're often better educated than the natives, and work harder.

In general the view I've taken over the years is that minimum wages are a bad thing, arguing that they are mainly paid for by the people who otherwise wouldn't get a job at all. Only a job can lead to a better job, and if people are unemployed for a long time, they often become unemployable. So by this logic, keeping unemployment down should in the long-run be better for the poorest.

But, there is a trade off. When I grew up, late '80s and '90s, I cannot recall seeing cars washed by hand. When my father wasn't exploiting child labour by getting me and my brother to do a rubbish, half-arsed job for which we expected to be paid handsomely, we went to see the "blue Dougals" at the petrol station. The UK as a wealthy country, had substituted Capital for Labour, and cars were washed by big machines at every petrol station. But a team of a dozen hard-working and cheerful eastern Europeans can set up a car-wash, do inside and out for very little capital outlay - a jet washer, and some sponges, so when the EU accession countries citizens moved to seek work, this is what many did. The car wash machines were gradually removed and replaced by people. This is the opposite of progress.

Let's take a step back and look at the big picture.

Europe's wealth, it's vitality, its progress didn't spring from European individual or cultural superiority. It started when half the population was wiped out by Yersinia pestis in the 14th Century. There was a certain amount of luck - the same event increased the power of the landowner in Rice states and in pre-feudal societies farther East, but in Northwestern Europe, this created a shortage of Labour, and the peasants rose up a generation afterwards to demand higher wages from their lords. When this happened in Italy, the energy was put into sculpture of the nude male form, and was called "the Renaissance". When wages rise, it makes sense to build machines rather than employ labour, which has a virtuous feedback loop: skilled people running the machines drive up production, and become richer, which creates an incentive for further innovation. More widespread desire for, and access to education is grease in the wheels of this, the motor of progress that led to the industrial revolution.

The opening up of America, a nation with a perpetual and long-lasting shortage of labour not only added another motor to that European culture of innovation which grew up after the Black Death, but also absorbed the excess labour of Europe. While there is a labour shortage, immigration can be managed, though immigrants in large numbers have nowhere, ever been welcomed by the people they move to. Even when the people are kith and kin, the 'Scots Irish' (in reality, families originally from Northern England and the Scottish Borders) were moved on by the Germans and English who'd already settled the East coast. They ended up in Appalachia.

It's clear, then in the short run and in aggregate, wages aren't "driven down" by migration in a market economy. Part of that, in modern times may be due to the minimum wage, which protects some of the people most vulnerable to substitution, but also the 'lump of Labour fallacy'. Immigrants, especially young workers with families bring demand as well as supply and these things more-or-less balance. They aren't "taking our jobs" but they are changing the nature of jobs available. And the vast supply of excess labour from the subcontinent, africa and the poorer bits of Europe is not exactly an incentive to invest in productivity-enhancing machines, as the car-wash example shows. The mass immigration from the poor world has the potential to stall the western motor of innovation and may contribute to wages not rising as far as they might, especially for the lowest skilled workers.

The UK has a problem with productivity. UK employers have got good at employing the excess Labour of a serious chunk of the world, UK wages have been flat for a decade, and these things are linked. So the Chancellor is hiking the minimum wage in the hope of good headlines, and to incentivise investment to drive productivity. So. What effect will this have on immigration. Will it draw more migrants to the UK hoping for higher wages, like European immigration to the USA, or will it price low-skilled immigration out of the Labour market and allow the motor of progress to continue?

Splits that used to be geographic - some countries were rich, and others poor and the movement between the two was rare, is moving to one where there are still two countries, it's just the divide is social, educational, and cultural. You have a global, liberal, free market culture, which values education and novelty. And you have national, 'c' conservatives who just want their own culture, don't care about education all that much, won't move to find a job, and expect to be looked after who stay put and resent incomers. And the latter are disproportionately annoyed about foreigners moving into "Their" neighbourhoods while it's the former who have more to fear in the short term from highly skilled competition, minimum wages see to that. And if minimum wages rise far enough, low skilled workers will not be able to get jobs and they will stop coming to the UK. The problem is, the lowest skilled people are often native. The cost of a raised minimum wage will be borne by those least able to cope.

If we are to avoid society fracturing permanently into Morlocks and Eloi we do need to manage migration, to keep that motor humming. We cannot let the world come at will. But there was no need to pull up the drawbridge against EU migrants who always looked like collateral damage to me.

It's not all about economic self-interest, nor is it wholly naked in-group preference (what educated, open minded people call "bigotry"). It is the interplay between the two. Ultimately the stagnation of UK wages over the last 10 years isn't due to migration, but the recovery from a balance-sheet recession of 2007-9. It's the feeling of ennui caused by a decade of stagnation which has caused the anti-immigration nonsense, the rather blameless Poles have just become a Piñata and for a population that was persuaded to lash out at the EU when they really wanted to lash out at "the Muslims". The tragedy is all this happened just as we were getting back to normal.

Nicola and Theresa. Phwooar.

By Jackart (noreply@blogger.com)

The Daily Mail's headline "Legs-it" about Scottish First Minister and British Prime Minister Theresa May's shapely legs was pathetic. But remember, the Mail is written by women, for women, and women judge each other, all the time, harshly and vindictively. Judged especially harshly are women more accomplished or better looking than the average Daily Mail reader.


To call this "sexism" is to miss the point. This isn't about women being held down by sexist male tittle tattle. Clearly, two of the most powerful people in the country haven't been held down in any meaningful way. Any executive head of Government is fair game for any and all criticism. What these women have done is rise above the level at which society normally seeks to protect women from abuse.

Male politicians are made fun of for their appearance and clothing all the time. It's the sea men swim in. Whether it's Donald Trump's expensive, but ill-fitting suits and too-long ties like he's stepped out of a 1980s pop video caricature of a businessman, or Cameron's forehead, or the fact that middle-aged men are always assumed to be repulsive, this abuse is normal.  The ridicule a male politician faces when he's seen in public wearing anything other than a blue suit is extraordinary. From Tony Blair wearing a clean barbour, to William Hague's baseball cap or Cameron's beachwear, there's a reason male politicians dress identically. When women's clothing (far more interesting by the way, than the sober suits of most male politicians) is commented on, it enables a personal brand to be created that much easier. Theresa May's shoes are like Margaret Thatcher's handbag. True, women do have to think harder about their clothing - too much leg, cleavage etc... and you immediately invite scorn (of other women, mainly), but the fact the female wardrobe stands out against the endless blue/grey suits and red or blue ties of the male is as much an opportunity as it is a minefield.

Any comment about May's shoes, for example is part of her deliberately curated brand, and shoe-designers are falling over themselves to get their products onto her feet. This isn't sexist. Women like shoes, and there's no reason why Theresa May shouldn't have fun with them.

Lower down the pecking order there's a taboo against men commenting negatively on a woman's appearance, lest you hurt the poor dear's feelings. Yes male 'locker room' banter will discuss who's attractive, but it's rude to do so in front of women and by and large, gentlemen don't. Women don't typically have these conversations about men in earshot of men either, but describing men as "revolting" or "creepy" is so normal as to be unworthy of comment, and completely unnoticed. May and Sturgeon have risen above this social protection, and are subject to the same rules of engagement as men are. i.e that if we have feelings, tough.

These women are grown-ups doing important jobs. If you think the Mail's light-hearted front page is an insult to them, you're an idiot. Of course Sarah Vine who wrote the thing, knows exactly the response it would get, howls of idiot outrage from the usual suspects on Twitter, and from Sturgeon herself. This allows the paper to swat the complaints aside with contempt. This signals to their readership that the Mail is on their side against the bien-pensant left with their idiotic & totalitarian outrage about human trivialities. May by rising above it, does the same. The Mail is one of the Best-selling papers in the UK, and one of the world's most visited "news" (ish) websites. Who won that exchange?

The po-mo left, obsessed with identity politics, used to being able to bully dissenting opinion down STILL hasn't got the new rules of the game. Someone's pointed out the Emperor's naked, but he's still acting like he's in charge and hasn't noticed the mood's changed. Yet.



Completely unrelated, but thank you to the Anonymous commenter who wrote this. It cheered me up.

On Class, Culture and the New Politics

By Jackart (noreply@blogger.com)

The two tribes of politics, broadly the Tory and Labour parties divided over the 20th Century principally on the matter of economics. Simplifying: Tories preferred market solutions to state planning, and preferred lower taxes and less generous state spending.
The Labour party, which when it abandoned clause IV, surrendered on the economic question, not coincidentally a few years after the Berlin wall came down.
As a result, the great battles since then have been essentially cultural. Gay rights, racial integration etc. The confusion stems from there being no consensus within the Tory or Labour tribes on these issues. Plenty of Tories are happily socially liberal, many of the Labour tribe are socially conservative, especially when you look at voters rather than representatives.
Which brings us to the tribal division of Britain: class. The middle class: liberal, internationalist, universalists; vs a working class: authoritarian, insular and particular world view. The former is comfortable with diversity and immigration. The latter isn't. The former's kids live a long way from home, and move for work, the latters kids live in the same town and expect the work to come to them. The former don't speak to their neighbours, the latter care what their neighbours do and think. These labels are correlated roughly with, but independent of, economic status. It's possible to be middle class, in a local-authority home living on benefits, and working class, earning seven figures and living in a manor house. (Though it's likely these people's kids will change tribes)
There are elements of these cultures in all major parties in the UK, but the rest of us rarely communicate with people from the other tribe. The people you have round for dinner will most probably be from your tribe. Half the country holds its knife like a pen, yet none have sat round my table. When the two tribes meet, it's awkward. Those difficult bottom-sniffing conversations seeking common ground are easy to conclude when two members of the same tribe meet, and difficult when you meet the other half.
There have always been working class Tories, because much of the working class is as comfortable with the certainties of heirarchy as a shire Tory, and doesn't much care for this freedom and opportunity nonsense, preferring a better boss instead. And it's interesting to watch the Tories dangle the protectionism and insularity the working class has long demanded. Middle class labour fabians and the working class methodists have always sat uncomfortably together. Brexit has shattered that coalition, the labour party has been handed to the idiot socialists and will die, unless somehow moderates can oust corbyn before 2020.
Which brings us to the Tory coalition. The high-Tory have promised the old certainties back to the white working class. Meanwhile, middle-class liberals who make up most of the parliamentary party are distinctly uncomfortable with much of what is being done in Brexit's name, but will stick with the Tories, because they offer the promise of power, and however dreadful Brexit is, Jeremy Corbyn is worse. A new coalition is being forged between the Tory squirearchy, and the Working class based on nationalism, social conservatism and heirarchy, directly taking Labour's core vote. This is why UKIP, a working class movement that thinks it *is* the conservative party, apes the style of a country gent. The working class have always got on well with the Gentry, sharing sociailly conservative values. Both despise the middle class.
Brexit split the country down a line more on class values, split the country and handed it to the socially authoritarian party. Whether this is the new politics, with the Tories moving from being the middle-class party to the working class party, as the Republicans did after the war in the USA, or whether the middle-class will wrest back control over both parties in time waits to be seen.
I suspect unless May softens her tone, and thows some bones to the liberals, her coalition will only survive until there's a credible opposition. A more appropriate division of politics would be a ConservaKIP'ish alliance of WWC and high-tory squires, vs LibLabCon middle-class liberals. Therea May seems to be actively seeking it.
Over the Channel, Emmanuel Macron and Marine Le Pen exemplify this split. The candidates of the parties of left, Socialists; and right, RPR are likely to be eliminated in the first round. Macron is likely to win comfortably. His movement 'En Marche!' was only formed a year ago. There's a lesson for British liberals there.

Tories have profoundly damaged the UK. You Should Join the Tories.

By Jackart (noreply@blogger.com)

2016 happened because decent people don't join political parties, leaving the business of Government to socially inadequate, physically repellent gits with an axe to grind*. In normal circumstances, this makes politics easier for genuinely impressive people to progress through the flotsam of monomaniacs. To be a Grown-up in the Tory Party 1997-2010 was to be able to consider an issue beyond the EU. For Labour it's all about not dreaming of Strike Action by "the workers". Thus the Liberal Centre consolidated a hold on the country, but became complacent to the poison seeping into parties even as the Smug centrist consensus made everyone fat and rich.
There has been a steady, and persistent hollowing out of the political parties. Labour used to be allied to a Trades Union movement that delivered services - health insurance, education and so forth to its members. The Trades Unions of Pre-War Britain where an overwhelming force for good. Atlee's welfare state nationalised all the good the Trades Unions used to do, and so corrupted both the principle of welfare (now far, far from Beveridge's original vision of low, universal payments like Child benefit, topped up with contributory elements) and the Trades unions which became a mere tub-thumper for more state spending. This left the Labour party with the sole purpose of defending a welfare settlement that is not under threat, and a Trades Union movement whose purpose had been nationalised so simply became resistant to all and any reform which might make the system as is function better; unions a mere vested interest of public-sector workers. This isn't a place where people capable of holding more than one idea at a time feel comfortable, and so the Labour party was colonised by people who think not shaving is a political act.
This malodorous and poorly groomed cancer has destroyed the Labour party. It's over, there's no point being in Labour unless you're a Identity politics obsessed Corbynite who laments the end of the Soviet Union. 
Labour, 2010-Present
The Tories at least had the sense to try to vomit the most toxic of their nutters into a bucket marked UKIP, a bucket the dog is unfortunately returning to. The Conservative party my Grandfather joined (from CPGB, as it happens, Labour even back then were cliquey dick-heads) used to be a forum for the upper middle class (and anyone who aspired to join them) to meet, mate and do business. But the horrible young Tories of the '80s, and the Euro-nutters of the '90s meant that by 1997, the Tories were only really suitable for people who were prepared to discuss "Europe" endlessly in ever-more foaming tones, persuading themselves that the EU is a historic enemy like Napoleon, the Kaisar, Hitler or the USSR. To their credit, the Tory Leadership has long known what to do. All David Cameron ever asked of his party was to "stop banging on about Europe". They couldn't stop picking at the scab, and the result is a catastrophe that has already crashed the Pound, weakened the UK (perhaps fatally) and may yet cause a political crisis in Europe and embolden Putin to start rebuilding the USSR.
Tories, 1997-2010
The more say over policy and leadership given to the membership, the more the membership has dwindled (unless, like Labour, the membership criteria are designed to invite entryism for the purposes of choosing a leader - by people who've been quietly loyal to the Bennite project for decades). Giving members a say in who leads the party is absurd. Who the prime minister is, should be a matter for MPs, and MPs alone. It is they who must give the Prime Minister a majority and internal party democracy risks, well, exactly what has happened to Labour. 
However, that Rubicon has been crossed. Party members now expect a vote on the Leader. The question is what to do about this, and the answer is to choose to be a member of a party at all times, hold your nose if necessary. Do NOT identify with the party, but consider which is best placed to advance your objectives. At the moment, the foul bigots, monomaniacs and morons of UKIP are being re-absorbed from a position where they can do little harm beyond foaming at the mouth and masturbating to Daily Express editorials, to one where they can choose the next prime minister, and Mrs May isn't a healthy specimen. The ex-'KIPpers chance may come to choose their PM sooner than expected.
I'm often asked "How come you're still a Tory?"  
Were the Liberal Democrats stronger, I'd be considering them, but I don't trust them on electoral reform (about which they're as silly as Tories are about Europe). But as the Lib-Dems are so far from power, I don't see the tactical benefit of leaving the Tories in a huff, and I broadly agree with the Tories on everything except Brexit. What I'm worried about is the 'KIPpers who're returning to the fold. Unless you want a foul, divisive and ignorant Brexit headbanger to replace May in 2023 or so (Gove for example), Join the Tories, because thanks to Labour's meltdown, Tories and Tories alone will choose the next PM. All not joining a party does is strengthen those (*we) weirdos who still do. Labour moderates, disgusted by Corbyn should cross the floor to the Tories or Liberal democrats, instead of flouncing off to the V&A and opening the way for UKIPish Brexit-o-twats to fight and win a by-elections under Tory colours. Were Tristram hunt now a Tory, not only we could soften this brexit idiocy but also signal just how broad a church the Tories are. 40% of Tory members voted Remain. The tribe that needs to understand the value of a bit of entryism is the liberal centre, who need to abandon any loyalty to their Parties and go to where the power is. The Liberal Centre is complacent because they have for so long occupied the ground sought by all parties, they've not really had to compromise. 
At the moment the business of Government is, and will be for the foreseeable future, a Tory-only affair. That need not look like Nigel Farage, but it will, if Remainers abandon the Tories entirely.

The End of A 'Belle Époque'. 1991-2016.

By Jackart (noreply@blogger.com)

The interlocking webs of policy which 'politics' seeks to knit are complicated. Whole books can be written on how two individual policies interact. PhDs in Economics are awarded for small snapshots of the whole cloth. Most people don't have the time to keep abreast of developments or read sufficient history to understand why some policies are bad. Thus, people use heuristics - rules of thumb - to make decisions  about that which they aren't expert. "Is this person trustworthy" is a key issue, and we tend to overweight the opinion of those near us. "He is my brother, and I say he's ok" says a friend, you are more likely to believe a mutual friend, than the opinion of a stranger on the same issue.

In the evolutionary past, such a question was a matter of life and death. People only really had to trust those with whom they shared a close genetic relationship. Since the development of agriculture, we've been steadily widening that circle of trust. The wider you spread that circle of trust, the richer your society will be. Even before it had a name, Free market economics allowed people to become blacksmiths, knowing others have water, food, shelter and so forth covered in return. More specialisation, greater productivity, means greater wealth.

Eventually, this requires trust in people we've not met. Towns' food supplies require that farmers unknown and distant supply the basics of existence. Nowadays, It's unlikely the west could quickly supply all available plenty currently manufactured in China. Nor could China supply quickly the complex components and tools shipped from Japan, Europe and USA. Both China, and "the west" are richer from the exchange. And yet, we still don't trust "globalisation".

Most persistent fallacies in political economics are the result of simple policies that appeal to some base heuristics, but which when applied to the larger and wider society, fail catastrophically. Thus egalitarianism in one form or another pops up every 3 generations or so and succeeds in making everyone equal, but some more equal than others, and even more, dead. Then nationalism comes along, and says it's all [another, arbitrarily defined group of humans with slightly different modes of speech] fault, leading to more waste and piles of corpses. And even when the results aren't catastrophic, we seek out the views of those who agree with us on say, Nationalism to inform our opinion on, say, whether or not people are responsible for climate change.

Which political tribes stumble into being right or wrong on any given issue appears arbitrary, because no-one's asking for the evidence before they decide on the policy. Instead of asking "what's right", we're asking what's popular (amongst the coalition of tribes that voted for me) right now. That an opponent comes out with an identical policy, for different reasons is reason enough to oppose something, forgetting completely prior support for it. After all, whatever [another political tribe] thinks must be wrong, right.

Thus
The Labour party opposes ID cards. The Labour party has always opposed ID cards. The Tory party is for the Free market and was never in favour of the Corn Laws. We have always been at war with Eastasia. Perhaps if we could think for ourselves rather than just accepting tribal dogma, we'd get better governance. But none of us have the time. So "Democracy" is merely a means to give temporary permission to one coalition of tribes to push through dogmas over many issues, until either the population notices, or the coalition of tribes breaks up, and the electorate takes a punt on the other tribe's prejudices for a bit, and then gets on with whatever they were doing before.

Society ultimately advances by eliminating prejudices it's acceptable to hold thus widening the circle of trust, and increasing riches. By falling back on ancient heuristics to answer the wrong question ("who's fault?" is the wrong question) 2016 democracy has delivered the worst political outcomes on a broad front, as a result of which, we are poorer, and more likely to start fighting as a result of the collapse in political trust we have seen over this year. The post Cold-War 'Belle Époque', which saw half of humanity, 3 billion people, lifted out of poverty, is over.

Idiots cheer.

Boston Dynamics and The Late Sir Terry Pratchett

By Jackart (noreply@blogger.com)

Everyone knows how driverless cars will work: they will be like ordinary cars, except you read a book rather than acting as pilot. And so, people's understanding of what a technology can do is clouded by what the old technology it replaces does. Which means people without imagination, Head of IBM Thomas Watson, for example, say things like
"There may be a world market for maybe five computers"
and get it wrong. In 1943, computers were used for cryptography, and that's it. (At least he knew what a "computer" was, which few did back then). Predictions are hard, especially about the future. But it's probably worth noting here that the famous World Wide What? front page of The Sun, was in fact rather a good a spoof, by The Sun.


Boston Dynamics makes robots.


via GIPHY

Who needs Robots? Well, like computers or the internet or driverless cars, the technology is coming. And it will change people's behaviour in many, unpredictable ways. For example, mobile phones were conceived as portable analogues for the phone on your desk or in your hall. SMS text messaging was added as an afterthought, but became THE dominant means of communication. Calling someone is now rude, often you text first to see if a call would be convenient. Who (apart from mums) leaves voicemail messages any more? Few predicted that change in our behaviour. The smartphone is now ubiquitous, and is more about accessing the internet than calling friends, but wasn't imagined before the internet, Except by Douglas Adams (and John Brunner of whom I'd not heard until I discussed the issue on Twitter). Driverless cars will be as close to the car, as the car is to a buggy and four. And robots, when they become ubiquitous, will be unlike anything we've considered.

I look at Boston Dynamics Robots, the big dog is conceived as a load carrying mule for soldiers on rough terrain, and I think of The Luggage, Rincewind's inscrutable companion on the discworld. I suspect everyone will one day have a robot the size of a dog to carry daily necessaries, following them round. You could send your luggage to someone else, by smartphone app to pick something up. Your luggage could take your shopping home and collect it from the store for you. Large luggages could be sent on ahead with bags. Small luggages could replace handbags and briefcases. The labour and time saving would be vast, spawning whole new areas of employment, servicing and modifying your faithful electronic companion and providing for the opportunities they create to effectively be in two places at once. Freed from the ownership of motor vehicles by the fact we'll be taking taxis everywhere, our Robot luggage will perhaps become the next status symbol around which society is built, replacing the car.

Like cars, I suspect the battery technology will be the limiting step, and like cars, I suspect the fuel cell will be the answer. Small fuel cells will one day power your smart phone too.

But think about the opportunities for people from smart phone. There are tens of thousands of app designers round the world now, a job that had barely been considered as recently as 2007, when the first iPhone was released, and that is similar to how the jobs which will be taken by the robots, will be replaced. That is why people who fear of a "post-jobs" future were wrong in 1816 and are still wrong 200 years later. The world's only limitless resource is human ingenuity.

Anway. I for one welcome our new robot overlords, and this guy should totally be locked up.


via GIPHY

Fidel Castro is Dead. (Some of) his Legacy will Live on

By Jackart (noreply@blogger.com)

Let's be clear, Castro was a murderous bastard who impoverished his country, and whose views on homosexuality and on the importance of brevity in speeches were nothing short of horrifying. It's true, Cubans do have access to better healthcare than many countries of equivalent GDP per capita, and if I had to choose a Communist hell-hole to live in, it'd probably be Castro's Cuba. But the Cuban healthcare system is not the fantasy of western dewey-eyed left-wingers, and Cubans often are excluded from what excellence there is, as it's one of the few means the country has of generating hard currency earnings. Rich foreigners get the best doctors, and more are exported to other successful "progressive" regimes like Venezuela.

"But he was an anti-imperialist". So why were cuban troops in Africa in support of the USSR, which was by any measure or definition an Empire? Anti-Imperialsim is just the justification leftists give for knee-jerk anti-Americanism. And the flood of people risking death to reach the USA should tell you all you need to know about the relative merits of America's and Cuba's system.

Contrasting the attitudes of the USA to Castro, to their attitude to equally murderous bastards like Pinochet misses the point. The US embargo on Cuba is one of the legacies of the Cold war, kept bubbling by the politics of Florida, home to so many Cuban-Americans. There is no Doubt that the US blocade has impoverished Cubans, and that with the fall in the Berlin wall and the collapse of the USSR, such an embargo was no longer justified. However politics are what they are. Fidel Castro's death provides an opportunity for further thawing in relations.

The USA supported "our son of a bitch" all over the world, turning a blind-eye to horrific human rights abuses, though often (albeit less often than we should) working behind the scenes to try and mitigate the worst behaviour. Thatcher is rarely credited with preventing the execution of Nelson Mandela, but she consistently urged Mandela's release, even as she argued against sanctions and branding the ANC "Terrorists". This is one reason why the cold-war piles of dead of Nasty fascist bastards are usually lower than those of nasty communist bastards. I also think the point made by CS Lewis holds. Right wing dictators rarely pretend to be GOOD, making their appeal more on effectiveness.
"The robber baron's cruelty may sometimes sleep, his cupidity may at some point be satiated; but those who torment us for our own good will torment us without end for they do so with the approval of their own conscience."
And one by one, following the collapse of Communism, the support from the USA and its allies for these disgusting regimes was withdrawn. Apartheid South Africa, much of South and Central America saw right authoritarian regimes fall. Genuine democracies were often created in the rubble. The USA didn't support dictators because the USA is an imperialist power, but because it IS a power, and with that comes responsibility. They judged at the time the alternative, Communism, was worse, and represented a genuine existential threat to the USA and its core allies.

This is why for example the USA and its allies mostly support the Regime in the Kingdom of Saudi Arabia. The Saudi regime is repellent, but given the probable alternatives wouldn't be nice, liberal, democratic-minded progressives, they'd be salafist nutcases who'd have access to billions of dollars of oil revenues and the legitimacy of being the Guardians of the Two Mosques. The House of Saud is all that stands between the West and a plausible salafist caliphate with sufficient legitimacy and money to one day threaten the west. We'd rather do business with nice, stable democracies under the rule of law. But seeing as we cannot do to every country on earth what we did to Germany in the late 40s and 50s, we make the best of the options given.

Castro appeared to be a true beleiver in Socialism, so he refused to recognise his philosophy had failed, and his island limped on, a socialist throwback in the age of globalisation. The current poverty of Cuba is partly America's doing, but mostly due to decisions made by Castro himself, policies which set him and the Cuban people at odds with the regional hegemon, in persuit of an evil idealogy. Fidel Castro was on the wrong side of history, and his people suffered because of his stubborness. Now he's dead, it's Cubans turn to make the most of the positive legacy - Cubans are the best-educated poor people on earth, and the mighty economy of the USA is right on their doorstep. There is going to be a lot of money to be made there, and this time, for the first time, Cubans will share in it.

Hail, Trump! God-Emperor of the Alt.Right

By Jackart (noreply@blogger.com)

And Let's be honest, he's ghastly and despite brown-nosing by Nigel Farage, he's no friend of the UK's, because he doesn't value anything the UK brings to the table. Rumour has it, he asked Farage to intervene in an offshore windfarm decision affecting his Scottish interests, which suggests he doesn't understand the concept of 'conflicts of interests' when in elected office.

This further suggests Trump will attempt to use the office of President to enrich himself, rather than doing so after leaving office, as is accepted. All this is rather feudal; the office holder as gold-giver, distributing patronage and receiving tribute. He's an entertainer and showman, which hails to an even older tradition of politics: that of Imperial Rome, where emperors used state coffers to enrich themselves and their clients,while keeping the mob quiet with bread and circuses.

Donald J. Trump is psychologically unsuited to office in a mature democracy. He is thin-skinned, autocratic, insecure, ignorant, and completely without any understanding of the levers of power he now wields. Much like (later caricatures of?) Nero, Commodus or Caligula.


Despite (or perhaps because of) this, the adolescent losers of Alt.Right see Trump as a God-Emperor (no, really they do. Video surfaced today of people making Roman Salutes, saying "Hail Trump", and distribute Memes based on Games Workshop's futuristic figure-based tabletop wargame, Warhammer 40,000 where humanity is defended from Chaos by a psychic God Emperor). If Trump is Imperator, then the Secret Service is a Praetorian Guard. And how did the Praetorian serve Commodus, to pick one example?

Trump might, were he capable of reading a book, muse on the fact he's surrounded by armed men sworn to uphold the Constitution of the United States of America, and defend it from Enemies DOMESTIC and foreign. Thankfully, the USA is a mature democracy. Where once armed men acted as kingmaker, courts now do. For the simple reason Ignorance is no defence, and the fact that Trump's loathing of 'Washington' is fully reciprocated, I find it unlikely that Trump will survive his term alive and unimpeached. Unfortunately I cannot find odds on a Trump impeachment before 2020. Perhaps it's a racing certainty.

Sexism and the Loss Aversion Heuristic

By Jackart (noreply@blogger.com)

Men are physically stronger than women, respond quicker to physical training, and suffer less injury under physical stress. Men are more robust, suffer less morbidity than women in almost all phases of life. Obviously these things exist in a normal distribution, but men's distributions are typically platykurtic - there are more men in the tails of the distribution than women. Thus, even where the means are near identical, such as intelligence, you'd expect to see more male geniuses, and imbeciles among men than women, who're more concentrated around the mean. Feel like taking issue with any of these statements? Then you might as well be a creationist.

Men are more accepting of risk, and will prioritise pay over flexibility. So you'd expect men to make up the majority of soldiers and miners and race car drivers. It also means you'd expect to see more men make up corporate boards, everything being equal. More men are more drawn to the cut and thrust of business, and are more likely to prioritise work over other commitments. Women value stability and flexibility more highly than men. This means women, on average don't choose to make the effort necessary to climb the greasy pole. Women (sensibly, in my view as I have done the same) are more likely to think other things more important.

Thus, the brute fanny-counting of media analysis of sexism and the "gender pay gap" ignores female choices and attributes, thus denigrating both women and men for the choices they make. Women for their part see their contribution to society in caring professions such as medicine (more doctors are now women, as well as nurses) and teaching denigrated because these women aren't seeking to be at the top of BAE systems, or whatever. Likewise men, when they see women are going to hired so they form 50% of the workforce of a mining company feel devalued for their skills and attributes because the only way BHP Billiton could make 50% of its employees women is by discriminating against the larger number of men who will apply to drive a bloody great truck miles from nowhere in a bloody great hole in the ground in the middle of a bloody great desert surrounded by nothingness, and live in towns whose bars serve tinnies through wire grilles, and where kicking each others' heads in represents the primary saturday night entertainment.

But worse, by forcing women into traditionally working class men's jobs, you further alienate and disorientate a bit of society which already feels put upon, neglected, belittled and scorned. This is why they voted for Brexit in the UK, and in the USA, will vote for Trump. Working class men are lashing out, because their raison d'etre, to provide for their offspring, has been nationalised, and no other opportunity for them has been provided and they as individuals have too often been thrown on the scrap heap, derided as workshy deadbeats. The working class used to have pride in providing for their family and often doing dangerous, dirty jobs to do so. Opportunity isn't "equal access to university", for which working class men is a middle-class rite of passage, but decent jobs that will allow them to support their family, but which is blocked by the petty credentialism that values paper qualifications over experience and dumb diligence over inspiration.

That loss of pride is agonising. And people mourn loss far more than they celebrate gain. The aim of this post-modern obsession with equality of outcome therefore might as well be to make men despise themselves and women feel inadequate for the inclinations their biology and society has fitted them. Men become 2nd rate women, and women become 2nd rate men. By all means allow everyone to seek their own path, but to imagine men and women will sort 50/50 everywhere is totalitarian in its foolishness and cruelty.

The EU Deserves what's coming.

By Jackart (noreply@blogger.com)

One of the main reasons to oppose brexit is that the UK doesn't benefit from being "out" should the EU collapse. A disorderly break-up of the EU would damage the UK, independently of our status in or out. (any comment saying "it's better to bail early" will be deleted as a failure of comprehension read the post, please, it's that argument I'm dealing with). Indeed preventing a disorderly collapse should be the UK's priority. And when we were in, a disorderly collapse was unlikely. The UK kept the lid on Brussels insanity. Not only has Brexit given free rein to some of the very worst people in the UK, it also removes a brake on the insane Federasts  of Brussels.

Far from Remainers "talking the UK down", Brexiters have been doing so for decades - talking down the UK's influence in the EU to the extent we're actually thinking of walking out of the UK's proudest creation: the single market. It is now a shibboleth that the UK has "no influence in the EU", whereas the UK drove the single market, kept half the continent out of the poisonous grip of the Euro and pioneered enlargement to the east following the end of the cold war. The UK drove Russian sanctions to this day. The UK was one of the Big three and on many issues, more influential than France. The UK largely writes EU financial regulation for example (as is meet and proper).

But the EU over-reached. Voters, especially in the UK resented the EU's usurpation of the trappings of National sovereignty far more than the reality of "the laws made in Brussels" which was really just code for an underlying vision they (and I) don't like. And what is true of the UK is true of France and the Netherlands and everywhere else. Remainers like to mock the Be.Leaver's joy over the anticipated return of the blue passport. I however have long resented the words "European Union" above (ABOVE!) the crown on the front. It's like the bureaucrats are trying to rub the British People's nose in it. It's a symbol of something burning in the EU's core, which the average voter neither desires, nor trusts.

The ridiculous and unnecessary potemkin parliament with its farcical shuttle from Brussels to Strasbourg focusses the voters minds on the EU, without giving them any outlet to do anything about it. The EU looms much larger than it ought as a result of the charade of Euro elections. Democracy without a demos is pointless - what commonality do Socialist members from spain and the UK have?:

The EU was flawed, Thanks to the UK some of its worst excesses - the Euro for example were limited to countries that really wanted it. And now without a powerful country holding the reins and steering away from "ever closer union" the Brake that was put on at Maastrict and beyond will be removed. The EU will integrate itself to death, there will be chaos when the voters of Europe can take the tin-eared arrogance of Brussels no more. There was no need for all those millions of lives to be attenuated during that process. While leave voters will say "I told you so", a better analogy would be jumping out of a moving car suffering broken bones and extensive skin abrasions, but saying "it would have been worse" because the lunatic who grabbed the wheel when you bailed steered it directly into a tree.

Spending 1% of GDP to write trade and some business law could much more easily be done intragovernmentally, with a humble and small central bureaucracy. There is no need for "Presidents" and parliaments which lead to grandiose visions; visions which slam painfully, like the Euro, into the unyielding wall of reality. Unobtrusively aligning business regulation and deepening economic integration is necessary. A parliament, a flag, an anthem and a head of "state" are not. The EU has paid the price for this arrogant and pompous grandiosity.

Both the EU and UK are and will be significantly worse off as a result of Brexit. And now, just as Brexit is a bad idea that will be tested, so too will European integration. Both Brussels panjandrums and the brexiters fed off each others' fantasies. Both needed to believe integration was happening, even if it wasn't. Ultimately, the costs will become apparent to the UK pretty rapidly. The EU will suffer much more slowly. It's almost like co-operation is a non-zero-sum game, or something.

On Populism: What do we do? vs Who do we blame?

By Jackart (noreply@blogger.com)

If you ask the wrong question, the answers will not work.

"Populism" is, like pornography, hard to define, but you know it when you see it. Wikipedia defines it thus
"a political ideology that holds that virtuous citizens are mistreated by a small circle of elites, who can be overthrown if the people recognize the danger and work together. Populism depicts elites as trampling on the rights, values, and voice of the legitimate people"
It's clear Farage's lauding of a victory for "mediocre ordinary, decent scum people" he was speaking in this vein. But I don't think this captures the essence of populism. Mainstream politicians "Managerialists" in the Populists' vernacular ask "how do we solve this problem". You can be a capitalist, or a socialist, believing in different answers, but at least you agree on the question. Populists aren't asking this question, but instead "who do we blame?". The answer given by Momentum and UKIP may differ: Bosses vs Immigrants, Capitalists vs the EU but the question is the same.

There's also the populists view that MPs rather than being representatives paid to exercise judgement, are delegates paid to vote on someone else's behalf. In this, Paul Mason and Douglas Carswell are in agreement. But this is simply mob rule and behind it is a fear that legislators may Go Native, if they're allowed thanks to the corrosive influence of "[insert boogeyman]" in their long-running campaign to keep the "real" people down. But perhaps legislators know best; they have exposure and access to what passes for facts in this field, and are paid to study it, maybe there's something in the idea of representative democracy after all.

It's always easier to imagine you're the victim of an elite conspiracy, subject to "discrimination" on the grounds of class or race, or at risk from being "flooded" by immigrants, than it is to answer the question "what to I do?". Whether you're running your own life, or that of a nation, what to do is hard, and one of the stresses of modern life is the extent to which people are free, which means they have to make choices. No longer can you just follow dad into the Factory. Because many suffer from crippling loss aversion, these choices are scary, which is why stupid people yearn to be led. They look for leaders who offer answers which fit their prior prejudices and make sense of a complicated world. Corbyn and Farage have made careers finding and stroking a tribe's prejudices, soothing their people's indignation against a world they feel is against them.

The reason populism is so toxic to political discourse is that in apportioning blame, they create a slipway for the launching of vastly damaging ideas. "It's all the EU's fault" leads to Brexit*. "It's all the Fat Cats' fault" and you have a country that looks like Venezuela. If you start blaming immigrants or minorities, well we saw where that went in the last century. It's also why the Brexiteers ran from office at the moment of victory. Delivery isn't in the populists' skillset. The permanent masturbatory pleasures of opposition are what they crave, always losing so they can keep telling their people the game's rigged against them. If they win, then all those inadequate people will have to start making choices and they feel completely lost again. Much easier to simmer in resentment against an immovable object which allows you to blame it, rather than yourself for your failings.

*This isn't a place for a debate on the merits or otherwise of Brexit. Any comments on that subject will be deleted.

One of the reasons for the Populist's success (please note the "one of" at the start of this sentence) is Russia on the internet. The internet allows people to form much denser ideological defences against reality. And into the internet, there is a wounded superpower, pouring poison, poison which people use as ammunition in the defence of their ideological redoubt. Putin's toxic little propaganda swamps like RT and Sputnik are manufacturing and promoting stories which appeal to the populist mindset. Notice how Racists will share RT stories about Immigrants raping white women while members of the Green party will share horror stories about fracking from the same source. Some of these stories will be true. But many are manufactured, exaggerated and twisted specifically to support any party or idea that causes problems to the democratic governments of the west. This is not a random process. It is directed and controlled by the intelligence agency which has captured Russia. Maskirovka raised to a governing principle.

One of the reasons for the UK's relative success as a nation is that up until now, we have been mostly immune from the allure of the populist demagogue. We simply don't have it in us to put too much belief in one man, whether as protagonist or antagonist. Let's hope Brexit is a flash in the pan, and not part of a widespread descent of mature democracies into populist demagoguery. We'll know in 12 months whether democracy can survive or whether, thanks to Trump, Farage and Le Pen, we're going back to pogroms and a summer "campaigning season".

Please let's stop listening to Putin' useful idiots pedalling fallacious simplicity, and start listening to fallible and all-too-human experts again. At least the experts are asking the right question.

Letting Birds scooters fly free

(Note: These issues were disclosed to Bird, and they tell me that fixes have rolled out. I haven't independently verified)

Bird produce a range of rental scooters that are available in multiple markets. With the exception of the Bird Zero[1], all their scooters share a common control board described in FCC filings. The board contains three primary components - a Nordic NRF52 Bluetooth controller, an STM32 SoC and a Quectel EC21-V modem. The Bluetooth and modem are both attached to the STM32 over serial and have no direct control over the rest of the scooter. The STM32 is tied to the scooter's engine control unit and lights, and also receives input from the throttle (and, on some scooters, the brakes).

The pads labeled TP7-TP11 near the underside of the STM32 and the pads labeled TP1-TP5 near the underside of the NRF52 provide Serial Wire Debug, although confusingly the data and clock pins are the opposite way around between the STM and the NRF. Hooking this up via an STLink and using OpenOCD allows dumping of the firmware from both chips, which is where the fun begins. Running strings over the firmware from the STM32 revealed "Set mode to Free Drive Mode". Challenge accepted.

Working back from the code that printed that, it was clear that commands could be delivered to the STM from the Bluetooth controller. The Nordic NRF52 parts are an interesting design - like the STM, they have an ARM Cortex-M microcontroller core. Their firmware is split into two halves, one the low level Bluetooth code and the other application code. They provide an SDK for writing the application code, and working through Ghidra made it clear that the majority of the application firmware on this chip was just SDK code. That made it easier to find the actual functionality, which was just listening for writes to a specific BLE attribute and then hitting a switch statement depending on what was sent. Most of these commands just got passed over the wire to the STM, so it seemed simple enough to just send the "Free drive mode" command to the Bluetooth controller, have it pass that on to the STM and win. Obviously, though, things weren't so easy.

It turned out that passing most of the interesting commands on to the STM was conditional on a variable being set, and the code path that hit that variable had some impressively complicated looking code. Fortunately, I got lucky - the code referenced a bunch of data, and searching for some of the values in that data revealed that they were the AES S-box values. Enabling the full set of commands required you to send an encrypted command to the scooter, which would then decrypt it and verify that the cleartext contained a specific value. Implementing this would be straightforward as long as I knew the key.

Most AES keys are 128 bits, or 16 bytes. Digging through the code revealed 8 bytes worth of key fairly quickly, but the other 8 bytes were less obvious. I finally figured out that 4 more bytes were the value of another Bluetooth variable which could be simply read out by a client. The final 4 bytes were more confusing, because all the evidence made no sense. It looked like it came from passing the scooter serial number to atoi(), which converts an ASCII representation of a number to an integer. But this seemed wrong, because atoi() stops at the first non-numeric value and the scooter serial numbers all started with a letter[2]. It turned out that I was overthinking it and for the vast majority of scooters in the fleet, this section of the key was always "0".

At that point I had everything I need to write a simple app to unlock the scooters, and it worked! For about 2 minutes, at which point the network would notice that the scooter was unlocked when it should be locked and sent a lock command to force disable the scooter again. Ah well.

So, what else could I do? The next thing I tried was just modifying some STM firmware and flashing it onto a board. It still booted, indicating that there was no sort of verified boot process. Remember what I mentioned about the throttle being hooked through the STM32's analogue to digital converters[3]? A bit of hacking later and I had a board that would appear to work normally, but about a minute after starting the ride would cut the throttle. Alternative options are left as an exercise for the reader.

Finally, there was the component I hadn't really looked at yet. The Quectel modem actually contains its own application processor that runs Linux, making it significantly more powerful than any of the chips actually running the scooter application[4]. The STM communicates with the modem over serial, sending it an AT command asking it to make an SSL connection to a remote endpoint. It then uses further AT commands to send data over this SSL connection, allowing it to talk to the internet without having any sort of IP stack. Figuring out just what was going over this connection was made slightly difficult by virtue of all the debug functionality having been ripped out of the STM's firmware, so in the end I took a more brute force approach - I identified the address of the function that sends data to the modem, hooked up OpenOCD to the SWD pins on the STM, ran OpenOCD's gdb stub, attached gdb, set a breakpoint for that function and then dumped the arguments being passed to that function. A couple of minutes later and I had a full transaction between the scooter and the remote.

The scooter authenticates against the remote endpoint by sending its serial number and IMEI. You need to send both, but the IMEI didn't seem to need to be associated with the serial number at all. New connections seemed to take precedence over existing connections, so it would be simple to just pretend to be every scooter and hijack all the connections, resulting in scooter unlock commands being sent to you rather than to the scooter or allowing someone to send fake GPS data and make it impossible for users to find scooters.

In summary: Secrets that are stored on hardware that attackers can run arbitrary code on probably aren't secret, not having verified boot on safety critical components isn't ideal, devices should have meaningful cryptographic identity when authenticating against a remote endpoint.

Bird responded quickly to my reports, accepted my 90 day disclosure period and didn't threaten to sue me at any point in the process, so good work Bird.

(Hey scooter companies I will absolutely accept gifts of interesting hardware in return for a cursory security audit)

[1] And some very early M365 scooters
[2] The M365 scooters that Bird originally deployed did have numeric serial numbers, but they were 6 characters of type code followed by a / followed by the actual serial number - the number of type codes was very constrained and atoi() would terminate at the / so this was still not a large keyspace
[3] Interestingly, Lime made a different design choice here and plumb the controls directly through to the engine control unit without the application processor having any involvement
[4] Lime run their entire software stack on the modem's application processor, but because of [3] they don't have any realtime requirements so this is more straightforward

comment count unavailable comments

Percent Milkfat

"So what's dark energy?" "Cosmologists and the FDA are both trying very hard to find out."

Keycloak 7.0.1 released

To download the release go to Keycloak downloads.

For details on what is included in the release check out the Release notes. The full list of resolved issues are available in JIRA

Before you upgrade remember to backup your database and check the upgrade guide for anything that may have changed.

Dissolvable PVA support

By noreply@blogger.com (RevK)

The TAZ Pro has two extruders which allows me to try and use dissolvable PVA support. Support is simple enough but hard to remove from the print cleanly, so using PVA allows extra options - just dissolve it!

I have had to play with the Simpify3D settings a bit as the settings for the TAZ 6 did not quite work. I am not sure if the bed is different, the nozzle, or what but my prints were almost welded to the bed. I have tweak the settings for nice clean prints with nGen now. The next challenge was settings for PVA supports.

I ordered some from RS (yes, the price was not silly, strangely), part 174-0082. Well, actually I ordered from someone else, and realised wrong diameter, after opening it, D'Oh, but now I have the right stuff I googled a bit to find temperature.

It is funny stuff, and I ended up printing at 205C which is apparently on the high side. I could also see from simply feeding the filament that it came out thick and slow (around 1mm).

The key setting needed to stop it just curling up was speed - it needs to be very slow. In the end I ran with 2x multiplier, 1mm wide, 20% print speed, and that actually worked. Well, mostly (the eyes went a tad wonky, but worked).


For a start, the PVA comes away from the model really easily, so that is a good start.


Then, put in warm water for a while to remove the last bits, and yay, it worked.


Now to try something more complex with enclosed parts that simply could not have been printed before.

Faculty:Student Ratio

They managed to briefly hit the top of the rankings when they rejected everyone except one applicant, published 5 billion research papers that just said "Hi," and hired one of their graduates for $50 trillion/year (then fired them after 10 microseconds.)

Engineers without borders, silos, and vendor walls

I've seen a bit of variety in how different companies handle engineering problems. Some are big. Others are small. Some build things, and others don't. For some places, the tech is the product, but at others, it's a distraction at best. This is just to say that no one solution is expected to solve every problem, but it's still possible to find things that generally work better than others.

Let's talk about communication and teamwork. If you think those are generally good to have in your organization, you might be prone to make decisions to maintain what you already have and perhaps grow more. Keep that in mind as I describe some scenarios.

Scenario number one is a company which has a product which then depends on a bunch of different services. The product isn't important - it could involve cat pictures, influencing elections, or delivering pizzas. We'll say they have hard dependencies on 20 different services which must all be up and running for the business to function. Maybe one service is a database, another one is a cache, a third one is a group of web servers, a fourth tracks "upvotes", "likes" or "stars", and so on.

In this organization, the 20 services are owned by 20 teams in a 1:1 mapping. Team A owns service A, team B owns service B, and so on down the line. Some of these teams are quite good at what they do, and rarely cause trouble for the business. We'll even say that most of them are pretty solid, and generally don't break things.

There are, however, three services which have significant challenges. They fall over a lot. They stop working. They take down the whole operation. It doesn't matter how reliable the other 17 parts are, since one of these "terrible three" will show up and wreck the whole thing.

Fortunately, this company is enlightened, and has embraced a philosophy where people are able to talk about these things openly, and reflect on the problems and not the people involved. More to the point, the best engineers from other parts of the company are able, willing, and allowed to "wander around" into the troubled parts to help out. This kind of knowledge transfer happens, and pretty soon the roughest spots have been smoothed out, and now everything's a lot better. The cat pictures keep going out, the elections keep being hacked, and the pizzas show up on time. Life's pretty good.

Now let's jump into scenario number two. It's another company that has similar hard dependencies. They also have 20 services which must be up and running to make their business "go". Those 20 services are also run by 20 separate teams, as before, with one team owning one service. Most of them are also pretty good, and only a few of them have issues.

Unfortunately, that's the end of the similarities. Company number two has this "siloing" thing going on. If you're not familiar with the term, consider yourself lucky. It's when a company isolates one thing (a system, department, etc) from another. Well, this company has a LOT of siloing happening. People are very possessive of their services, and their team's "turf". Outsiders are to be suspected, since they probably have some nefarious intent in mind. The fact that all of these people nominally work for the same company with the same supposed goal in mind doesn't matter.

The corporate firewalls are up, they're numerous, and they're pretty tough. If a good person is on one side of the wall, and there's an interesting problem on the other that they could fix, the wall is going to prevent it. There will not be any cross-pollination between the teams. The best you might see is a few individuals moving around between teams in a shared silo, but you'll never see anything more than that.

The organization has been set up with defenses against this. People who try to poke their nose in, even if they have the best possible goals in mind, are the enemy. They must be blocked or reported. They definitely must be thwarted. They must not see the weaknesses in the system because it will be used to attack somehow and take over part of the turf!

Imagine running a company this way, where you can get these protected realms where the employees are "untouchable" and also somehow unable to deliver on the same requirements as everyone else. Worse still, you find yourself unable to send in helpers since the immune system will flare up and attack them in every way imaginable.

In such an environment, I'd expect it to become obvious by way of the general sense of malaise, acceptance of the status quo, and a lot of shrugs - "it's always been like that". "They're protected". "Those requirements don't apply to them". Maybe you've heard some of these before.

I'd hope that most people would try to avoid this with their companies, and part of that would involve breaking down the walls between groups which aren't mixing it up enough. The whole notion of engineers moving around and sharing their talents with whoever needs it has to be supported and rewarded.

Now I'm going to throw another complication into the mix with scenario three. This is a third company which amazingly also relies on 20 different services staying up and available the whole time for their business to work.

But, unlike company #1 and company #2, this one has a completely different approach to services. By default, they go out to Hacker News, find the shiniest thing in that space, and then pull out their checkbooks and throw money at whatever products they find on this romp through the web. They end up with 20 different services, sure, but they are coming from 20 different vendors.

Maybe most of the vendors are reasonably competent and so you never notice problems with them. They take your money and you get some level of service in return. It's good enough and so you probably forget about them. This is akin to the 17 or so good ones at the other two companies.

There's always a catch, though. Three of these services are garbage, just like at the other two companies. Their vendors are just not good at doing whatever they are purportedly selling. They're consuming lots of customer money and are delivering fatal errors, timeouts, or worse.

When this kind of thing happens at company 1, there's always the option of retasking some of the better engineers to do a field trip to the troubled teams to bail them out. If it happens at company 2, the silo walls prevent it, but those silo walls can in theory be torn down, and then they can turn into company 1.

But company 3? That's a different kind of trouble. All of their services are on the other side of a vendor relationship. Maybe some of those vendors are best-in-class, and are amazing -- it happens! But, some of those vendors definitely are not. Do you think company 3 can convince the awesome vendors to send engineers over to the terrible vendors to fix things up? Yeah, I don't think so. That's not going to happen. It's the ultimate silo, and you're never going to break it.

Would you ever willingly build a company like #2? I hope not. But, if you build a company like #3, you've basically done it anyway: you get all of the walls and none of the opportunities to tear them down later.

There are plenty of other gotchas which come with each of these three scenarios, but I'll leave it there for now. It boils down to this: the proliferation of interconnected vendors leads to a loss of control, and few things are more depressing than that.

USB-C not so easy

By noreply@blogger.com (RevK)

Using a USB-C connector for power only is, sadly, not as simple as I thought.

Yes, the pins are tiny, butt the end pins are double pins on the connector and just about solderable (0.6mm wide for two pins together).


However, whilst this works when you use a legacy cable from a USB-A, giving 5V, this will not work to a true USB-C power supply or device.

Why?


Well, resistance is not futile, it seems. There are two connectors (CC1 and CC2) on the USB-C which need resistors to GND to tell the other end you want power.

Whilst the end power connections are two pins at a time (0.6mm), the CC1/2 pins are not, and are 0.3mm wide at 0.5mm spacing. That is pretty much impossible to mill, as the milled track is anything from 0.3mm to 0.6mm wide. The picture above shows around 0.5mm milled track, which is deliberately spaced to allow soldering to the pin 6th from the right. So double pin on right (GND), next double pin in (VBUS) and then another pin we don't care for and then the CC pin. Same on the other side of the connector, except the CC pin is next to the VBUS on that side.

Yes, it is possible to solder!


Then to add the 5.1kΩ resistors to GND.


The end result is power from USB-C...

P.S. Thanks to John for pointing this out to me.
P.P.S. John also pointed out that you do need the two resistors - and cannot simply common up CC1/CC2 with one resistor (as RasPi4 did, by mistake).

Chemistry Nobel

Most chemists thought the lanthanides and actinides could be inserted in the sixth and seventh rows, but no, they're just floating down at the bottom with lots more undiscovered elements all around them.

Introducing Keycloak.X

By Stian Thorgersen

What are we trying to improve?

The first stable release of Keycloak was way back in 2014. As always when building software there are things that could have been done better.

With Keycloak.X we are aiming to introduce some bigger changes to make Keycloak leaner, easier and more future-proof.

A few goals with Keycloak.X are:

This work will be broken into several parts:

Distribution

Building a new distribution powered by Quarkus will allow us to significantly reduce startup time and memory footprint.

We will be able to create a leaner distribution in terms of size and dependencies as well. Reducing dependencies will further reduce the number of CVEs in third-party libraries.

We are also planning to introduce a proper Keycloak configuration file, where we will document directly how to configure everything related to Keycloak. In the current WildFly based distribution the configuration file is very complex as it contains everything to configure the underlying application server, and more often than not it is required to refer to WildFly documentation to figure out how to configure things properly.

Storage

The current storage layer is complex, especially when deployed to multiple-sites. It has a number of scalability issues like the number of realms and clients. Sessions are only kept in-memory, which can be good for performance, but not so great for scaling when you consider a large portion of sessions are idle and unused most of the time.

Exactly what the new storage layer will look like is still to be decided, but we know for sure that we want to:

Providers

Providers today have some issues that we would like to address. Including:

Continuous Delivery

We are aiming to make it easier to use Keycloak in a continuous delivery world. This should consider Keycloak upgrades, custom providers as well as configuration.

Keycloak upgrades should be seamless and there should not be any breaking changes, rather deprecation periods.

It should be possible to more easily manage and reproduce the config of Keycloak, including realm config, in different environments. A developer should be able to try some config changes in a dev environment, push to a test environment, before finally making the changes live in a production environment.

Contributing

We would love help from the community on Keycloak.X. You can contribute with code, with discussions or simply just trying it out and giving us feedback.

Migration to Keycloak.X

There will be a migration required to Keycloak.X. In fact there will be multiple migrations required as everything mentioned earlier will not be ready in one go.

It is an aim to make this migration as simple and painless as possible though.

Timing

We are staring with the Quarkus powered distribution. The aim is to have a fully functional stable distribution by the end of 2019, but we already have a prototype you can try out and contribute to.

In 2020 we are aiming to work on both the storage layer and providers. Hopefully, by the end of 2020 we will have most if not everything sorted out.

We will continue to support the current Keycloak version in parallel with Keycloak.X and will give everyone plenty of time to do the migration before we eventually will pull the plug on the old.

LulzBot TAZ Pro (dual extruder)

By noreply@blogger.com (RevK)

I have been 3D printing for a long time - and even coded a slicer once.

I have tried many printers. My current favourite for cost and performance is the LulzBot TAZ. We have a TAZ 6 at the office and (even though not on the A&A web site) we do 3D printing if you want.

It is a nice heated bed, which works well, especially with my filament of choice ColorFabb nGen.

I have been using to make cases for various electronics / R&D.

Sadly I slightly fried my TAZ 6 units. I have a new controller board on the way, but decided to check what they have now, and saw the TAZ Pro. So I ordered one and to my surprise it arrived in a couple of days (in spite of warnings of back orders and long lead times). Nice.

It is nice...


But is it worth the price (around £5k)?

Well, possible. It has some nice features and works very well. I have only been playing with it for a day now, but I can make some comments. The bed levelling is faster and seems more consistent. The Z axis is belt driven meaning it can easily use Z moves when moving from one part to another (far too slow when Z axis is screw). The big thing is the dual extruder.

Cura?

LulzBot recommend Cura, a good, free, 3D slicer. It works well, and makes some impressive prints, but...

However, it did work, as I say. And the reason I tried it is that Simplify3D, which I was using, had no profile for the new printer.

But, Simplify3D support emailed me one, within a few hours of asking. It works!

Simplify3D

Whilst I do not usually end up recommending paid-for software, this is good. It works well. It is way faster. It is not perfect, but nothing it, but it is nice to use. So I recommend it.

Dual Extruder

This is the first time I have used a dual extruder. But the TAZ Pro does it really well. The heads are motorised to retract completely out of the way. The full bed size is still available to both extruders. It really works well.

There are several reasons to use a dual extruder.
  • Two colour prints - obviously. To be honest this is a pretty minor use case. But it works well.
  • Mixed materials - combine fixed brittle material and flexible rubber to make complex designs - not tried it yet, but fun possibility.
  • Using dissolvable supports - this is likely to be the main use.
The dissolvable supports will be subject of another blog when the PVA reel arrives. Basically, 3D printing like this cannot always print what you want as some things are "in mid air". Using support material works, but has to be cut/broken off, and is impossible to do "inside" some designs. Using dissolvable supports allows the impossible to be printed, and then put in warm water for a while. I look forward to it.

The dual head working is impressive...


In the mean time - two colour test print...



Any downsides

The only one so far is the heads are covered by a safety guard with warning about being hot - which means you cannot see what is printed as it prints.  Ironically it means you cannot see the print head, and can end up burning your finger when trying to adjust something because you cannot see where your finger is. Elf 'n' safety gone mad, IMHO. If it always "just works" then I guess it is not a problem. TBH they should have designed with angled plastic to make a guard that allowed viewing of the actual print head. This may seem trivial but I do feel is more important than they realise. Even ignoring the practical aspects of knowing a print is not working right ASAP, seeing what is being printed it important for selling the whole idea of 3D printing...

Let’s Encrypt support for older Debian

By pete

Debian Jessie and Debian Stretch include dehydrated, a useful command line tool for managing Let’s Encrypt certificates. We use it fairly extensively for managing certificates throughout our servers and with our managed customers. Unfortunately due to a change in capitalisation at Let’s Encrypt, the standard copy of dehydrated shipped with Debian Jessie and Debian Stretch […]

How Old

We've met! I remember you when you were thiiiis tall! [*holds a hand an inch above their head*]

Powering widgets

By noreply@blogger.com (RevK)

Making widgets for the alarm system means that power is quite simple - the alarm wiring has 12V DC, and a simple regulator means I can connect to that - typically with screw terminals.

However, making other widgets with an ESP32, like the environmental monitor, or the Brexit clock, means finding a way to power them. I am not yet playing with battery powered stuff (will do, eventually), so need a power lead.

So what to use?

Initially I tried a micro-USB. Leads for this are very common, and USB-A sockets providing 5V are so common they are fitted to standard power sockets even, so seems ideal.

The issue is the connectors. I have struggled to find what I need. I did see some from China (which have not yet arrived) which have only the power tabs on them making soldering easier, and have clips to hold to the PCB. Whilst waiting for those, I tried some simple surface mount connectors.

The problem is they are not very robust, even superglued to the board, they can become detached very quickly.

I have actually made a set of tools under OpenSCAD two make tight fitting 3D cases to help hold the connector in place, which has helped, but that is still a challenge, and I am not happy about it.


The other catch is the tiny tiny surface mount connectors... Thankfully I only need the ones at the ends. For reference, the three pins at the bottom are 0.1" spaced.

So, I wanted to find a solution, and turned to USB-C. These are a nightmare, not only tiny tiny tiny surface mount tabs, but tabs under the connector so you cannot get to them with a soldering iron. Finally I found a part that will do, and from a UK supplier.

It did mean some fine milling, and even finer soldering, but again, only needing the double connectors at the ends, so just about possible. Those pads are 0.5mm spaced!


The result is a nice solid, soldered to the board, connector.


an Oxford CPZ (controlled parking zone)

By danny

The area we're in has recently been made a controlled parking zone, meaning that only vehicles with an area permit can park in it. Residents have to pay £60/year for a permit, with a maximum of two per house, and get a set of once-off vouchers for use by visitors or tradespeople. Unlike the Iffley […]

Break before make, abstractions, and sleazy ISPs

Back in July, I wrote about some of my reliability list items, including a few mentions of "make before break", "A, AB, B" and the like.

Now I'm going to drop a concrete reason as to why you should care about this kind of thing. It's also related to what happens when you've abdicated responsibility to a bunch of magic systems which do things behind your back and you can't see what's going on. Sometimes they pull this "break before make" business on you, and you might not notice it at all. Worse still, someone might decide it's acceptable.

Here's the scenario: someone is using one of these "infrastructure as code" things, because they're hooked on the cloud, and they've started stacking vendor stuff on top of vendor stuff to manage all of it. They decide to make a small change to their DNS. Maybe they want to shift an A record from a.b.c.1 to a.b.c.2.

They're not stupid, so they have servers running at both IP addresses ahead of time. This ensures that even if someone has the .1 version cached for a while, things will still work. They will shut down service on .1 at some later date.

They are also not stupid in the other way. The .2 IP address actually works just fine, and will serve traffic without any sort of side-effects. This is also not the problem I'm writing about.

This isn't even a problem of not having sticky sessions and potentially doing a "pogo" thing between .1 and .2. They handled that, too.

No, this is about what happened to those DNS zone files when they asked their "IaC" thing to make the change from .1 to .2. This is what happened.

First, there was the original zone file with a.b.c.1 in it. That had to go away, so the system sent an RPC to the cloud provider to delete that A record. It was acknowledged, and it disappeared as requested. The cloud provider started handing out NXDOMAINs to anyone asking for that A record. It's the DNS equivalent of a 404 - nobody's home.

Then, to get the new IP address in place, the system sent another RPC to the cloud provider to create the A record with a.b.c.2 as the IP address. The cloud provider acknowledged this too, and it appeared as requested, and now anyone asking for it got the new IP address in response.

How long elapsed with the NXDOMAINs going out? Maybe a couple of seconds. Most clients didn't notice, or if they did, they started working again a few seconds later.

But then there was a whole other group of clients that fell off entirely and did not come back. Minutes passed, and they weren't coming back online. It took a while, but someone eventually realized that all of these clients were using the same (very large) ISP. There must have been something in common, and oh yeah, there definitely was.

Someone got a test machine running on the ISP and did a query for the hostname, and got back an IP address which was neither .1 or .2. It was something else entirely, off in a completely different net block, routed by some rando autonomous system. Actually going there in a regular web browser turned up some weird error page.

What happened? First, that particular ISP's resolvers got a NXDOMAIN back during the seconds-long window just like everyone else. But, unlike most places, this ISP happens to be a real piece of crap, and they replace NXDOMAINs with their own A records for their "helpful" ad network. So, instead of getting some kind of DNS error from your browser, app, or device, you get taken for a ride. You end up at a weird ad-laden page, your app goes insane with data it can't handle, or maybe (if you're lucky), it complains about a certificate mismatch and just stops there.

Of course, this malicious injection had a relatively long TTL set, and once it landed in the ISP's resolvers, it stayed there like a bad penny, not going away. All of those clients just kept going to the wrong place. Even though the NXDOMAIN was long gone, the clients were still offline, and people were starting to complain loudly.

Actually fixing it involved pulling some strings to get the scummy ISP to clear the cached records in their recursive DNS resolvers, at which point they'd fetch the real (a.b.c.2) data, and things started working again.

Did the cloud provider offer a way to update the existing record without having to delete it outright? Probably. Did the extra layer of abstraction know that? Maybe, maybe not. Did anyone have any idea what was about to happen? Absolutely not.

This is why I say some of this stuff is entirely too complicated. We've brought this upon ourselves: building breathtakingly high stacks of ridiculous systems where few (if any) people can keep the whole thing in their head. Just like code, configs also have to "run" on people first in order to be written and reviewed honestly, and if you can't know the stack, there's no way to know what will really happen.

I keep asking if people do this on purpose as a job security gambit. The number of companies which exist to just stack things higher and higher and higher seems to confirm that a whole lot of money exists in this space. They keep selling and people keep buying it.

If you're using things which do macro expansion or anything else that involves you writing format A and it generating format B which actually does the work (or worse yet, gets turned into format C), you really owe it to yourself to run a 'diff' on the before-and-after versions of the output from the tool BEFORE it goes and takes any action on your behalf.

Otherwise, you too may get your DNS hijacked by a sleazy ad vendor.

Travel Equipment: 2019 Edition

Taking a look at some of the key travelling equipment I've grown to like in the last year of travel.

ASGI 3.0

Upgrading the ASGI spec to simplify it, while keeping backwards compatibility.

A Django Async Roadmap

Taking a look at what it would take to make Django async-native, what it enables, and if we should even do it at all.

Python & Async Simplified

Event loops, coroutines and awaits, oh my!

Channels 2.0

Finally, the promised land is here and Channels 2.0 is released. But how much has changed? And why?

The Sheets Of San Francisco

Finally, my 3D city maps return, and this time they're mapping the streets and hills of San Francisco.

Channels 2: October

What's happening in the world of Channels? How many times have I rewritten the API now?

New Zealand

Adventures in the land of volcanoes, unique birds, fjords, and long white clouds.

Towards Channels 2.0

Outlining my plan for iterating on Channels' design, and what the future might hold for both Django and Python in general.

Taiwan

An adventure of food, cities, industry, and astonishing natural landscapes.