Microsoft Whiteboard Sticky Notes and Text Box

Two ways to add text to Microsoft Whiteboard sessions — ways that aren’t dragging your finger or mouse around in an attempt to draw legible text — are available. I’d like to be able to change the font in the text box — I get that their font choice is meant to evoke hand-written text, but it strikes me as non-professional.

PrivateTmp Strangeness — apachectl v/s systemctl

This is a very strange problem — we had a web server upgraded recently. We use “sudo apachectl start” to bring up the server since the server is maintained by a dedicated Unix support team, and the site worked fine. Until … Sunday morning after the log rotation. Then Box Spout was unable to access the XML data for an Excel file to compress it. Lots of errors:

 

[Mon Sep 14 10:59:39.137728 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Warning: ZipArchive::close(): Zlib error: stream error in /path/to/site/classes/vendor/box/spout/src/Spout/Writer/Common/Helper/ZipHelper.php on line 199, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.137785 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Warning: fopen(/tmp/xlsx5f5f934699dcd9.17695276.zip): failed to open stream: No such file or directory in /path/to/site/classes/vendor/box/spout/src/Spout/Writer/Common/Helper/ZipHelper.php on line 213, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.137803 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Warning: stream_copy_to_stream() expects parameter 1 to be resource, boolean given in /path/to/site/classes/vendor/box/spout/src/Spout/Writer/Common/Helper/ZipHelper.php on line 214, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.137814 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Warning: fclose() expects parameter 1 to be resource, boolean given in /path/to/site/classes/vendor/box/spout/src/Spout/Writer/Common/Helper/ZipHelper.php on line 215, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.138360 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Fatal error: Uncaught exception ‘Box\\Spout\\Common\\Exception\\IOException’ with message ‘Cannot perform I/O operation outside of the base folder: /tmp’ in /path/to/site/classes/vendor/box/spout/src/Spout/Common/Helper/FileSystemHelper.php:130\nStack trace:\n#0 /path/to/site/classes/vendor/box/spout/src/Spout/Common/Helper/FileSystemHelper.php(82): Box\\Spout\\Common\\Helper\\FileSystemHelper->throwIfOperationNotInBaseFolder(‘/tmp/xlsx5f5f93…’)\n#1 /path/to/site/classes/vendor/box/spout/src/Spout/Writer/XLSX/Helper/FileSystemHelper.php(369): Box\\Spout\\Common\\Helper\\FileSystemHelper->deleteFile(‘/tmp/xlsx5f5f93…’)\n#2 /path/to/site/classes/vendor/box/spout/src/Spout/Writer/XLSX/Internal/Workbook.php(134): Box\\Spout\\Writer\\XLSX\\Helper\\FileSystemHelper->zipRootFolderAndCopyToStream(Resource id #26)\n#3 /path/to/site/ in /path/to/site/classes/vendor/box/spout/src/Spout/Common/Helper/FileSystemHelper.php on line 130, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.139468 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Warning: ZipArchive::close(): Zlib error: stream error in /path/to/site/classes/vendor/box/spout/src/Spout/Writer/Common/Helper/ZipHelper.php on line 199, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.139504 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Warning: fopen(/tmp/xlsx5f5f934699dcd9.17695276.zip): failed to open stream: No such file or directory in /path/to/site/classes/vendor/box/spout/src/Spout/Writer/Common/Helper/ZipHelper.php on line 213, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.139515 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Warning: stream_copy_to_stream() expects parameter 1 to be resource, boolean given in /path/to/site/classes/vendor/box/spout/src/Spout/Writer/Common/Helper/ZipHelper.php on line 214, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.139533 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Warning: fclose() expects parameter 1 to be resource, boolean given in /path/to/site/classes/vendor/box/spout/src/Spout/Writer/Common/Helper/ZipHelper.php on line 215, referer: https://hostname.example.com/path/to/code.php
[Mon Sep 14 10:59:39.139599 2020] [:error] [pid 57117] [client 10.1.2.3:49276] PHP Fatal error: Uncaught exception ‘Box\\Spout\\Common\\Exception\\IOException’ with message ‘Cannot perform I/O operation outside of the base folder: /tmp’ in /path/to/site/classes/vendor/box/spout/src/Spout/Common/Helper/FileSystemHelper.php:130\nStack trace:\n#0 /path/to/site/classes/vendor/box/spout/src/Spout/Common/Helper/FileSystemHelper.php(82): Box\\Spout\\Common\\Helper\\FileSystemHelper->throwIfOperationNotInBaseFolder(‘/tmp/xlsx5f5f93…’)\n#1 /path/to/site/classes/vendor/box/spout/src/Spout/Writer/XLSX/Helper/FileSystemHelper.php(369): Box\\Spout\\Common\\Helper\\FileSystemHelper->deleteFile(‘/tmp/xlsx5f5f93…’)\n#2 /path/to/site/classes/vendor/box/spout/src/Spout/Writer/XLSX/Internal/Workbook.php(134): Box\\Spout\\Writer\\XLSX\\Helper\\FileSystemHelper->zipRootFolderAndCopyToStream(Resource id #26)\n#3 /path/to/site in /path/to/site/classes/vendor/box/spout/src/Spout/Common/Helper/FileSystemHelper.php on line 130, referer: https://hostname.example.com/path/to/code.php

 

The postupdate script is “systemctl reload httpd.service” — so not exactly the same thing we used to launch the service originally. But I’ve never seen differing behavior between apachectl and systemctl started HTTPD instances. Quick/dirty solution is to disable PrivateTmp, but I’m hoping to be able to isolate why exactly the postupdate script appears to break the service’s access to the private tmp space.

Python Time-Expiring Cache

I needed to post information into a SharePoint Online list. There’s an auth header required to post data, but the authentication expires every couple of minutes. Obviously, I could just get a new auth string each time … but that’s terribly inefficient. I could also use what I had and refresh it when it fails … inelegant but effective. I wanted, instead, to have a value cached for a duration slightly less than the server-side expiry on the auth string. This decorator allows me to use the cached auth header string for some period of time and actually run the function that grabs the auth header string before the string is invalidated.

import functools
import time
from datetime import datetime

def timed_cache(iMaxAge, iMaxSize=128, boolTyped=False):
    #######################################
    # LRU cache decorator with expiry time
    #
    # Args:
    #    iMaxAge: Seconds to live for cached results. 
    #    iMaxSize: Maximum cache size (see functools.lru_cache).
    #    boolTyped: Cache on distinct input types (see functools.lru_cache).
    #######################################
    def _decorator(fn):
        @functools.lru_cache(maxsize=iMaxSize, typed=boolTyped)
        def _new(*args, __time_salt, **kwargs):
            return fn(*args, **kwargs)

        @functools.wraps(fn)
        def _wrapped(*args, **kwargs):
            return _new(*args, **kwargs, __time_salt=int(time.time() / iMaxAge))
        return _wrapped

    return _decorator

# Usage example -- 23 second cache expiry
@timed_cache(23)
def slow_function(iSleepTime: int):
    datetimeStart = datetime.now()
    time.sleep(iSleepTime)
    return f"test started at {datetimeStart} and ended at at {datetime.now()}"


print(f"Start at {datetime.now()}")

for i in range(1, 50):
    print(slow_function(5))
    
    if i % 5 is 0:
        print(f"sleeping 5 at {datetime.now()}")
        time.sleep(5)
        print(f"done sleeping at {datetime.now()}\n\n")

print(f"Ended at at {datetime.now()}")

Ohio Absentee Ballot — Confirming Rejected Ballot

I requested an absentee ballot this year — we’d used absentee ballots once back when we lived in Geauga county and delivered the ballots to the Board of Elections office, but we generally vote in person. I wanted Anya to experience the process (and they give out cute stickers!). But we’ll have more time to explore what the ballot actually is at home, and there won’t be a bunch of people about. But — and the one thing that makes me want to do the early in-person voting — they can reject your ballot if the signature doesn’t match. I didn’t have a problem with my absentee ballot request, but Scott’s got rejected for a signature mismatch. And that had be worried about my actual ballot.

But, amid all of Trump’s blathering last night? Biden managed to convey that a lot of states have a process for curing rejected absentee ballots. I had no idea. Per Ohio Rev Code § 3509.06:

“(b) If the election officials find that the identification envelope statement of voter is incomplete or that the information contained in that statement does not conform to the information contained in the statewide voter registration database concerning the voter, the election officials shall mail a written notice to the voter, informing the voter of the nature of the defect. The notice shall inform the voter that in order for the voter’s ballot to be counted, the voter must provide the necessary information to the board of elections in writing and on a form prescribed by the secretary of state not later than the seventh day after the day of the election. The voter may deliver the form to the office of the board in person or by mail. If the voter provides the necessary information to the board of elections not later than the seventh day after the day of the election and the ballot is not successfully challenged on another basis, the voter’s ballot shall be processed and counted in accordance with this section.”

Which means I’d be notified if my ballot is rejected, and I could go to the Board of Elections within seven days of the election to provide whatever sort of identification they need to be satisfied. A total of fifteen states provide a remediation path for signature challenges — details for those states at https://www.ncsl.org/research/elections-and-campaigns/vopp-table-15-states-that-permit-voters-to-correct-signature-discrepancies.aspx

VSCode — Shortcut for Uppercase and Lowercase Conversion

While you can run a command to convert the selected text to upper (or lower) case, there doesn’t appear to be a quick way to do it. Luckily, you can define your own keyboard shortcuts and map those shortcuts to commands. From the File menu, select “Preferences” and “Keyboard Shortcuts” (or use the Ctrl-K Ctrl-S combo).

In the upper right-hand corner, click this icon to open the custom keyboard shortcut JSON file

Add JSON elements for the shortcuts you want to define — the key combination, the command to run, and on what to run the command

Sample key command bindings:

[
 {
    "key": "ctrl+shift+u",
    "command": "editor.action.transformToUppercase",
    "when": "editorTextFocus"
 },
 {
    "key": "ctrl+shift+l",
    "command": "editor.action.transformToLowercase",
    "when": "editorTextFocus"
 }
]

Save … voila, a keyboard shortcut to change to upper and lower case.

2020 Presidential Debate Number One

The problem, I guess, with being a TV president … there are a non-trivial number of shows that go on far longer than they should. The context of premise that connected with viewers (relatable, entertaining, novel, whatever) changes over the shows run. It’s often difficult to wholesale change the direction of your show, people stop watching, the show starts to go wild directions to bring back viewers (i.e. ‘jump the shark’ both in the literal instance that begat the phrase and other subsequent figurative jumps), and eventually gets cancelled.
I posit that the Trump presidency jumped the shark tonight. In 2016, running as an outsider who wasn’t going to be constrained by all of the BS political rules … that was a viable message (obviously). Saying ‘the current guy created a lot of problems, there are a lot of longstanding problems just because of the way government works, and I’m an outsider who doesn’t need the political machine behind my candidacy. I can fix it” was a viable message. Bullying, name calling, anti-social interactions with other candidates were new — offered catharsis similar to yelling at the TV screen when politicians were defending the status quo. Personally, the race baiting and outright racist comments put me off. I know a lot of people who give older relatives a “pass” on racist comments, though and proceeded to do the same for Trump.
In 2020? Running against yourself is a bit of a long-shot. Trump’s never managed a logical campaign message beyond “it is all awful, and I can fix it”. But he’s had years to fix it this time around, so the message isn’t as powerful. I’d observed earlier this year that his response to the 2016 approach not appealing to voters was to be Trumpier — louder, more violent, more divorced from reality, more racist. Hey, white suburban housewives — fear the melanin that’s going to invade your utopia if you don’t vote for me … which was out of touch on so many levels. The debate tonight was a natural evolution of being Trumpier. Slate counted 128 interruptions in the course of the 90-minute debate (https://slate.com/…/trump-interruptions-first…). The Boston Globe cited an exchange where Trump interrupted Biden 10 times in three minutes (https://www.bostonglobe.com/…/trump-interrupted-biden…/) … “and it got worse from there”. As noted, Trump asked the Proud Boys to “stand back and stand by” — then followed that sentence “But I’ll tell you what — somebody’s got to do something about Antifa and the left because this is not a right wing problem this is a left wing.” Which sounds a lot more like inciting violence than the condemnation he was asked to make.
Sure, there’s some frighteningly large percentage of the population who looks at Trump and thinks this is awesome. And I’m sure they are energized by this debate performance. People like the groups of centrist Republicans who are publishing their support of Biden? I cannot see how Trump swayed them back tonight — he substantiated everything they say about Trump that is pushing their vote to Biden.
Biden managed to talk a few times. He managed to convey the most important thing (Trump can only lie and construct a new reality if you let him — go vote no matter how many times he threatens to disenfranchise you). That some states provide a mechanism to cure rejected absentee ballots. And that he’s proud of his son — that’s one that I think might stand out to individuals but be lost in professional analysis. Biden was speaking about one of his sons, and Trump interrupted to bad-mouth the other son. And not just to bad-mouth the guy but specifically to call out the fact the guy had a coke problem. There’s a substantial meth problem / opioid epidemic going on in the country — one that impacts rural America. A lot of people have a friend, relative, and even kid who has a drug problem. A father proud of his son for overcoming addiction is relatable. Someone using a kid’s addiction to attack both the kid and parent? That’s an off-putting move even for someone whose kid isn’t suffering with addiction. I cannot imagine how awful that sounds to someone whose kid is/was addicted to drugs.

Large Numbers

It’s often difficult to conceptualize large numbers — something that allows statistics dealing with large numbers to convey something other than reality. I think I heard Trump say the government is ready to vaccinate 200k people a day. That sounds like a lot of people (it is a lot of people), but there are a lot of people in the US: an estimated 328.2 million according to a quick Google search.

 

That’s four and a half years to vaccinate the current population of the US at 200k a day, every day. Which doesn’t take into account new people being born (or aging into the range where a vaccine is administered). The CDC shows 3.79 million births in 2018 — of course that number changes every year, and it’s been decreasing. But at 3.5 million births per year, new people still add a few months to the vaccination timeline. About four and three quarter years to vaccinate the US population. And that assumes a one-dose vaccine. Administering two doses to everyone, at 200k people per year, would take just under ten years. Saying ‘it could take us five years to vaccinate everyone’ isn’t nearly as impressive sounding as ‘we can administer 200,000 vaccines each day’ — but it’s the same thing.

Speculation — Why he didn’t release his taxes

I’ve long speculated that Trump doesn’t release his taxes because beyond paying zero dollars (which everyone pretty much expects), he’s taking refundable deductions and having the government pay him. Well, the NYTimes has finally gotten access to years of returns for Trump and his businesses … and I’ve got a new hypothesis. It was only time before someone with access to Trump’s taxes sent that info to reporters. Had he stayed a private citizen, no one would have cared. And people who could have accessed the documents wouldn’t have bothered — they weren’t important.

The “loss” he claimed and carried back to request a 70 million dollar refund is questionable. If he got interest in the reformed company, he didn’t actually walk away from the investment. Before the tax returns were publicized, no one knew that the details of the subsequent transactions were of interest. Now that it’s public? Someone has access to information that’s pertinent to the IRS investigation. It’s only a matter of time before those details are splashed across some news paper’s page.

On Taxes and Businesses

I expect a lot of hype about how little Trump paid in taxes — and, yeah, it really sucks that someone is able consider private planes, meals, club memberships, car leases, etc to be a tax-deductible business expense. One of my first introductions to the working world was a privately-held company. I was the IT department, and one of my jobs was to move data from the old systems (mainframe for order management, database for inventory, and paper ledger for accounting) into the new all-in-one business management platform. Which meant I not only had access to all of the company’s accounting, but that I had to read through it all to get the information typed into the new platform. The company owner’s plane was owned by the business, so the hangar and maintenance was a business expense. He’d hire time in the plane for person use, but he got a really good discount from his company’s transportation service. Same for the company car he drove. And the country club membership — that’s where he’d meet with clients to solicit business, after all. Food and drink at those client meetings were business expenses too. It was all perfectly legal and designed both to maximize the owner’s enjoyment of life and the minimize the business’s profits. As a broke out-of-college kid, it seemed awfully unfair that the rich old dude was able to eat every day and avoid paying some taxes in doing so but the huge chunk of my paycheque that went to various taxes meant I had some rice to eat that day.

There were subordinate companies that paid consulting fees back to the main company to zero out any profits they made. And that parent company had a bunch of “business expenses” that minimized their profits. Ideally, the CFO told me, you’d net zero every year (or even have a paper loss) and not have to send the federal government anything in business taxes. Which I get — people shop around for the best price, find coupons and promo codes … you try to get the best deal. And, if the legal structure allows you to do so, why wouldn’t you avoid paying taxes altogether?

I’ve heard people say that a business needs to show a profit every ten years — that’s not true. If you don’t show a profit once in a ten year period, you may be asked to prove to the IRS that it’s a legit business. I come across this in the soap-making community — buying stuff for my soap-making hobby is not tax deductible even if I construct a business entity under which to make those purchase. Even if I happen to sell a few bars of soap to friends and neighbors. But if you’re advertising your product, going out to craft fairs and selling your soap … you provide the IRS evidence of your attempts to sell your product and you could be losing money every year for decades and still write off business expenses.

And the tax code is designed to encourage businesses to minimize their net — investing in your business offsets profit too. It’s one of the biggest problems I had with the interaction Obama had with Joe the not-a-plumber. If you buy a plumbing business that grosses a million dollars a year? You hire another plumber, buy another truck … you invest in a new tool that lets you offer more services. You spend some of that money and don’t have to pay taxes on it. Well, that hiring and purchasing also improves the country’s economy.

Hop Garlic Marinade

Hop Garlic Marinade

Recipe by LisaCuisine: AmericanDifficulty: Easy
Prep time

10

minutes

Ingredients

  • 304 cloves garlic

  • 1/2 cup olive oil

  • 2-3 Tbsp hop tea

  • 1 tsp honey

  • 1 tsp salt

  • 1/2 tsp pepper

  • 1/2 tsp Aleppo Pepper

Method

  • Whirl everything in a food processor until emulsified.