Jekyll2022-09-27T19:36:32-07:00http://amyszczepanski.com/feed.xmlAmy SzczepanskiMath and cats and yarn and work and data and airplanes and musings and sewing and stuff.Jury Duty? More Like Fury Duty2022-09-27T18:31:00-07:002022-09-27T18:31:00-07:00http://amyszczepanski.com/2022/09/27/jury-duty-more-like-fury-duty<p>All of the people who I talk to on a regular basis are sick of hearing me
complain about jury duty. And then I remembered that I have a blog! I can
complain about jury duty on my blog!</p>
<p>Yes, yes, it is true, it has been <em>an entire week</em> since this happened, and I
am still irritated!</p>
<p>My premise here is that even though you may have a <em>right</em> to a jury trial in
certain situations, it is often <em>rude</em> to exercise that right. This is not the
only right that falls into this category. There are a lot of things that you
can say (freedom of speech) that it are better left unsaid. There are arms that
you might bear but that you would be better off not bearing.</p>
<p>Based on my reading of the court calendar, most of the cases with jury trials
are civil cases. Over the past few weeks of me reading the court calendar,
there has only been one criminal jury case in San Diego County. Thus, everything
that I’m writing in this post is about <em>civil court</em>.</p>
<p>In case you didn’t know, the only civil cases that qualify for a jury trial are
those where you are asking for money. If you want someone to stop doing things,
then it’s a judge trial. It’s only if you want money from the other party that
you might have the option for a jury trial.</p>
<p>When I showed up for jury duty, they informed us that they were trying to pick
a jury for a TWELVE DAY TRIAL. I do not get paid for jury duty. I do not have
12 days of vacation saved up. I would be out <em>real and actual money</em> if I was
chosen to serve on that jury. While the court would excuse people in cases of
extreme financial hardship, I would still be able to buy food and whatever even
without 12 days of income. However, that does not change the fact that this is
roughly 5% of my income for the entire year. Someone is asking someone else for
money, and I was at risk of being caught in the crossfire and ending up being
out 5% of my income for the year. Rude.</p>
<p>Sure, some of the people on a jury will be retired or government workers who
get paid for jury duty, but some of them won’t. How much should people be asked
to suffer so that someone can have a civil suit heard by a jury? Can the people
on the jury offer to chip in some extra money to beef up the defendant’s best
offer of a settlement so that the case will go away?</p>
<p>Based on my reading of the court calendar (which is a public record published
on the court’s webpage), this was a case about someone who bought a Jaguar
and had a warranty claim. However, in California
we have really strong consumer protection laws – if you follow the rules. If
the buyer of this car had followed the checklist in the Tanner Consumer
Protection Act, then this probably would not have been headed to a jury trial.
The Tanner Act is pretty clear about car warranty claims. You could take care of
this with a judge-trial without taking up too much time.</p>
<p>Please note that I am developing very strong opinions about the Tanner
Consumer Protection Act and the Song-Beverly Consumer Warranty Act. It is my
firmly-held and sincere belief that someone with a car warranty complaint
absolutely must pursue it via the protections of the Tanner Consumer Protection
Act. I would never find for someone who was making a claim under only the
Song-Beverly Act.</p>
<p>The only automatic excuses for avoiding this jury were (1) extreme financial
hardship, (2) having a pre-paid and non-refundable vacation planned (!!!), (3)
being a primary caretaker and unable to hire a replacement caretaker, and (4)
having a non-reschedulable medical appointment. You know what else made this
12-day trial so rude? It included both Rosh Hashanah <em>and</em> Yom Kippur. But
apparently that was not grounds for being excused. Also rude.</p>
<p>At this point I will point out that nowhere in the Constitution does it say
that a jury has to be a “jury of your peers.” It just says that the jury needs
to be impartial. Do you think that I would be impartial on a case where the
lawyer for the plaintiff is being paid on contingency. That would be, “NO!”
If I am not getting paid, then the lawyer is not getting paid, either. There
is no reason that these civil cases need to be heard by arbitrary members of
the general public. This is <em>especially</em> true if any money that would be
awarded is going to be paid by an insurance company. Have a judge trial! Start
using professional jurors! Or a mix of professional jurors and people who
don’t need to be at work!</p>
<p>Or limit civil jury trials to one day! Jury duty starts at 8am. Instead of
showing us some sort of video about how important our civic duty is, start with
a speed round of voir dire (8am - 9am). Plaintiff presents from 9am - noon.
Have a break for lunch. Defense gets to present from 1pm - 4pm. Deliberate
until 5pm. Everyone goes home. BOOM! Done! If it’s something really complex,
let it have two days. People would be much more willing to do jury duty if
it only lasted 1-2 days.</p>
<p>Do note that a car warranty case most definitely could fit within that
timeframe, as the Tanner Consumer Protection Act is <em>very clear</em> about what
must be done.</p>
<p>Some of the cases that are slated to come up for jury trials are pretty wild.
You should read about <a href="https://www.gofundme.com/f/zwfnu-85000">the case of the French bulldog that died while under the
care of a veterinarian</a>. Sad, sure, but
worth disrupting the lives of a dozen people for many days?</p>
<p>Fortunately for me, the case with the 12-day trial decided mid-morning that
they did not need a jury after all, so they sent us all home. I’m also pleased
to report that I do not seem to have caught any respiratory viruses hanging
out in a crowded room with a bunch of sniffling and coughing members of the
general public.</p>All of the people who I talk to on a regular basis are sick of hearing me complain about jury duty. And then I remembered that I have a blog! I can complain about jury duty on my blog!The Tentative Return of the Blog2022-07-24T16:09:00-07:002022-07-24T16:09:00-07:00http://amyszczepanski.com/2022/07/24/the-tentative-return-of-the-blog<p>Wow, this blog has gotten dusty. Sorry about that.</p>
<p>Well, you see, I think that the last post was written in that strange time between
when I <em>knew</em> that I was going to start a new job but <em>before</em> I gave notice.
Maybe it was written after I’d given notice? I know that they still had me
interviewing candidates after I gave notice. Fun fact about one of the
comments that I made at the end of the previous post: When I said that the SQL
question was similar to one that is asked at other companies it’s because it
turned out to be one that <em>I</em> was asked when interviewing. Since I do manage to
have some common sense every now and then, I just solved the problem rather
than trying to build rapport with my interviewer by saying, “Funny thing! I ask
my candidates this same question!”</p>
<p>And then I started a new job! And I didn’t want to say anything that would jinx
things. Or that my then-new colleagues would take out of context! I think that
they have come to accept that I am eccentric and sometimes have no filter.</p>
<p>But don’t worry! I can keep it together enough to not say anything awkward!
It helps that one of the biggest disappointments is the quality of the free
t-shirts. AoPS was <em>killing it</em> in the free t-shirt department. Not only did
we have our own t-shirts (and many varienties thereof), but we also had
random hedge fund t-shirts. While the AoPS t-shirt are made of nice fabric,
the hedge fund t-shirts are made of <em>really</em> nice fabric. AoPS also gave us
free hedge fund pajamas. My current workplace has not provided us with any
pajamas <em>even though we all work from home</em>.</p>
<p>In other irrelevant news, the cute, tiny, underpowered computer that I had been
using to write this blog died. Like, you turn it on, it makes the chime noise,
and then it does <em>nothing</em>. If you try to boot it into recovery mode, it does
nothing. If you try to do the thing where you zap some internal settings, it
makes the screen flash a few times, and then it does nothing. Before it died,
it had reached a point of being almost useless. For example, it did not let you
read the Wikipedia nor Stack Exchange with either Safari or Chrome. While, yes,
it was the purse-dog of computers, it was still remarkably useful for writing
plain words. So let’s see if this new, very modern computer will actually build
the page for this new post.</p>
<p>Update: Yay! The blog works! Boo! The posts with snarky JS don’t work
because of CORS or similar nonsense!</p>Wow, this blog has gotten dusty. Sorry about that.Random Numbers2021-09-15T04:31:00-07:002021-09-15T04:31:00-07:00http://amyszczepanski.com/2021/09/15/random-numbers<p>Based on how long it has been since I have updated this blog, I am now confident that the
sticky note that says “write about random numbers” has been on my laptop for several
weeks. This is supported by the fact that the ink is somewhat smudged and that the
other sticky notes are arranged in such a way that the random numbers note looks like
it was there before them.</p>
<p>Part of the reason for blog silence goes under the general umbrella of “interview stuff”
and part of it is “don’t snark about the landscapers until the project is done.”</p>
<ol>
<li>
<p>I got my lesson on the irrigation system yesterday, which signals that the project is
pretty much done; I also wrote a large check, which supports that theory. We are not sure
what gets watered by zone 10, nor have we determined which zone waters my lemon tree. My
beloved zone 11 has been remapped to zone 9. Unlike the iPod that I had many years ago,
the controller for the sprinkler system does not have a “shuffle” mode. I need to make
decisions about how much water each zone will get how many times per day and how many
times per week. The lemon tree might be on its own.</p>
</li>
<li>
<p>There is a project that I worked on last year and wrote thousands of lines of code.
Right before it was supposed to be merged to master, the stakeholders decided that they
wanted to make major changes, but that they were not sure exactly what needed to be done,
so the project was put aside. (Added wrinkle: I also wrote a bunch of API endpoints – on
an entirely different system – as helpers for this project, and they have been in
production for nearly a year – but based on the older version of the spec.) Yesterday I
discovered that they have come up with a plan of what they want and that someone who is
not me is going to be working on this. (They have no idea what a good call they made by
asking someone else to work on it.) I let her know where to find my previous work. I also
let her know that the test server that can be used for those API endpoints always has a
highly sanitized database that contains none of the information that is needed to
actually test them. Since it’s not anywhere in my branch, I also pasted into the Slack
thread the chunk of SQL that I use to fill the database with random data to be used for
testing.</p>
</li>
<li>
<p>A house on my block went up for sale a little over a month ago for $1.3 million. It is
currently listed as “pending.” This is crazy-money because I live in north county inland,
roughly 35 miles from downtown San Diego. It is routinely 20 degrees hotter here than it
is in coastal areas. People ask if it is safe to live in this city; we have uniformly
terrible schools; someone at work refers to this city with the suffix “-ghetto” because
it is known for having a lot of poor people. Yes, it’s a much nicer house than mine, but
is it really worth <em>that</em> much? Hashtag California real estate. No matter what economics
class tried to teach me about efficient markets, I find it hard to believe that there is
any rhyme or reason about the price of houses in San Diego County. For years politicians
have been telling us that California is going to be a ghost town because it is too
expensive and everyone is moving to Texas. I’ve never had any interest in moving to
Texas. I’ve come to discover that some people in Texas support my point of view.</p>
</li>
<li>
<p>This one is clearly about interview stuff: We are interviewing people to do things
that are similar to what I do, so I was put in charge of setting up the interview tasks.
So far we have not had much in the way of interview tasks that test the candidate’s
skills with SQL. I’ve developed two sets of tasks: One for the preliminary phone screen
(hello candidates who are googling me because you have phone screens this week or next
week) and one for later in the process. The one for the later round needs to be similar
in spirit to the data that we use on a daily basis, but it can’t be <em>real</em> because our
real data comes from small children, and it would be <em>wrong</em> for us to share it – even
anonymized – with interview candidates. I needed to conjure data out of thin air.</p>
</li>
<li>
<p>When creating the generated data for the interview task, I came face-to-face with the
oft-repeated sentiment that R is slow. I’ve always brushed that off because most things
that I’ve done with R have finished running in a few seconds. Is it worth it for me to
write statistical code in a language not designed for statistics in order to save the
computer a few seconds of work? Up until now, no. This interview task needs to parallel
our real data in size and complexity, so I needed to make a lot of fake data. To make
sure the relationships were not perfectly deterministic, I needed random number
generators to fuzz the connections between some variables. I started my data-generation
code running on a Friday afternoon, and it was <em>still running Monday morning</em>. At which
point I decided to rewrite it in Node.js, even though it is definitely not meant for
statistical programming. During this process I learned that d3 (an interactive
visualization library used for making nice data visualizations for the web) has a
<em>really nice collection of random number generators</em>. I was able to rewrite the entire
thing in node before the R version finished running. The node version did take a few
minutes to run, but I can live with that.</p>
</li>
<li>
<p>There is probably more that I could say about how I made my random data other than
“R is slow, and d3 came through for me,” but this would reveal the total Rube Goldberg
machine of infrastructure that I am dealing with as well as my short-term thinking of
writing the data to the database belonging to the server where the data generation
script is running rather than to the database belonging to the interview server.</p>
</li>
<li>
<p>On the other hand, the phone screen SQL task is pretty standard stuff without any
nuance or complication to the data. You would probably write very similar queries when
interviewing for other companies; if you have an understanding of fundamentals, you
should be <em>fine</em>.</p>
</li>
</ol>Based on how long it has been since I have updated this blog, I am now confident that the sticky note that says “write about random numbers” has been on my laptop for several weeks. This is supported by the fact that the ink is somewhat smudged and that the other sticky notes are arranged in such a way that the random numbers note looks like it was there before them.Another Knitting Update2021-07-26T20:30:00-07:002021-07-26T20:30:00-07:00http://amyszczepanski.com/2021/07/26/another-knitting-update<p>I spent this weekend trying to get caught up on my knitting. I can’t show your the
sweater right now because I am having a lot of angst about it. I was trying to
kitchener together some 2x2 rib, and I don’t want to talk about it. I’m also still a bit
worried that the arms are too long and/or the body is too short. These are all solvable
problems, but I have a lot of other things on my mind right now. For example, the
customer service rep who is allegedly handling my insurance claim for the damage to my
gate has not confirmed receipt of the two estimates for having my gate repaired.</p>
<p>Meanwhile, I spent the better part of yesterday knitting up some swatches.</p>
<p><img src="http://amyszczepanski.com/assets/2021-07-26-swatch.jpg" alt="random stitches" width="600px" /></p>
<p><img src="http://amyszczepanski.com/assets/2021-07-26-swatch2.jpg" alt="ring stitch" width="600px" /></p>
<p>My goal is to find some sort of stitch that I can do mindlessly while doing other stuff
and then use it to make scarves of some sort out of all the yarn that I impulse-bought
but that I don’t have enough of to make anything big out of. I’ve previously tried to
make things out of an assortment of various yarns. It never goes well, and the finished
object usually ends up in the trash.</p>
<p>The ring-lace stitch isn’t a good choice for mindless because I have a really hard time
keeping track of where I am in that pattern. I feel like I would need to have a stitch
marker every six stitches in order to have any hope of making anything at all with that
stitch. I will note that I have tried this lace pattern many different times over the
years, and this is the first time that it was not a total fail. The secret is to use
a normal needle size and don’t think that going up a needle size is going to help. Also I
tugged on it really hard (in the vertical direction), which made the holes much better
defined.</p>
<p>You can’t really see all the things that I tried on the other swatch (btw, I used a US 5
needle for everything there; the stitches really are that different in size). Near the
top I have some variations on linen stitch that probably fall under the umbrella of
twill stitch. These aren’t mindless either because you need to keep track of where you
are, and there is too much purling.</p>
<p>Sort of in the middle are some variants on the cartridge belt rib stitch. Much better
because there is no purling.</p>
<p>The stripey one in the middle is brioche stitch, but done back-and-forth instead of
sliding it to the other end of the needle. The vertical striped one near the bottom is
a slight variation on brioche stitch where you slip the same stitches in both directions
after you change colors.</p>
<p>Depending what happens in terms of this whole “return to the office” nonsense, I might
also need to knit myself something to keep me warm while at work. The current office has
a terrible HVAC system where it is always too cold somewhere in the building – and I
usually have to be in that particular somewhere. We have too many people to go back to
the old office, so we are getting a new office in December. However, no word yet on how
cold it is in the new office. Thus, I am holding off on buying new yarn and trying to
knit my way through the backlog.</p>I spent this weekend trying to get caught up on my knitting. I can’t show your the sweater right now because I am having a lot of angst about it. I was trying to kitchener together some 2x2 rib, and I don’t want to talk about it. I’m also still a bit worried that the arms are too long and/or the body is too short. These are all solvable problems, but I have a lot of other things on my mind right now. For example, the customer service rep who is allegedly handling my insurance claim for the damage to my gate has not confirmed receipt of the two estimates for having my gate repaired.Never a Dull Moment2021-07-20T05:05:00-07:002021-07-20T05:05:00-07:00http://amyszczepanski.com/2021/07/20/never-a-dull-moment<p>In addition to the normal chaos that happens around here, we had some unexpected
annoyance yesterday.</p>
<p>We’ve decided that the nice new house deserves nice new furniture, so we have been
working on that. So far we have bought a rug (ok, not furniture, but part of the whole
home-dec theme) and a cabinet.</p>
<p>We interviewed two decorators for this project. One of them (who we didn’t end up hiring)
does all-custom work for the furniture and will sometimes buy back pieces from her old
clients. I mention this because the cabinet that <em>she</em> recommended had previously been
owned by one of the Real Housewives of Orange County (Vicki). I admit that I was intrigued
by the possibility of owning a cabinet (well, in this case, a credenza) that had
previously been on television.</p>
<p>Using the more conventional decorator means that our cabinet came from one of those
furniture stores that you will see in your Facebook ads if you do anything at all that
gives your browser cookies a “furniture” sort of vibe. We ordered the cabinet about a
week and a half ago, and I got an email last week that it was going to be delivered. I
got to pick which delivery option I wanted (I went with the $20 option for having the
crew bring the package just inside the front door since it is a 100-pound cabinet). Then
I clicked some options for getting texts about the status, clicked something to confirm
my delivery time etc., etc.</p>
<p>The cabinet arrived yesterday. The cabinet itself is fine. It is a very nice cabinet.</p>
<p>The issue was with the delivery. This is a major furniture vendor, and this is a fairly
large metropolitan area. There is a lot of furniture being delivered each day, so my
cabinet was delivered in a <em>very large</em> box truck. In terms of the size, I’m guessing it
was roughly equivalent to the largest U-Haul you could rent. This is a substantial truck.
It would have a decent amount of momentum. It’s probably only slighly narrower than my
driveway. Backing this truck up my (fairly steep) driveway would be <em>very challenging</em>.</p>
<p>Turns out that the driver was not up for the challenge, as he clobbered my gate.</p>
<p><img src="http://amyszczepanski.com/assets/2021-07-20-gate-view.jpg" alt="Gate closeup" width="600px" /></p>
<p><img src="http://amyszczepanski.com/assets/2021-07-20-gate-closeup.jpg" alt="Gate view" width="600px" /></p>
<p>The furniture company pinky-swears that they will coordinate everything for me to file
a claim with the delivery contractor’s insurance company. So far I have not yet received
the paperwork that they promised to email, so we shall see how this unfolds.</p>In addition to the normal chaos that happens around here, we had some unexpected annoyance yesterday.Knitting Update2021-07-12T06:35:00-07:002021-07-12T06:35:00-07:00http://amyszczepanski.com/2021/07/12/kntting-update<p>The yarn store has been sending me email. The message is: You bought a sweater’s worth
of yarn about seven months ago and haven’t bought any yarn since then. Aren’t you done
with that sweater by now? Shouldn’t you be buying more yarn? This reminds me of when I
was in grad school and people would ask me how my dissertation was going. Actually,
this is much better than grad school because the sweater is actually coming together
pretty well, and a certain professor will not be examining every single stitch and
making lots of critical comments.</p>
<p>I’m making the <a href="https://www.purlsoho.com/create/2016/10/19/botanical-yoke-pullover/">Botanical Yoke Pullover from Purl Soho</a>. I wasn’t
particularly happy with the way that the neckline looks on the model in the pattern
photo, so I also added some short rows following a pattern for a totally different
sweater.</p>
<p><img src="http://amyszczepanski.com/assets/2021-07-12-sweater.jpg" alt="Sweater in progress" width="600px" /></p>
<p>I’m currently running into two problems making this sweater. No, wait, three.</p>
<p><img src="http://amyszczepanski.com/assets/2021-07-12-sophie.jpg" alt="Sophie on pattern" width="600px" /></p>
<ol>
<li>
<p>Sophie loves to lie on the pattern. Sophie says that I should not consider her to be a
problem. Thus, I will say that the first problem is that 12-over-12 cables are really
annoying.</p>
</li>
<li>
<p>Too many other things to do. I literally spend hours per week watering plants that
are out of range of the sprinkler system. I feel a little bit bad about this because we
are having a drought in California. I’m also having more plants put in later this
summer and am having mixed feelings about that. But some of the new plants are trees,
and parts of my yard really, really, really need the shade. Also in terms of my yard,
at some point I need to go out and rake flowers because jasmine flowers don’t seem to
disintegrate the way that most other flowers do. I also have some tree that has been
dropping yellow flowers to such an extent that I need to rake them or sweep them or
something. And since we don’t have real seasons here, some plant is always dropping
leaves instead of them all being nice enough to do it all at once in the fall.</p>
</li>
<li>
<p>I think that the arms of the sweater are too long. I really struggled to get row
gauge as I was knitting. I have knit and re-knit the sleeves a total of four times (two
sleeves \(\times\) two attempts). I think that they are still wrong. If they turn out
to be only a little bit long at the end, then I am going to ignore that. If they are
just past the point of ignoring, I’m going to unravel from the cuff end and then bind
off with a crochet hook, even though that’s not ideal for ribbing. If they are off
enough that the sleeve shaping is wrong, I’m going to have to remove the bottom third or
half of the sleeve, reknit that part (YET AGAIN) with fewer rows between decreases, and
then kitchener the replacements into place.</p>
</li>
</ol>The yarn store has been sending me email. The message is: You bought a sweater’s worth of yarn about seven months ago and haven’t bought any yarn since then. Aren’t you done with that sweater by now? Shouldn’t you be buying more yarn? This reminds me of when I was in grad school and people would ask me how my dissertation was going. Actually, this is much better than grad school because the sweater is actually coming together pretty well, and a certain professor will not be examining every single stitch and making lots of critical comments.I Have No Idea What the County is Reporting2021-07-11T12:10:00-07:002021-07-11T12:10:00-07:00http://amyszczepanski.com/2021/07/11/i-have-no-idea-what-the-county-is-reporting<p>I was going to spend my weekend knitting, organizing my knitting stuff, and selling
excess knitting stuff. (WOULD YOU LIKE SOME MACHINE KNITTING MAGAZINES FROM THE 1980s?)</p>
<p>However, I have finally gotten irritated at the way that San Diego County is(n’t)
reporting its COVID-19 numbers. It used to be reported daily. I wasn’t entirely happy
with the way that they broke down the data, but it was <em>easy</em> for me to go to their
webpage and see the daily number of new cases. Now that we have decided that the pandemic
is over, they announced that they were only going to update the numbers once a week.
Apparently, they changed their minds, and now they are reporting on weekdays and each
update shows the number of new cases since the previous update – so in order to get
new cases per day, you need to know how many days since the latest update.</p>
<p>No problem, I thought, I will just dust off my old code for getting data from the County’s
API. (Aside: Why does government love ArcGIS so much?) Turns out that the data served by
the API is also updated on the same sporadic schedule (but at least the payload has
dates).</p>
<p>Next up: Checking with the state. You would think that there was <em>someone</em> in the state
of California who could put together a reasonable API. I think that I can get the data
that I need, but it took a lot of digging to find it. The state’s data might also only
be sporadic. I may have to monitor this over the next few days before I make a dedicated
page that I can use to keep track of things.</p>
<p>The state’s data is not great either. I really want to see the case data broken down by
age. I really, really want to know how much I should be annoyed that the new cases are
coming from unvaccinated adults (most of whom should know better) vs. unvaccinated
children (typically not their fault).</p>
<p>While there is a chance that they’d consider binning things by age, there is no chance
that they’re going to break things down by vaccination status (especially since a lot
of people are bad at interpreting numbers). That’s really what I want to know so that I
can decide how much of a risk it is for me to go to Trader Joe’s and the yarn store. I’ve
gotten so frustrated buying yarn online and being disappointed by the colors.</p>
<p>Fun fact about the state API: you send SQL to the endpoint, and it returns the result of
your query. In order to prevent you from doing SQL injection the state merely wraps your
entire query in <code class="language-plaintext highlighter-rouge">SELECT * FROM () AS blah LIMIT 32001</code>. The “blah” is not a placeholder
that I am using here; it is really part of what is processed by the endpoint. There
doesn’t seem to be anything that keeps me from doing some sort of gnarly self-join on
the table, but fortunately, today’s task is simple enough that I won’t accidentally write
a query that grinds their server to a halt. They’re running Postgres 9.6.19, which you
can learn by sending <code class="language-plaintext highlighter-rouge">SELECT VERSION()</code> as your query instead of asking about public
health data.</p>
<div>
<button id="fetch-data">Get Data!</button>
</div>
<div id="covidData"></div>
<script>
document.getElementById("fetch-data").addEventListener("click", async function(){
const response = await fetch("https://data.ca.gov/api/3/action/datastore_search_sql?sql=SELECT%20%2A%20from%20%226a1aaf21-2a2c-466b-8738-222aaceaa168%22%20WHERE%20%22area%22%20LIKE%20%27San%20Diego%27%20AND%20%22date%22%20IS%20NOT%20NULL%20ORDER%20BY%20%22date%22%20DESC%20LIMIT%205");
const stateData = await response.json();
let covidUpdate
if (stateData.success === true) {
const dataArray = stateData.result.records.filter(
entry => parseInt(entry.reported_cases) > 0
);
if (dataArray.length > 1) {
const newCases = dataArray[0].reported_cases;
const recentDate = dataArray[0].date;
const previousDate = dataArray[1].date;
covidUpdate = "<p>The most recent data I can find is from " +
recentDate + ". It says that there were " + parseInt(newCases) +
" new cases since " + previousDate + ".</p>";
} else {
covidUpdate = "<p>Couldn't find trustworthy numbers.</p>"
}
covidUpdate += "<details>" +
"<summary>Look what we got back from the state:</summary>" +
JSON.stringify(stateData.result.records) +
"</details>";
} else {
covidUpdate = "<p>API call was unsuccessful.</p>"
}
covidUpdate;
document.getElementById("covidData").innerHTML = covidUpdate;
});
</script>I was going to spend my weekend knitting, organizing my knitting stuff, and selling excess knitting stuff. (WOULD YOU LIKE SOME MACHINE KNITTING MAGAZINES FROM THE 1980s?)Startups or Trolling?2021-07-05T07:00:00-07:002021-07-05T07:00:00-07:00http://amyszczepanski.com/2021/07/05/startups-or-trolling<p>I’m starting to think that the recruiters might be trolling me, based on how ludicrous
the concepts are for some of these startups. Also, one of them was looking for
“strong Frontend Engineers,” noting “The tech-stack is primarily javascript, but prior
experience is not a must have.”</p>
<p>If you want to experience getting cold emails from recruiters without actually receiving
email, just click the button!</p>
<div>
<button id="generate">Disrupt!</button>
</div>
<div id="yourBusiness"></div>
<script>
document.getElementById("generate").addEventListener("click", async function(){
const companies = [
"Uber",
"Pinterest",
"Facebook",
"Shopify",
"Peloton",
"Slack",
"GitHub",
"PayPal",
"Etsy",
"YouTube",
"Dropbox",
"eBay",
"Clippy",
];
const technologies = [
"video chat",
"SaaS",
"AI",
"blockchain",
"support for legacy APIs",
"CRM",
"content moderation",
"streaming data",
"drag and drop",
"smart watches",
];
const everydayItems = [
"toast",
"dogs",
"health insurance",
"motocycles",
"rechargable batteries",
"intellectual property",
"parking",
"parenting",
"public transit",
"memes",
];
const offlineBusinesses = [
"coffeeshops",
"grocery stores",
"furniture stores",
"banks",
"car dealerships",
"gyms",
"churches",
"airlines",
"stadiums",
];
const businessDepartments = [
"project managemnent",
"human resources",
"warehousing and logistics",
"market research",
"social media marketing",
];
const concepts = [];
const pickRandom = function(optionArray) {
return optionArray[Math.floor(Math.random() * optionArray.length)];
}
const companyForThing = function() {
const companyName = pickRandom(companies);
const things = [
...technologies,
...everydayItems,
...offlineBusinesses,
...businessDepartments
];
const thing = pickRandom(things);
return "" + companyName + " for " + thing;
}
concepts.push(companyForThing);
const companyWithTechnology = function() {
companies.splice(companies.indexOf("Clippy"), 1);
const companyName = pickRandom(companies);
const technology = pickRandom(technologies);
return "" + companyName + " with " + technology;
}
concepts.push(companyWithTechnology);
const solveWithTechnology = function() {
const technology = pickRandom(technologies);
const industry = pickRandom(offlineBusinesses);
const problems = [
...everydayItems,
...businessDepartments
];
problem = pickRandom(problems);
return "using " + technology + " to help " + industry + " with " + problem;
}
concepts.push(solveWithTechnology);
const startupGenerator = pickRandom(concepts);
const yourStartupPitch = startupGenerator();
const nameStartup = async function() {
const response = await fetch("https://random-word-api.herokuapp.com/word?number=1&swear=0");
const wordArray = await response.json();
let firstWord = wordArray[0];
const suffixPredictor = Math.floor(Math.random() * 5);
switch (suffixPredictor) {
case 1:
firstWord += "ly";
break;
case 2:
firstWord += "ful";
break;
}
const startupName = firstWord.charAt(0).toUpperCase() + firstWord.slice(1);
return startupName;
}
const nameManager = async function() {
const response = await fetch("http://namey.muffinlabs.com/name.json?with_surname=true", {mode: "cors"});
const nameArray = await response.json();
return nameArray[0];
}
const startupName = await nameStartup();
const managerName = await nameManager();
const appealToAuthority = [
"Facebook",
"Google",
"Apple",
"Amazon",
"NetFlix",
];
const pastCompany = pickRandom(appealToAuthority);
const recruiterPitch = "<p>I'm reaching out to tell you about an exciting " +
"opportunity. " + startupName +
" is " + yourStartupPitch + ".</p>" +
"<p>Based on your background, I think that you'd be a really good fit for a " +
" role on their team. They are looking for a Senior Software Engineer to " +
"tackle challenges and make a difference. You would report to " + managerName +
" (formerly of " + pastCompany + "), the head of engineering.</p>" +
"<p>Let me know when would be a good time to hop on a call to learn more!</p>";
document.getElementById("yourBusiness").innerHTML = recruiterPitch;
});
</script>I’m starting to think that the recruiters might be trolling me, based on how ludicrous the concepts are for some of these startups. Also, one of them was looking for “strong Frontend Engineers,” noting “The tech-stack is primarily javascript, but prior experience is not a must have.”Solar Panel A/B Testing2021-07-04T07:49:00-07:002021-07-04T07:49:00-07:00http://amyszczepanski.com/2021/07/04/solar-panel-a-b-testing<p>About a week and a half ago I got an email from the electric company called “Energy Use
Alert” letting me know that so far I had used $5.18 worth of electricity during the
billing cycle and that my monthly bill was projected to be somewhere between $8.80 and
$11.90. This email included a helpful tip: “Want to lower your bill? Reduce your
electricity use during On-Peak hours.”</p>
<p>I have a ground-based solar array with 26 panels, and they are filthy. I suspected that
washing the solar panels would do more for my electric bill than avoiding using appliances
at dinner time.</p>
<p>A quick review of the internet told me that <em>solar panel washing is a scam</em>. You should
not pay someone to wash your solar panels because it <em>does not help</em>. Washing solar
panels leads to a 1-2% improvement, maybe 3% if they are really dirty.</p>
<p>This seemed preposterous to me, as there is very obviously a whole bunch of opaque dirt
and bird crap between my solar panels and the sun. I see a daily dip in production when
the earth arranges itself so that there is a tree between the solar panels and the sun,
and the tree is not particularly large nor particularly near the solar panels. Temporary
tree-shade is a bigger problem than persistent dirt?</p>
<p>This, of course, meant that I needed to test my hypothesis. I got some distilled water and
a window-washing doohickey and started washing half the panels. Sadly, I am not tall
enough to reach all of them, so I ended up washing almost a third of the panels.</p>
<p><img src="http://amyszczepanski.com/assets/2021-07-04-solar.jpg" alt="Solar panels" width="600px" /></p>
<p>In order to compare the performance of the washed ones to the unwashed ones, I did my
split as a checkerboard because it would be a bad idea to only wash the ones that are
shaded by the tree. I washed them on June 30, so the July report for energy produced
to date is going to give a good sense of the difference in production between the clean
panels and the dirty ones. I’ve circled the clean ones.</p>
<p><img src="http://amyszczepanski.com/assets/2021-07-04-solar-clean.png" alt="Solar panel production" width="600px" /></p>
<p>The sample size is small enough that I’m not going to bother to calculate a confidence
interval for how much better the clean ones are doing than the dirty ones. Back of the
envelope, I’m pretty comfortable saying that I’m seeing a roughly 5% improvement in
production due to cleaning. The best improvment from dirty -> clean come from the
part of the array that doesn’t get shaded by the tree.</p>
<p>Like many good A/B tests, I have a pretty strong takeaway here: I need to get out the
ladder and clean the rest of the solar panels.</p>About a week and a half ago I got an email from the electric company called “Energy Use Alert” letting me know that so far I had used $5.18 worth of electricity during the billing cycle and that my monthly bill was projected to be somewhere between $8.80 and $11.90. This email included a helpful tip: “Want to lower your bill? Reduce your electricity use during On-Peak hours.”How to Use a Google Service Account for Google Sheets API with Node Without Using Environment Variables2021-06-24T20:11:00-07:002021-06-24T20:11:00-07:00http://amyszczepanski.com/2021/06/24/how-to-use-a-google-service-account-for-google-sheets-API-with-node-without-using-environment-variables<p>It’s time for the important tech content that is part of being a serious software
professional with a blog. It’s an amazing coincidence that recruiters are reaching
out to me about jobs using React and Node.js – the exact same stack that is used
by the team that I am on!</p>
<p>Since I am not a recipe blogger, I am not going to hide the important stuff at the
end, after my personal story. If you are using a service account and not OAuth2 to
authenticate to the Google Sheets API, the standard advice is to put the location of
the credential into an environment variable. Which is ok, I guess, for just fussing
around on your laptop but is never going to fly in production. I need the credential
to be in a config file.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">getAuthToken</span> <span class="o">=</span> <span class="k">async</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">auth</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">google</span><span class="p">.</span><span class="nx">auth</span><span class="p">.</span><span class="nx">GoogleAuth</span><span class="p">({</span>
<span class="na">keyFile</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/path/to/credential.json</span><span class="dl">"</span><span class="p">,</span>
<span class="na">scopes</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">https://www.googleapis.com/auth/spreadsheets</span><span class="dl">"</span><span class="p">],</span>
<span class="p">});</span>
<span class="kd">const</span> <span class="nx">authToken</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">auth</span><span class="p">.</span><span class="nx">getClient</span><span class="p">();</span>
<span class="k">return</span> <span class="nx">authToken</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>This has been working for me. I think I found it suggested in one of the READMEs in
the GitHub repo for the npm library for the Google APIs. I hunted a very long time before
I found it, and based on what I saw in the various dead ends that I encountered along
the way, I am not the first person to have been in this situation.</p>
<p>Back to our meandering and pointless narrative.</p>
<p>As has been a theme at work lately, people want decisive business information reported
to them in spreadsheets. Not to brag, but the number of KPIs that we have has been
taking off like a rocketship!!! Thus, I spent the past few days making a reporting tool
in Node and React where you enter some information on a page and click a button and
BOOM! the data you want magically appears in a Google Sheet.</p>
<p>Do you want to use Node to make your own Google Sheets reporting tool? The first thing
that you need to do is to read <a href="https://hackernoon.com/how-to-use-google-sheets-api-with-nodejs-cz3v316f">this blog post</a> by
Mandeep Singh Gulati who figured it out and did a really good job of writing it up.
I found this to be about a thousand times more useful than Google’s documentation of
the Sheets API. Admitedly, I’ve never been particularly impressed by Google’s
documentation of their APIs, but the Sheets API is really well documented! But the
blog post that I linked to is still way, way better. Read that blog post and refer to
the documentation and you will also be well on your way to having a fullstack JavaScript
reverse ETL pipeline (or whatever).</p>
<p>The other thing that I missed upon my first reading of the documentation is that the
request body is an object named <code class="language-plaintext highlighter-rouge">resource</code>. So if you are writing
<code class="language-plaintext highlighter-rouge">[["hi", "from"], ["my", "spreadsheet"]]</code> to some cells of your spreadsheet, you would
do something like</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Assume that you already have the spreadsheetId and auth</span>
<span class="kd">const</span> <span class="nx">request</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">spreadsheetId</span><span class="p">,</span>
<span class="nx">auth</span><span class="p">,</span>
<span class="na">valueInputOption</span><span class="p">:</span> <span class="nx">USER_ENTERED</span><span class="p">,</span>
<span class="na">range</span><span class="p">:</span> <span class="dl">"</span><span class="s2">B1:C2</span><span class="dl">"</span><span class="p">,</span>
<span class="na">resource</span><span class="p">:</span> <span class="p">{[[</span><span class="dl">"</span><span class="s2">hi</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">from</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">my</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">spreadsheet</span><span class="dl">"</span><span class="p">]]}</span>
<span class="p">};</span>
<span class="kd">const</span> <span class="nx">response</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">sheets</span><span class="p">.</span><span class="nx">spreadsheets</span><span class="p">.</span><span class="nx">values</span><span class="p">.</span><span class="nx">update</span><span class="p">(</span><span class="nx">request</span><span class="p">);</span>
</code></pre></div></div>
<p>When it comes to the React side of things, you are on your own. Since React is made out
of magic and lets you do silly things, I did silly things. For example, when you click
the button that sets off this entire process and runs a bunch of database queries before
sending the results to Google Sheets, I take away the button. That is right, the mere
act of clicking the button makes it go away until the data has landed in the sheet. You
can not keep clicking and clicking and clicking while you wait because the button <em>is
not there anymore</em>. This is why React is a valuable part of your analytics pipeline.</p>
<p>Speaking of KPIs, the mere act of creating an empty page with a button in React took
about 100 lines of boilerplate spread out across six files – before the button even
did anything!</p>It’s time for the important tech content that is part of being a serious software professional with a blog. It’s an amazing coincidence that recruiters are reaching out to me about jobs using React and Node.js – the exact same stack that is used by the team that I am on!