<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://naitian.org/blog">
	<title>Naitian&#39;s Blog</title>
	<subtitle>I write things sometimes, and you can read them.</subtitle>
	<link href="https://naitian.org/feed.xml" rel="self" />
	<link href="https://naitian.org/blog" />
	<updated
		>2025-06-05T23:35:03Z</updated
	>
	<id>https://naitian.org/blog</id>
	<author>
		<name>Naitian Zhou</name>
		<email>blog@naitian.org</email>
	</author>
	<entry>
		<title>Cultural collapse</title>
		<link href="https://naitian.org/blog/cultural-collapse/" />
		<updated>2024-08-16T00:00:00Z</updated>
		<id>https://naitian.org/blog/cultural-collapse/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;p&gt;There has been a bit of talk about model collapse, spurred by this &lt;a href=&quot;https://rdcu.be/dO9nC&quot;&gt;Nature
paper&lt;/a&gt; that was published a few weeks ago.  The paper
demonstrates some theoretic and empirical results about how training new models
from data generated by previous iterations of the model can result in degenerate
models.&lt;/p&gt;&lt;p&gt;There&#39;s been a fair amount of criticism of this paper, mainly centering on the
fact that the conditions tested in the paper don&#39;t really reflect the way
synthetic data is used to train models in the real world.&lt;/p&gt;&lt;p&gt;I&#39;m not particularly worried about the potential of model collapse. There&#39;s lots
of active research on how we can make use of synthetic data, and post-filtering
seems like a tractable and valid way of avoiding some degenerate cases. What
I&#39;ve been thinking about more is a sociotechnical problem: the influx of
AI-generated content may not be harmful for training future models, but I worry
that the reification of content generated by models that only have the
shallowest conception of meaning can result in an ecosystem in which cultural
artifacts are slowly leached of any depth. Model collapse doesn&#39;t bother me as
much as the potential of &lt;em&gt;cultural collapse&lt;/em&gt;&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;Maybe this term is a little
hyperbolic, but counterpoint: maybe not?&lt;/span&gt; does.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Layers of meaning&lt;/h2&gt;&lt;p&gt;Culture is a fuzzy object. I approach culture as socially negotiated meanings of
signs. Since I work on language (broadly defined), let&#39;s first consider how this
definition plays out in language as a cultural artifact. At the most basic
level, we consider words (signs) to have referential meanings. The word &quot;dog&quot;
evokes some conception in your mind of the four-legged mammal that wags its tail
and barks.&lt;/p&gt;&lt;p&gt;But there are other kinds of meaning as well: there is the social meaning about
regional identity embedded when someone, for instance, says &quot;pop&quot; instead of
&quot;soda&quot;.&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://www.popvssoda.com/&quot;&gt;https://www.popvssoda.com&lt;/a&gt;&lt;/span&gt; There is
meaning in interaction: it is &lt;em&gt;meaningful&lt;/em&gt; to respond to a question with
silence, even though no words were ever uttered. And speech is not only
referential, but performative. Uttering &quot;I do&quot; can marry a couple; saying &quot;I bet
you it will rain tomorrow&quot; initiates the wager (if the interlocutor
accepts).&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;These examples are from J. Searle, &lt;em&gt;How to do things with Words&lt;/em&gt;.&lt;/span&gt;
There is even meaning embedded in the way we dress&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://web.stanford.edu/~eckert/PDF/IndexicalField.pdf&quot;&gt;Penelope Eckert, &lt;em&gt;Variation and
the Indexical Field&lt;/em&gt;&lt;/a&gt;&lt;/span&gt; and the make-up we apply.&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://www.tandfonline.com/share/8WVWJY67PXVBAJT62RSI?target=10.1080/00141844.1996.9981527&quot;&gt;Norma Mendoza-Denton, &lt;em&gt;Muy
Macha&lt;/em&gt;&lt;/a&gt;&lt;/span&gt;
Within all of these semiotic fields, there is structure and meaning.&lt;/p&gt;&lt;p&gt;If there are multiple aspects of meaning, what kind of meaning do language
models learn? They are built on the idea of distributional semantics: words take
on meaning by how they relate to other words. Food is the set of things that you
&quot;eat&quot;. Eating is what you do to &quot;foods&quot;. This relational system of meaning is
internally useful for the model, and generally maps on relatively well to how we
interpret language, but the meaning making for &lt;em&gt;us&lt;/em&gt; happens when we read the
tokens that the model outputs. It&#39;s at that point that we decide that &quot;dog&quot;
means the same thing to the LLM as it does to you and I.&lt;/p&gt;&lt;p&gt;This is pretty effective in practice, and I find distributional semantics to be
a pretty compelling approach to understanding meaning. But it&#39;s worth
considering also what aspects of meaning &lt;em&gt;aren&#39;t&lt;/em&gt; learned in this scheme.
Introductions of distributional semantics often quote computational linguist
John Firth&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://cs.brown.edu/courses/csci2952d/readings/lecture1-firth.pdf&quot;&gt;Firth, &lt;em&gt;A Synoposis of Linguistic
Theory&lt;/em&gt;&lt;/a&gt;&lt;/span&gt; as
saying &quot;You shall know a word by the company it keeps.&quot; But in that section, he
explains that &lt;em&gt;collocational&lt;/em&gt;&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;A word&#39;s appearance in relation to other words.&lt;/span&gt;
meaning is but one aspect of meaning, and that collocation should not be
mistaken for context, which is sociocultural. Meaning takes place across words,
but also all kinds of other signs. Modern systems are learning
aspects of meaning that are largely removed from socialcultural context!&lt;/p&gt;&lt;p&gt;What&#39;s concerning is that, for the most part, companies developing AI products
are okay with this. At minimum, there is a lack of critical engagement with how
language can construct power dynamics and social structure: to build systems
that serve a particular language variety means neglecting the diversity of other
ones. And this is not just hypothetical. Studies have shown, for example, that
speech recognition technology works much worse for Black English speakers than
white ones.&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://fairspeech.stanford.edu/&quot;&gt;Koenecke et al., &lt;em&gt;Racial disparities in automated speech
recognition&lt;/em&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;What is perhaps more insidious, I think, is when people build these systems to
&lt;em&gt;engage&lt;/em&gt; with culture. Like this startup whose ad was floating around the
internet a little bit ago:&lt;/p&gt;&lt;figure&gt;
&lt;img src=&quot;https://naitian.org/assets/img/book_startup.png&quot; alt=&quot;A screenshot of an ad on Reddit for a service that uses AI to produce summaries of books. The advertisement reads &amp;#x27;Turn hard books into easy books with Magibook! Maximize your reading potential and avoid difficult language today.&amp;#x27; It then shows an example from The Great Gatsby, where simplifies a sentence. The original sentence is &amp;#x27;In my younger and more vulnerable years, my father gave me some advice that I&amp;#x27;ve been turning over in my mind ever since.&amp;#x27; The simplified sentence is &amp;#x27;When I was young, my dad told me something that I still think about.&amp;#x27;&quot; /&gt;
&lt;/figure&gt;&lt;p&gt;What bothers me isn&#39;t even the product necessarily; there are instances where
simplifying text might be useful! But I object to the problematization of
&quot;difficult language&quot;, and especially to the implication that your reading
potential is measured by the number of book summaries you can ingest. What
aspects of meaning are we losing when we focus solely on the plot? Language is
meaningful, and we need to be intentional about which aspects of meaning we keep
and which we discard.&lt;/p&gt;&lt;p&gt;This temptation to boil everything down to the essence reflects a total
misunderstanding of the point of the exercise in creating and consuming culture.
In trying to distill the plot, we may have lost it altogether.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The nature of the enterprise&lt;/h2&gt;&lt;p&gt;So what are we trying to do here? Recently, there was an ad for Google Gemini
that caught some viewers off guard. A father asks Gemini to write a fan letter
on behalf of his daughter.&lt;/p&gt;&lt;figure&gt;
&lt;iframe width=&quot;100%&quot; style=&quot;aspect-ratio: 16/9&quot; src=&quot;https://www.youtube.com/embed/NgtHJKn0Mck&quot; title=&quot;Google + Team USA — Dear Sydney&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/figure&gt;&lt;p&gt;To many people, myself included, this seems to miss the point of writing a fan
letter entirely. But why? Pegah Moradi, a PhD student at the Cornell I-School,
wrote an excellent piece about the &lt;em&gt;autopen&lt;/em&gt;, the machine that can replicate
signatures.&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://ijoc.org/index.php/ijoc/article/view/21842/4466&quot;&gt;Moradi and Levy, &lt;em&gt;&quot;A Fountain Pen Come to Life&quot;: The Anxieties of
the Autopen&lt;/em&gt;&lt;/a&gt;&lt;/span&gt; In the
essay, she covers three cases in which use of the autopen elides &lt;em&gt;social values&lt;/em&gt;
that we attach to the &lt;em&gt;act&lt;/em&gt; of creating a signature: authenticity,
accountability, and care.&lt;/p&gt;&lt;p&gt;That is to say, the shape of the signature doesn&#39;t contain the meaning, but
rather what the signature signifies. And this signified meaning comes because we
have historically agreed on the cultural significance of a signed name. To
mechanically create or recreate the signature outside of that context reduces
its meaning. To generate a letter removes the labor of care that gives the
letter meaning in the first place. The &quot;grammar&quot; of the fan-mail ritual requires
the work that goes into constructing the letter; to remove that work results in
a semantically vacuous interaction.&lt;/p&gt;&lt;p&gt;Google&#39;s assertion that generating this letter is equivalent (or preferable,
even) to the act of writing one is an erasure of the richness of cultural
meaning that gives the ritual of fan-mail its significance. It reifies the idea
that culture is reduced to the tokens which comprise the artifact; culture
becomes a decontextualized facsimile of itself. This is what I mean by cultural
collapse.&lt;/p&gt;&lt;p&gt;In my opinion, the point of writing, of art, of creating and consuming culture,
is to &lt;em&gt;create&lt;/em&gt; meaning, not to transmit it. I write these words not with the
hope that you will think my thoughts, but that they will play a role in
inspiring your own.&lt;/p&gt;&lt;p&gt;I don&#39;t mean to suggest that culture and computation are mutually exclusive.
My own research is all about computationally studying these other aspects of meaning
-- for example, what are the different meanings contained in condolence-giving&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://naitian.org/blog/cultural-collapse/#&quot;&gt;Zhou and Jurgens, &lt;em&gt;Condolence and Empathy in Online Communities&lt;/em&gt;&lt;/a&gt;&lt;/span&gt; or embedded in the meme templates that we choose
to use on Reddit?&lt;label for=&quot;undefined&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;undefined&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://naitian.org/social-memeing&quot;&gt;Zhou, Jurgens and Bamman, &lt;em&gt;Social
Meme-ing&lt;/em&gt;&lt;/a&gt;&lt;/span&gt;
In fact, this kind of work has really been &lt;em&gt;enabled&lt;/em&gt; by the great progress in
NLP and computer vision. But culture as it exists around is incredibly rich with
layers and layers of meaning, and we need to think critically about which
meanings we are computing on, and which we are ignoring.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Shaky writing</title>
		<link href="https://naitian.org/blog/shaky-writing/" />
		<updated>2024-06-04T00:00:00Z</updated>
		<id>https://naitian.org/blog/shaky-writing/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;It&#39;s been a minute.&lt;/h2&gt;&lt;p&gt;I recently received a kind email from a reader who asked me how things are
going.
This was a pleasant reminder that others actually read my writing, and a less
pleasant reminder that it &lt;em&gt;has&lt;/em&gt; been a while since I&#39;ve posted on this blog.&lt;/p&gt;&lt;p&gt;This hiatus hasn&#39;t been due to a lack of inspiration; in fact, there&#39;s been a
lot on my mind recently about grad school, my research, and what it means to
&quot;study culture&quot; empirically. I have wanted to write about all of these things.
So what gives?&lt;/p&gt;&lt;p&gt;I think, since starting my PhD, my relationship to writing has changed a bit. In
the past, I assigned very little stakes to the writing that I put out (in fact,
this wasn&#39;t really something that I thought about.)
But now I feel much more ownership of my words and ideas and, with that
ownership, a greater pressure to only share the good ones.&lt;/p&gt;&lt;p&gt;Perhaps I am placing too much value on this blog, but I would like to use this
platform to discuss ideas that I find meaningful. To an extent, I think this
&lt;em&gt;does&lt;/em&gt; warrant a deeper, more critical level of engagement with what I am
writing.&lt;/p&gt;&lt;p&gt;On the other hand, when I&#39;ve started drafting posts, I&#39;ve found myself paralyzed
by indecision or talking myself into knots. I am compelled to endlessly
explicate, constantly contextualize; I find myself exhausted, paragraphs deep,
and no closer to making my point. I need to make my peace with the fact that
discourse is ambiguous, messy, and interpretive. I can&#39;t expect to fit an entire
discourse into a single turn, so I need to just put my thoughts out there and
start talking.&lt;/p&gt;&lt;p&gt;I&#39;ve recently begun reading &lt;em&gt;The Archaeology of Knowledge&lt;/em&gt;. At the end of the
introduction, Foucault talks about writing with uncertainty:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;What, do you imagine that I would take so much trouble and so much pleasure
in writing, do you think that I would keep so persistently to my task, if I were
not preparing – with a rather shaky hand – a labyrinth into which I can venture,
in which I can move my discourse, opening up underground passages, forcing it to
go far from itself, finding overhangs that reduce and deform its itinerary, in
which I can lose myself and appear at last to eyes that I will never have to
meet again.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;And so too shall I proceed, hands shaky, into the labyrinth.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Reflections 2022</title>
		<link href="https://naitian.org/blog/reflections-2022/" />
		<updated>2023-01-02T00:00:00Z</updated>
		<id>https://naitian.org/blog/reflections-2022/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;New Year, New Me.&lt;/h2&gt;&lt;p&gt;I look forward to writing these every year, because time just flies by and I
don&#39;t have much chance to take a step back and let life sink in. I am
particularly savoring the opportunity this year because it has been an eventful
one.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/reflections-2022/#this-year-in-numbers&quot;&gt;This Year in Numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/reflections-2022/#highlights&quot;&gt;Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/reflections-2022/#reflections&quot;&gt;Reflections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;This Year in Numbers&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;250&lt;/strong&gt; Github contributions (back on the decline, but that&#39;s ok)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;700&lt;/strong&gt; miles ran (including 1.5 marathons!)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;324&lt;/strong&gt; New York Times daily crosswords completed&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; musical attended (&lt;em&gt;Jagged Little Pill&lt;/em&gt; at the Golden Gate Theatre)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; cap and gown 🎓&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Highlights&lt;/h2&gt;&lt;p&gt;This was the first &lt;strong&gt;January&lt;/strong&gt; in 16 years that I did not have any classes. A
short-lived respite; my classes start again next Tuesday. I ran 79 miles and
got my first PhD program acceptances. Also found out about Wordle (what a
moment that was.)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;February&lt;/strong&gt;, though short, was also eventful. I ran 79 miles, got my first
Covid booster, and traveled to Madison, WI. It is a neat city with pretty
buildings, a cool art museum, and a lake that you can walk on! Towards the end
of the month, I flew out to LA with some friends, which leads us into...&lt;/p&gt;&lt;p&gt;&lt;strong&gt;March&lt;/strong&gt; was the month of travel for me. I ran 106 miles, including my first
half marathon, and flew for probably a few thousand more. It started out with
the LA trip; we went to Joshua Tree (who knew the desert could be so pretty),
Pomona (who knew a college campus could be so pretty), and the Academy Museum
of Motion Pictures (who knew Studio Ghibli films could be so pretty&lt;label for=&quot;ghibli&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;ghibli&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;(A lot of people, actually)&lt;/span&gt;).
March was also the month of grad school visits, so a week after getting back
from Los Angeles, I flew out to Switzerland for the EPFL visit days (and for
Switzerland). It was a really great experience, and the entire country is so
picturesque. After Lausanne, I visited Jungfraujoch and Zurich. The day after
returning from Zurich, I drove to Ithaca with my parents to visit Cornell. It
was gorges, and snowy, even by my Michigan standards. Two days later, I flew
out to Berkeley, CA, which had neither gorges nor snow, but did have some
beautiful sunsets.&lt;/p&gt;&lt;p&gt;By comparison, &lt;strong&gt;April&lt;/strong&gt; was a bit more relaxed. I walked for graduation and
ran 148 miles.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;May&lt;/strong&gt; was the same way, largely spent in Ann Arbor and at home, just taking a
break and running (for 157 miles). I did, however, spend about a week immersing
myself in Hayao Miyazaki&#39;s directorial oeuvre: I watched, in the following
order, &lt;em&gt;The Wind Rises&lt;/em&gt;, &lt;em&gt;Lupin III&lt;/em&gt;, &lt;em&gt;Nausicaä&lt;/em&gt;, &lt;em&gt;Laputa&lt;/em&gt;, &lt;em&gt;Totoro&lt;/em&gt;, &lt;em&gt;Porco
Rosso&lt;/em&gt;, &lt;em&gt;Princess Mononoke&lt;/em&gt;, &lt;em&gt;Spirited Away&lt;/em&gt;, &lt;em&gt;Howl&#39;s Moving Castle&lt;/em&gt;, and
&lt;em&gt;Ponyo&lt;/em&gt;. I had watched &lt;em&gt;Kiki&#39;s Delivery Service&lt;/em&gt; a few months earlier, in LA.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;June&lt;/strong&gt;, I went backpacking for the first time, hiking around 20 miles in
two days. In the future, I will bring more camp activities and spend less time
walking. It was also the month of the Banff Marathon, which I had been training
for the whole month. My parents and I flew up to Banff (absolutely stunning),
where we visited Lake Louise, picked up my packet, and prayed for the rain to
go away. The race was a totally unique experience; I saw several rams along the
route, and it was just breathtaking the whole way through&lt;label for=&quot;breath&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;breath&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;Which, granted, is not idea for aerobic activities.&lt;/span&gt;. After the
race, I limped all the way to Seattle, where I visited some friends.&lt;/p&gt;&lt;p&gt;I officially moved out of my room in Ann Arbor in &lt;strong&gt;July&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;August&lt;/strong&gt;, I moved to California and started school. There&#39;s a lot to say
about that, but I will leave it at that for now.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;September&lt;/strong&gt; and &lt;strong&gt;October&lt;/strong&gt; flew by. I got my California ID, my parents came
to visit, and I submitted another GRF application (second times the charm??)&lt;/p&gt;&lt;p&gt;I saw &lt;em&gt;Jagged Little Pill&lt;/em&gt; with Isabelle in &lt;strong&gt;November&lt;/strong&gt;. We also went on a
hike in Marin (that lasted a bit longer than expected...). I celebrated my 23rd
birthday (oh my god) and went on strike. For Thanksgiving, I flew to Seattle to
visit some friends and we took a weekend trip to Portland (also a great city,
with a massive bookstore.) Michigan won The Game. I took the Amtrak back from
Seattle (unfortunately, most of the trip was in the dark) and continued strike
action.&lt;/p&gt;&lt;p&gt;And finally, in &lt;strong&gt;December&lt;/strong&gt;, I came home for the first time since I left for
California. I watched the World Cup finals with my dad, who is a massive futbol
fan. Now I am sitting on the couch, into the last week of break, wondering
where all the time went.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Reflections&lt;/h2&gt;&lt;p&gt;I&#39;ve had a harder time writing this post than in previous years. Last year, I
wrote&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&quot;I&#39;m temporarily stuck looking ahead into a bright cloud of complete uncertainty.&quot;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;In many ways, much of that uncertainty is gone. This time last year, I didn&#39;t
know where I would be living in a year. Now, I know where I will be for the
next five or six.&lt;/p&gt;&lt;p&gt;But, like a new pair of shoes, I have stepped into a new life in which I&#39;m not
yet comfortable. There is the nagging rigidity of preformed expectations: the
program milestones I need to achieve, the ideas I had about what grad school
would be like, and what I thought my twenties would entail. At the same time,
it feels alien: moving to a new place, adopting a new habits. Right now it
feels like an awkward fit, not yet broken in.&lt;/p&gt;&lt;p&gt;I have a pretty good idea now of what the next few years will be like -- of
what I will be doing and where I will be. The Berkeley iSchool has a pretty
comprehensive guide on the timeline to do a PhD. But in between those
milestones will be thousands of ephemeral moments (and a handful of defining
ones) that are entirely unknown to me, and it is those that I look forward to
the most. These moments are the wrinkles and creases and scratches of a
well-worn shoe that shape it snugly around my feet.&lt;/p&gt;&lt;p&gt;Breaking in a new pair of shoes can be frustrating and sometimes painful. I am
not the most patient person. I find myself sometimes yearning for the
comfortable, lived-in, familiar past. But I know that this feeling will
diminish with time, as I settle into the rhythms of this new part of my life.
There&#39;s no other way to break in a shoe than to just start walking.&lt;/p&gt;&lt;p&gt;So happy new year. I guess I&#39;ll get going now.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>How to ask questions at grad visits</title>
		<link href="https://naitian.org/blog/grad-interviews/" />
		<updated>2022-12-27T00:00:00Z</updated>
		<id>https://naitian.org/blog/grad-interviews/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;p&gt;Grad school visit days are an opportunity to learn more about your potential
advisor and school. You&#39;ll need to make some tough decisions in the near future
about where to attend, and you&#39;re going to want as much data to make this
decision as possible.&lt;/p&gt;&lt;p&gt;This past semester, I took a qualitative methods class&lt;label for=&quot;1&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;1&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;A fascinating course, because I come from a very quantitative background.&lt;/span&gt;, where we learned about
conducting interviews. Here are a few tips from that course which I wish I&#39;d
known when I was talking to professors and grad students&lt;label for=&quot;2&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;2&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;These are just tips for getting better information, but don&#39;t stress out about following these to the tee (or even following them at all)!&lt;/span&gt;.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Interview Strategies&lt;/h2&gt;&lt;p&gt;You want to know what your life will be like at school X working with professor
Y for the next four to six years. How do you get that data? In this case, you
ask others about their experiences, and use that to inform your mental model.&lt;/p&gt;&lt;p&gt;But question-asking is a lossy information transfer. People frequently forget
to mention things, make ambiguous statements, or have trouble putting their
thoughts into words. It is your task to aid them in this process, so that the
information you receive is a faithful interpretation fo their experience.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;1. Be prepared&lt;/h2&gt;&lt;p&gt;It&#39;s best to have a rough plan going in. Come up with a couple of themes that
you want to cover and some questions you want ask. When I was talking to
current PhD students, I usually asked about their experience working with X
advisor, living in Y city, working in Z university. I would also ask them how
they decided where to attend &lt;label for=&quot;3&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;3&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;This last question usually yielded insightful responses.&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;Remember, though, that this is just a guide, and the nature of an interview is
organic. So, it is best to have these questions and themes at the back of your
mind as you have a &lt;em&gt;conversation&lt;/em&gt; with whoever you are talking to.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;2. Be specific&lt;/h2&gt;&lt;p&gt;Sometimes it is tempting to ask broad questions, since it is hard to know what
specific questions to ask. This makes sense! After all, you have never done a
PhD (and possibly never even gone to grad school), so how would you know what
it is you want to find out?&lt;/p&gt;&lt;p&gt;However, broad questions elicit broad answers, and vivid, detailed
answers are more useful for you.&lt;/p&gt;&lt;p&gt;So instead of asking a question like&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&quot;What don&#39;t you like about X University?&quot;,&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;try asking something more specific like&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&quot;What are some logistical frustrations about being at X?&quot;.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Or even better, ask about &lt;em&gt;specific experiences&lt;/em&gt;, like&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&quot;Can you tell me about a recent time when you felt frustrated by some logistics at X?&quot;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;In general, if you can ask about experiences, those will result in the richest
descriptions, since people can draw on their memories instead of trying to
generalize.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;3. Ask follow-ups&lt;/h2&gt;&lt;p&gt;Another way to get richer answers is to follow up on anything you find
ambiguous, or that you&#39;d like to learn more about. This may seem obvious, but
for me, this is actually quite challenging, because you need to quickly
synthesize what they said and respond.&lt;/p&gt;&lt;p&gt;It might be helpful to think of some likely follow-ups when preparing -- this
will also serve as practice for coming up with follow-ups. You might also want
to note down what follow-up questions you thought of in previous interviews or
visits, so that you have them top of mind in the future.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;4. Be creative&lt;/h2&gt;&lt;p&gt;Though meeting in a coffee-shop or on Zoom might be the easiest, it might not
be the most effective setting. If you&#39;re visiting on campus, consider maybe
doing a &quot;walking interview&quot; through campus or meeting in the office space. This
might trigger certain memories, experiences or anecdotes that people may forget
to mention otherwise.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;5. Take notes&lt;/h2&gt;&lt;p&gt;Remember to remember! It can be hard to have a conversation while scribbling
down notes, so I recommend jotting down some thoughts after the meeting
instead. It will still be fresh enough for you to remember the important
points, and this allows you engage more actively in the conversation instead of
trying to multitask.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Concluding thoughts&lt;/h2&gt;&lt;p&gt;When I was going around doing visits, I had a rough idea of the things I wanted
to know about, but the questions I asked often resulted in the same set of
general, surface-level answers.&lt;/p&gt;&lt;p&gt;Hopefully, with some of these tips, you can be better prepared to have deeper
conversations that result in more informative answers. But don&#39;t miss the
forest for the trees! The important thing is that you are meeting with people
and learning about the campus and surroundings in a way that is comfortable for
&lt;em&gt;you&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;So if the strategies I&#39;ve mentioned provide some helpful guidance for you,
great! But if they seem awkward or difficult to implement, don&#39;t worry about
it. Just do what feels good for you.&lt;/p&gt;&lt;p&gt;I think interviews and visits two of my favorite parts of the application
process. I had some insightful and inspiring conversations. I hope you enjoy
this process as well. Good luck and have fun!&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>The 600 Mile Marathon</title>
		<link href="https://naitian.org/blog/banff-marathon/" />
		<updated>2022-06-23T00:00:00Z</updated>
		<id>https://naitian.org/blog/banff-marathon/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Starting at the finish line&lt;/h2&gt;&lt;p&gt;I ran the Banff Marathon on Sunday, June 19th. I finished in 4 hours and 11 minutes, but the race was the culmination of a training effort that took months. It was the most difficult thing I have ever done.&lt;/p&gt;&lt;!-- [^1] --&gt;&lt;!-- [^1]: Just a quick note: I wrote this without a real plan of what I wanted to say. While I think there&#39;s a nice chord progression into a key change at the end, it also means the impact is in the last section. So even though I want you to read the whole thing (of course), you should definitely at the very least read the last part. --&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/banff-marathon/#starting-at-the-start-or-why-i-did-this-to-myself&quot;&gt;Starting at the start (or why I did this to myself)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/banff-marathon/#the-journey-not-the-destination&quot;&gt;The journey, not the destination&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/banff-marathon/#finishing-past-the-finish-line&quot;&gt;Finishing past the finish line&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Starting at the start (or why I did this to myself)&lt;/h2&gt;&lt;p&gt;I graduated a semester early, so I was searching for something to fill up my extra time. Having just submitted my grad school applications in December, I decided to run a marathon, an ambitious undertaking that is &lt;a href=&quot;https://ristretto.black/what-if-your-phd-didnt-need-to-feel-as-long-and-tiring-as-a-marathon/&quot;&gt;frequently&lt;/a&gt; &lt;a href=&quot;https://twitter.com/ithinkwellHugh/status/751408154936684544?s=20&amp;#x26;t=N5UJeAY-fmFUgdu_69YGYA&quot;&gt;compared&lt;/a&gt; &lt;a href=&quot;https://www.theguardian.com/higher-education-network/2016/apr/06/doing-a-phd-is-as-tough-as-training-for-a-marathon-and-im-doing-both&quot;&gt;to a&lt;/a&gt; certain other one that &lt;a href=&quot;https://naitian.org/blog/why-phd/&quot;&gt;I recently committed to&lt;/a&gt;&lt;label for=&quot;phd&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;phd&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://naitian.org/blog/why-phd/&quot;&gt;&lt;em&gt;Why do I want to do a PhD?&lt;/em&gt;&lt;/a&gt;&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;A natural-born athlete, I am not. I was on the track team in high school, but
as a pole vaulter so I could minimize the amount of running to about 60 feet at
a time. I tried and failed to pick up distance running as a hobby multiple
times in the past. Being a runner was something I had always aspired to, but
never actually achieved.&lt;/p&gt;&lt;p&gt;I wanted to run because it seemed like a cheap&lt;label for=&quot;cheap&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;cheap&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;It turns out running shoes are not cheap.&lt;/span&gt;, healthy&lt;label for=&quot;healthy&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;healthy&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;It turns out it&#39;s pretty common to get injured running.&lt;/span&gt;
activity that I could do anywhere. But more importantly, I wanted to run to
prove to myself that I could. I figured the push to a marathon finish would
yield some amount of self-discipline and other useful lessons I could take with
me as I started my PhD in the fall.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The journey, not the destination&lt;/h2&gt;&lt;p&gt;Having explicitly decided to run a marathon as a character-building exercise,
here are the character-building lessons I learned in the process (in no
particular order):&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;There will always be bad miles.&lt;/strong&gt; It&#39;s impossible to run a lot and feel
good about every mile. The bad runs -- the ones that were slow or painful or
just felt harder than they &lt;em&gt;should&#39;ve&lt;/em&gt; -- are inevitable. Just accept it and
look forward to the next run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Take time off to recover.&lt;/strong&gt; I was guilty of not doing this enough in my
training block, which resulted in the knee injury I&#39;m hobbling around with
now. It&#39;s tempting to stick to the schedule, especially when there&#39;s a set
deadline, but that can lead to worse injuries and worse performance in the
future.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be consistent, but be flexible.&lt;/strong&gt; I traveled a lot in March and April
visiting grad schools. My schedule was all over the place, and I frequently
had flights on days I was supposed to run. This meant I had to shift my
training around to accommodate. That can be difficult because I was leaning
heavily on a set training plan to make up for my lack of experience, but it
also meant I got to go on some very scenic runs in Switzerland and Ithaca
and Berkeley (with lots of hill running).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run your own race.&lt;/strong&gt;  I&#39;m a competitive person, and I feel the strong
temptation to pass people, but I had to learn to run at my own pace. Getting
a running watch helped me to keep my own time, but I also learned to accept
that everyone is training at different levels. I set a time goal I&#39;d
personally be happy with and focused on that instead of comparing myself to
others.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lean on your support network.&lt;/strong&gt; Having (and finding) a community also
helped me a lot. My friends helped me so much with encouragement and general
enthusiasm for my plan, and the broader running community is so supportive
and willing to share knowledge with runners at all levels.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;Just keep running.&quot;&lt;/strong&gt; When push came to shove and I was feeling all sorts
of pain at mile 24 of the race, I knew I had to just push myself to run to
the finish. For the last 2k of the race, I kept repeating to myself the
mantra of &quot;just keep running&quot;. Focusing on putting one step in front of the
other, I tried to ignore the pain. Eventually, I rounded the corner and the
finish line came into view.&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Finishing past the finish line&lt;/h2&gt;&lt;p&gt;Crossing the finish line, I felt such an overwhelming sense of relief that I
burst into tears. The race didn&#39;t just span the 26.2 miles I had run that day,
but the 600+ miles I had run in the months leading up to it.&lt;/p&gt;&lt;p&gt;Within an hour of finishing, though, I already found myself thinking about the
next race I wanted to run. So here&#39;s biggest lesson I learned in this whole
experience, and one that I didn&#39;t understand until the very end: &lt;strong&gt;there is
always going to be the next race&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;I have a habit of getting into obsessive sprints: two days to code a website,
six months to run a marathon, a year to finish a paper. Even when I was
training for an endurance race, I approached it with a fixation on a single,
short-term goal: finish the Banff Marathon in June.&lt;/p&gt;&lt;p&gt;That approach has aligned closely with my world so far, which was one
delineated by quarters and semesters and final exams. But looking into the
future, the terminal points are becoming less clear, and short obsessive bursts
of energy either won&#39;t be enough or will cause me pain in the long run&lt;label for=&quot;lol&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;lol&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;Heh. Get it?&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;Facing this reality is scary, and I&#39;m sure internalizing and adjusting to it
will be hard -- maybe the most difficult thing I have ever done. But I&#39;ve
learned a lot about running long runs and doing difficult things in the past
few months; I feel confident now that I&#39;ll learn plenty more in the years to
come.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Why do I want to do a PhD?</title>
		<link href="https://naitian.org/blog/why-phd/" />
		<updated>2022-06-15T00:00:00Z</updated>
		<id>https://naitian.org/blog/why-phd/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;p&gt;In a couple of months, I&#39;ll be starting my PhD at UC Berkeley School of
Information. The whole grad school application process was a wild ride, and
something I&#39;d like to write more about in the future, but for now, I&#39;d like to
write a bit about my motivations for deciding to do a PhD in the first place.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Hedges (and acknowledging the audience (that&#39;s you!))&lt;/h2&gt;&lt;p&gt;If you&#39;re considering applying to grad schools, please don&#39;t take this post as
anything other than my own thoughts as I navigated this decision. If you relate
to them, that&#39;s great! Maybe you &lt;em&gt;should&lt;/em&gt; do a PhD. Maybe neither of us should
(whoops).&lt;/p&gt;&lt;p&gt;If you are someone who has done a PhD in the past (or are in the middle of one
right now), I&#39;m not sure why you&#39;re reading this, but if it reminds you of your
own motivations, that&#39;s great! If it doesn&#39;t... Different strokes for different
folks, I guess.&lt;/p&gt;&lt;p&gt;If you are me from the future, hi! I hope things are going well, and if they&#39;re
not and you&#39;re really doubting me for signing you up for this, here is why I
(you (we)) decided to do it in the first place.&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;Anyway, I decided to do a PhD because...&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;...I&#39;d like to satisfy my curiosity.&lt;/h2&gt;&lt;p&gt;I became interested in doing research in undergrad because I read a paper I
really liked. It was the first time I enjoyed reading a research paper, and
that made me realize that there&#39;s scientific research happening that I&#39;m
actually interested in.&lt;/p&gt;&lt;p&gt;I would like to read more of those types of papers. I would like to read more
papers full of other people&#39;s interesting ideas, but there are also papers I
would like to read that test my personal hypotheses about the world. Because I
don&#39;t have the resources to fund my own research lab and tell people to write
those papers, it seems the next easiest thing to do is to tell myself to write
those papers. So that then I can read them.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;...I want to get better at research.&lt;/h2&gt;&lt;p&gt;The flaw in the above plan is that I&#39;m not very good at writing papers right
now, so I need to get some practice operationalizing research ideas, writing
code, synthesizing literature, (and writing papers). If only there were some
kind of educational institution in which I could practice conducting research.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;...the alternatives weren&#39;t as appealing.&lt;/h2&gt;&lt;p&gt;I&#39;ve also done software engineering and data journalism internships.&lt;/p&gt;&lt;p&gt;I wasn&#39;t that thrilled with my SWE experience: the work was sometimes
interesting, but I missed having a sense of ownership over what I was doing. In
my research experience, I owned my work, and I liked that feeling. The flip
side is that there&#39;s less of a mental safety net -- failures feel more
personal. There&#39;s a constant pressure to be productive because if you&#39;re not
working on your project, it&#39;s not like someone else in the org will be. But to
experience higher highs, it makes sense you have to also take the lower lows,
and it was a great feeling to see my name on a published paper.&lt;/p&gt;&lt;p&gt;I&#39;ll write more about data journalism in the future probably -- I worked on the
data graphics at NBC News Digital for a semester. It was a generally fantastic
experience, but I felt two frustrations: 1) you have to work on the news, which
isn&#39;t always necessarily what you&#39;re interested in and 2) it&#39;s a bigger ask to
use some more advanced methodologies because it&#39;ll both take more time and be
harder to explain to readers.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;...why not?&lt;/h2&gt;&lt;p&gt;Finally, it&#39;s just something I&#39;d like to do. Why do we climb mountains or run
marathons or set out to do anything at all? There are moments where you&#39;ll feel
great, for sure, but also plenty of pretty terrible moments. But I think any
meaningful experience has good parts and bad parts. On balance, having done a
PhD will probably make me a more improved person, so it seems like there&#39;s not
much reason &lt;em&gt;not&lt;/em&gt; to do one if I, for whatever arbitrary reason, just want to.&lt;/p&gt;&lt;p&gt;If life is just a collection of experiences, then this is an experience I&#39;d like to collect.&lt;/p&gt;&lt;h1&gt;PS&lt;/h1&gt;&lt;p&gt;I did the nested parentheticals a couple of times in this post. I think I like
it. I hope it didn&#39;t bother you too much.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>So you want to build a high tech college newsroom</title>
		<link href="https://naitian.org/blog/college-newsrooms/" />
		<updated>2022-02-16T00:00:00Z</updated>
		<id>https://naitian.org/blog/college-newsrooms/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;p&gt;College newsrooms have traditionally been the launchpad for many successful
journalism careers. They provide a lower-stakes environment for aspiring
journalists to hone their skills, gain an understanding of the industry and
make connections.&lt;/p&gt;&lt;p&gt;In recent years, major national newsrooms like the New York Times and The
Washington Post have &lt;a href=&quot;https://www.washingtonpost.com/pr/2020/12/09/washington-post-expands-investment-emerging-storytelling-technology-with-new-lede-lab/&quot;&gt;ramped up their tech
efforts&lt;/a&gt;
to &lt;a href=&quot;https://www.nytimes.com/projects/2020-report/index.html&quot;&gt;revitalize their digital
products&lt;/a&gt;, and there
are &lt;a href=&quot;https://newspack.pub/&quot;&gt;many&lt;/a&gt; &lt;a href=&quot;https://source.opennews.org/&quot;&gt;initiatives&lt;/a&gt;
to help smaller newsrooms keep up with this technological revolution within the
industry as well.
But despite the growing importance of newsroom engineers, data journalists and
graphics developers, many college newsrooms don&#39;t offer a space for students
with these career aspirations.&lt;/p&gt;&lt;!-- However, this success is rarely replicated when it comes to technology in the --&gt;&lt;!-- newsroom[^1]. --&gt;&lt;!----&gt;&lt;p&gt;A traditional computer science background is also insufficient for the aspiring
newsroom technologist&lt;label for=&quot;1&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;1&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;Note: there is a huge variance in the types of roles encompassed by &quot;newsroom tech&quot;: anything from using data science in service of reporting to building newsroom tools to developing web apps and graphics.&lt;/span&gt;. While more traditional software engineering
positions exist within the newsroom, many roles (like graphics or data
reporting) have &lt;a href=&quot;https://twitter.com/Wattenberger/status/1339569158506352642?s=20&amp;#x26;t=LKJ3dYX3P2agnHQqPLWJoA&quot;&gt;different workflows with different timelines and
expectations&lt;/a&gt;
compared to the typical software engineering job. In my experience, the hiring
process also differs from traditional software engineering companies. There
seems to be a greater emphasis on explaining your prior work, as opposed to the
LeetCode-heavy recruiting process in big tech companies. Finally, newsroom
hiring efforts are dwarfed by Big Tech, to the point where many students are
likely unaware of newsroom engineering as a viable career path at all.&lt;/p&gt;&lt;p&gt;Over the past three years, as a student at the University of Michigan (a
university without a j-school!), I&#39;ve been working alongside other
extraordinarily talented students to turn The Michigan Daily into a high tech
newsroom: one which prepares students for the code-heavy newsrooms of the
future.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 1: Sell the vision&lt;/h2&gt;&lt;p&gt;In the best case, your college newsroom is the &lt;a href=&quot;https://graphicsdesk.github.io/&quot;&gt;Columbia
Spectator&lt;/a&gt;. In the worst case, your college
newsroom views technology as a perversion of the sacrosanct art of journalism.
More likely than not, though, your newsroom is totally unaware of the exciting
possibility of newsroom tech (or they have dismissed it as beyond the
capabilities of a college paper). In any case, you need to make a strong pitch.&lt;/p&gt;&lt;p&gt;A college newsroom has two missions: 1) deliver quality journalism and 2)
develop aspiring journalists. Here are some brief talking points that address
both:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Data analysis and statistics skills are important to uncover interesting
stories (journalism), provide a new angle (journalism) or even just critically evaluate
the truthfulness of certain claims (pedagogy).&lt;/li&gt;
&lt;li&gt;The digital medium opens up many storytelling possibilities that increase
engagement (journalism) while also allowing students to rapidly experiment with
new technologies (pedagogy).&lt;/li&gt;
&lt;li&gt;In fact, all this is so true that major national newsrooms have begun doing
this years ago!&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;At The Daily, we were fortunate to already have a web team when I first joined.
However, it was poorly integrated and had little buy-in from the rest of the
newsroom. This means projects would frequently fail to see the light of day.
This underscores the importance of (first) getting the rest of the newsroom
excited about your web team and (second) building out the processes and
workflows to get projects out the door.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 2: Set up a structure&lt;/h2&gt;&lt;p&gt;It turns out, college newsrooms work because they&#39;ve had decades&lt;label for=&quot;2&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;2&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/The_Dartmouth&quot;&gt;if not centuries&lt;/a&gt;!&lt;/span&gt; to figure
out how to operate. This includes processes like how to pitch a story, how to
train new hires, how to collaborate between sections,
etc. You likely have four years at most to build out these processes for what
might be a brand new &quot;web team&quot;, so you better get cracking!&lt;/p&gt;&lt;p&gt;The first step is to figure out how tech fits into your newsroom. At The Daily,
we have a &quot;web team&quot;, which falls into the org chart as another section
alongside News and Sports and others. You may want to separate out further,
since people working on newsroom tools don&#39;t produce content. Or you may want
to integrate more tightly, since your graphics developers or data journalists
need to work with other sections to get stories out the door. Or both. Newsroom
tech is a big umbrella, with different timelines and expectations for different
types of work.&lt;/p&gt;&lt;p&gt;You also need to determine what roles you want to fill. Since there is so much
variety in the type of software you can write in a newsroom, you might want to
focus on developing a subset of skills at the onset. At The Daily, we put a lot
of effort initially into developing our data graphics subteam. This increased
our presence in the newsroom, produced some tangible outputs and gave us the
leeway to expand into other areas (like mobile app development and web
projects).&lt;/p&gt;&lt;p&gt;Your web team doesn&#39;t exist in a vacuum, and you need to figure out how to
integrate with the newsroom; what responsibilities will you take on? How will
this affect the work that other sections do? For example, you might want to
have a chat with the design section about how your graphics developers will fit
into the current workflow and what changes might be necessary. How will you
produce stories? Will your data team be working with reporters from other
sections or pitching their own stories (or both)?&lt;/p&gt;&lt;p&gt;After you make these decisions, you need to communicate it all to the rest of
the newsroom. Make sure other sections are aware of the work you&#39;re capable of
doing, the work you&#39;d like to take on and how that aligns with the work they
do.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 3: Develop your team&lt;/h2&gt;&lt;p&gt;While most college students have at least some amount of writing experience by
the time they end up in the newsroom, that&#39;s much less likely to be the case
when it comes to software engineering. The floor to entry is much higher, since
there&#39;s a lot of prerequisite knowledge to start producing content. The big
challenge is to provide the minimal amount of training for students to start
contributing to projects, while assuming minimal prior experience.&lt;/p&gt;&lt;p&gt;Again, the pedagogical value comes mainly from experiential learning. That
means your training shouldn&#39;t resemble or replace coursework (after all,
everyone is already in college to take courses). Offer support and expertise to
give students their greatest chance of success (publishing anything is better
than nothing), but also provide the room to experiment and fail.&lt;/p&gt;&lt;p&gt;This is something we are in the process of constantly refining at The Daily.
The biggest priority for senior leadership is developing a culture for newer
members to learn and flourish.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 4: Enculturation&lt;/h2&gt;&lt;p&gt;Just as your web team doesn&#39;t exist in a vacuum, neither does your newsroom.
Try to expose your team (and yourself) to the surrounding community of college
and professional newsrooms. In my experience, the &quot;news nerd&quot; community of
newsroom technologists has been incredibly open and generous with knowledge.&lt;/p&gt;&lt;p&gt;Learn about the processes and workflows other organizations use, as well as the
tools and technologies they employ. See what stories other organizations are
producing, and how they are executing their vision. This all feeds into
inspiration for &lt;em&gt;your&lt;/em&gt; newsroom&#39;s next big project.&lt;/p&gt;&lt;p&gt;Impress upon your team the possibility of working in the newsroom. Make them
aware of various newsroom internships for the summer or during the school year.
Encourage them to apply! This gives great insight into how professional
newsrooms operate and helps build valuable connections as you advance your
career.&lt;/p&gt;&lt;p&gt;The most important thing you can do to guarantee the success of your high tech
newsroom is to ingrain an inclusive, productive culture. Get your old members
to teach your new members, and get your new members to come back year after
year.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 5: Profit!&lt;/h2&gt;&lt;p&gt;There you go. You did it. Your college newsroom now has an amazing team of
software engineers and data journalists and graphics developers and UI/UX
designers working on a half dozen different projects for the newsroom.
Remember: it didn&#39;t start like this. It started with just a handful of people
(or maybe even just you) who were excited about the idea of working where tech
and journalism intersect.&lt;/p&gt;&lt;p&gt;And it doesn&#39;t end like this either: The Michigan Daily web team is still
growing and evolving to better serve the newsroom and better serve our
students. I can only hope that I helped The Daily take those first steps -- and
I hope you might be inspired to take them, too.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Acknowledgements&lt;/h2&gt;&lt;p&gt;Thanks to my former co-managing online editor, Parth Dhyani, as well as current
MOEs Eric Lau and Dora Guo, who all provided valuable feedback and support (in
writing this piece, in The Michigan Daily, and in general.)&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;P.S.&lt;/h2&gt;&lt;p&gt;If you are interested in, or have been in the process of, setting up a more
tech-forward organization in the college newsroom, please reach out to me! I&#39;d
love to chat with you. You can find me
&lt;a href=&quot;https://twitter.com/NaitianZhou&quot;&gt;@NaitianZhou&lt;/a&gt; on Twitter, or email me at
&lt;a href=&quot;mailto:naitian@umich.edu&quot;&gt;naitian@umich.edu&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you do tech + news professionally, I&#39;d also love to hear your thoughts. And
if you&#39;re hiring, I know some very qualified students who would make fantastic
interns or employees :)&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Reflections 2021</title>
		<link href="https://naitian.org/blog/reflections-2021/" />
		<updated>2022-01-05T00:00:00Z</updated>
		<id>https://naitian.org/blog/reflections-2021/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Time flies&lt;/h2&gt;&lt;p&gt;Usually I post one of these on New Year&#39;s Eve. Unfortunately, I was busy this
year watching Michigan play&lt;label for=&quot;1&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;1&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;Play might be too strong a term for what happened on the field that night...&lt;/span&gt; Alabama in the Orange Bowl, so here we are, a
few days later.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/reflections-2021/#this-year-in-numbers&quot;&gt;This Year in Numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/reflections-2021/#highlights&quot;&gt;Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/reflections-2021/#reflections&quot;&gt;Reflections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;This Year in Numbers&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;585&lt;/strong&gt; Github contributions (a new high score!)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;33&lt;/strong&gt; more college credits&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; Bachelor&#39;s degree (!!)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;11&lt;/strong&gt; PhD applications&lt;/p&gt;&lt;p&gt;...and &lt;strong&gt;a lot&lt;/strong&gt; of things on my mind.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Highlights&lt;/h2&gt;&lt;p&gt;In &lt;strong&gt;January&lt;/strong&gt;, I began my penultimate semester of college (although I didn&#39;t
know it at the time). I also began my term as one of the managing online
editors at &lt;a href=&quot;https://michigandaily.com/&quot;&gt;The Michigan Daily&lt;/a&gt; (more on this
later). I also got &lt;em&gt;super&lt;/em&gt; into the NYT spelling bee, and I implemented Naive
Bayes for homework for the third and fourth time.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;February&lt;/strong&gt;, The Daily published a couple of projects and stories that I
had a hand in: the &lt;a href=&quot;https://magnify.michigandaily.us/love/&quot;&gt;Statement Love
Edition&lt;/a&gt;, which I helped coordinate,
and a &lt;a href=&quot;https://www.michigandaily.com/research/how-effective-are-stay-home-orders-and-recommendations-reducing-spread-covid-19/&quot;&gt;data-driven piece on Covid
cases&lt;/a&gt;.
This would mark the beginning of a lot more rich online content from The Daily.
I also got Sunday donuts from Loomi Cafe for the first time. This became a
weekly tradition that was unfortunately short-lived, as Loomi closed this December.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;March&lt;/strong&gt; flew by with a lot of Daily work: a &lt;em&gt;bunch&lt;/em&gt; more data stories from
The Daily, including a multi-part piece on feeder schools that would go on to
win an award and get a ton of readers. We also published a special project,
reflecting on one year of online classes. Finally, we launched a brand new
website, opening up a lot more flexibility in the projects we&#39;d be able to
tackle in the future.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;April&lt;/strong&gt;, I got vaccinated.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;May&lt;/strong&gt;, it felt like the world once again existed outside the confines of
my own room, and I was eager to take advantage. In roughly chronological order,
I: helped my family move back to Troy, Michigan (after having moved from Troy
just a couple years ago), learned to skateboard, read &lt;em&gt;Pachinko&lt;/em&gt; and &lt;em&gt;Abolish
Silicon Valley&lt;/em&gt;, attended my friend&#39;s graduation at UVA and climbed Old Rag in
Shenandoah. I also (virtually) began my summer internship at the University of
Washington.&lt;/p&gt;&lt;p&gt;I departed for Seattle in &lt;strong&gt;June&lt;/strong&gt;, opting to take the Amtrak &lt;em&gt;Empire Builder&lt;/em&gt;
from Chicago. This was a two-and-a-half day trip, and I loved every minute of
it (give or take). You can read some of my thoughts about it
&lt;a href=&quot;https://twitter.com/NaitianZhou/status/1430571386263818245?s=20&quot;&gt;here&lt;/a&gt;. Aside
from the train trip, I explored lots of Seattle (especially U District), went
on a few runs, climbed a couple of mountains, and endured a really killer heat
wave.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;July&lt;/strong&gt; contained more Seattle adventures, including more hiking, some
kayaking, a trip to Portland, and I got my Seattle Public Library card.&lt;/p&gt;&lt;p&gt;I wrapped up my time in Seattle in &lt;strong&gt;August&lt;/strong&gt;. My parents came to see Mt.
Rainier and Olympic National Park with me before we flew back home to Michigan.
I also began my last ever semester as an undergrad at the University of
Michigan.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;September&lt;/strong&gt;, I house-sat a cat and it was the best week of my life.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;October&lt;/strong&gt; was a Michigan fall, and I did all of the classic Michigan fall
things™. This included a trip to a cider mill with the Blablablab, making my
&lt;em&gt;own&lt;/em&gt; cider (also with the Blablablab), a couple of backyard bonfires, and (of
course) a Michigan football game. I also submitted my NSF GRF application.&lt;/p&gt;&lt;p&gt;I turned 22 in &lt;strong&gt;November&lt;/strong&gt;. Oh yeah, and Michigan beat OSU for the first time
in close to a decade. That was a good day.&lt;/p&gt;&lt;p&gt;That brings us to &lt;strong&gt;December&lt;/strong&gt;. If some of these months seem sparse in detail,
it&#39;s because this past year really flew by -- &lt;em&gt;especially&lt;/em&gt; this past month.
There were a lot of good-byes, a lot of lasts, and not a lot of time to process
all of it...&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Reflections&lt;/h2&gt;&lt;p&gt;Which I suppose leads us to this section. Some time to process everything that
happened this past year and, really, these past three and a half years of
college.&lt;/p&gt;&lt;p&gt;It&#39;s hard to know where to begin, so maybe I&#39;ll contextualize by starting with
my &lt;em&gt;last&lt;/em&gt; graduation. When I graduated from high school, I felt a sense of
completion and a really strong optimism for the future. This is what I wrote in
my 2018 reflection:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;I can only hope that the next five years will be as fulfilling and
interesting and fun as the past five. I hope that, just as I found a home in
Virginia, I&#39;ll find a home in Michigan, and wherever life might take me next.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;What I hadn&#39;t anticipated was the tumult. The best way to describe the past
couple of years would be careening down the interstate with the windows down,
and a stray newspaper just flew into my face. Thrilling, sure, but also
terrifying.&lt;/p&gt;&lt;p&gt;I&#39;m ending my years at Michigan a semester early (I achieved this through a
convoluted series of events, which is fit for a whole other post...) It feels
like I&#39;ve slammed on the brakes, flown out of the vehicle, and extended this
analogy past its breaking point. What I&#39;m trying to say is, I don&#39;t feel the
same sense of closure that I felt four years ago after high school.&lt;/p&gt;&lt;p&gt;I&#39;m sure this is in no small part due to the crazy circumstances of the past
couple of years. Aside from a global pandemic that resulted in my coursework
being online for half of the time I was at Michigan, my family has also moved
four times in three years, meaning somehow I&#39;ve accumulated five or six
different Michigan zip codes. When I said I hoped to find a home in Michigan, I
should have clarified: I&#39;d be content with just one, and not six.&lt;/p&gt;&lt;p&gt;But premature departures, pandemics and Zhou family migration patterns are
trivial in the bigger picture of my experience at (in, and around) Michigan.
They may have made this ending come sooner or seem quicker in its approach, but
I doubt I&#39;d be any more prepared with any amount of lead time. I have put a lot
of myself into the people and organizations and life in Ann Arbor, and it&#39;s
hard to imagine waving goodbye to all of that.&lt;/p&gt;&lt;p&gt;I&#39;m proud to have helped build up two stellar student organizations from close
to nothing: the Michigan Data Science Team and the web team at The Michigan
Daily. They are in excellent hands now, but it&#39;s still hard to say goodbye. But
even greater than that, I&#39;m proud to have built so many lasting relationships
with people here -- people I can laugh with, confide in, rant to, seek support
from. Those are the hardest goodbyes.&lt;/p&gt;&lt;p&gt;Fulfilling, interesting and fun? Definitely.&lt;/p&gt;&lt;p&gt;That brings us to now: I&#39;ve applied to PhD programs which I&#39;m waiting to hear
back from, which means I&#39;m temporarily stuck looking ahead into a bright cloud
of complete uncertainty.&lt;/p&gt;&lt;p&gt;Usually, at the end of these reflections, I like to take a look forward into
the next year. This time, though, I don&#39;t think that&#39;s feasible. I don&#39;t know
where I will physically be this time next year, much less what I&#39;ll be doing or
what I&#39;ll have to look forward to. Just... something interesting, probably.&lt;/p&gt;&lt;p&gt;So I&#39;ll bide my time for now, sitting with my feet dangling off a precipice
overlooking the entire rest of my life. I think I&#39;ll spend the next couple of
months savoring the end of the beginning.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Reflections 2020</title>
		<link href="https://naitian.org/blog/2020/12/31/Reflections-2020/" />
		<updated>2020-12-31T08:00:00Z</updated>
		<id>https://naitian.org/blog/2020/12/31/Reflections-2020/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;An R.E.M. song&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;It&#39;s the end of the world as we know it&lt;/p&gt;
&lt;p&gt;And I feel fine.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/12/31/Reflections-2020/#this-year-in-numbers&quot;&gt;This Year in Numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/12/31/Reflections-2020/#highlights&quot;&gt;Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/12/31/Reflections-2020/#reflections&quot;&gt;Reflections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;This Year in Numbers&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;415&lt;/strong&gt; Github contributions (making a comeback!)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;31&lt;/strong&gt; more college credits (I think? I&#39;m starting to lose track...)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;12&lt;/strong&gt; weeks reading papers this summer at USC ISI.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;12&lt;/strong&gt; more weeks making plots and crunching numbers at NBC News.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; musical attended (Hadestown, on &lt;em&gt;Broadway&lt;/em&gt;!!)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; &lt;a href=&quot;https://blablablab.si.umich.edu/projects/condolence&quot;&gt;first-author paper&lt;/a&gt;
published (in Proceedings of EMNLP 2020)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;27&lt;/strong&gt; &lt;a href=&quot;https://muckrack.com/naitian-zhou/articles&quot;&gt;bylines&lt;/a&gt; from &lt;strong&gt;2&lt;/strong&gt; news organizations.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2&lt;/strong&gt; new library cards (Boston and New York City Public Libraries)&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Highlights&lt;/h2&gt;&lt;p&gt;This will be difficult because it feels like time didn&#39;t really exist before
March, but I&#39;ll try anyway.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;January&lt;/strong&gt;, the Michigan Union held its grand opening before shutting back
down due to Covid just three months later. We kicked off a new semester of
Michigan Data Science Team with a new set of workshops targeted for beginners. I
read &lt;em&gt;The Signal and the Noise&lt;/em&gt; by Nate Silver. Finally, after talking to my
roommate Parth, I decided to join the data team at the Michigan Daily.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;February&lt;/strong&gt; was short but still plenty eventful. I started working on my &lt;a href=&quot;https://www.michigandaily.com/section/government/can-money-buy-votes-how-financial-contributions-michigan-could-impact-primaries&quot;&gt;first
analysis for the
Daily&lt;/a&gt;,
read &lt;em&gt;Fortune Cookie Chronicles&lt;/em&gt; by Jennifer 8. Lee, and went axe throwing with
MDST. On the last (leap) day, I landed in Boston to visit my friend Nina at
Harvard.&lt;/p&gt;&lt;p&gt;This leads into &lt;strong&gt;March&lt;/strong&gt;, where I wrapped up my spring break with what in
hindsight was probably an ill-advised tour down the east coast. I wrapped up
Boston by getting a library card from Boston Public Library (absolutely
beautiful), visitng the Isabella Stewart Gardner museum, getting Chinese food
and desserts from Chinatown, and seeing the ducks in Boston commons. After a
harrowing sprint to South Station, I made it to New York, where I had more
Chinese food, attended a comedy show at my hostel, and visited the New York
Times building, the Highline, the Chinese American History Museum, the New York
Public Library (also very pretty), Hadestown on Broadway, the MoMA, and then
sprinted to Penn Station to catch an Amtrak to DC. From DC, I continued to
Pittsburgh, catching up with friends at CMU and Pitt, before driving back up to
Ann Arbor. All this took place over the first week of March, after which
everything descended into chaos: we had primaries coverage for the Daily,
immediately after which Michigan shut down for Covid. March ends with making a
premature departure from campus.&lt;/p&gt;&lt;p&gt;After a &lt;em&gt;very&lt;/em&gt; eventful March, &lt;strong&gt;April&lt;/strong&gt; was boring by comparison, marked
mostly by online classes and exams as the semester wrapped up.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;May&lt;/strong&gt; was mostly enjoying my summer vacation before school began and
finalizing my paper for EMNLP. I also resolved to sew myself a backpack as a
summer project only to discover all the sewing machines were out of stock! I
started my research internship at USC after Labor day. Finally, I watched as
SpaceX launched the first astronauts into space from the US in close to a
decade. An early interest in rockets and space really propelled me onto a STEM
track, and this was a reminder of what had inspired me so many years before.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;June&lt;/strong&gt;, I finally managed to buy a sewing machine (but no materials yet). I
was introduced to crossword puzzles and proceeded to &lt;del&gt;waste&lt;/del&gt; spend a few hours
every day on crosswords...&lt;/p&gt;&lt;p&gt;&lt;strong&gt;July&lt;/strong&gt; is when my backpacking plans went into full force as I finally received
my supplies. Plenty of mistakes were made, and I had to disassemble and repair
the sewing machine more than once.&lt;/p&gt;&lt;p&gt;I finally, in a mad dash over three days, finished my backpack in &lt;strong&gt;August&lt;/strong&gt;.
This was just in time to move back onto campus, where I would proceed to take
all my classes from my room and leave the backpack sitting dejectedly in a
corner. I also made some fantastic productivity purchases: a nice chair from
Ikea and a standing desk (amazing).&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;September&lt;/strong&gt;, I started at NBC News and covered the first presidential
debate my second week of work. It was an exhilarating experience for someone
totally new to the news scene as we worked to debug our vis literally up until
the minute the debate began. I received notice that my paper was accepted to
EMNLP. I also deep-fried food for the first time and it was a resounding
success. Finally, I bought a crossword subscription, much to the detriment of my
productivity.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;October&lt;/strong&gt; was dominated by covering Presidential debates (the ones that
weren&#39;t cancelled, at least), prepping for EMNLP, crosswords and other word
games, and enjoying the last of the good Ann Arbor weather.&lt;/p&gt;&lt;p&gt;In line with March and September, &lt;strong&gt;November&lt;/strong&gt; was quite eventful. Election week
coverage, deep frying more food, attending and presenting at my first
conference, and celebrating my 21st birthday (by not going to any of the bars)!
Somehow, a lot of these things also happened in the same week...&lt;/p&gt;&lt;p&gt;Finally, &lt;strong&gt;December&lt;/strong&gt; saw the end of the semester and my internship at NBC. It
also saw the renewal of my crossword and Netflix subscriptions, both of which I
was not comfortable maintaining during the semester.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Reflections&lt;/h2&gt;&lt;p&gt;This is the end of a &lt;em&gt;very&lt;/em&gt; eventful year. It&#39;s one that I can safely say I did
not see coming, filled with disappointments and hardships. But it has also had
some really amazing moments. With the switch to a new normal in terms of media
of communication, I&#39;ve been able to reconnect with many friends I&#39;ve lost touch
with over the years. I&#39;ve also had so many fantastic opportunities
professionally, and I&#39;ve met some really fantastic people at both USC and NBC.&lt;/p&gt;&lt;p&gt;And in the midst of personal, national, and international chaos, I&#39;ve grown to
appreciate so many of the things I used to take for granted: seeing my friends
and loved ones in person; being able to travel to China to visit my
grandparents; seeing the bottom halves of strangers faces. I&#39;ve also learned to
take care of myself in trying times: to create a space I want to live in; to
find joy in my routines (think you crosswords); to reach out to my friends for
company and support.&lt;/p&gt;&lt;p&gt;Every year sees ups and downs, setbacks and growth. This year was no different
in that regard, and I&#39;m confident that 2021, whatever it has in store, will also
bring both plenty of disappointments and plenty of joy. In many ways, my limits
were tested this year -- in some cases, I grew and stretched those limits. In
others, I saw the cracks and learned when I should ease back. The trials of this
past year have taught me a lot about myself.&lt;/p&gt;&lt;p&gt;I&#39;m looking forward to a year filled with new joys and new disappoints. I&#39;m
looking forward to a year where I can see and hug my family and friends. I&#39;m
looking forward to the year I start my senior year of college, where I meet new
people and experience new things. But mostly, I&#39;m looking forward to a year that
will hopefully chill the fuck out.&lt;/p&gt;&lt;p&gt;Good night, 2020. Good morning, 2021.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Understanding D3</title>
		<link href="https://naitian.org/blog/2020/05/27/Understanding-D3/" />
		<updated>2020-05-27T07:00:00Z</updated>
		<id>https://naitian.org/blog/2020/05/27/Understanding-D3/</id>
		<content xml:lang="en" type="html"
			>&lt;blockquote&gt;
&lt;p&gt;This is a first draft. I will likely revise (multiple times) in the future
for clarity. But hopefully, even in its current state, you might find this
useful.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#the-strange-case-of-d3&quot;&gt;The strange case of D3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#the-big-idea-and-why-its-so-hard&quot;&gt;The big idea (and why it&#39;s so hard)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#lets-start-with-just-a-line&quot;&gt;Let&#39;s start with just a line&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#set-up&quot;&gt;Set up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#the-code&quot;&gt;The Code&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#elements&quot;&gt;Elements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#functions&quot;&gt;Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#data&quot;&gt;Data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/27/Understanding-D3/#why-this-way&quot;&gt;Why this way?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The strange case of D3&lt;/h2&gt;&lt;p&gt;Dr. Jekyll: D3 is famous for being an incredibly versatile visualization
library.&lt;/p&gt;&lt;p&gt;Mr. Hyde: D3 is &lt;em&gt;infamous&lt;/em&gt; for having a steep learning curve and being difficult
to understand past copy and pasting examples.&lt;/p&gt;&lt;p&gt;I have experienced the dark side of D3, but recently, I feel as if I have had
minor breakthrough, so hopefully I can in turn provide you with some sort of
lightbulb moment.&lt;/p&gt;&lt;p&gt;But just as a disclaimer: in no way do I profess to be an expert (or anywhere
close). I&#39;ve still a lot to learn. I just think something clicked for me.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The big idea (and why it&#39;s so hard)&lt;/h2&gt;&lt;p&gt;Having gained some understanding, I now know this is the mantra you must repeat
to yourself.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;D3 gives you &lt;strong&gt;functions&lt;/strong&gt; to work with &lt;strong&gt;data&lt;/strong&gt; bound to &lt;strong&gt;elements&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Does that sound kind of familiar? It probably should. Here&#39;s the first sentence
on the D3 website.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;D3.js is a JavaScript library for manipulating documents based on data&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;and later on...&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;D3 allows you to bind arbitrary data to a Document Object Model (DOM), and
then apply data-driven transformations to the document&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;That leads me to believe D3 is difficult to learn because it relies on a very
simple and powerful concept -- too simple to warrant understanding when just
starting out and too powerful to appreciate without building and seeing lots of
examples.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Let&#39;s start with just a line&lt;/h2&gt;&lt;p&gt;We will begin with the three basic parts to working with D3. We will have an
element in the DOM (element). We will have some data, with which we&#39;ll draw a
line (data). And we&#39;ll use D3 to put those things together (functions).&lt;/p&gt;&lt;p&gt;D3 has a lot of conventions. These are useful to learn as a stepping stone to
learning the concepts, so I will try to use a few of them here.&lt;/p&gt;&lt;p&gt;This is what the result looks like.&lt;/p&gt;&lt;script src=&quot;https://d3js.org/d3.v5.min.js&quot;&gt;&lt;/script&gt;&lt;style&gt;
    svg {
        position: relative;
        left: 50%;
        transform: translateX(-50%);
    }
&lt;/style&gt;&lt;script&gt;
function draw () {
    // Data
    const X = [1, 2, 3, 4, 5];
    const Y = [3, 5, 1, 6, 9];
    const data = X.map((x, i) =&gt; [x, Y[i]]);

    // Set sizes
    let width = 600;
    let height = 300;
    let margin = {top: 5, right: 0, bottom: 30, left: 30};

    // Create functions
    let xScale = d3.scaleLinear()
                    .domain(d3.extent(data.map(d =&gt; d[0])))
                    .range([0, width - margin.left - margin.right]);
    let yScale = d3.scaleLinear()
                    .domain(d3.extent(data.map(d =&gt; d[1])))
                    .range([height - margin.top - margin.bottom, 0]);
    let line = d3.line().x(d =&gt; xScale(d[0])).y(d =&gt; yScale(d[1]));
    let xAxis = d3.axisBottom().scale(xScale);
    let yAxis = d3.axisLeft().scale(yScale);

    // Create elements
    let svg = d3.select(&quot;figure.example &gt; svg&quot;)
        .attr(&quot;width&quot;, width)
        .attr(&quot;height&quot;, height)

    let chart = svg.append(&quot;g&quot;)
        .attr(&quot;transform&quot;, `translate(${margin.left}, ${margin.top})`);
    let chart__line = chart.append(&quot;path&quot;)
        .attr(&quot;fill&quot;, &quot;none&quot;)
        .attr(&quot;stroke&quot;, &quot;black&quot;);
    let chart__xaxis = chart.append(&quot;g&quot;)
        .attr(&quot;class&quot;, &quot;g__xaxis&quot;)
        .attr(&quot;transform&quot;, `translate(0, ${height - margin.top - margin.bottom})`);
    let chart__yaxis = chart.append(&quot;g&quot;)
        .attr(&quot;class&quot;, &quot;g__yaxis&quot;)

    // Bind data and call functions
    chart__line.datum(data)
        .attr(&quot;d&quot;, line);

    chart__xaxis.call(xAxis);
    chart__yaxis.call(yAxis);
}
window.onload = draw;
&lt;/script&gt;&lt;figure class=&quot;example&quot;&gt;
&lt;h2 class=&quot;figure__title&quot;&gt;Figure: Just a Line Plot&lt;/h2&gt;
&lt;svg&gt;
&lt;/svg&gt;
&lt;/figure&gt;&lt;h3&gt;Set up&lt;/h3&gt;&lt;p&gt;Let&#39;s start with the easiest part to set up: the DOM. This is all the HTML I
have:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-html&quot;&gt;&lt;span class=&quot;hljs-tag&quot;&gt;&amp;#x3C;&lt;span class=&quot;hljs-name&quot;&gt;figure&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;example&quot;&lt;/span&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-tag&quot;&gt;&amp;#x3C;&lt;span class=&quot;hljs-name&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;figure__title&quot;&lt;/span&gt;&gt;&lt;/span&gt;Figure: Just a Line Plot&lt;span class=&quot;hljs-tag&quot;&gt;&amp;#x3C;/&lt;span class=&quot;hljs-name&quot;&gt;h2&lt;/span&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-tag&quot;&gt;&amp;#x3C;&lt;span class=&quot;hljs-name&quot;&gt;svg&lt;/span&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-tag&quot;&gt;&amp;#x3C;/&lt;span class=&quot;hljs-name&quot;&gt;svg&lt;/span&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-tag&quot;&gt;&amp;#x3C;/&lt;span class=&quot;hljs-name&quot;&gt;figure&lt;/span&gt;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We have a simple dataset (5 points to form a line).&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-js&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; X = [&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;];
&lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; Y = [&lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;6&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;9&lt;/span&gt;];
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Again, nothing special.&lt;/p&gt;&lt;h3&gt;The Code&lt;/h3&gt;&lt;p&gt;This is the interesting part, but don&#39;t be intimidated. In fact, this chart is
made with only 16 lines of actual code.&lt;/p&gt;&lt;p&gt;First, let&#39;s define some variables we want to keep track of:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-js&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; width = &lt;span class=&quot;hljs-number&quot;&gt;600&lt;/span&gt;;
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; height = &lt;span class=&quot;hljs-number&quot;&gt;300&lt;/span&gt;;
&lt;span class=&quot;hljs-comment&quot;&gt;// this is the margin convention&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; margin = {&lt;span class=&quot;hljs-attr&quot;&gt;top&lt;/span&gt;: &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;hljs-attr&quot;&gt;right&lt;/span&gt;: &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;hljs-attr&quot;&gt;bottom&lt;/span&gt;: &lt;span class=&quot;hljs-number&quot;&gt;30&lt;/span&gt;, &lt;span class=&quot;hljs-attr&quot;&gt;left&lt;/span&gt;: &lt;span class=&quot;hljs-number&quot;&gt;30&lt;/span&gt;};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Remember our mantra: data, function, elements. Again, let&#39;s start with elements.&lt;/p&gt;&lt;h4&gt;Elements&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-js&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// Create elements&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;// select SVG&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; svg = d3.select(&lt;span class=&quot;hljs-string&quot;&gt;&quot;figure.example &gt; svg&quot;&lt;/span&gt;)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;width&quot;&lt;/span&gt;, width)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;height&quot;&lt;/span&gt;, height)

&lt;span class=&quot;hljs-comment&quot;&gt;// create chart&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; chart = svg.append(&lt;span class=&quot;hljs-string&quot;&gt;&quot;g&quot;&lt;/span&gt;)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;transform&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;`translate(&lt;span class=&quot;hljs-subst&quot;&gt;${margin.left}&lt;/span&gt;, &lt;span class=&quot;hljs-subst&quot;&gt;${margin.top}&lt;/span&gt;)`&lt;/span&gt;);
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; chart__line = chart.append(&lt;span class=&quot;hljs-string&quot;&gt;&quot;path&quot;&lt;/span&gt;)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;fill&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;none&quot;&lt;/span&gt;)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;stroke&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;black&quot;&lt;/span&gt;);
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; chart__xaxis = chart.append(&lt;span class=&quot;hljs-string&quot;&gt;&quot;g&quot;&lt;/span&gt;)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;class&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;g__xaxis&quot;&lt;/span&gt;)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;transform&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;`translate(0, &lt;span class=&quot;hljs-subst&quot;&gt;${height - margin.top - margin.bottom}&lt;/span&gt;)`&lt;/span&gt;);
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; chart__yaxis = chart.append(&lt;span class=&quot;hljs-string&quot;&gt;&quot;g&quot;&lt;/span&gt;)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;class&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;g__yaxis&quot;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I won&#39;t go too far into the details here, but the basic idea is we create all of
our chart elements under a single &quot;chart&quot; group. This has to do with the
convention of defining a size for the SVG, defining margins, and adjusting the
size of your &quot;canvas&quot; accordingly.&lt;/p&gt;&lt;p&gt;I want to stress that this &lt;em&gt;sets up&lt;/em&gt; our chart, but we&#39;ve yet to actually draw
anything. We have added the &lt;strong&gt;elements&lt;/strong&gt;, but we haven&#39;t set up any functions or
bound any data. So let&#39;s do some of that now.&lt;/p&gt;&lt;h4&gt;Functions&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-js&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// Create functions&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; xScale = d3.scaleLinear()
                .domain(d3.extent(data.map(&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-params&quot;&gt;d&lt;/span&gt; =&gt;&lt;/span&gt; d[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;])))
                .range([&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;, width - margin.left - margin.right]);
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; yScale = d3.scaleLinear()
                .domain(d3.extent(data.map(&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-params&quot;&gt;d&lt;/span&gt; =&gt;&lt;/span&gt; d[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;])))
                .range([height - margin.top - margin.bottom, &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;]);
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; line = d3.line().x(&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-params&quot;&gt;d&lt;/span&gt; =&gt;&lt;/span&gt; xScale(d[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;])).y(&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-params&quot;&gt;d&lt;/span&gt; =&gt;&lt;/span&gt; yScale(d[&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;]));
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; xAxis = d3.axisBottom().scale(xScale);
&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; yAxis = d3.axisLeft().scale(yScale);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here, we set up our scales, axes, as well as the line generator. This doesn&#39;t
draw anything either, because we&#39;ve yet to put the functions and elements
together. Luckily for us, that step is pretty easy.&lt;/p&gt;&lt;h4&gt;Data&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-js&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// Bind data and call functions&lt;/span&gt;
chart__line.datum(data)
    .attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;d&quot;&lt;/span&gt;, line);

chart__xaxis.call(xAxis);
chart__yaxis.call(yAxis);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I want to focus on two things here. First, notice how we now bind our data to
the &lt;code&gt;chart__line&lt;/code&gt; element. We use &lt;code&gt;datum&lt;/code&gt; because we are drawing one line, so
we&#39;re binding this one piece of data (singular: datum). Now, when we set the &lt;code&gt;d&lt;/code&gt;
attribute, we can pass in a function that takes the datum (our array of
coordinates) as input and returns the line path as output.&lt;/p&gt;&lt;p&gt;Second, notice how we&#39;re drawing the axes. We set up the &lt;code&gt;xAxis&lt;/code&gt; and &lt;code&gt;yAxis&lt;/code&gt;
functions earlier, and the &lt;code&gt;.call&lt;/code&gt; is essentially passing our selection as input
to the function. It&#39;s equivalent to &lt;code&gt;xAxis(chart__xaxis)&lt;/code&gt;, for example, so don&#39;t
let the syntax scare you.&lt;/p&gt;&lt;p&gt;Using &lt;code&gt;.call&lt;/code&gt; is convenient for chaining functions, and this pattern is
recommended for creating reusable charts. The idea is you can have a selection
of &lt;code&gt;svg&lt;/code&gt;s with bound data, call your chart on that selection, and draw charts
using the bound data for each element in your selection.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Why this way?&lt;/h2&gt;&lt;p&gt;It&#39;s possible to create D3 graphics without following this pattern. I&#39;d bet most
people (myself included) did not start creating graphics with this pattern. So
why take the extra effort to learn and implement these ideas?&lt;/p&gt;&lt;p&gt;There are a couple of reasons which go hand-in-hand.&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;This is the way D3 was designed to be used.&lt;label for=&quot;1&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;1&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;I will qualify this statement by saying that, since I didn&#39;t design D3, technically I don&#39;t know if this is true. That said, having read a lot of Mike Bostock&#39;s (and others&#39;) writing on best practices for D3, this seems to be the &quot;right way&quot;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Because of this, when you implement things this way, things are more likely
to &quot;just work&quot;.&lt;/li&gt;
&lt;li&gt;Also because of this, debugging becomes easier because you&#39;re not trying to
resolve any conflicts between your mental model and the model D3 adopts.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;I&#39;ll provide an example of how you might be tempted to do things, and how those
end up causing headaches later on. The tl;dr is that problems arise when you
don&#39;t separating elements, data, and functions effectively.&lt;/p&gt;&lt;p&gt;In the past, I used to do this a lot:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-js&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// draw axes&lt;/span&gt;
g.append(&lt;span class=&quot;hljs-string&quot;&gt;&quot;path&quot;&lt;/span&gt;).datum(data).attr(&lt;span class=&quot;hljs-string&quot;&gt;&quot;d&quot;&lt;/span&gt;, line)
g.append(&lt;span class=&quot;hljs-string&quot;&gt;&quot;g&quot;&lt;/span&gt;).call(xAxis)
g.append(&lt;span class=&quot;hljs-string&quot;&gt;&quot;g&quot;&lt;/span&gt;).call(yAxis)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Why is this bad?&lt;/strong&gt; We don&#39;t save our selections, and you can think of this as
treating the &lt;code&gt;path&lt;/code&gt; element as bound to this specific &lt;code&gt;datum&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;What does that mean?&lt;/strong&gt; If we want to change our data, we will update &lt;code&gt;data&lt;/code&gt;
and run that code again, but since we don&#39;t keep a pointer to the &lt;code&gt;path&lt;/code&gt;
element, we end up just appending another path. Instead of redrawing the line,
we draw a new line. Additionally, if we wanted our graphic to be responsive
(that is, resize when the browser window resizes), we need to update and redraw
our axes. That means we should also keep pointer to the axes elements.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Moral of the story?&lt;/strong&gt; Set up your elements once, then use D3 functions to bind
data and draw many times. Since you&#39;re not creating a new element every update,
D3 can keep track of the current bound data and update accordingly. This also
lets you use D3 transitions more easily.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Modeling Moments so Dear</title>
		<link href="https://naitian.org/blog/2020/05/25/Modeling-Moments-so-Dear/" />
		<updated>2020-05-25T07:00:00Z</updated>
		<id>https://naitian.org/blog/2020/05/25/Modeling-Moments-so-Dear/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;p&gt;In the time that you&#39;ve started reading this, there&#39;s a
&lt;span class=&quot;output time&quot;&gt;&lt;/span&gt; chance that you&#39;ve experienced, as Jonathan
Larson put it, a moment so dear&lt;label for=&quot;1&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;1&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;assuming you experienced one immediately before this page load -- this provides a lower bound&lt;/span&gt;.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/25/Modeling-Moments-so-Dear/#how-do-you-measure-a-year&quot;&gt;How do you measure a year?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/25/Modeling-Moments-so-Dear/#send-in-the-clowns-stats&quot;&gt;Send in the &lt;del&gt;Clowns&lt;/del&gt; Stats&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/25/Modeling-Moments-so-Dear/#calculating-probabilities&quot;&gt;Calculating Probabilities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/25/Modeling-Moments-so-Dear/#confidence-intervals&quot;&gt;Confidence Intervals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2020/05/25/Modeling-Moments-so-Dear/#life-lessons&quot;&gt;Life Lessons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;How do you measure a year?&lt;/h2&gt;&lt;p&gt;&lt;em&gt;RENT&lt;/em&gt; is a Tony Award and Pulitzer Prize winning musical describing the
bohemian lifestyle of a group of young artists in Lower Manhattan. It remains
one of the longest running shows on Broadway.&lt;/p&gt;&lt;p&gt;Even if you haven&#39;t heard of the musical, you&#39;ve probably heard one of its most
famous numbers: &lt;em&gt;Seasons of Love&lt;/em&gt;, which has become a popular hit in its own
right. Here is the iconic first verse:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Five hundred twenty-five thousand six hundred minutes \
Five hundred twenty-five thousand moments so dear \
Five hundred twenty-five thousand six hundred minutes \
How do you measure, measure a year?&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;I&#39;m less interested in how to measure a year, and more interested in getting my
fair share of moments so dear.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Send in the &lt;del&gt;Clowns&lt;/del&gt; Stats&lt;/h2&gt;&lt;p&gt;We know from the lyrics that there are 525,000 moments so dear in one year.
There are 525,600 minutes. That means there is, on average, one moment so dear
(MsD) approximately every 1.001 minutes.&lt;/p&gt;&lt;p&gt;It makes sense to model the distribution of our MsDs (MssD?) as exponential.
Exponential distributions are frequently used to model &quot;waiting time&quot; problems,
because they have a couple of properties, which are reflected in our scenario.&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The random variable (in our case, the amount of time until a moment so dear,
since the last moment so dear) is always positive.&lt;/strong&gt; This makes sense, since we
shouldn&#39;t ever say something like &quot;the next moment so dear is -3 minutes from
the previous moment so dear&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The distribution is memoryless.&lt;/strong&gt; That means it doesn&#39;t matter if we have
been waiting for 3 minutes or 3 hours, the probability of a moment so dear
occurring in the next minute will always be the same. As the cast sings in
&lt;em&gt;Finale B&lt;/em&gt;, there is &quot;no day but today&quot;.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;With those conditions, I claim our moments so dear can be modeled as:&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;&lt;mjx-container class=&quot;MathJax&quot; jax=&quot;SVG&quot; display=&quot;true&quot;&gt;&lt;svg style=&quot;vertical-align: -0.566ex;&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;20.6ex&quot; height=&quot;2.262ex&quot; role=&quot;img&quot; focusable=&quot;false&quot; viewBox=&quot;0 -750 9105.1 1000&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;defs&gt;&lt;path id=&quot;MJX-1-TEX-I-1D440&quot; d=&quot;M289 629Q289 635 232 637Q208 637 201 638T194 648Q194 649 196 659Q197 662 198 666T199 671T201 676T203 679T207 681T212 683T220 683T232 684Q238 684 262 684T307 683Q386 683 398 683T414 678Q415 674 451 396L487 117L510 154Q534 190 574 254T662 394Q837 673 839 675Q840 676 842 678T846 681L852 683H948Q965 683 988 683T1017 684Q1051 684 1051 673Q1051 668 1048 656T1045 643Q1041 637 1008 637Q968 636 957 634T939 623Q936 618 867 340T797 59Q797 55 798 54T805 50T822 48T855 46H886Q892 37 892 35Q892 19 885 5Q880 0 869 0Q864 0 828 1T736 2Q675 2 644 2T609 1Q592 1 592 11Q592 13 594 25Q598 41 602 43T625 46Q652 46 685 49Q699 52 704 61Q706 65 742 207T813 490T848 631L654 322Q458 10 453 5Q451 4 449 3Q444 0 433 0Q418 0 415 7Q413 11 374 317L335 624L267 354Q200 88 200 79Q206 46 272 46H282Q288 41 289 37T286 19Q282 3 278 1Q274 0 267 0Q265 0 255 0T221 1T157 2Q127 2 95 1T58 0Q43 0 39 2T35 11Q35 13 38 25T43 40Q45 46 65 46Q135 46 154 86Q158 92 223 354T289 629Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-223C&quot; d=&quot;M55 166Q55 241 101 304T222 367Q260 367 296 349T362 304T421 252T484 208T554 189Q616 189 655 236T694 338Q694 350 698 358T708 367Q722 367 722 334Q722 260 677 197T562 134H554Q517 134 481 152T414 196T355 248T292 293T223 311Q179 311 145 286Q109 257 96 218T80 156T69 133Q55 133 55 166Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-45&quot; d=&quot;M128 619Q121 626 117 628T101 631T58 634H25V680H597V676Q599 670 611 560T625 444V440H585V444Q584 447 582 465Q578 500 570 526T553 571T528 601T498 619T457 629T411 633T353 634Q266 634 251 633T233 622Q233 622 233 621Q232 619 232 497V376H286Q359 378 377 385Q413 401 416 469Q416 471 416 473V493H456V213H416V233Q415 268 408 288T383 317T349 328T297 330Q290 330 286 330H232V196V114Q232 57 237 52Q243 47 289 47H340H391Q428 47 452 50T505 62T552 92T584 146Q594 172 599 200T607 247T612 270V273H652V270Q651 267 632 137T610 3V0H25V46H58Q100 47 109 49T128 61V619Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-78&quot; d=&quot;M201 0Q189 3 102 3Q26 3 17 0H11V46H25Q48 47 67 52T96 61T121 78T139 96T160 122T180 150L226 210L168 288Q159 301 149 315T133 336T122 351T113 363T107 370T100 376T94 379T88 381T80 383Q74 383 44 385H16V431H23Q59 429 126 429Q219 429 229 431H237V385Q201 381 201 369Q201 367 211 353T239 315T268 274L272 270L297 304Q329 345 329 358Q329 364 327 369T322 376T317 380T310 384L307 385H302V431H309Q324 428 408 428Q487 428 493 431H499V385H492Q443 385 411 368Q394 360 377 341T312 257L296 236L358 151Q424 61 429 57T446 50Q464 46 499 46H516V0H510H502Q494 1 482 1T457 2T432 2T414 3Q403 3 377 3T327 1L304 0H295V46H298Q309 46 320 51T331 63Q331 65 291 120L250 175Q249 174 219 133T185 88Q181 83 181 74Q181 63 188 55T206 46Q208 46 208 23V0H201Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-70&quot; d=&quot;M36 -148H50Q89 -148 97 -134V-126Q97 -119 97 -107T97 -77T98 -38T98 6T98 55T98 106Q98 140 98 177T98 243T98 296T97 335T97 351Q94 370 83 376T38 385H20V408Q20 431 22 431L32 432Q42 433 61 434T98 436Q115 437 135 438T165 441T176 442H179V416L180 390L188 397Q247 441 326 441Q407 441 464 377T522 216Q522 115 457 52T310 -11Q242 -11 190 33L182 40V-45V-101Q182 -128 184 -134T195 -145Q216 -148 244 -148H260V-194H252L228 -193Q205 -192 178 -192T140 -191Q37 -191 28 -194H20V-148H36ZM424 218Q424 292 390 347T305 402Q234 402 182 337V98Q222 26 294 26Q345 26 384 80T424 218Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-28&quot; d=&quot;M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-I-1D6FD&quot; d=&quot;M29 -194Q23 -188 23 -186Q23 -183 102 134T186 465Q208 533 243 584T309 658Q365 705 429 705H431Q493 705 533 667T573 570Q573 465 469 396L482 383Q533 332 533 252Q533 139 448 65T257 -10Q227 -10 203 -2T165 17T143 40T131 59T126 65L62 -188Q60 -194 42 -194H29ZM353 431Q392 431 427 419L432 422Q436 426 439 429T449 439T461 453T472 471T484 495T493 524T501 560Q503 569 503 593Q503 611 502 616Q487 667 426 667Q384 667 347 643T286 582T247 514T224 455Q219 439 186 308T152 168Q151 163 151 147Q151 99 173 68Q204 26 260 26Q302 26 349 51T425 137Q441 171 449 214T457 279Q457 337 422 372Q380 358 347 358H337Q258 358 258 389Q258 396 261 403Q275 431 353 431Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-3D&quot; d=&quot;M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-31&quot; d=&quot;M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-2E&quot; d=&quot;M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-30&quot; d=&quot;M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-N-29&quot; d=&quot;M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z&quot;&gt;&lt;/path&gt;&lt;/defs&gt;&lt;g stroke=&quot;currentColor&quot; fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; transform=&quot;scale(1,-1)&quot;&gt;&lt;g data-mml-node=&quot;math&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D440&quot; xlink:href=&quot;#MJX-1-TEX-I-1D440&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(1328.8,0)&quot;&gt;&lt;use data-c=&quot;223C&quot; xlink:href=&quot;#MJX-1-TEX-N-223C&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mtext&quot; transform=&quot;translate(2384.6,0)&quot;&gt;&lt;use data-c=&quot;45&quot; xlink:href=&quot;#MJX-1-TEX-N-45&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;78&quot; xlink:href=&quot;#MJX-1-TEX-N-78&quot; transform=&quot;translate(681,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;70&quot; xlink:href=&quot;#MJX-1-TEX-N-70&quot; transform=&quot;translate(1209,0)&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(4149.6,0)&quot;&gt;&lt;use data-c=&quot;28&quot; xlink:href=&quot;#MJX-1-TEX-N-28&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mi&quot; transform=&quot;translate(4538.6,0)&quot;&gt;&lt;use data-c=&quot;1D6FD&quot; xlink:href=&quot;#MJX-1-TEX-I-1D6FD&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(5382.3,0)&quot;&gt;&lt;use data-c=&quot;3D&quot; xlink:href=&quot;#MJX-1-TEX-N-3D&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mn&quot; transform=&quot;translate(6438.1,0)&quot;&gt;&lt;use data-c=&quot;31&quot; xlink:href=&quot;#MJX-1-TEX-N-31&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;2E&quot; xlink:href=&quot;#MJX-1-TEX-N-2E&quot; transform=&quot;translate(500,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;30&quot; xlink:href=&quot;#MJX-1-TEX-N-30&quot; transform=&quot;translate(778,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;30&quot; xlink:href=&quot;#MJX-1-TEX-N-30&quot; transform=&quot;translate(1278,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;31&quot; xlink:href=&quot;#MJX-1-TEX-N-31&quot; transform=&quot;translate(1778,0)&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(8716.1,0)&quot;&gt;&lt;use data-c=&quot;29&quot; xlink:href=&quot;#MJX-1-TEX-N-29&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/mjx-container&gt;&lt;/div&gt;&lt;p&gt;where &lt;span class=&quot;math math-inline&quot;&gt;&lt;mjx-container class=&quot;MathJax&quot; jax=&quot;SVG&quot;&gt;&lt;svg style=&quot;vertical-align: -0.439ex;&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;1.281ex&quot; height=&quot;2.034ex&quot; role=&quot;img&quot; focusable=&quot;false&quot; viewBox=&quot;0 -705 566 899&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;defs&gt;&lt;path id=&quot;MJX-2-TEX-I-1D6FD&quot; d=&quot;M29 -194Q23 -188 23 -186Q23 -183 102 134T186 465Q208 533 243 584T309 658Q365 705 429 705H431Q493 705 533 667T573 570Q573 465 469 396L482 383Q533 332 533 252Q533 139 448 65T257 -10Q227 -10 203 -2T165 17T143 40T131 59T126 65L62 -188Q60 -194 42 -194H29ZM353 431Q392 431 427 419L432 422Q436 426 439 429T449 439T461 453T472 471T484 495T493 524T501 560Q503 569 503 593Q503 611 502 616Q487 667 426 667Q384 667 347 643T286 582T247 514T224 455Q219 439 186 308T152 168Q151 163 151 147Q151 99 173 68Q204 26 260 26Q302 26 349 51T425 137Q441 171 449 214T457 279Q457 337 422 372Q380 358 347 358H337Q258 358 258 389Q258 396 261 403Q275 431 353 431Z&quot;&gt;&lt;/path&gt;&lt;/defs&gt;&lt;g stroke=&quot;currentColor&quot; fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; transform=&quot;scale(1,-1)&quot;&gt;&lt;g data-mml-node=&quot;math&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D6FD&quot; xlink:href=&quot;#MJX-2-TEX-I-1D6FD&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/mjx-container&gt;&lt;/span&gt; is the mean, and &lt;span class=&quot;math math-inline&quot;&gt;&lt;mjx-container class=&quot;MathJax&quot; jax=&quot;SVG&quot;&gt;&lt;svg style=&quot;vertical-align: 0;&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;2.378ex&quot; height=&quot;1.545ex&quot; role=&quot;img&quot; focusable=&quot;false&quot; viewBox=&quot;0 -683 1051 683&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;defs&gt;&lt;path id=&quot;MJX-3-TEX-I-1D440&quot; d=&quot;M289 629Q289 635 232 637Q208 637 201 638T194 648Q194 649 196 659Q197 662 198 666T199 671T201 676T203 679T207 681T212 683T220 683T232 684Q238 684 262 684T307 683Q386 683 398 683T414 678Q415 674 451 396L487 117L510 154Q534 190 574 254T662 394Q837 673 839 675Q840 676 842 678T846 681L852 683H948Q965 683 988 683T1017 684Q1051 684 1051 673Q1051 668 1048 656T1045 643Q1041 637 1008 637Q968 636 957 634T939 623Q936 618 867 340T797 59Q797 55 798 54T805 50T822 48T855 46H886Q892 37 892 35Q892 19 885 5Q880 0 869 0Q864 0 828 1T736 2Q675 2 644 2T609 1Q592 1 592 11Q592 13 594 25Q598 41 602 43T625 46Q652 46 685 49Q699 52 704 61Q706 65 742 207T813 490T848 631L654 322Q458 10 453 5Q451 4 449 3Q444 0 433 0Q418 0 415 7Q413 11 374 317L335 624L267 354Q200 88 200 79Q206 46 272 46H282Q288 41 289 37T286 19Q282 3 278 1Q274 0 267 0Q265 0 255 0T221 1T157 2Q127 2 95 1T58 0Q43 0 39 2T35 11Q35 13 38 25T43 40Q45 46 65 46Q135 46 154 86Q158 92 223 354T289 629Z&quot;&gt;&lt;/path&gt;&lt;/defs&gt;&lt;g stroke=&quot;currentColor&quot; fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; transform=&quot;scale(1,-1)&quot;&gt;&lt;g data-mml-node=&quot;math&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D440&quot; xlink:href=&quot;#MJX-3-TEX-I-1D440&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/mjx-container&gt;&lt;/span&gt; is the random variable for minutes until
the next MsD.&lt;/p&gt;&lt;p&gt;At this point, you may be asking yourself, what are the implications?&lt;/p&gt;&lt;p&gt;The implications, my friend, are many.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Calculating Probabilities&lt;/h2&gt;&lt;p&gt;First, this means &lt;strong&gt;we can make claims about, say, the probability of
experiencing a moment so dear&lt;/strong&gt;.&lt;/p&gt;&lt;style&gt;
    .vis svg {
        position: relative;
        left: 50%;
        transform: translateX(-50%);
    }

    figure {
        margin: 2rem 0;
    }

    .color {
        font-weight: bold;
    }

    .color.blue {
        color: blue;
    }
    .color.red {
        color: red;
    }
    .color.black {
        color: black;
    }

    input.inline {
        min-width: 1ch;
        padding: 0;
        font-family: inherit;
        font-size: inherit;
        font-weight: bold;
        border: none;
        border-bottom: 1px dotted gray;
        text-align: center;
    }

    .output {
        border-bottom: 1px dotted gray;
    }

    input[type=number]::-webkit-inner-spin-button,
    input[type=number]::-webkit-outer-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }

&lt;/style&gt;&lt;script src=&quot;https://d3js.org/d3.v5.min.js&quot;&gt;&lt;/script&gt;&lt;script&gt;
    const startTime = new Date();
    const format = d3.format(&quot;.2%&quot;)
    const updateProbAnswer = function (el) {
        document.querySelector(&quot;span.prob.output&quot;).innerText = format(cdf(el.value));
    }
    const updateTimeProb = function () {
        let timeDiff = new Date() - startTime;
        timeDiff /= (60 * 1000);
        document.querySelectorAll(&quot;span.time.output&quot;).forEach(el =&gt; el.innerText = format(cdf(timeDiff)))
    }
    window.onload = function () {
        document.querySelectorAll(&quot;input.inline&quot;).forEach(el =&gt; {
            el.style.width = `${el.value.length}ch`;
            el.addEventListener(&quot;keyup&quot;, function (e) {
                e.target.style.width =  `${e.target.value.length}ch`
            })
        })
        document.querySelector(&quot;input.prob&quot;).addEventListener(&quot;change&quot;, e =&gt; {
            updateProbAnswer(e.target);
        })
        updateProbAnswer(document.querySelector(&quot;input.prob&quot;));

        window.setInterval(updateTimeProb, 10)
        init();
    }


    let width = 600;
    let height = 350;
    let margins = {top: 5, right: 0, bottom: 40, left: 30}
    let svg, g, xAxis, yAxis;
    let pdfLine, pdfFill, cdfLine;
    let scaleX, scaleY, area, line;

    let COLORS = {
        gray: &quot;#EFEFEF&quot;,
        blue: &quot;#AAAAFF&quot;
    }
    const LAMBDA = 525000 / 525600.0

    const pdf = (x) =&gt; LAMBDA * Math.E ** (-LAMBDA * x)

    const cdf = (x) =&gt; 1 - Math.E ** (-LAMBDA * x)

    const resize = function () {
        width = window.innerWidth * 0.9;
        svg.attr(&quot;width&quot;, width).attr(&quot;height&quot;, height);
        g.attr(&quot;width&quot;, width - margins.left - margins.right)
            .attr(&quot;height&quot;, height - margins.top - margins.bottom)
            .attr(&quot;transform&quot;, `translate(${margins.left}, ${margins.top})`);
        scaleX = d3.scaleLinear()
            .domain([0, 7])
            .range([0, width - margins.left - margins.right]);
        scaleY = d3.scaleLinear()
            .domain([0, 1])
            .range([height - margins.top - margins.bottom, 0]);
        area = d3.area().x(d =&gt; scaleX(d.x)).y1(d =&gt; scaleY(d.y)).y0(scaleY(0));
        line = d3.line().x(d =&gt; scaleX(d.x)).y(d =&gt; scaleY(d.y));
        xAxis = d3.axisBottom(scaleX)
        yAxis = d3.axisLeft(scaleY)
        update();
    }

    const init = function () {
        console.log(&quot;hello&quot;);
        svg = d3.select(&quot;figure.vis.distribution&quot;).append(&quot;svg&quot;);
        g = svg.append(&quot;g&quot;);
        pdfLine = g.append(&quot;path&quot;).attr(&quot;class&quot;, &quot;pdf__line&quot;);
        pdfFill = g.append(&quot;path&quot;).attr(&quot;class&quot;, &quot;pdf__fill&quot;);
        cdfLine = g.append(&quot;path&quot;).attr(&quot;class&quot;, &quot;cdf__line&quot;);
        g__xaxis = g.append(&quot;g&quot;);
        g__yaxis = g.append(&quot;g&quot;);
        x__label = g.append(&quot;text&quot;);
        resize();
    }

    const update = function () {
        pdfdata = d3.range(0, width - margins.left - margins.right)
            .map(scaleX.invert)
            .map(x =&gt; ({
            x: x,
            y: pdf(x)
        }));
        cdfdata = d3.range(0, width - margins.left - margins.right)
            .map(scaleX.invert)
            .map(x =&gt; ({
            x: x,
            y: cdf(x)
        }));
        pdfFill.datum(pdfdata)
            .attr(&quot;d&quot;, area)
            .attr(&quot;fill&quot;, COLORS.blue)
            .attr(&quot;opacity&quot;, 0.8)
        pdfLine.datum(pdfdata)
            .attr(&quot;d&quot;, line)
            .attr(&quot;fill&quot;, &quot;none&quot;)
            .attr(&quot;stroke-width&quot;, &quot;1px&quot;)
            .attr(&quot;stroke&quot;, &quot;black&quot;);
        cdfLine.datum(cdfdata)
            .attr(&quot;d&quot;, line)
            .attr(&quot;fill&quot;, &quot;none&quot;)
            .attr(&quot;stroke-width&quot;, &quot;1px&quot;)
            .attr(&quot;stroke&quot;, &quot;red&quot;);
        g__xaxis.attr(&quot;transform&quot;, `translate(0, ${height - margins.top - margins.bottom})`)
            .call(xAxis);
        g__yaxis.call(yAxis);
        x__label.attr(&quot;transform&quot;, `translate(${width/2}, ${height - margins.top})`)
            .style(&quot;text-anchor&quot;, &quot;middle&quot;)
            .text(&quot;minutes since last MsD&quot;);
    }
    window.onresize = resize;
&lt;/script&gt;&lt;figure class=&quot;vis distribution&quot;&gt;
&lt;/figure&gt;&lt;p&gt;In this figure, the &lt;span class=&quot;color black&quot;&gt;black&lt;/span&gt; line represents the
probability density function of our random variable &lt;span class=&quot;math math-inline&quot;&gt;&lt;mjx-container class=&quot;MathJax&quot; jax=&quot;SVG&quot;&gt;&lt;svg style=&quot;vertical-align: 0;&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;1.928ex&quot; height=&quot;1.545ex&quot; role=&quot;img&quot; focusable=&quot;false&quot; viewBox=&quot;0 -683 852 683&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;defs&gt;&lt;path id=&quot;MJX-4-TEX-I-1D44B&quot; d=&quot;M42 0H40Q26 0 26 11Q26 15 29 27Q33 41 36 43T55 46Q141 49 190 98Q200 108 306 224T411 342Q302 620 297 625Q288 636 234 637H206Q200 643 200 645T202 664Q206 677 212 683H226Q260 681 347 681Q380 681 408 681T453 682T473 682Q490 682 490 671Q490 670 488 658Q484 643 481 640T465 637Q434 634 411 620L488 426L541 485Q646 598 646 610Q646 628 622 635Q617 635 609 637Q594 637 594 648Q594 650 596 664Q600 677 606 683H618Q619 683 643 683T697 681T738 680Q828 680 837 683H845Q852 676 852 672Q850 647 840 637H824Q790 636 763 628T722 611T698 593L687 584Q687 585 592 480L505 384Q505 383 536 304T601 142T638 56Q648 47 699 46Q734 46 734 37Q734 35 732 23Q728 7 725 4T711 1Q708 1 678 1T589 2Q528 2 496 2T461 1Q444 1 444 10Q444 11 446 25Q448 35 450 39T455 44T464 46T480 47T506 54Q523 62 523 64Q522 64 476 181L429 299Q241 95 236 84Q232 76 232 72Q232 53 261 47Q262 47 267 47T273 46Q276 46 277 46T280 45T283 42T284 35Q284 26 282 19Q279 6 276 4T261 1Q258 1 243 1T201 2T142 2Q64 2 42 0Z&quot;&gt;&lt;/path&gt;&lt;/defs&gt;&lt;g stroke=&quot;currentColor&quot; fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; transform=&quot;scale(1,-1)&quot;&gt;&lt;g data-mml-node=&quot;math&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D44B&quot; xlink:href=&quot;#MJX-4-TEX-I-1D44B&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/mjx-container&gt;&lt;/span&gt;. The &lt;span class=&quot;color red&quot;&gt;red&lt;/span&gt; line, which is more interesting for us, represents
the cumulative density function. This value is the same as the &lt;span class=&quot;color blue&quot;&gt;blue&lt;/span&gt; area under the curve. You can interpret it as
&lt;span class=&quot;color red&quot;&gt;y&lt;/span&gt; is the probability that we experience a moment
so dear in the first &lt;span class=&quot;color red&quot;&gt;x&lt;/span&gt; minutes.&lt;/p&gt;&lt;p&gt;So if we want to know the probability of experiencing a moment so dear in the
five minutes following our previous MsD, we can plug in &lt;input class=&quot;color red inline prob&quot; type=&quot;number&quot; value=&quot;5&quot; /&gt; minutes and solve for &lt;span class=&quot;color red&quot;&gt;y = &lt;span class=&quot;prob output&quot;&gt;&lt;/span&gt;&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;So there&#39;s a 99% chance that a moment so dear will occur within 5 minutes of the
previous one.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Confidence Intervals&lt;/h2&gt;&lt;p&gt;We might also be curious how confident we are in this model. After all, who&#39;s to
say there are always 525,000 moments so dear in a year? We should naturally
expect there to be some variance -- we might get some more dear moments in one
year, in a week, indeed in a minute, than the next!&lt;/p&gt;&lt;p&gt;Assuming we&#39;re right to use the exponential distribution, how good is our guess
of the parameters (in this case, the average waiting time)? Since we&#39;re looking
at means, we can use the Central Limit Theorem to give a rough confidence
interval. We know, for large &lt;span class=&quot;math math-inline&quot;&gt;&lt;mjx-container class=&quot;MathJax&quot; jax=&quot;SVG&quot;&gt;&lt;svg style=&quot;vertical-align: -0.025ex;&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;1.357ex&quot; height=&quot;1.025ex&quot; role=&quot;img&quot; focusable=&quot;false&quot; viewBox=&quot;0 -442 600 453&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;defs&gt;&lt;path id=&quot;MJX-5-TEX-I-1D45B&quot; d=&quot;M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z&quot;&gt;&lt;/path&gt;&lt;/defs&gt;&lt;g stroke=&quot;currentColor&quot; fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; transform=&quot;scale(1,-1)&quot;&gt;&lt;g data-mml-node=&quot;math&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D45B&quot; xlink:href=&quot;#MJX-5-TEX-I-1D45B&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/mjx-container&gt;&lt;/span&gt;, the mean follows the normal distribution&lt;label for=&quot;2&quot; class=&quot;margin-toggle sidenote-number&quot;&gt;&lt;/label&gt;&lt;input type=&quot;checkbox&quot; id=&quot;2&quot; class=&quot;margin-toggle&quot; /&gt;&lt;span class=&quot;sidenote&quot;&gt;parameterized by the mean and the variance (notably, variance and not standard deviation)&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;&lt;mjx-container class=&quot;MathJax&quot; jax=&quot;SVG&quot; display=&quot;true&quot;&gt;&lt;svg style=&quot;vertical-align: -0.566ex;&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;11.186ex&quot; height=&quot;2.565ex&quot; role=&quot;img&quot; focusable=&quot;false&quot; viewBox=&quot;0 -883.9 4944.2 1133.9&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;defs&gt;&lt;path id=&quot;MJX-6-TEX-C-4E&quot; d=&quot;M343 705Q358 705 358 698Q360 696 370 658T411 524T484 319Q536 174 590 82L595 73L615 152Q646 274 683 407Q729 571 752 637T799 727Q852 780 937 788Q939 788 947 788T958 789H962Q979 789 979 765Q979 722 951 692Q942 683 924 683Q888 681 859 672T818 654T803 639Q784 608 708 322T631 15Q631 14 630 15Q630 17 629 15Q628 14 628 12Q621 -4 601 -17T560 -31Q550 -31 546 -28T530 -7Q484 67 458 123T398 272Q352 392 314 514L306 535V534Q306 533 296 488T272 379T234 239T185 100T127 -7T61 -50Q34 -50 4 -34T-27 8Q-27 33 -12 61T18 90Q21 90 36 77T87 57H92Q109 57 123 78T162 173Q206 299 232 417T265 599T276 667Q284 681 304 693T343 705Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-6-TEX-N-28&quot; d=&quot;M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-6-TEX-I-1D707&quot; d=&quot;M58 -216Q44 -216 34 -208T23 -186Q23 -176 96 116T173 414Q186 442 219 442Q231 441 239 435T249 423T251 413Q251 401 220 279T187 142Q185 131 185 107V99Q185 26 252 26Q261 26 270 27T287 31T302 38T315 45T327 55T338 65T348 77T356 88T365 100L372 110L408 253Q444 395 448 404Q461 431 491 431Q504 431 512 424T523 412T525 402L449 84Q448 79 448 68Q448 43 455 35T476 26Q485 27 496 35Q517 55 537 131Q543 151 547 152Q549 153 557 153H561Q580 153 580 144Q580 138 575 117T555 63T523 13Q510 0 491 -8Q483 -10 467 -10Q446 -10 429 -4T402 11T385 29T376 44T374 51L368 45Q362 39 350 30T324 12T288 -4T246 -11Q199 -11 153 12L129 -85Q108 -167 104 -180T92 -202Q76 -216 58 -216Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-6-TEX-N-2C&quot; d=&quot;M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-6-TEX-N-32&quot; d=&quot;M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-6-TEX-N-2F&quot; d=&quot;M423 750Q432 750 438 744T444 730Q444 725 271 248T92 -240Q85 -250 75 -250Q68 -250 62 -245T56 -231Q56 -221 230 257T407 740Q411 750 423 750Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-6-TEX-I-1D45B&quot; d=&quot;M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-6-TEX-N-29&quot; d=&quot;M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z&quot;&gt;&lt;/path&gt;&lt;/defs&gt;&lt;g stroke=&quot;currentColor&quot; fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; transform=&quot;scale(1,-1)&quot;&gt;&lt;g data-mml-node=&quot;math&quot;&gt;&lt;g data-mml-node=&quot;TeXAtom&quot; data-mjx-texclass=&quot;ORD&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;4E&quot; xlink:href=&quot;#MJX-6-TEX-C-4E&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(979,0)&quot;&gt;&lt;use data-c=&quot;28&quot; xlink:href=&quot;#MJX-6-TEX-N-28&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mi&quot; transform=&quot;translate(1368,0)&quot;&gt;&lt;use data-c=&quot;1D707&quot; xlink:href=&quot;#MJX-6-TEX-I-1D707&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(1971,0)&quot;&gt;&lt;use data-c=&quot;2C&quot; xlink:href=&quot;#MJX-6-TEX-N-2C&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;msup&quot; transform=&quot;translate(2415.7,0)&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D707&quot; xlink:href=&quot;#MJX-6-TEX-I-1D707&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mn&quot; transform=&quot;translate(636,413) scale(0.707)&quot;&gt;&lt;use data-c=&quot;32&quot; xlink:href=&quot;#MJX-6-TEX-N-32&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;TeXAtom&quot; data-mjx-texclass=&quot;ORD&quot; transform=&quot;translate(3455.2,0)&quot;&gt;&lt;g data-mml-node=&quot;mo&quot;&gt;&lt;use data-c=&quot;2F&quot; xlink:href=&quot;#MJX-6-TEX-N-2F&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mi&quot; transform=&quot;translate(3955.2,0)&quot;&gt;&lt;use data-c=&quot;1D45B&quot; xlink:href=&quot;#MJX-6-TEX-I-1D45B&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(4555.2,0)&quot;&gt;&lt;use data-c=&quot;29&quot; xlink:href=&quot;#MJX-6-TEX-N-29&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/mjx-container&gt;&lt;/div&gt;&lt;p&gt;We can use this mean and standard deviation to calculate a 95% confidence
interval: we can state with 95% confidence that the true mean of our exponential
distribution lies in the interval &lt;span class=&quot;math math-inline&quot;&gt;&lt;mjx-container class=&quot;MathJax&quot; jax=&quot;SVG&quot;&gt;&lt;svg style=&quot;vertical-align: -0.566ex;&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;13.703ex&quot; height=&quot;2.262ex&quot; role=&quot;img&quot; focusable=&quot;false&quot; viewBox=&quot;0 -750 6056.7 1000&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;defs&gt;&lt;path id=&quot;MJX-7-TEX-N-5B&quot; d=&quot;M118 -250V750H255V710H158V-210H255V-250H118Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-7-TEX-N-30&quot; d=&quot;M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-7-TEX-N-2E&quot; d=&quot;M78 60Q78 84 95 102T138 120Q162 120 180 104T199 61Q199 36 182 18T139 0T96 17T78 60Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-7-TEX-N-39&quot; d=&quot;M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-7-TEX-N-38&quot; d=&quot;M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-7-TEX-N-34&quot; d=&quot;M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-7-TEX-N-2C&quot; d=&quot;M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-7-TEX-N-31&quot; d=&quot;M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-7-TEX-N-5D&quot; d=&quot;M22 710V750H159V-250H22V-210H119V710H22Z&quot;&gt;&lt;/path&gt;&lt;/defs&gt;&lt;g stroke=&quot;currentColor&quot; fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; transform=&quot;scale(1,-1)&quot;&gt;&lt;g data-mml-node=&quot;math&quot;&gt;&lt;g data-mml-node=&quot;mo&quot;&gt;&lt;use data-c=&quot;5B&quot; xlink:href=&quot;#MJX-7-TEX-N-5B&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mn&quot; transform=&quot;translate(278,0)&quot;&gt;&lt;use data-c=&quot;30&quot; xlink:href=&quot;#MJX-7-TEX-N-30&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;2E&quot; xlink:href=&quot;#MJX-7-TEX-N-2E&quot; transform=&quot;translate(500,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;39&quot; xlink:href=&quot;#MJX-7-TEX-N-39&quot; transform=&quot;translate(778,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;39&quot; xlink:href=&quot;#MJX-7-TEX-N-39&quot; transform=&quot;translate(1278,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;38&quot; xlink:href=&quot;#MJX-7-TEX-N-38&quot; transform=&quot;translate(1778,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;34&quot; xlink:href=&quot;#MJX-7-TEX-N-34&quot; transform=&quot;translate(2278,0)&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(3056,0)&quot;&gt;&lt;use data-c=&quot;2C&quot; xlink:href=&quot;#MJX-7-TEX-N-2C&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mn&quot; transform=&quot;translate(3500.7,0)&quot;&gt;&lt;use data-c=&quot;31&quot; xlink:href=&quot;#MJX-7-TEX-N-31&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;2E&quot; xlink:href=&quot;#MJX-7-TEX-N-2E&quot; transform=&quot;translate(500,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;30&quot; xlink:href=&quot;#MJX-7-TEX-N-30&quot; transform=&quot;translate(778,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;30&quot; xlink:href=&quot;#MJX-7-TEX-N-30&quot; transform=&quot;translate(1278,0)&quot;&gt;&lt;/use&gt;&lt;use data-c=&quot;34&quot; xlink:href=&quot;#MJX-7-TEX-N-34&quot; transform=&quot;translate(1778,0)&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mo&quot; transform=&quot;translate(5778.7,0)&quot;&gt;&lt;use data-c=&quot;5D&quot; xlink:href=&quot;#MJX-7-TEX-N-5D&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/mjx-container&gt;&lt;/span&gt;.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Life Lessons&lt;/h2&gt;&lt;p&gt;If you are like me, you may have been surprised by just how frequently these
moments so dear arise. After all, since you&#39;ve loaded this page, there&#39;s a &lt;span class=&quot;time output&quot;&gt;&lt;/span&gt; chance that you&#39;ve experienced a moment so dear.&lt;/p&gt;&lt;p&gt;I certainly didn&#39;t think that was the case, but maybe there&#39;s a lesson to be
learned here.  Maybe I &lt;em&gt;do&lt;/em&gt; experience a moment that I should hold dear every
minute or so.  Maybe we should cherish more of the little things and embrace the
delight that comes with our normal everyday life.&lt;/p&gt;&lt;p&gt;After all, the numbers never lie, right?&lt;/p&gt;&lt;/section&gt;&lt;style&gt;
mjx-container[jax=&quot;SVG&quot;] {
  direction: ltr;
}

mjx-container[jax=&quot;SVG&quot;] &gt; svg {
  overflow: visible;
  min-height: 1px;
  min-width: 1px;
}

mjx-container[jax=&quot;SVG&quot;] &gt; svg a {
  fill: blue;
  stroke: blue;
}

mjx-container[jax=&quot;SVG&quot;][display=&quot;true&quot;] {
  display: block;
  text-align: center;
  margin: 1em 0;
}

mjx-container[jax=&quot;SVG&quot;][display=&quot;true&quot;][width=&quot;full&quot;] {
  display: flex;
}

mjx-container[jax=&quot;SVG&quot;][justify=&quot;left&quot;] {
  text-align: left;
}

mjx-container[jax=&quot;SVG&quot;][justify=&quot;right&quot;] {
  text-align: right;
}

g[data-mml-node=&quot;merror&quot;] &gt; g {
  fill: red;
  stroke: red;
}

g[data-mml-node=&quot;merror&quot;] &gt; rect[data-background] {
  fill: yellow;
  stroke: none;
}

g[data-mml-node=&quot;mtable&quot;] &gt; line[data-line], svg[data-table] &gt; g &gt; line[data-line] {
  stroke-width: 70px;
  fill: none;
}

g[data-mml-node=&quot;mtable&quot;] &gt; rect[data-frame], svg[data-table] &gt; g &gt; rect[data-frame] {
  stroke-width: 70px;
  fill: none;
}

g[data-mml-node=&quot;mtable&quot;] &gt; .mjx-dashed, svg[data-table] &gt; g &gt; .mjx-dashed {
  stroke-dasharray: 140;
}

g[data-mml-node=&quot;mtable&quot;] &gt; .mjx-dotted, svg[data-table] &gt; g &gt; .mjx-dotted {
  stroke-linecap: round;
  stroke-dasharray: 0,140;
}

g[data-mml-node=&quot;mtable&quot;] &gt; g &gt; svg {
  overflow: visible;
}

[jax=&quot;SVG&quot;] mjx-tool {
  display: inline-block;
  position: relative;
  width: 0;
  height: 0;
}

[jax=&quot;SVG&quot;] mjx-tool &gt; mjx-tip {
  position: absolute;
  top: 0;
  left: 0;
}

mjx-tool &gt; mjx-tip {
  display: inline-block;
  padding: .2em;
  border: 1px solid #888;
  font-size: 70%;
  background-color: #F8F8F8;
  color: black;
  box-shadow: 2px 2px 5px #AAAAAA;
}

g[data-mml-node=&quot;maction&quot;][data-toggle] {
  cursor: pointer;
}

mjx-status {
  display: block;
  position: fixed;
  left: 1em;
  bottom: 1em;
  min-width: 25%;
  padding: .2em .4em;
  border: 1px solid #888;
  font-size: 90%;
  background-color: #F8F8F8;
  color: black;
}

foreignObject[data-mjx-xml] {
  font-family: initial;
  line-height: normal;
  overflow: visible;
}

mjx-container[jax=&quot;SVG&quot;] path[data-c], mjx-container[jax=&quot;SVG&quot;] use[data-c] {
  stroke-width: 3;
}
&lt;/style&gt;</content
		>
	</entry>
	<entry>
		<title>Reflections 2019</title>
		<link href="https://naitian.org/blog/2019/12/31/Reflections-2019/" />
		<updated>2019-12-31T08:00:00Z</updated>
		<id>https://naitian.org/blog/2019/12/31/Reflections-2019/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Here we go again.&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;My my, how can I resist you?&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;It&#39;s another year, and that means another end-of-year wrap-up.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/12/31/Reflections-2019/#this-year-in-numbers&quot;&gt;this year in numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/12/31/Reflections-2019/#highlights&quot;&gt;Highlights&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/12/31/Reflections-2019/#reflections&quot;&gt;Reflections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;this year in numbers&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;215&lt;/strong&gt; Github contributions (oof)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;36&lt;/strong&gt; more college credits&lt;/p&gt;&lt;p&gt;&lt;strong&gt;10&lt;/strong&gt; weeks crunching numbers and making graphs this summer at Capital One.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt; musicals attended (watched?) (Miss Saigon, The Band&#39;s Visit, Dear Evan
Hansen, and West Side Story!)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3(?)&lt;/strong&gt; countries visited (Canada, China, Australia, and a layover in New
Zealand).&lt;/p&gt;&lt;p&gt;Over &lt;strong&gt;3.4 thousand&lt;/strong&gt; Facebook reactions on my post in Subtle Asian Dating
analyzing the language use of SAD posts.&lt;/p&gt;&lt;p&gt;And &lt;strong&gt;1&lt;/strong&gt;
&lt;a href=&quot;https://blog.xkcd.com/2019/08/23/book-tour-and-contest-winner/&quot;&gt;shout-out&lt;/a&gt;
from Randall Munroe (of xkcd fame) for my &lt;a href=&quot;https://covers.naitian.org/&quot;&gt;book cover sentence
generator&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Highlights&lt;/h2&gt;&lt;p&gt;If last year was a year of drastic change, this year was one of settling into
the flow of things.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;January&lt;/strong&gt;, I saw Miss Saigon at the Kennedy Center (starring Emily Bautista
as Kim). This was the first of three musicals I had the opportunity to see at
the Kennedy Center this year. Our seats were amazing, and the Kennedy Center is
really beautiful at night (and all the rest of the time too). I also did a lot
of math.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;February&lt;/strong&gt; was a &lt;em&gt;lot&lt;/em&gt; more math homework (it kind of took over my life), but
with one eventful uh... event. As I mentioned above, I wrote up a fun joke paper
analyzing language use of the subtle asian dating Facebook group, and it was met
with lots of positive feedback (and I&#39;m now evaluating whether I have too much
time on my hands).&lt;/p&gt;&lt;p&gt;We had our spring break in &lt;strong&gt;March&lt;/strong&gt;, and that apparently still means college
visits even a year into college. First I went to UVA for HooHacks and to catch
up with some friends from high school (the whole thing was kind of a TJ
reunion). Then I met up with my U-M squad to drive up to Toronto, where we had
Japanese-Mexican fusion tacos, exorbitant amounts of bubble tea, enjoyed
Canadian Netflix, and ate dumplings with my friend at U of Toronto.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;April&lt;/strong&gt;, &lt;a href=&quot;https://blueprintlm.com/&quot;&gt;Blueprint&lt;/a&gt; published its 8th issue
featuring my good friend Xindi&#39;s art on the cover! Also played in the spring
band concert, attended my first Michigan MT performance (Sweeney Todd), and
finished up freshman year of college with Coco bubble tea and instant hotpot.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;May&lt;/strong&gt; was a month at my new home in Michigan. It was also my new home because
I got naturalized! Other noteworthy events included my car getting towed (it&#39;s a
long story) and attending the Dog Bowl in Frankenmuth, MI!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;June&lt;/strong&gt; marked the beginning of my second summer at Capital One. I worked on a
hackathon project which detected when you scrolled past a cat picture and
suggested a donation to your local pet charity based on how many cat pictures
you&#39;ve seen. Also hiked the Billy Goat trail and met up with some friends from
high school.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;July&lt;/strong&gt;, I celebrated my first fourth of July as an American, and watched
the DC fireworks from my apartment in Pentagon City. The day after, I went to
the archives to see Constitution and Declaration of Independence in person for
the first time. Also went to the Lawn at the National Building Museum,
celebrated the 50th anniversary of the moon landing, and got a DC library card.
Last but not least, I saw The Band&#39;s Visit at the Kennedy Center, and that might
have been the highlight of this year. We had amazing tickets in the center of
the orchestra section, and the entire musical was just so beautifully well
crafted. Highly recommend.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;August&lt;/strong&gt; was equally busy. It started with a visit to the White House (cool,
but honestly underwhelming) and farewells to my team and friends at Capital One.
Then Dear Evan Hansen at the Kennedy Center (set design was amazing), seeing the
sunrise in DC, and celebrating &lt;a href=&quot;http://davidzhao.me/&quot;&gt;David&#39;s&lt;/a&gt; 20th birthday
before departing on my travels.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;August Travels&lt;/strong&gt;: First on the itinerary was Santa Monica where I spent my 12
hour layover at LAX. After seeing &lt;em&gt;The Farewell&lt;/em&gt;, eating Street Noods, and
watching a west coast sunset, I took off for Chengdu. In China, I visited
family, friends, and ate lots of food (the existence of AYCE personal hotpot
makes me believe in a higher power). I only spent a couple of days in Chengdu
before heading off to Melbourne, Australia where I met up with my friend Jacob.
We spent over a week in Australia, where we experienced Melbourne&#39;s White Night,
the Twelve Apostles, friendly birds, and delicious food. We also snuck into an
Australian Costco, hiked the Blue Mountains (where we met an international
student from Thailand / Virginia!), explored Sydney, ate emu / kangaroo pizza,
and watched West Side Story at &lt;em&gt;the&lt;/em&gt; Sydney Opera House! Pad that out with
platypi, Nepalese dumplings, and some more hiking, and we&#39;re at September.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;September&lt;/strong&gt; was the start of sophomore year and my first year living in our
house off campus. Also the first MDST meeting in my new role as VP of Projects
(in other news, lots and lots of meetings and planning for the MIDAS Data
Challenge).&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;October&lt;/strong&gt;, we kicked off the MIDAS Data Challenge and had hotpot at
Xindi&#39;s.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;November&lt;/strong&gt;, we wrapped up the Data Challenge, I turned 20 (!!), and I
played Dem Debate Bingo. I also tried quince for the first time.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;December&lt;/strong&gt; was wrapping up the fall semester and wrapping up this semester&#39;s
&lt;a href=&quot;https://www.mdst.club/projects/rateme/rateme-writeup&quot;&gt;MDST project&lt;/a&gt;. Then I
traveled around California with my family, saw lights in Georgetown with
friends, and went to go see the Space Shuttle Discovery at the Udvar-Hazy Center.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Reflections&lt;/h2&gt;&lt;p&gt;Now that we&#39;re heading into 2020, I guess it might be a good idea to look at not
just the past year, but the past decade. A lot has happened in these 10 years.&lt;/p&gt;&lt;p&gt;In 2010, my family had just bought our first house. We bought another car. We
received our green cards. After so many years of uncertainty, worrying about
visas, living in apartments, it felt like things were finally settling down.
Little did I know, the next decade -- the next half of my life -- would see me
moving farther, living in more apartments, and growing much much more than I
could have ever imagined (seriously, who could&#39;ve guessed I&#39;d be over six feet
tall).&lt;/p&gt;&lt;p&gt;I lived in our house for all of 3 years before moving to an apartment totally
foreign city a few hundred miles away. Since 2010, I&#39;ve lived in more than six
different zip codes, I&#39;ve gotten drivers licenses in two states, and I have like
5 different library cards. I moved from a middle school where my biology teacher was
hesitant to teach evolution to one of the best high schools in the nation. I&#39;ve
learned so much about life, about myself, about love, and about linear algebra
(in no particular order). And I know I have so much more to learn and experience
in the next decade, and hopefully many more after that.&lt;/p&gt;&lt;p&gt;Maybe one important lesson I&#39;ve learned, as I step back and look at these past
10 years from a thousand-mile-high vantage point, is that you should never
settle. My dad took a huge risk when he decided to enter residency. My mom took
a huge risk when she decided to move the two of us to Virginia. We had a house,
two cars, and neighbors with a dog. We had a free pass to stay in the country.
According to everything I&#39;ve read, that sounds a lot like the American Dream™.
But sometimes we yearn for something more, and that requires taking risks and
jumping in without knowing exactly where we&#39;ll land. It requires courage,
courage I&#39;m glad my parents had, and courage I hope to inherit as I take my
first steps into adulthood and the pursuit of my own goals and ambitions in 2020.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Matisse is a Team Player</title>
		<link href="https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/" />
		<updated>2019-07-26T07:00:00Z</updated>
		<id>https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/</id>
		<content xml:lang="en" type="html"
			>&lt;figure class=&quot;figure fullwidth&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/bookstory.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;Henri Matisse works well with others in the courtyard of the Kabbalist, and in
the morning, Leonardo&#39;s shadow got to give the people what they want.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Two very influential artists, to be sure, but what was Matisse doing
collaborating with Kabbalists, and what exactly did the people want from
Leonardo&#39;s shadow?&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/#some-context&quot;&gt;Some Context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/#the-project&quot;&gt;The Project&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/#grammar-school-constituency&quot;&gt;Grammar School: Constituency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/#the-nitty-gritty&quot;&gt;The Nitty Gritty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/#parsing&quot;&gt;Parsing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/#creating-sentences&quot;&gt;Creating Sentences&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/26/Matisse-is-a-Team-Player/#gallery&quot;&gt;Gallery&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Some Context&lt;/h2&gt;&lt;p&gt;In mid-June, Randall Munroe, the genius behind &lt;a href=&quot;http://xkcd.com/&quot;&gt;xkcd&lt;/a&gt; and the
author of
&lt;a href=&quot;https://www.amazon.com/Thing-Explainer-Complicated-Stuff-Simple/dp/0544668251/&quot;&gt;quite&lt;/a&gt;
a
&lt;a href=&quot;https://www.amazon.com/What-If-Scientific-Hypothetical-Questions-ebook/dp/B00IYUYF4A&quot;&gt;few&lt;/a&gt;
&lt;a href=&quot;https://www.amazon.com/How-Absurd-Scientific-Real-World-Problems/dp/0525537090&quot;&gt;books&lt;/a&gt;,
announced he was going on a book tour to promote his latest book: &lt;em&gt;How To:
Absurd Scientific Advice for Common Real-World Problems&lt;/em&gt;&lt;/p&gt;&lt;p&gt;As part of the announcement, he introduced an interesting challenge:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Write the best story using nothing but book covers.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;The winner of the challenge would be rewarded by a visit from Munroe as part of
the tour. Even though Ann Arbor was already in the itinerary, I couldn&#39;t help
but think about this challenge... and how I could use some of my linguistics
knowledge to my advantage.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The Project&lt;/h2&gt;&lt;p&gt;I decided I would try to hack this challenge by acquiring a dataset of book
titles, and having a computer generate these stories for me.&lt;/p&gt;&lt;p&gt;I found a &lt;a href=&quot;https://github.com/uchidalab/book-dataset/&quot;&gt;list&lt;/a&gt; of over 200,000
books listed on Amazon, and a couple of Jupyter notebooks and Python packages
later, we were off to the races.&lt;/p&gt;&lt;h3&gt;Grammar School: Constituency&lt;/h3&gt;&lt;p&gt;The key concept behind this project was something I learned in my introduction
to linguistics class last fall: constituency trees. The basic idea is that each
sentence can be represented as a combination of words and phrases
(constituents).&lt;/p&gt;&lt;p&gt;For example, a sentence is, in its base form, a noun phrase and a verb phrase:&lt;/p&gt;&lt;p&gt;&lt;code&gt;S -&gt; NP VP&lt;/code&gt;&lt;/p&gt;&lt;p&gt;And a noun phrase might be a noun, with optional adjectives and determiners, and
maybe a prepositional phrase.&lt;/p&gt;&lt;p&gt;&lt;code&gt;NP -&gt; [DET] [ADJ] N [PP]&lt;/code&gt;&lt;/p&gt;&lt;p&gt;And a prepositional phrase, in turn, might be a preposition followed by a noun
phrase.&lt;/p&gt;&lt;p&gt;&lt;code&gt;PP -&gt; [P] [NP]&lt;/code&gt;&lt;/p&gt;&lt;p&gt;And in this way, we can construct a very expressive and &lt;em&gt;productive&lt;/em&gt; grammar for
the English language. Productivity here means that, with even a limited
vocabulary, we can form many distinct sentences and thoughts.&lt;/p&gt;&lt;p&gt;So the main idea was we would label each book title as a noun phrase, verb phrase,
adjective phrase, etc. Then, we could use this grammar to compose sentences.&lt;/p&gt;&lt;h3&gt;The Nitty Gritty&lt;/h3&gt;&lt;p&gt;Although there were over 200,000 books in the dataset, I couldn&#39;t use all of
them. In fact, out of 32 categories, I used only 10. Books with categories such
as cookbooks, calendars, etc were excluded because those titles were generally
not very useful.&lt;/p&gt;&lt;p&gt;The categories I ended up using were:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Biographies &amp;#x26; Memoirs&lt;/li&gt;
&lt;li&gt;Children&#39;s Books&lt;/li&gt;
&lt;li&gt;Engineering &amp;#x26; Transportation&lt;/li&gt;
&lt;li&gt;History&lt;/li&gt;
&lt;li&gt;Humor &amp;#x26; Entertainment&lt;/li&gt;
&lt;li&gt;Literature &amp;#x26; Fiction&lt;/li&gt;
&lt;li&gt;Mystery, Thriller &amp;#x26; Suspense&lt;/li&gt;
&lt;li&gt;Science Fiction &amp;#x26; Fantasy&lt;/li&gt;
&lt;li&gt;Self-Help&lt;/li&gt;
&lt;li&gt;Teen &amp;#x26; Young Adult&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I also did some preprocessing on the titles before parsing the constituents.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-py&quot;&gt;cleaned_titles = books.title.&lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;.lower()  &lt;span class=&quot;hljs-comment&quot;&gt;# Lowercase&lt;/span&gt;
cleaned_titles = cleaned_titles.&lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;.replace(&lt;span class=&quot;hljs-string&quot;&gt;r&quot;\(.+\)&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;)  &lt;span class=&quot;hljs-comment&quot;&gt;# Remove everything in parentheses&lt;/span&gt;
cleaned_titles = cleaned_titles.&lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;.replace(&lt;span class=&quot;hljs-string&quot;&gt;r&quot;\[.+\]&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;)  &lt;span class=&quot;hljs-comment&quot;&gt;# Remove everything in brackets&lt;/span&gt;
cleaned_titles = cleaned_titles.&lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;.replace(&lt;span class=&quot;hljs-string&quot;&gt;r&quot;(volume|vol\.) (\d+|\w+)&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;)  &lt;span class=&quot;hljs-comment&quot;&gt;# Remove volume numbers&lt;/span&gt;
cleaned_titles = cleaned_titles.&lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;.replace(&lt;span class=&quot;hljs-string&quot;&gt;r&quot;issue (\d+|\w+)&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;)  &lt;span class=&quot;hljs-comment&quot;&gt;# Remove issue numbers&lt;/span&gt;
cleaned_titles = cleaned_titles.&lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;.strip(&lt;span class=&quot;hljs-string&quot;&gt;&#39;-, &#39;&lt;/span&gt;)  &lt;span class=&quot;hljs-comment&quot;&gt;# Remove dashes&lt;/span&gt;
cleaned_titles = cleaned_titles.apply(&lt;span class=&quot;hljs-keyword&quot;&gt;lambda&lt;/span&gt; x: x.split(&lt;span class=&quot;hljs-string&quot;&gt;&#39;:&#39;&lt;/span&gt;)[&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;])  &lt;span class=&quot;hljs-comment&quot;&gt;# Only keep first part of title (no subtitles)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The last part -- getting rid of subtitles -- sometimes helped and sometimes did
not.&lt;/p&gt;&lt;h3&gt;Parsing&lt;/h3&gt;&lt;p&gt;I used &lt;a href=&quot;https://pypi.org/project/benepar/&quot;&gt;benepar&lt;/a&gt;, which is a state of the art
constituency parser that fits nicely into NLTK. I found that it provided decent
results. One issue that I ran into was handling more granular details such as
subject verb plurality alignment. In those cases, I wanted to know what the noun
was in the noun phrase, etc.&lt;/p&gt;&lt;p&gt;For this, I used a different grammar model: dependency grammar. In dependency
grammars, instead constituents, each word is dependent on exactly one other word
in the sentence. This image from Wikipedia is pretty good at showing the
difference between the two.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/0/0d/Wearetryingtounderstandthedifference_%282%29.jpg&quot; alt=&quot;Dependency vs Constituency&quot; /&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;I use the root of each dependency tree as the &quot;active noun&quot; or &quot;active verb&quot; in
the phrase, and their parts of speech include markers for plurality, properness,
verb tense, etc.&lt;/p&gt;&lt;h3&gt;Creating Sentences&lt;/h3&gt;&lt;p&gt;Afterwards, it was just a process of returning a random sample for each
constituent. I wanted the sentence generation to be completely automated, but I
ended up adopting a more hybrid process where I would query for noun phrases,
for example, until I found one I thought was interesting, then move on to a verb
phrase.&lt;/p&gt;&lt;h3&gt;Gallery&lt;/h3&gt;&lt;p&gt;Here are a couple more sentences I put together with the help of computers. Stay
tuned for an online interactive version in coming days that will let you
construct your own book cover stories.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://imgur.com/w7eq9RN.jpg&quot; alt=&quot;&quot; /&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Radioactive horses and ponies thank you for being a good friend, but not the
hippopotamus.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://imgur.com/PXWmSqe.jpg&quot; alt=&quot;&quot; /&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;19 varieties of gazelle found apple, apples everywhere!&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://imgur.com/eLuT35e.jpg&quot; alt=&quot;&quot; /&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;The Russian Kremlin desperately seeking exclusivity around the world with
Justin Bieber.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Merry Belated Christmas</title>
		<link href="https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/" />
		<updated>2019-07-07T07:00:00Z</updated>
		<id>https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Christmas in July&lt;/h2&gt;&lt;p&gt;It&#39;s Independence Day when I&#39;m writing this, which seems like a good time to
write about my winter holiday cards from last year. In a previous blog post, I
wrote about a small project I made with my
&lt;a href=&quot;https://naitian.holiday/isyp&quot;&gt;naitian.holiday&lt;/a&gt; domain name.  However, that
wasn&#39;t the original purpose for the domain. The first use for the domain was
digital holiday cards for some of my friends.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/#planning&quot;&gt;Planning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/#implementation&quot;&gt;Implementation&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/#infrastructure&quot;&gt;Infrastructure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/#design&quot;&gt;Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/#build-process&quot;&gt;Build Process&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/#authentication&quot;&gt;Authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/07/07/Merry-Belated-Christmas/#email-notifications&quot;&gt;Email Notifications&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Planning&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;AKA all the things I wanted to do but didn&#39;t.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;There were a couple of clear requirements that were non-negotiable:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;There had to be at least some form of authentication (so not everyone can see
everyone else&#39;s card)&lt;/li&gt;
&lt;li&gt;Emails would be sent out notifying people of their cards.&lt;/li&gt;
&lt;li&gt;Cards need to be personalized with:
&lt;ul&gt;
&lt;li&gt;Greeting&lt;/li&gt;
&lt;li&gt;Name (duh)&lt;/li&gt;
&lt;li&gt;Message&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Later, I also decided a couple more requirements, both for fun and for
education:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Everything would be compiled and hosted statically on S3.&lt;/li&gt;
&lt;li&gt;In the theme of using AWS for everything, I&#39;d also send email notifications
with Amazon&#39;s Simple Email Service (SES) and handle domain name /
certificates with Route53.&lt;/li&gt;
&lt;li&gt;Each person would only see pretty URLs (e.g. naitian.holiday/nate)&lt;/li&gt;
&lt;li&gt;Cards would include these draggable Polaroid-style pictures from my Google
Photos.&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Implementation&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;AKA what I ended up doing&lt;/p&gt;
&lt;/blockquote&gt;&lt;h3&gt;Infrastructure&lt;/h3&gt;&lt;p&gt;I will be totally honest with you and say I don&#39;t actually remember all the
details to the infrastructure on AWS, but it wasn&#39;t super complex. The gist is:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;All the static files are hosted with S3&#39;s static website hosting.&lt;/li&gt;
&lt;li&gt;I used Cloudfront as the CDN for the S3 files.&lt;/li&gt;
&lt;li&gt;I have a hosted zone for &lt;code&gt;naitian.holiday&lt;/code&gt; in Route53 which points to the
Cloudfront endpoint (which in turn points to the S3 bucket).&lt;/li&gt;
&lt;li&gt;Photos were hosted on Google Photos&lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;Design&lt;/h3&gt;&lt;p&gt;Aesthetically, I decided to go for a festive red with a subtle gradient. I chose
a classy serif typeface and drew this freaking amazing &lt;del&gt;Christmas&lt;/del&gt;
non-denominational holiday tree.&lt;/p&gt;&lt;h3&gt;Build Process&lt;/h3&gt;&lt;p&gt;Each card was defined as a yaml file. I wrote a Python script to read these yaml
files and used markdown to render them into HTML files. At the same time, I
generated the SES email template data for bulk sending the notification emails.&lt;/p&gt;&lt;p&gt;I also had a Makefile which would run the rendering script, compile the SCSS
into CSS, minify CSS and JS, and push everything to S3. There were also Make
steps which would send a test email and send out the actual emails.&lt;/p&gt;&lt;h3&gt;Authentication&lt;/h3&gt;&lt;p&gt;One of the most interesting parts of this whole exercise was figuring out a good
authentication method. I definitely did not want to make anyone sign in or
create any accounts (partly also because I wanted this to be a totally static
site).&lt;/p&gt;&lt;p&gt;I ended up compromising with a &quot;good-enough&quot; authentication plan, which I had to
alter a little bit to also keep the pretty URLs. Here&#39;s how it ended up working:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;When a card is rendered, it is actually placed in a directory named after its
SHA256 hash.&lt;/li&gt;
&lt;li&gt;This hash is used as an auth token in the link.&lt;/li&gt;
&lt;li&gt;Not only is an HTML file generated with the card&#39;s content, another HTML page
is generated with Javascript for authentication and a hidden input field
containing a SHA256 hash of the token.&lt;/li&gt;
&lt;li&gt;When a user navigates to the site (e.g. naitian.holidy/nate), they are
actually navigating to the page with only the auth code.
&lt;ul&gt;
&lt;li&gt;On the client side, the token (if it&#39;s present) is hashed and compared
to the correct token.&lt;/li&gt;
&lt;li&gt;If incorrect, the user is rejected.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If correct, there is an XHR request that fetches the actual HTML and displays
it.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;This means the user would have a hard time even realizing that any
authentication had occurred in the first place.&lt;/p&gt;&lt;p&gt;To recap, for each card, the path structure looked like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-axapta&quot;&gt;naitian.holiday/&amp;#x3C;SHA256&gt;/&lt;span class=&quot;hljs-keyword&quot;&gt;index&lt;/span&gt;.html   &amp;#x3C;- &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; the HTML &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; the card
naitian.holiday/nate/&lt;span class=&quot;hljs-keyword&quot;&gt;index&lt;/span&gt;.html       &amp;#x3C;- &lt;span class=&quot;hljs-keyword&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; the HTML &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; authentication
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Of course, I also added a &lt;code&gt;robots.txt&lt;/code&gt; which disallowed any crawling. This makes
it pretty difficult to find the (very much public) SHA256 paths of any of the
cards.&lt;/p&gt;&lt;p&gt;So, while not airtight, this worked well enough to prevent people from just
typing in names of other people to see their cards.&lt;/p&gt;&lt;p&gt;I also stored the tokens in local storage, so after the first visit, the token
isn&#39;t actually required.&lt;/p&gt;&lt;p&gt;Nifty.&lt;/p&gt;&lt;h3&gt;Email Notifications&lt;/h3&gt;&lt;p&gt;Emails were surprisingly straightforward to set up. I used the Simple Email
Service from Amazon. Initially, I planned to do a lot more CSS for the HTML
emails, but ultimately decided against it for two reasons: it would have been
more work to implement and try to test, and I felt like it would feel more
personal if it was more &quot;raw&quot;.&lt;/p&gt;&lt;p&gt;I had a &lt;code&gt;make&lt;/code&gt; rule which would send just test emails to myself and a different
rule to send out the emails for real.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>April Showers</title>
		<link href="https://naitian.org/blog/2019/04/20/April-Showers/" />
		<updated>2019-04-20T07:00:00Z</updated>
		<id>https://naitian.org/blog/2019/04/20/April-Showers/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;p&gt;It&#39;s supposed to rain all of today, and I&#39;m stuck inside, so I figured now might
be a good time to post this &quot;poem&quot; (flash fiction? flash flood?) that I wrote a
while ago.&lt;/p&gt;&lt;p&gt;I don&#39;t usually post my poetry, because I write these mostly for myself, but
here&#39;s a glimpse, I guess.&lt;/p&gt;&lt;p&gt;Of course, this one isn&#39;t actually about the rain -- but I do feel way more
comfortable writing about the weather than anything else this may be about, so
here you go. I&#39;ll stop stalling now.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Torrential&lt;/h2&gt;&lt;p&gt;A day in late summer.&lt;/p&gt;&lt;p&gt;You awaken one morning and it&#39;s in the air. The smell of anticipation. An
overwhelming sensation of tension.&lt;/p&gt;&lt;p&gt;It&#39;s in the air. Not rain, but the hint of rain. Not a storm, but the shadow of
a storm. You step outside and feel it on your skin.&lt;/p&gt;&lt;p&gt;And you brace yourself for the inevitable, the torrential.&lt;/p&gt;&lt;p&gt;The downpour.&lt;/p&gt;&lt;p&gt;As if God himself had flipped a switch and opened the gates. An instantaneous,
miraculous change. A refreshing change. And a flood of everything you didn&#39;t
know you wanted.&lt;/p&gt;&lt;p&gt;You stand there, getting drenched, revelling in the power of the staccato
beats, getting your fill, until you&#39;re dripping in it. The water rubs away any
past dirt still clinging to your skin.&lt;/p&gt;&lt;p&gt;A small voice way in the back is shouting at you, about ruining your clothes,
about catching a cold. But in the moment, that voice gives way to the
excitement, the thrill, the flashes of lightning, the crashes of thunder&lt;/p&gt;&lt;p&gt;You&#39;re afraid to move -- afraid that one wrong move would make it all stop.
Weather is finicky in that way, you say. So you stand there, paralyzed,
wondering how long until this, too, comes to an end.&lt;/p&gt;&lt;p&gt;&lt;em&gt;flip&lt;/em&gt;&lt;/p&gt;&lt;p&gt;And the rain stops. The clouds part, the sun reveals itself, and fresh, cool
rain makes way for suffocating humidity.&lt;/p&gt;&lt;p&gt;For the storm is gone, as quickly as it came, but a lingering taste remains of
what used to be.&lt;/p&gt;&lt;p&gt;The wet, sticky air clings to your skin, not letting go. Unable to let go.
Refusing to let go.&lt;/p&gt;&lt;p&gt;The dampness hangs there, static and unyielding, and you stand just as still as
before. You ask out loud, &quot;Where do I go now?&quot;&lt;/p&gt;&lt;p&gt;But the only response is the sound of water droplets dripping off your shirt.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Subtle Asian Meta</title>
		<link href="https://naitian.org/blog/2019/02/08/Subtle-Asian-Meta/" />
		<updated>2019-02-08T08:00:00Z</updated>
		<id>https://naitian.org/blog/2019/02/08/Subtle-Asian-Meta/</id>
		<content xml:lang="en" type="html"
			>&lt;blockquote&gt;
&lt;p&gt;Shameless plug: If you, one of the 5 people who visit this blog every month,
work in computational linguistics or related research, please contact me at
naitian at umich.edu. I would love to pick your brain and maybe even work with
you. Thank you and enjoy the rest of the show.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;section&gt;&lt;h2&gt;Subtle Asian Data&lt;/h2&gt;&lt;p&gt;I recently published a joke paper I wrote over the course of about three months
(with the help of David). While entirely a joke, it also contained entirely real
analysis of &lt;em&gt;subtle asian dating&lt;/em&gt; user demographics and language.&lt;/p&gt;&lt;p&gt;Here&#39;s the abstract:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Recent subtle asian Facebook groups have gained incredible popularity among
young adult Asian diaspora. We focus on one of these groups – &lt;em&gt;subtle asian dating&lt;/em&gt;
– and conduct a content analysis on its posts to examine what it can tell us about
the members of Asian youth subculture, and how their identity and culture affect
their view of and approach to dating and relationships.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;You can find the entire paper
&lt;a href=&quot;http://www-personal.umich.edu/~naitian/pub/subtleAsianData2019.pdf&quot;&gt;here&lt;/a&gt;. I
highly recommend it -- what it lacks in insight, it makes up for in just how
ridiculous it is.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The Critical Reaction&lt;/h2&gt;&lt;p&gt;The obvious resulting course of action was to post my paper on &lt;em&gt;subtle asian
dating&lt;/em&gt;. The post took off in popularity, gaining over 3.4 thousand reactions
and close to a thousand comments over the next three days.&lt;/p&gt;&lt;p&gt;The comments were pretty interesting to read at first, and for maybe the first
half of the first day, I was keeping up pretty closely as they rolled in.&lt;/p&gt;&lt;p&gt;That&#39;s when I made the following astute observation to my friend:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;So I think the breakdown in comments right now is:&lt;/p&gt;
&lt;p&gt;50% about how it was typeset in latex&lt;/p&gt;
&lt;p&gt;20% why did you do this&lt;/p&gt;
&lt;p&gt;10% umich represent!&lt;/p&gt;
&lt;p&gt;10% I&#39;m ashamed to go to the same school as this guy&lt;/p&gt;
&lt;p&gt;And 10% miscellaneous&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;To which she responded:&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;HAHA&lt;/p&gt;
&lt;p&gt;Misc tagging&lt;/p&gt;
&lt;p&gt;always&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Naturally, after the commenting had died down, I had to check myself. How far
off was I with my predictions? (Hint: very)&lt;/p&gt;&lt;p&gt;Just how many comments &lt;em&gt;were&lt;/em&gt; misc tagging? (Hint: not that many)&lt;/p&gt;&lt;p&gt;Exactly how many people were impressed with my LaTeX skills? (Hint: my &lt;span class=&quot;math math-inline&quot;&gt;&lt;mjx-container class=&quot;MathJax&quot; jax=&quot;SVG&quot;&gt;&lt;svg style=&quot;vertical-align: -0.488ex;&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;6.293ex&quot; height=&quot;2.108ex&quot; role=&quot;img&quot; focusable=&quot;false&quot; viewBox=&quot;0 -716.3 2781.3 931.8&quot; xmlns:xlink=&quot;http://www.w3.org/1999/xlink&quot;&gt;&lt;defs&gt;&lt;path id=&quot;MJX-1-TEX-I-1D43F&quot; d=&quot;M228 637Q194 637 192 641Q191 643 191 649Q191 673 202 682Q204 683 217 683Q271 680 344 680Q485 680 506 683H518Q524 677 524 674T522 656Q517 641 513 637H475Q406 636 394 628Q387 624 380 600T313 336Q297 271 279 198T252 88L243 52Q243 48 252 48T311 46H328Q360 46 379 47T428 54T478 72T522 106T564 161Q580 191 594 228T611 270Q616 273 628 273H641Q647 264 647 262T627 203T583 83T557 9Q555 4 553 3T537 0T494 -1Q483 -1 418 -1T294 0H116Q32 0 32 10Q32 17 34 24Q39 43 44 45Q48 46 59 46H65Q92 46 125 49Q139 52 144 61Q147 65 216 339T285 628Q285 635 228 637Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-I-1D434&quot; d=&quot;M208 74Q208 50 254 46Q272 46 272 35Q272 34 270 22Q267 8 264 4T251 0Q249 0 239 0T205 1T141 2Q70 2 50 0H42Q35 7 35 11Q37 38 48 46H62Q132 49 164 96Q170 102 345 401T523 704Q530 716 547 716H555H572Q578 707 578 706L606 383Q634 60 636 57Q641 46 701 46Q726 46 726 36Q726 34 723 22Q720 7 718 4T704 0Q701 0 690 0T651 1T578 2Q484 2 455 0H443Q437 6 437 9T439 27Q443 40 445 43L449 46H469Q523 49 533 63L521 213H283L249 155Q208 86 208 74ZM516 260Q516 271 504 416T490 562L463 519Q447 492 400 412L310 260L413 259Q516 259 516 260Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-I-1D447&quot; d=&quot;M40 437Q21 437 21 445Q21 450 37 501T71 602L88 651Q93 669 101 677H569H659Q691 677 697 676T704 667Q704 661 687 553T668 444Q668 437 649 437Q640 437 637 437T631 442L629 445Q629 451 635 490T641 551Q641 586 628 604T573 629Q568 630 515 631Q469 631 457 630T439 622Q438 621 368 343T298 60Q298 48 386 46Q418 46 427 45T436 36Q436 31 433 22Q429 4 424 1L422 0Q419 0 415 0Q410 0 363 1T228 2Q99 2 64 0H49Q43 6 43 9T45 27Q49 40 55 46H83H94Q174 46 189 55Q190 56 191 56Q196 59 201 76T241 233Q258 301 269 344Q339 619 339 625Q339 630 310 630H279Q212 630 191 624Q146 614 121 583T67 467Q60 445 57 441T43 437H40Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-I-1D438&quot; d=&quot;M492 213Q472 213 472 226Q472 230 477 250T482 285Q482 316 461 323T364 330H312Q311 328 277 192T243 52Q243 48 254 48T334 46Q428 46 458 48T518 61Q567 77 599 117T670 248Q680 270 683 272Q690 274 698 274Q718 274 718 261Q613 7 608 2Q605 0 322 0H133Q31 0 31 11Q31 13 34 25Q38 41 42 43T65 46Q92 46 125 49Q139 52 144 61Q146 66 215 342T285 622Q285 629 281 629Q273 632 228 634H197Q191 640 191 642T193 659Q197 676 203 680H757Q764 676 764 669Q764 664 751 557T737 447Q735 440 717 440H705Q698 445 698 453L701 476Q704 500 704 528Q704 558 697 578T678 609T643 625T596 632T532 634H485Q397 633 392 631Q388 629 386 622Q385 619 355 499T324 377Q347 376 372 376H398Q464 376 489 391T534 472Q538 488 540 490T557 493Q562 493 565 493T570 492T572 491T574 487T577 483L544 351Q511 218 508 216Q505 213 492 213Z&quot;&gt;&lt;/path&gt;&lt;path id=&quot;MJX-1-TEX-I-1D44B&quot; d=&quot;M42 0H40Q26 0 26 11Q26 15 29 27Q33 41 36 43T55 46Q141 49 190 98Q200 108 306 224T411 342Q302 620 297 625Q288 636 234 637H206Q200 643 200 645T202 664Q206 677 212 683H226Q260 681 347 681Q380 681 408 681T453 682T473 682Q490 682 490 671Q490 670 488 658Q484 643 481 640T465 637Q434 634 411 620L488 426L541 485Q646 598 646 610Q646 628 622 635Q617 635 609 637Q594 637 594 648Q594 650 596 664Q600 677 606 683H618Q619 683 643 683T697 681T738 680Q828 680 837 683H845Q852 676 852 672Q850 647 840 637H824Q790 636 763 628T722 611T698 593L687 584Q687 585 592 480L505 384Q505 383 536 304T601 142T638 56Q648 47 699 46Q734 46 734 37Q734 35 732 23Q728 7 725 4T711 1Q708 1 678 1T589 2Q528 2 496 2T461 1Q444 1 444 10Q444 11 446 25Q448 35 450 39T455 44T464 46T480 47T506 54Q523 62 523 64Q522 64 476 181L429 299Q241 95 236 84Q232 76 232 72Q232 53 261 47Q262 47 267 47T273 46Q276 46 277 46T280 45T283 42T284 35Q284 26 282 19Q279 6 276 4T261 1Q258 1 243 1T201 2T142 2Q64 2 42 0Z&quot;&gt;&lt;/path&gt;&lt;/defs&gt;&lt;g stroke=&quot;currentColor&quot; fill=&quot;currentColor&quot; stroke-width=&quot;0&quot; transform=&quot;scale(1,-1)&quot;&gt;&lt;g data-mml-node=&quot;math&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D43F&quot; xlink:href=&quot;#MJX-1-TEX-I-1D43F&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mspace&quot; transform=&quot;translate(681,0)&quot;&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mpadded&quot; transform=&quot;translate(356,0)&quot;&gt;&lt;g transform=&quot;translate(0,210)&quot;&gt;&lt;g data-mml-node=&quot;TeXAtom&quot; data-mjx-texclass=&quot;ORD&quot;&gt;&lt;g data-mml-node=&quot;mstyle&quot; transform=&quot;scale(0.707)&quot;&gt;&lt;g data-mml-node=&quot;TeXAtom&quot; data-mjx-texclass=&quot;ORD&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D434&quot; xlink:href=&quot;#MJX-1-TEX-I-1D434&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mspace&quot; transform=&quot;translate(886.3,0)&quot;&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mi&quot; transform=&quot;translate(716.3,0)&quot;&gt;&lt;use data-c=&quot;1D447&quot; xlink:href=&quot;#MJX-1-TEX-I-1D447&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mspace&quot; transform=&quot;translate(1420.3,0)&quot;&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mpadded&quot; transform=&quot;translate(1280.3,0)&quot;&gt;&lt;g transform=&quot;translate(0,-215.5)&quot;&gt;&lt;g data-mml-node=&quot;TeXAtom&quot; data-mjx-texclass=&quot;ORD&quot;&gt;&lt;g data-mml-node=&quot;mi&quot;&gt;&lt;use data-c=&quot;1D438&quot; xlink:href=&quot;#MJX-1-TEX-I-1D438&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mspace&quot; transform=&quot;translate(2044.3,0)&quot;&gt;&lt;/g&gt;&lt;g data-mml-node=&quot;mi&quot; transform=&quot;translate(1929.3,0)&quot;&gt;&lt;use data-c=&quot;1D44B&quot; xlink:href=&quot;#MJX-1-TEX-I-1D44B&quot;&gt;&lt;/use&gt;&lt;/g&gt;&lt;/g&gt;&lt;/g&gt;&lt;/svg&gt;&lt;/mjx-container&gt;&lt;/span&gt;
skills are not very impressive)&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Subtle Asian Meta&lt;/h2&gt;&lt;p&gt;So I went ahead and scraped all the comments from the post.&lt;/p&gt;&lt;h3&gt;Data Collection&lt;/h3&gt;&lt;p&gt;For the curious, I did all the data collection in Chrome Dev Tools.&lt;/p&gt;&lt;p&gt;Terrible code, but it worked I guess.&lt;/p&gt;&lt;h3&gt;Analysis&lt;/h3&gt;&lt;p&gt;I tossed the generated JSON object into Jupyter Notebook to see what I could
get. The following numbers are just for top level comments (this means replies
are excluded):&lt;/p&gt;&lt;p&gt;There were &lt;strong&gt;618&lt;/strong&gt; comments. Almost &lt;strong&gt;95%&lt;/strong&gt; of users tagged someone else in their
comment, so &quot;misc tagging&quot; was pretty accurate. However, I was more interested
in who commented &lt;em&gt;only&lt;/em&gt; to tag someone else. That is, the body of their comment
consisted only of a tag.&lt;/p&gt;&lt;p&gt;In that case, the number drops to less than &lt;strong&gt;25%&lt;/strong&gt;. But wait, there&#39;s more.&lt;/p&gt;&lt;p&gt;How many people were impressed with my LaTeX? Surely less than 50%. And Shirley
would be correct. In fact, only &lt;strong&gt;6.5%&lt;/strong&gt; (N=40) mentioned LaTeX in their
comments.&lt;/p&gt;&lt;p&gt;And how many people thought it was cool that I went to their school? Well, I
looked through the posts and filtered by any of the following keywords:&lt;/p&gt;&lt;p&gt;&lt;code&gt;[&#39;school&#39;, &#39;michigan&#39;, &#39;hoo&#39;, &#39;blue&#39;, &#39;umich&#39;, &#39;mich&#39;, &#39;uva&#39;, &#39;virginia&#39;]&lt;/code&gt;&lt;/p&gt;&lt;p&gt;which encompasses both U-M and UVa. A couple of false positives? Probably. False
negatives? Also probably. But this gives us a general sense. Even fewer comments
matched the criteria for this filter: &lt;strong&gt;5.8%&lt;/strong&gt; (N=36).&lt;/p&gt;&lt;p&gt;Finally, I took a cursory glance at who was incredulous, by filtering by the
following keywords:&lt;/p&gt;&lt;p&gt;&lt;code&gt;[&#39;wtf&#39;, &#39;why&#39;, &#39;time&#39;, &#39;tf&#39;, &#39;believe&#39;]&lt;/code&gt;&lt;/p&gt;&lt;p&gt;And it turns out that only includes &lt;strong&gt;5%&lt;/strong&gt; of posts.&lt;/p&gt;&lt;p&gt;In conclusion, I was totally wrong, but my version of reality was way funnier,
so who really won this fight?&lt;/p&gt;&lt;p&gt;So there you go. &lt;em&gt;subtle asian metadata&lt;/em&gt;&lt;/p&gt;&lt;/section&gt;&lt;style&gt;
mjx-container[jax=&quot;SVG&quot;] {
  direction: ltr;
}

mjx-container[jax=&quot;SVG&quot;] &gt; svg {
  overflow: visible;
  min-height: 1px;
  min-width: 1px;
}

mjx-container[jax=&quot;SVG&quot;] &gt; svg a {
  fill: blue;
  stroke: blue;
}

mjx-container[jax=&quot;SVG&quot;][display=&quot;true&quot;] {
  display: block;
  text-align: center;
  margin: 1em 0;
}

mjx-container[jax=&quot;SVG&quot;][display=&quot;true&quot;][width=&quot;full&quot;] {
  display: flex;
}

mjx-container[jax=&quot;SVG&quot;][justify=&quot;left&quot;] {
  text-align: left;
}

mjx-container[jax=&quot;SVG&quot;][justify=&quot;right&quot;] {
  text-align: right;
}

g[data-mml-node=&quot;merror&quot;] &gt; g {
  fill: red;
  stroke: red;
}

g[data-mml-node=&quot;merror&quot;] &gt; rect[data-background] {
  fill: yellow;
  stroke: none;
}

g[data-mml-node=&quot;mtable&quot;] &gt; line[data-line], svg[data-table] &gt; g &gt; line[data-line] {
  stroke-width: 70px;
  fill: none;
}

g[data-mml-node=&quot;mtable&quot;] &gt; rect[data-frame], svg[data-table] &gt; g &gt; rect[data-frame] {
  stroke-width: 70px;
  fill: none;
}

g[data-mml-node=&quot;mtable&quot;] &gt; .mjx-dashed, svg[data-table] &gt; g &gt; .mjx-dashed {
  stroke-dasharray: 140;
}

g[data-mml-node=&quot;mtable&quot;] &gt; .mjx-dotted, svg[data-table] &gt; g &gt; .mjx-dotted {
  stroke-linecap: round;
  stroke-dasharray: 0,140;
}

g[data-mml-node=&quot;mtable&quot;] &gt; g &gt; svg {
  overflow: visible;
}

[jax=&quot;SVG&quot;] mjx-tool {
  display: inline-block;
  position: relative;
  width: 0;
  height: 0;
}

[jax=&quot;SVG&quot;] mjx-tool &gt; mjx-tip {
  position: absolute;
  top: 0;
  left: 0;
}

mjx-tool &gt; mjx-tip {
  display: inline-block;
  padding: .2em;
  border: 1px solid #888;
  font-size: 70%;
  background-color: #F8F8F8;
  color: black;
  box-shadow: 2px 2px 5px #AAAAAA;
}

g[data-mml-node=&quot;maction&quot;][data-toggle] {
  cursor: pointer;
}

mjx-status {
  display: block;
  position: fixed;
  left: 1em;
  bottom: 1em;
  min-width: 25%;
  padding: .2em .4em;
  border: 1px solid #888;
  font-size: 90%;
  background-color: #F8F8F8;
  color: black;
}

foreignObject[data-mjx-xml] {
  font-family: initial;
  line-height: normal;
  overflow: visible;
}

mjx-container[jax=&quot;SVG&quot;] path[data-c], mjx-container[jax=&quot;SVG&quot;] use[data-c] {
  stroke-width: 3;
}
&lt;/style&gt;</content
		>
	</entry>
	<entry>
		<title>First Semester Reflections</title>
		<link href="https://naitian.org/blog/2019/01/08/First-Semester-Reflections/" />
		<updated>2019-01-08T08:00:00Z</updated>
		<id>https://naitian.org/blog/2019/01/08/First-Semester-Reflections/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/01/08/First-Semester-Reflections/#eve-of-destruction&quot;&gt;Eve of Destruction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2019/01/08/First-Semester-Reflections/#a-list-of-things-that-happened&quot;&gt;A List of Things That Happened&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Eve of Destruction&lt;/h2&gt;&lt;p&gt;And by destruction, of course, I mean winter semester. School starts up again
tomorrow, so I figured today I&#39;d share some reflections on my first semester of
college (or as our friends across the pond say, uni).&lt;/p&gt;&lt;p&gt;And since I&#39;m lazy, I&#39;ll do it in list form.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;A List of Things That Happened&lt;/h2&gt;&lt;p&gt;&lt;em&gt;and how I felt about them, etc etc.&lt;/em&gt;&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;The football team is pretty good at, you know, football.&lt;/li&gt;
&lt;li&gt;We do not speak of the OSU game.&lt;/li&gt;
&lt;li&gt;Homework actually counts for something&lt;/li&gt;
&lt;li&gt;Homework is apparently useful for reinforcing lecture material.&lt;/li&gt;
&lt;li&gt;Math is definitely easier when learning it for the second time.&lt;/li&gt;
&lt;li&gt;I have way more time than I know what to do with.&lt;/li&gt;
&lt;li&gt;I should work on more projects.&lt;/li&gt;
&lt;li&gt;I should do research.&lt;/li&gt;
&lt;li&gt;CAEN is definitely run better than tjCSL&lt;/li&gt;
&lt;li&gt;Working at CAEN is nowhere near as fun as working at tjCSL.&lt;/li&gt;
&lt;li&gt;Late nights are okay on weekends, never on weekdays.&lt;/li&gt;
&lt;li&gt;I definitely sleep way more than I used to.&lt;/li&gt;
&lt;li&gt;It&#39;s a bad idea to get trapped in downpour at 3am.&lt;/li&gt;
&lt;li&gt;Looking forward to chemistry, the saturation point also means, after a
certain extent, it&#39;s physically impossible to get more wet.&lt;/li&gt;
&lt;li&gt;Projects and homework take a lot of time.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mdst.club/&quot;&gt;Michigan Data Science Team&lt;/a&gt; is pretty cool.&lt;/li&gt;
&lt;li&gt;I miss playing in band (am playing in band W19).&lt;/li&gt;
&lt;li&gt;There are lots of opportunities for free food.&lt;/li&gt;
&lt;li&gt;Trello is really useful for making sense of my life.&lt;/li&gt;
&lt;li&gt;Who am I kidding, it&#39;s impossible to make sense of my life.&lt;/li&gt;
&lt;li&gt;I appreciate histograms.&lt;/li&gt;
&lt;li&gt;CAEN SSH does not allow Kerberos ticket auth and that makes me mad.&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>If You Start Playing...</title>
		<link href="https://naitian.org/blog/2019/01/06/If-You-Start-Playing/" />
		<updated>2019-01-06T08:00:00Z</updated>
		<id>https://naitian.org/blog/2019/01/06/If-You-Start-Playing/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;naitian.holiday&lt;/h2&gt;&lt;p&gt;I discovered early December 2018 that there existed &lt;code&gt;.christmas&lt;/code&gt; and &lt;code&gt;.holiday&lt;/code&gt;
TLDs. Naturally, I had to purchase one, so I sprung for the non-denominational
(and, more importantly, cheaper) &lt;a href=&quot;https://naitian.holiday/&quot;&gt;naitian.holiday&lt;/a&gt;
domain.&lt;/p&gt;&lt;p&gt;The next question, of course, was what I should do with it. I ended up using it
for two projects, so I definitely got my money&#39;s worth. One of the projects was
&lt;a href=&quot;https://naitian.holiday/iysp/?preset=umich&quot;&gt;if you start playing&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;if you start playing...&lt;/h2&gt;&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;If you start playing YouTube Rewind 2018 at 11:53 and 2 seconds on New Year&#39;s Eve, Will Smith will say &quot;uhhhh that&#39;s hot&quot; at exactly midnight.&lt;/p&gt;— Fab NZ (@fab_nz) &lt;a href=&quot;https://twitter.com/fab_nz/status/1079555364759031808?ref_src=twsrc%5Etfw&quot;&gt;December 31, 2018&lt;/a&gt;&lt;/blockquote&gt;&lt;p&gt;Inspired by this meme format, I decided to make a New Year&#39;s countdown that
would automatically start playing these videos at the correct time.&lt;/p&gt;&lt;p&gt;Here are the specs for the project:&lt;/p&gt;&lt;h3&gt;specs&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;client side&lt;/strong&gt;: it really doesn&#39;t need a backend, and I wanted to host on
S3, serve through CloudFront, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;customizable&lt;/strong&gt;: I want to be able to share links to custom videos /
timestamps.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;dark theme&lt;/strong&gt;: for the nighttime countdown, of course.&lt;/li&gt;
&lt;/ol&gt;&lt;h3&gt;tech&lt;/h3&gt;&lt;p&gt;Building out the application was actually pretty straightforward, thanks to the
Youtube iframe API.&lt;/p&gt;&lt;p&gt;To make it customizable and all on the client side, I used &lt;code&gt;window.location&lt;/code&gt; to
get URL parameters.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-js&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; url = &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; URL(&lt;span class=&quot;hljs-built_in&quot;&gt;window&lt;/span&gt;.location.href);
&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (url.searchParams.get(&lt;span class=&quot;hljs-string&quot;&gt;&#39;custom&#39;&lt;/span&gt;)) {
   &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; id = url.searchParams.get(&lt;span class=&quot;hljs-string&quot;&gt;&#39;id&#39;&lt;/span&gt;);
   &lt;span class=&quot;hljs-keyword&quot;&gt;const&lt;/span&gt; timestamp = url.searchParams.get(&lt;span class=&quot;hljs-string&quot;&gt;&#39;timestamp&#39;&lt;/span&gt;);
   vid = {
       id,
       timestamp
   }
} &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
    &lt;span class=&quot;hljs-comment&quot;&gt;// Get from list of presets&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can check it out at
&lt;a href=&quot;https://naitian.holiday/iysp/?preset=umich&quot;&gt;naitian.holiday/iysp/?preset=umich&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;https://github.com/naitian/startplaying&quot;&gt;Github Repo&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Reflections 2018</title>
		<link href="https://naitian.org/blog/2018/12/31/Reflections-2018/" />
		<updated>2018-12-31T08:00:00Z</updated>
		<id>https://naitian.org/blog/2018/12/31/Reflections-2018/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;What&lt;/h2&gt;&lt;p&gt;Wow time flies. I&#39;ll try to keep this short and sweet, but we have a lot of
stuff to cover.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/31/Reflections-2018/#this-year-in-numbers&quot;&gt;This Year in Numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/31/Reflections-2018/#things-that-have-happened-at-some-point-in-2018&quot;&gt;Things That Have Happened At Some Point in 2018&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/31/Reflections-2018/#reflections&quot;&gt;Reflections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;This Year in Numbers&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;491&lt;/strong&gt; Github contributions (less than last year -- sad...)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;17&lt;/strong&gt; credits of college courses taken&lt;/p&gt;&lt;p&gt;&lt;strong&gt;8&lt;/strong&gt; weeks spent surviving Java Spring during my summer internship at Capital
One&lt;/p&gt;&lt;p&gt;Over &lt;strong&gt;1.4 thousand&lt;/strong&gt; likes and reacts to my post on UMich Memes for Wolverteens
-- my crowning achievement.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;0%&lt;/strong&gt; -- the battery capacity of my laptop that died&lt;/p&gt;&lt;p&gt;&lt;strong&gt;8%&lt;/strong&gt; -- the battery level of my new laptop as I&#39;m typing this post.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Things That Have Happened At Some Point in 2018&lt;/h2&gt;&lt;p&gt;In &lt;strong&gt;January&lt;/strong&gt;, I published an Alexa skill with my friend, went to a couple of
track meets, and released the Ion bus app. I also went to HoyaHacks at
Georgetown, where I made &lt;a href=&quot;https://github.com/naitian/scout&quot;&gt;Scout&lt;/a&gt; with
&lt;a href=&quot;https://github.com/davidbzhao&quot;&gt;David&lt;/a&gt;, and had a couple of delicious cupcakes.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;February&lt;/strong&gt;, I ate (and was subsequently disappointed by) a kiwano melon. I
also stole the show as Banker Number Three in the TJHSST production of &lt;em&gt;Mary
Poppins&lt;/em&gt;. To top it all off, tjCSL achieved an consecutive 7 days of uptime on
all services, which was unfortunately very exciting for me.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;March&lt;/strong&gt;, production started ramping up for &lt;em&gt;Threshold Litmag&lt;/em&gt;, went on a
class trip to Washington, DC, where I got my Library of Congress library card.
We also moved out of our apartment.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;April&lt;/strong&gt;, I deployed Ion Signage 3 and went to Bitcamp, where my team used
&lt;strong&gt;machine learning :wow:&lt;/strong&gt; and a Myo armband to determine whether you were
holding a can. Also did some more pole vaulting, and went to Chicago, where I
experienced deep dish pizza for the first time.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;May&lt;/strong&gt;, I wore a skirt. I also played at Chantilly Jazz Fest with the jazz
band, constructed a gondola out of cardboard, executed a flawless (read: heavily
flawed) prom asking, and ran tech support for tjSTAR (also presented my senior
research project at tjSTAR). May turned out to be pretty eventful.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;June&lt;/strong&gt;, I went to prom, then graduated and took lots of pictures and said
lots of goodbyes. Then I went to orientation, at which I met my very first
college friends. Then I came back to Virginia, moved into George Mason
University, then began working at Capital One! I also went to the National BBQ
Festival, in which the free samples and free stuff make up for the price of
admissions. The week after, I saw the National Symphony Orchestra perform.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;July&lt;/strong&gt;, I went to the &quot;A Capitol Fourth&quot;, except it was the dress
rehearsal, so it was mostly sound checks and John Stamos forgetting his lines
(sick burn). Also checked out the National Building Museum and &lt;em&gt;funhaus&lt;/em&gt;, then
ordered food at a Chinese restaurant for the first time, completing my
transition into Asian Adulthood. Ooh! I also witnessed the aftermath of a
microtornado, so that was cool, I guess.&lt;/p&gt;&lt;p&gt;In &lt;strong&gt;August&lt;/strong&gt;, my team at C1 moved into the newly constructed headquarters,
featuring a hot chocolate machine on every other floor and pricey yet delicious
cafeteria food. Then I flew to Detroit, then San Francisco (where I was stuck
for almost 14 hours due to flight delays), then to Chengdu. I caught up with
family, friends, and an abundance of Uniqlo stores. I also flew a
(simulated) airplane and managed not to crash, so that&#39;s pretty exciting,
too.&lt;/p&gt;&lt;p&gt;On &lt;strong&gt;September&lt;/strong&gt; 1st, I moved into the University of Michigan. I took a picture
in the Big House and then got rained on. In September, I also went to my first
Michigan football game, took a selfie with a helicopter, traversed the
interconnected buildings of North Campus, and saw the Philadelphia Orchestra.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;October&lt;/strong&gt; involved a squishy moon in the UMMA, MHacks (!), HackHarvard (!!!),
and some really beautiful sunsets in Ann Arbor.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;November&lt;/strong&gt; included one (1) fake mustache, many Welcome Wednesday Bagels,
first snow, seeing Candide live (hilarious and wonderful), trying to climb into
the walls of Rackham Graduate Building, and heading back to Virginia for
Thanksgiving.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;December&lt;/strong&gt; was a last push to finish out the semester. I built a gingerbread
house, discovered this really cool bookstore in downtown Ann Arbor, turned on
the Christmas lights in the CAEN cave (where I work), and practiced a lot
(relatively). I also had a Zingerman&#39;s sandwich for the first time, which means
I&#39;m basically an Ann Arbor native now. After school ended, I flew back to China,
where I went to Guangzhou (saw a tomb and a huge library), Chengdu (saw my
grandparents, ate hot pot), Zhuhai (went to the beach, saw a huge clam-shaped
thing and a whale shark). I should clarify, the clam-shaped thing is a building
(the opera house), and the whale shark was in an aquarium. I did not see those
things as I was walking along the beach.&lt;/p&gt;&lt;p&gt;And so that brings us to now. This was a pretty cursory look at the past year,
and I guess there wasn&#39;t much reflecting going on -- mostly just remembering
what the hell I did for another 525,600 minutes.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Reflections&lt;/h2&gt;&lt;p&gt;This past year was pretty busy, and there were a lot of firsts. I lived on my
own for the first time. I wore a graduation gown for the first time (hopefully
not the last). But there were also a lot of lasts -- a lot of farewells bade
(bidden? biddeth?).&lt;/p&gt;&lt;p&gt;This year was the start of a new era for me, one with greater independence, with
more responsibilities, with new people to meet and new things to discover. But
the start of a new era means the end of an old one, and as I think about not
just this past year, but the past 5 that I&#39;ve spent in the state of Virginia, I
realize just how lucky I was to have the privilege of living there, of meeting
the great people that I did.&lt;/p&gt;&lt;p&gt;I&#39;ve lived in a lot of places in my life -- the five years I&#39;ve spent in
Virginia is maybe the longest amount of time I&#39;ve spent in one place; it&#39;s
certainly the span of time with the most significant changes and growth.&lt;/p&gt;&lt;p&gt;I&#39;m not sure where I&#39;m going with this. I guess, as I ring in the New Year (in
about 50 minutes), I can only hope that the next five years will be as
fulfilling and interesting and fun as the past five. I hope that, just as I
found a home in Virginia, I&#39;ll find a home in Michigan, and wherever life might
take me next.&lt;/p&gt;&lt;p&gt;And you know what?&lt;/p&gt;&lt;p&gt;I&#39;m almost certain it will be.&lt;/p&gt;&lt;p&gt;Happy 2019!&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Procrastination and Showering</title>
		<link href="https://naitian.org/blog/2018/12/18/Procrastination-and-Showering/" />
		<updated>2018-12-18T08:00:00Z</updated>
		<id>https://naitian.org/blog/2018/12/18/Procrastination-and-Showering/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Procrastination&lt;/h2&gt;&lt;p&gt;I have a final in just over two hours. In fact, it&#39;s the last final
of my first semester. The final final, so to speak.&lt;/p&gt;&lt;p&gt;And like the model student I am, I&#39;m not studying right now. Instead,
I&#39;m writing an entry for a blog that probably only I read.&lt;/p&gt;&lt;p&gt;But whatever. Here&#39;s a quick tip I&#39;ve picked up.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Showering&lt;/h2&gt;&lt;p&gt;Yes, that is indeed something one should do at college. But there&#39;s more.
I&#39;ve discovered, the time spent under the shower head is a great time to
do math homework!&lt;/p&gt;&lt;p&gt;On multiple occasions, I&#39;ve figured out a problem or a proof while being
pummeled by particles of water. I think it has something to do with the
white noise of water and not having any distractions.&lt;/p&gt;&lt;p&gt;Here are a couple of ways to set yourself up for success in seeking your
shower-solution:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;You should definitely attempt the problem before showering. You should
know the problem inside and out before you try to throw suds at the
solution.&lt;/li&gt;
&lt;li&gt;Don&#39;t shower immediately after attempting the problem. I like to sleep
on it, so try it the night before, then shower in the morning.&lt;/li&gt;
&lt;li&gt;A good way to know if you will find success in the shower is if you
feel like you&#39;re incredibly close to the answer, but you&#39;re missing
one key insight, or your mental processes are clouded by the fact
that you&#39;ve been working on it for so long.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;One pitfall of this technique, of course, is the inexplicable lack of
accessible showers in the exam setting. But you win some and you lose some,
I guess.&lt;/p&gt;&lt;p&gt;Best of luck to you in your hot-shower homework endeavours. I need to go
cram for a final now.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Let it Snow</title>
		<link href="https://naitian.org/blog/2018/12/13/Let-it-Snow/" />
		<updated>2018-12-13T08:00:00Z</updated>
		<id>https://naitian.org/blog/2018/12/13/Let-it-Snow/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;Just drag this link to the bookmark bar, click it, and you, too, can be
greeted by the non-denominational red deer-pulled guy:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;javascript:void%20function(){function%20e(){var%20e=/[\%3F%26]flake=([^%26%23]*)/,n=e.exec(window.location.href);null!==n%26%26(g=t(n[1])),e=/[\%3F%26]colors=([^%26%23]*)/,n=e.exec(window.location.href),null!==n%26%26(M=o(t(n[1])))}function%20t(e){e=unescape(e);for(var%20t=%22%22,o=0,n=0,a=0;o%3Ce.length;)n=e.charCodeAt(o),128%3En%3Ft+=String.fromCharCode(n):224%3En%26%26n%3E191%3F(a=e.charCodeAt(++o),t+=String.fromCharCode((31%26n)%3C%3C6|63%26a)):(a=e.charCodeAt(++o),c3=e.charCodeAt(++o),t+=String.fromCharCode((15%26n)%3C%3C12|(63%26a)%3C%3C6|63%26c3)),o++;return%20t.replace(/%26/g,%22%26amp;%22).replace(/%3C/g,%22%26lt;%22).replace(/%3E/g,%22%26gt;%22)}function%20o(e){var%20t=%220123456789abcdef%22,o=e.split(%22,%22);o=o.map(function(e){return%20e.split(%22:%22)});for(var%20n,a,r,l,s=[],i=0;i%3C500*o.length;i++)if(n=o[Math.floor(Math.random()*o.length)],n[1]){for(a=%22%22,r=Math.random(),l=0;l%3Cn[0].length;l++){var%20d=parseInt(n[0][l],16),f=parseInt(n[1][l],16);a+=t[Math.floor(r*d+(1-r)*f)]}s.push(%22%23%22+a)}else%20s.push(%22%23%22+n[0]);return%20s}function%20n(){E=window.outerWidth,T=window.outerHeight,j=E-40,O=T-(z%3F5:37),z%26%26(G=N/j),A%26%26(F=150)}function%20a(){if(e(),document.body.classList%3Fdocument.body.classList.add(%22has-snow%22):document.body.className+=%22%20has-snow%22,H=document.createElement(%22div%22),H.id=%22snowcontainer%22,H.style.position=%22fixed%22,H.style.top=%220%22,H.style.left=%220%22,H.style.width=%22100%25%22,H.style.height=%22100%25%22,H.style.marginTop=%22-20px%22,H.style.overflow=%22hidden%22,H.style.zIndex=%2210%22,H.style.pointerEvents=%22none%22,document.body.appendChild(H),K%26%26(k=document.createElement(%22img%22),k.src=P,k.style.position=%22absolute%22,k.style.top=Math.floor(Math.random()*O-R)+%22px%22,k.style.zIndex=%22-1%22,H.appendChild(k)),z)for(var%20t=0;N%3Et;t++)_[t]=O;if(A%26%26!h){var%20o=document.createElement(%22canvas%22);o.style.position=%22absolute%22,o.style.left=%220%22,o.style.top=%220%22,o.style.width=E+%22px%22,o.style.height=T+%22px%22,o.style.zIndex=%22-1%22,o.style.pointerEvents=%22none%22,I=o.getContext(%222d%22),document.body.appendChild(o),I.lineWidth=2,I.strokeStyle=%22white%22}for(var%20t=0;u%3E=t;t++)D[t]=document.createElement(%22span%22),g%20instanceof%20Array%3FD[t].innerHTML=g[Math.floor(Math.random()*w)]:D[t].innerHTML=g,D[t].style.color=M[Math.floor(Math.random()*M.length)],D[t].style.fontFamily=x[Math.floor(Math.random()*x.length)],q=Math.floor(Math.random()*B)+b,D[t].size=q,z%26%26(D[t].size-=5),D[t].style.fontSize=q+%22pt%22,D[t].style.position=%22absolute%22,D[t].x=Math.floor(Math.random()*j),W[t]=Math.floor(Math.random()*O),D[t].style.left=D[t].x+%22px%22,D[t].style.top=W[t]+%22px%22,D[t].fall=v*q/5,D[t].style.zIndex=%22-2%22,H.appendChild(D[t]);window.requestAnimationFrame(z%3Fr:A%3Fs:l)}function%20r(){K%26%26(V+=U,V%3E=j+Q%26%26(V=-Q,k.style.top=Math.floor(Math.random()*O-R)+%22px%22),k.style.left=V+%22px%22);for(var%20e=0;u%3E=e;e++)if(W[e]+=D[e].fall,D[e].style.top=W[e]+%22px%22,S=D[e].x+10*Math.sin(W[e]/9),D[e].style.left=S+%22px%22,L=Math.floor(G*(S+D[e].size/2)),W[e]+D[e].size%3E_[L]){var%20t=D[e].innerHTML;(_[L+1]-_[L]%3C5%26%26_[L-1]-_[L]%3C5||W[e]%3E=O)%26%26(_[L]=W[e]%3C_[L]%3FW[e]:_[L],D[e]=document.createElement(%22span%22),D[e].innerHTML=t,D[e].style.color=M[Math.floor(Math.random()*M.length)],D[e].style.fontFamily=x[Math.floor(Math.random()*x.length)],q=Math.floor(Math.random()*B)+b,D[e].size=q-5,D[e].style.fontSize=q+%22pt%22,D[e].style.position=%22absolute%22,D[e].x=Math.floor(Math.random()*j),W[e]=-D[e].size,D[e].style.left=D[e].x+%22px%22,D[e].style.top=W[e]+%22px%22,D[e].fall=v*q/5,D[e].style.zIndex=%22-1%22,H.appendChild(D[e]))}setTimeout(function(){window.requestAnimationFrame(r)},1e3/snowfps)}function%20l(){K%26%26(V+=U,V%3E=j+Q%26%26(V=-Q,k.style.top=Math.floor(Math.random()*O-R)+%22px%22),k.style.left=V+%22px%22);for(var%20e=0;u%3E=e;e++)W[e]+=D[e].fall,W[e]%3E=O%26%26(W[e]=-D[e].size),D[e].style.top=W[e]+%22px%22,D[e].style.left=D[e].x+10*Math.sin(W[e]/9)+%22px%22;setTimeout(function(){window.requestAnimationFrame(l)},1e3/snowfps)}function%20s(){K%26%26(V+=U,V%3E=j+Q%26%26(V=-Q,k.style.top=Math.floor(Math.random()*O-R)+%22px%22),k.style.left=V+%22px%22);for(var%20e=0;u%3E=e;e++)W[e]+=D[e].fall,W[e]%3E=O%26%26(W[e]=-D[e].size,setTimeout(%22iterfastpile()%22,10)),D[e].style.top=W[e]+%22px%22,D[e].style.left=D[e].x+10*Math.sin(W[e]/9)+%22px%22;setTimeout(function(){window.requestAnimationFrame(s)},1e3/snowfps)}var%20i=%22myCss%22;if(!document.getElementById(i)){var%20d=document.getElementsByTagName(%22head%22)[0],f=document.createElement(%22link%22);f.id=i,f.rel=%22stylesheet%22,f.type=%22text/css%22,f.href=%22https://gist.githubusercontent.com/naitian/6c7d304f80fd72ca2e116f8bfe03b6a1/raw/b38981c888ec2dab53d2e844348ff7f016fb13c6/snow.css%22,f.media=%22all%22,d.appendChild(f)}var%20p=%22https://ion.tjhsst.edu/static/themes/snow/%22,h=%22Microsoft%20Internet%20Explorer%22===navigator.appName,c=-1!==navigator.userAgent.toLowerCase().indexOf(%22android%22),m=c,y=!h;if(%22undefined%22==typeof%20u)var%20u=m%3F15:100;window.requestAnimationFrame||(window.requestAnimationFrame=function(e){return%20e()});var%20M=[%22%23aac%22,%22%23ddF%22,%22%23ccD%22],w=3,x=[%22Arial%20Black%22,%22Arial%20Narrow%22,%22Times%22,%22Comic%20Sans%20MS%22];if(%22undefined%22==typeof%20g)var%20g=h%3F%22*%22:[%22%E2%9D%84%22,%22%E2%9D%85%22,%22%E2%9D%86%22];if(%22undefined%22==typeof%20v)var%20v=y%3F.5:1;if(%22undefined%22==typeof%20C||%22undefined%22==typeof%20b)var%20C=m%3F44:22,b=m%3F16:8;%22undefined%22==typeof%20snowfps%26%26(snowfps=30);var%20z=y,A=!y;A=A%26%26!h;var%20E,T,F,I,S,L,q,H,k,N=200,B=C-b,D=[],W=[],j=1e3,O=1e3,_=[],G=N/j,J=new%20Date,K=11===J.getMonth()%26%26J.getDate()%3C=25,P=p+%22santa_xsnow.gif%22,Q=210,R=83,U=5,V=-Q;window.onresize=n,n();a()}();&quot;&gt;❄️Let it Snow❄️&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://naitian.org/assets/img/let-it-snow-screenshot.png&quot; alt=&quot;Screenshot of Christmas&quot; /&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://ion.tjhsst.edu/&quot;&gt;Ion&lt;/a&gt; has a winter theme that gets activated every December,
with snowfall and a &lt;a href=&quot;https://github.com/tjcsl/ion/blob/master/intranet/static/themes/snow/snow.js#L102&quot;&gt;Non-denominational Red Deer-Pulled Guy&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I found myself missing this, since Michigan&#39;s &quot;Intranet&quot;, Wolverine Access (which is actually
just Oracle SIS, but I digress) doesn&#39;t have this nifty feature.&lt;/p&gt;&lt;p&gt;So I decided to port the snow theme over to a bookmarklet, so I can access get snow at any time!&lt;/p&gt;&lt;p&gt;Thanks Derek Morris (TJ &#39;11) and Zachary Yaro (TJ &#39;12) for the actual code.&lt;/p&gt;&lt;p&gt;Pro Tip: if you click it multiple times, you&#39;ll get multiple non-denominational holidays!&lt;/p&gt;&lt;p&gt;Pro Tip 2: if you click it enough times, your computer will overheat to keep you warm
during those cold winter nights.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>The Consequence Eradicator™</title>
		<link href="https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/" />
		<updated>2018-12-12T08:00:00Z</updated>
		<id>https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/#mhacks-11-and-the-customary-apologies&quot;&gt;MHacks 11 (and the customary apologies)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/#conrad-the-consequence-eradicator&quot;&gt;Conrad: the Consequence Eradicator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/#step-1-data-collection&quot;&gt;Step 1: Data Collection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/#step-2-data-preprocessing&quot;&gt;Step 2: Data Preprocessing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/#step-3-modelling&quot;&gt;Step 3: Modelling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/#step-4-building-the-extension&quot;&gt;Step 4: Building the Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2018/12/12/The-Consequence-Eradicator/#wrap-up&quot;&gt;Wrap-Up&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;MHacks 11 (and the customary apologies)&lt;/h2&gt;&lt;p&gt;I have been kind of terrible about keeping up this blog. Sorry about that. That said,
a lot has happened since the last blog post almost a full year ago. For one thing, I
am a college kid now!&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://media.giphy.com/media/xWBUky3nYTGDwCUH0T/giphy.gif&quot; alt=&quot;Go Blue!&quot; /&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;I also had a great time as a tech intern for Capital One over the summer (something I&#39;m
definitely going to be writing about very soon).&lt;/p&gt;&lt;p&gt;But let&#39;s get back to this story.&lt;/p&gt;&lt;p&gt;MHacks 11 was held at the University of Michigan from October 12 - 14. I convinced my
friend, David, to fly up to Ann Arbor all the way from Charlottesville for the event.&lt;/p&gt;&lt;p&gt;What follows is the story of how David (UVA &#39;19), Renee (also U-M &#39;22), and I did our parts in
contributing to the eerie convergence between the Simpsons and reality.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Conrad: the Consequence Eradicator&lt;/h2&gt;&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/edoo6dH19ko&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;p&gt;You don&#39;t need to watch the whole video (though I highly encourage it). Basically, Lisa and a
team of programmers write an artificial intelligence (Conrad) to predict the outcomes of
social media posts.&lt;/p&gt;&lt;p&gt;Thusly inspired, we made a Chrome extension which predicts the reactions a post on Facebook
would get.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 1: Data Collection&lt;/h2&gt;&lt;p&gt;Fortunately for us, &lt;a href=&quot;https://github.com/minimaxir&quot;&gt;@minimaxir&lt;/a&gt; on Github had a relatively large
dataset of public posts from large Facebook pages, and their reactions. The dataset is linked
&lt;a href=&quot;https://github.com/minimaxir/interactive-facebook-reactions&quot;&gt;here&lt;/a&gt;. I only found out later that
he also did our exact same project, but whatever.&lt;/p&gt;&lt;p&gt;Anyway, that was data collection.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 2: Data Preprocessing&lt;/h2&gt;&lt;p&gt;We chose only to look at posts with text content (so we ignored shared links, photos, videos, etc.)
We also only considered posts less than 1000 characters long, and which had more than 11 non-like
reacts.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 3: Modelling&lt;/h2&gt;&lt;p&gt;We spent most of Saturday doing preprocessing, and then eventually realized we still had to actually
build a model. We started off by trying a random forest regression with bag of words. Results were not
great.&lt;/p&gt;&lt;p&gt;After tweaking the hyperparameters around a bit, it became clear results weren&#39;t improving.&lt;/p&gt;&lt;p&gt;That&#39;s when we took the leap to using &lt;code&gt;gensim&lt;/code&gt; and &lt;code&gt;doc2vec&lt;/code&gt; to generate sentence embeddings.
This meant that, instead of just using word frequency, we used a much more complex model to encode
posts which took into account word order.&lt;/p&gt;&lt;p&gt;This yielded much better results, especially after I also normalized the target output.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Step 4: Building the Extension&lt;/h2&gt;&lt;p&gt;At this point, it was the morning of demos, and while we had a halfway decent model, the chrome
extension was non-existent.&lt;/p&gt;&lt;p&gt;So came the mad scramble, in which I was literally writing code as we walked to the IM building.
I wrote a small Flask API backend, which the Chrome extension was supposed to call.&lt;/p&gt;&lt;p&gt;Initially, I didn&#39;t want to deal with the Chrome messaging protocol, so I tried to make the call
directly from the content script (which ran as Javascript code on the client with no extra
permissions).&lt;/p&gt;&lt;p&gt;We ran into a roadblock, where cross origin requests were forbidden. I tried to overcome this
by editing my &lt;code&gt;/etc/hosts&lt;/code&gt; file to redirect some ancillary Facebook domain to &lt;code&gt;localhost&lt;/code&gt;. This
&lt;em&gt;almost&lt;/em&gt; worked, except Facebook also expected https-only requests, so I was stuck with having
to do the &lt;em&gt;correct&lt;/em&gt; thing of using Chrome&#39;s messaging protocol.&lt;/p&gt;&lt;p&gt;By this point, I&#39;m writing the code while we are standing at our demo table.&lt;/p&gt;&lt;p&gt;It turned out to actually be super easy to use the messaging protocol, but that didn&#39;t stop me
from screwing up 11 times before I finally got everything working.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://media.giphy.com/media/l2JejtUtX0ImRvLnq/giphy.gif&quot; alt=&quot;Literally Me Celebrating&quot; /&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;This was me when I finally got the Chrome extension to work.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Wrap-Up&lt;/h2&gt;&lt;p&gt;Unfortunately, I have no screenshots of the actual app working, &lt;em&gt;but&lt;/em&gt; if you want to run the janky
code for yourself, it&#39;s all open source on &lt;a href=&quot;https://github.com/naitian/conrad&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I learned a lot through this hackathon. It was the first hackathon project that I did with a
heavy data science workflow.&lt;/p&gt;&lt;p&gt;This hackathon was a blast, and &lt;a href=&quot;http://davidzhao.me/&quot;&gt;David&lt;/a&gt; and &lt;a href=&quot;https://github.com/reneeli411&quot;&gt;Renee&lt;/a&gt;
were awesome teammates.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Reflections 2017</title>
		<link href="https://naitian.org/blog/2017/12/31/Reflections-2017/" />
		<updated>2017-12-31T08:00:00Z</updated>
		<id>https://naitian.org/blog/2017/12/31/Reflections-2017/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/12/31/Reflections-2017/#hello-again&quot;&gt;Hello again&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/12/31/Reflections-2017/#this-year-in-numbers&quot;&gt;This Year in Numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/12/31/Reflections-2017/#revisiting-last-year&quot;&gt;Revisiting Last Year&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/12/31/Reflections-2017/#this-website&quot;&gt;This Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/12/31/Reflections-2017/#this-blog&quot;&gt;This Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/12/31/Reflections-2017/#this-life&quot;&gt;This Life&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/12/31/Reflections-2017/#looking-forward&quot;&gt;Looking forward&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Hello again&lt;/h2&gt;&lt;p&gt;It&#39;s been a while. I&#39;ve been pretty busy doing senior year things like college applications and senior research (&lt;em&gt;cough&lt;/em&gt; not really). But anyway, I figured now would be a good time to reflect on this past year - what I did, what I didn&#39;t do, and what I should be doing next year.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;This Year in Numbers&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;563&lt;/strong&gt; Github Contributions&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt; Palantir Social Impact Prize&lt;/p&gt;&lt;p&gt;&lt;strong&gt;4&lt;/strong&gt; weeks spent surviving PHP and MySQL during my internship, during which:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;I added &lt;strong&gt;18&lt;/strong&gt; hotels&lt;/li&gt;
&lt;li&gt;processed &lt;strong&gt;64&lt;/strong&gt; images&lt;/li&gt;
&lt;li&gt;and modified &lt;strong&gt;10055&lt;/strong&gt; lines of code!&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;6&lt;/strong&gt; college applications submitted (and &lt;strong&gt;1&lt;/strong&gt; acceptance received!!!)&lt;/p&gt;&lt;p&gt;In Ion, I made &lt;strong&gt;168&lt;/strong&gt; commits, with &lt;strong&gt;4230&lt;/strong&gt; additions and &lt;strong&gt;6669&lt;/strong&gt; deletions.&lt;/p&gt;&lt;p&gt;I cleared &lt;strong&gt;10&lt;/strong&gt; feet in pole vault, very narrowly qualifying myself for states!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3&lt;/strong&gt; AP exams taken&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Revisiting Last Year&lt;/h2&gt;&lt;p&gt;I made a post on January 1st that listed some goals for the year. Let&#39;s see how well I did.&lt;/p&gt;&lt;h3&gt;This Website&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;There’s still lots of work to be done, particularly in the little “terminal” easter egg on the home page, but I’m very happy with the site.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;I definitely worked on the website quite a bit this year. I fixed some big bugs with the terminal, and added some useful tools to improve my workflow. It&#39;s definitely a lot of fun to work on.&lt;/p&gt;&lt;h3&gt;This Blog&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;I definitely plan on posting more, and hopefully at least once every week&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Oops. I kinda dropped the ball on this one... That said, I did post more often than before, and I attribute that entirely to a smoother creation flow.&lt;/p&gt;&lt;h3&gt;This Life&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;That said, I’ll take to heart Dory’s advice of “Just keep swimming”, and keep you guys updated.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Update: I kept swimming, and finished junior pretty darn strong. It was hard, but totally worth it.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Looking forward&lt;/h2&gt;&lt;p&gt;Here are my resolutions for this year:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Go to college&lt;/li&gt;
&lt;li&gt;Clear 11&#39;&lt;/li&gt;
&lt;li&gt;Double the number of blog posts&lt;/li&gt;
&lt;li&gt;Get 100 stars on Github.&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>purple.com: a brief eulogy</title>
		<link href="https://naitian.org/blog/2017/11/29/purple-com-a-brief-eulogy/" />
		<updated>2017-11-29T08:00:00Z</updated>
		<id>https://naitian.org/blog/2017/11/29/purple-com-a-brief-eulogy/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;On November 2, 2017, I lost a close companion. &lt;a href=&quot;https://purple.com/&quot;&gt;purple.com&lt;/a&gt; is no longer the bold-yet-understated purple eyesore that I had grown to know and love.&lt;/p&gt;
&lt;p&gt;It has been replaced by &lt;a href=&quot;https://purple.com/&quot;&gt;purple&lt;/a&gt;, a mattress company that I keep getting ads for on Facebook.&lt;/p&gt;
&lt;p&gt;In a token of remembrance, here is the story of my life with purple.com.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;I first came across purple.com in the summer of 2015. I had finished my first year of high school, blissfully unaware that school could get much much worse, and I had been to my first hackathon, &lt;a href=&quot;https://hacktj.org/&quot;&gt;HackTJ&lt;/a&gt;, where I built something incredibly broken, but with which I was satisfied nonetheless. I was hooked on hackathons.&lt;/p&gt;&lt;p&gt;I only mention this because I encountered purple.com at my second hackathon ever. The internet was, as it usually does when a couple hundred people try to access it at once, slow and unreliable. I sat with a couple of my friends, annoyed and impatient. One of them, who was more acquaintance than friend at the time, let out a cry.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Guys, I have internet!&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;I looked at her screen. It was filled with a disgusting shade of purple.&lt;/p&gt;&lt;p&gt;&lt;em&gt;What the fuck is that.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&quot;It&#39;s purple.com,&quot; she informed us. &quot;It&#39;s the fastest loading webpage in the world.&quot;&lt;/p&gt;&lt;p&gt;That was a bold claim - one that I&#39;m pretty sure is not true - but I took her word for it, and ever since, purple.com has been a constant in my life.&lt;/p&gt;&lt;p&gt;purple.com has been around since August of 1994. That&#39;s over five years before I was born. When I learned about purple.com, it could legally drink alcohol. It&#39;s not just a website. It&#39;s an institution - one that has been replaced by a mattress company.&lt;/p&gt;&lt;p&gt;As I navigated my way through high school, purple.com has always been there for me.&lt;/p&gt;&lt;p&gt;At every hackathon, when the internet inevitably goes awry, the blinding purple is the bearer of good news: &lt;em&gt;You can google things now&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Every time I was frantically trying to connect to school WiFi so I could print that paper due next period, that luscious #DD00FF was there to reassure me: &lt;em&gt;Everything is okay. Your paper is horribly written, but at least you can print it out.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;And all of the late nights spent &lt;del&gt;working&lt;/del&gt; procrastinating, when I&#39;ve exhausted Facebook and Reddit and Youtube, and even my email, my muscle memory would turn to purple.com, and the really quite horrid purple would issue its stern admonishment: &lt;em&gt;Get back to work.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;But several weeks ago, that all changed.&lt;/p&gt;&lt;p&gt;I was having network connectivity problems. Unfazed, I opened my browser and navigated to my home away from home. And I watched the loading indicator spin.&lt;/p&gt;&lt;p&gt;That&#39;s okay, the network is still broken.&lt;/p&gt;&lt;p&gt;Then Google loaded.&lt;/p&gt;&lt;p&gt;Then Facebook, then Blackboard, then fcps.edu.&lt;/p&gt;&lt;p&gt;And purple.com just sat spinning.&lt;/p&gt;&lt;p&gt;I refused to lose faith.&lt;/p&gt;&lt;p&gt;&lt;em&gt;It&#39;s an old site, probably the server had to be replaced or something. It&#39;ll be back up soon.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;I held on to hope against hope that, the next day, everything would be back to normal.&lt;/p&gt;&lt;p&gt;I wanted to believe, but, alas, all good things must come to an end.&lt;/p&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/0700b93bcc18bcd5.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;Web archive of purple.com&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;Thanks purple.com for all the memories. I guess now I&#39;ll just have to go to &lt;a href=&quot;https://notpurple.com/&quot;&gt;notpurple.com&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>About this Site - The Terminal</title>
		<link href="https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/" />
		<updated>2017-05-26T07:00:00Z</updated>
		<id>https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/</id>
		<content xml:lang="en" type="html"
			>&lt;h3&gt;I&#39;m Back!&lt;/h3&gt;
&lt;p&gt;I&#39;ve been planning on continuing my &quot;About this Site&quot; series for a while now
(like over 2 months), but I guess I&#39;ve been distracted with other things (as a
high schooler does). Regardless, partly due to the prompting of a friend, here
is the third installment.&lt;/p&gt;
&lt;h3&gt;Table of Contents&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#inspiration&quot;&gt;Inspiration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#problems&quot;&gt;Problems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#specs&quot;&gt;Specs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#lets-get-down-to-business&quot;&gt;Let&#39;s Get Down to Business&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#better-design&quot;&gt;Better Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#procedural-generation&quot;&gt;Procedural Generation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#extensibility&quot;&gt;Extensibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#wrap-up&quot;&gt;Wrap-up&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/05/26/About-this-Site-The-Terminal/#improvements&quot;&gt;Improvements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Inspiration&lt;/h3&gt;
&lt;p&gt;I believe I have waxed poetic about the command line before. I most definitely
will in the future if I have not already. I was, therefore, kind of infatuated
with the idea of a website that has a little command line built into it. This
was implemented in my original website, where I even added scan lines and a
subtle flicker to really drive home the retro feel.&lt;/p&gt;
&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/old_site_terminal.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;My old website&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;For this refresh, though, I wanted to make something cleaner. More importantly,
I wanted to make something that required very little maintenance.&lt;/p&gt;
&lt;h3&gt;Problems&lt;/h3&gt;
&lt;p&gt;First, let&#39;s go through some of the problems with the previous Javascript
terminal. For one thing, there were errors that were straight up ignored (to be
fair, this error didn&#39;t break any functionality).&lt;/p&gt;
&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/old_terminal_errors.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;Look at all those
errors&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Also, just about everything, from the commands to the available files, was
hardcoded. This meant if I were to add a new section to my site, I would have to
manually update that code. What a drag. It ended up with code that looked like
this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-javascript&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (parsed.cmd === &lt;span class=&quot;hljs-string&quot;&gt;&#39;open&#39;&lt;/span&gt;) {
&lt;span class=&quot;hljs-keyword&quot;&gt;var&lt;/span&gt; target = &lt;span class=&quot;hljs-string&quot;&gt;&#39;#&#39;&lt;/span&gt; + parsed.arg;
$.smoothScroll({
&lt;span class=&quot;hljs-attr&quot;&gt;scrollTarget&lt;/span&gt;: target
});
} &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (parsed.cmd === &lt;span class=&quot;hljs-string&quot;&gt;&#39;ls&#39;&lt;/span&gt;) {
out = &lt;span class=&quot;hljs-string&quot;&gt;&#39;about&amp;#x26;nbsp;&amp;#x26;nbsp;&amp;#x26;nbsp;&amp;#x26;nbsp;&amp;#x26;nbsp;projects&amp;#x26;nbsp;&amp;#x26;nbsp;&amp;#x26;nbsp;&amp;#x26;nbsp;&amp;#x26;nbsp;contact&#39;&lt;/span&gt;;
} &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {
out = &lt;span class=&quot;hljs-string&quot;&gt;&#39;That command is not yet supported. Try ls or open.&#39;&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ewwwww.&lt;/p&gt;
&lt;h3&gt;Specs&lt;/h3&gt;
&lt;p&gt;So for this new and improved terminal, I wanted several features:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Better design (this meant a visible, blinking cursor)&lt;/li&gt;
&lt;li&gt;Procedurally generated files (this proved to be the most challenging)&lt;/li&gt;
&lt;li&gt;Extensible command system (I used ES6 classes for this)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Let&#39;s Get Down to Business&lt;/h3&gt;
&lt;p&gt;We&#39;re not going to defeat the Huns, but we &lt;em&gt;are&lt;/em&gt; going to make our new and
improved terminal.&lt;/p&gt;
&lt;h4&gt;Better Design&lt;/h4&gt;
&lt;p&gt;Okay, so this one is kind of vague. I mocked up the &lt;a href=&quot;https://naitian.org/blog/2017-03-05-About-this-Site---Design/&quot;&gt;design&lt;/a&gt;, which was heavily
inspired by my actual terminal.&lt;/p&gt;
&lt;p&gt;The most difficult part was probably hiding the cursor and replacing it with a
block cursor. I still don&#39;t have a perfect implementation - in case you didn&#39;t
realize, you can&#39;t actually move the cursor around on the line. It just stays at
the end of the line.&lt;/p&gt;
&lt;p&gt;The thing about the cursor (or caret, if you&#39;d like) is that it is always the
same color as your text. There&#39;s no way to style it individually. The trick here
is to &lt;strong&gt;make the text transparent&lt;/strong&gt;. Then, just add a text-shadow with your text
color and no offset. This keeps everything the same except for the caret, which
is now transparent!&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-css&quot;&gt;&lt;span class=&quot;hljs-selector-id&quot;&gt;#input&lt;/span&gt; {
    &lt;span class=&quot;hljs-attribute&quot;&gt;color&lt;/span&gt;: transparent;
    &lt;span class=&quot;hljs-attribute&quot;&gt;text-shadow&lt;/span&gt;: &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;#0EFF1F&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wow!! Nice.&lt;/p&gt;
&lt;p&gt;Another big problem was making scrolling work nicely. This was more difficult
than you would initially expect, because the input is a &lt;code&gt;contentEditable&lt;/code&gt; div,
while the rest of the text is a separate div. A couple of &lt;code&gt;overflow&lt;/code&gt; rules did
the job nicely, though.&lt;/p&gt;
&lt;h4&gt;Procedural Generation&lt;/h4&gt;
&lt;p&gt;This is the cool part! My biggest gripe with the old implementation was how much
was hardcoded. I wanted to be able to more or less browse the entire site with
the terminal, so hardcoding everything was not a viable option.&lt;/p&gt;
&lt;p&gt;This means I needed an API or something to query for all of the different parts
of the site. Fortunately, I have Jekyll!&lt;/p&gt;
&lt;p&gt;Here&#39;s the amazing thing about Jekyll: it can generate &lt;strong&gt;any&lt;/strong&gt; document. This
includes not just Markdown or HTML files. The trick is to use Jekyll to generate
a JSON file with information about the website.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;mind = blown&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here are the entire contents of &lt;code&gt;terminal.json&lt;/code&gt;, which is the relevant JSON
file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-js&quot;&gt;---
---
{% capture nl %}
{% endcapture %}
{% assign files = site.documents %}
{% &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; page &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; site.html_pages %}
{% assign files = files | push: page %}
{% endfor %}
{
    {% &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; page &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; files %}
    &lt;span class=&quot;hljs-string&quot;&gt;&quot;{{ page.url }}&quot;&lt;/span&gt;: {
        &lt;span class=&quot;hljs-string&quot;&gt;&quot;content&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;{{ page.content | replace: &#39;&quot;&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;&#39;, &quot;&#39;&lt;/span&gt;&lt;span class=&quot;hljs-string&quot;&gt;&quot; | normalize_whitespace}}&quot;&lt;/span&gt;
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s all there is to it. This generates a JSON object of all of the pages in
the website, with the url as the key and including the content as the sole
property of each page.&lt;/p&gt;
&lt;p&gt;You end up with a JSON file looking like &lt;a href=&quot;https://naitian.org/terminal.json&quot;&gt;this&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, this is still not wonderful, because all we have now is a bunch of file
paths. This doesn&#39;t encode information about what is and is not in the current
directory.&lt;/p&gt;
&lt;p&gt;So I added a &lt;code&gt;pwd&lt;/code&gt; variable. I now realize &lt;code&gt;pwd&lt;/code&gt; stands for &quot;print working
directory&quot;, so it doesn&#39;t really make sense to name a variable that, but in my
mind, it just means &quot;our current working directory&quot;, and &lt;code&gt;ocwd&lt;/code&gt; just doesn&#39;t have the same ring to it. I use this to keep track of where in the tree I am at the moment&lt;/p&gt;
&lt;p&gt;I then search down the list of files to see which paths are direct children of
the &lt;code&gt;pwd&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Everything else is pretty straightforward: I just inject the &lt;code&gt;content&lt;/code&gt; of the
selected path.&lt;/p&gt;
&lt;p&gt;This is what gets me the procedurally generated functionality of the terminal.
That&#39;s not all I wanted though; I wanted it to be even more dynamic. I wanted
the terminal to be extensible, so that I would be able to add new commands
really easily.&lt;/p&gt;
&lt;p&gt;Well then. Let&#39;s get started.&lt;/p&gt;
&lt;h4&gt;Extensibility&lt;/h4&gt;
&lt;p&gt;I decided on using ES6 classes to organize the JavaScript into a self-contained
unit.I&#39;ve experimented with this before to some success.&lt;/p&gt;
&lt;p&gt;The actual implementation was very strightforward. I basically have a map of
possible commands mapped to the functions that they call. All of the commands
have access to the instance variables. Easy, clean stuff.&lt;/p&gt;
&lt;h3&gt;Wrap-up&lt;/h3&gt;
&lt;p&gt;So I guess that sums up the tech componenet of the terminal easter egg. Even
though it was just an easter egg, it was probably one of the things I spent the
most time on, just to get everything working okay.&lt;/p&gt;
&lt;h4&gt;Improvements&lt;/h4&gt;
&lt;p&gt;There are still some improvements to be made; some (obviously) less trivial than
others.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I want tab completion.&lt;/li&gt;
&lt;li&gt;I want to be able to register new commands outside of the actual class&lt;/li&gt;
&lt;li&gt;Lists extend horizontally, not vertically.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Overall, I&#39;m really happy with how it turned out, though, and I think this is a
great foundation to keep building on.&lt;/p&gt;</content
		>
	</entry>
	<entry>
		<title>Do My Friends Care About Me?</title>
		<link href="https://naitian.org/blog/2017/04/15/Do-My-Friends-Care-About-Me/" />
		<updated>2017-04-15T07:00:00Z</updated>
		<id>https://naitian.org/blog/2017/04/15/Do-My-Friends-Care-About-Me/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;A Brief Analysis of my Facebook Friends&lt;/h2&gt;&lt;p&gt;This was a (not so) quick look at how I stacked up against my Facebook friends in a totally arbitrary measure.&lt;/p&gt;&lt;p&gt;I looked at the ratio of likes and reacts (henceforth to be referred to as a singular entity: &quot;realikes&quot;) to a user&#39;s profile picture to that user&#39;s friend count. That is, what percentage of a user&#39;s friends realiked his or her profile picture?&lt;/p&gt;&lt;h3&gt;Gathering Data&lt;/h3&gt;&lt;p&gt;&lt;em&gt;I&#39;ll post a more detailed write-up of the technical aspects of scraping the Facebook profiles, as well as an iPython Notebook with the code.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;The most challenging (and time consuming) part was gathering the data. I ran into several dead ends before finally scraping the data from Facebook using Selenium. I&#39;ll go through all of the failed methods and my succeessful method here.&lt;/p&gt;&lt;p&gt;I had already collected a list of Facebook profile URLs just using Chrome Dev Tools on the client side.&lt;/p&gt;&lt;p&gt;My first idea was to use the Facebook Graph API. However, that quickly proved to be impossible, mainly because &lt;a href=&quot;http://stackoverflow.com/a/39649908&quot;&gt;this StackOverflow answer&lt;/a&gt; said so.&lt;/p&gt;&lt;p&gt;So on to the second solution! I figured I could use the python &lt;code&gt;requests&lt;/code&gt; and &lt;code&gt;beautifulsoup&lt;/code&gt; libraries to crawl Facebook, and just pass in my Facebook cookies for auth. While the authentication totally worked (exciting!), I discovered that Facebook does basically all of the rendering client side, so the HTML that I received was just a bunch of links to async scripts.&lt;/p&gt;&lt;p&gt;Ultimately, I resorted to Selenium to scraping first the links to profile pictures, and later, the actual realike counts.&lt;/p&gt;&lt;h3&gt;Examining the Data&lt;/h3&gt;&lt;p&gt;After a little bit of cleaning up in Excel, I was ready to take a deeper look at the data.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Import our beloved libraries&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; pandas &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; pd
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; np
&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span class=&quot;hljs-keyword&quot;&gt;as&lt;/span&gt; plt
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Read in the data&lt;/span&gt;

data = pd.read_csv(&lt;span class=&quot;hljs-string&quot;&gt;&#39;./data.csv&#39;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# View the first 5 entries&lt;/span&gt;

data[:&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;# Likes on Pic&lt;/th&gt;
      &lt;th&gt;# Friends&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;77.0&lt;/td&gt;
      &lt;td&gt;321.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;137.0&lt;/td&gt;
      &lt;td&gt;527.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;2&lt;/th&gt;
      &lt;td&gt;176.0&lt;/td&gt;
      &lt;td&gt;563.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;3&lt;/th&gt;
      &lt;td&gt;54.0&lt;/td&gt;
      &lt;td&gt;898.0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;4&lt;/th&gt;
      &lt;td&gt;103.0&lt;/td&gt;
      &lt;td&gt;283.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# This includes &quot;bad&quot; rows, which don&#39;t have values for either or both of the columns&lt;/span&gt;
&lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(data)
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Drop the bad stuff&lt;/span&gt;
data = data.dropna()
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(data)
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;plt.plot(data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;], data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Likes on Pic&#39;&lt;/span&gt;], &lt;span class=&quot;hljs-string&quot;&gt;&#39;bo&#39;&lt;/span&gt;)
plt.title(&lt;span class=&quot;hljs-string&quot;&gt;&#39;Realikes to Friend Count&#39;&lt;/span&gt;)
plt.ylabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;Realikes&#39;&lt;/span&gt;)
plt.xlabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-mipsasm&quot;&gt;&amp;#x3C;matplotlib&lt;span class=&quot;hljs-meta&quot;&gt;.text&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;.Text&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x115283f28&lt;/span&gt;&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;figure&gt;
&lt;img src=&quot;https://naitian.org/assets/img/output_7_1&quot; alt=&quot;&quot; /&gt;
&lt;/figure&gt;&lt;p&gt;There seems to be a general upwards trend, with users with more friends receiving a greater amount of likes from friends. This makes sense, since their pictures go out to a larger audience. I am more interested in the ratio between the realike count and friend count.&lt;/p&gt;&lt;h3&gt;Looking at the Realike Ratios&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Insert new column of the ratios.&lt;/span&gt;
data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;] = data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Likes on Pic&#39;&lt;/span&gt;] / data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# First look at the ratios! Just a brief summary.&lt;/span&gt;
data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;].describe()
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-apache&quot;&gt;&lt;span class=&quot;hljs-attribute&quot;&gt;count&lt;/span&gt;    &lt;span class=&quot;hljs-number&quot;&gt;278&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;000000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;mean&lt;/span&gt;       &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;158833&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;std&lt;/span&gt;        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;093243&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;min&lt;/span&gt;        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;000000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;25&lt;/span&gt;%        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;083202&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;50&lt;/span&gt;%        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;159469&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;75&lt;/span&gt;%        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;220952&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;max&lt;/span&gt;        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;492114&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;Name&lt;/span&gt;: Ratio, dtype: float&lt;span class=&quot;hljs-number&quot;&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, so this summary provides some interesting information.&lt;/p&gt;&lt;p&gt;Just from clicking around Facebook earlier, I had thought that the average ratio would be somewhere between 20% and 30%, but it ended up being much lower, at 15.9%.&lt;/p&gt;&lt;p&gt;Also interesting to note is that no one had over half of their friends like their profile picture, although the max of 49.2% came pretty close.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Sort data by friend count&lt;/span&gt;
data = data.sort_values(by=&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;%matplotlib inline

plt.plot(data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;], data.Ratio, &lt;span class=&quot;hljs-string&quot;&gt;&#39;bo&#39;&lt;/span&gt;)
plt.xlabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;)
plt.ylabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;)
plt.title(&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends vs Realike Ratio&#39;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-mipsasm&quot;&gt;&amp;#x3C;matplotlib&lt;span class=&quot;hljs-meta&quot;&gt;.text&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;.Text&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x113fc76a0&lt;/span&gt;&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;img src=&quot;https://naitian.org/assets/img/output_14_1.png&quot; alt=&quot;&quot; /&gt;&lt;p&gt;One of the biggest things I was hoping to see was a correlation between friend size and ratio. However, that did not really manifest itself. As you can see, the points are relatively evenly distributed.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Top 5 realike ratios.&lt;/span&gt;
data.sort_values(by=&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;, ascending=&lt;span class=&quot;hljs-literal&quot;&gt;False&lt;/span&gt;)[:&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;# Likes on Pic&lt;/th&gt;
      &lt;th&gt;# Friends&lt;/th&gt;
      &lt;th&gt;Ratio&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;8&lt;/th&gt;
      &lt;td&gt;156.0&lt;/td&gt;
      &lt;td&gt;317.0&lt;/td&gt;
      &lt;td&gt;0.492114&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;11&lt;/th&gt;
      &lt;td&gt;155.0&lt;/td&gt;
      &lt;td&gt;376.0&lt;/td&gt;
      &lt;td&gt;0.412234&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;158&lt;/th&gt;
      &lt;td&gt;280.0&lt;/td&gt;
      &lt;td&gt;742.0&lt;/td&gt;
      &lt;td&gt;0.377358&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;4&lt;/th&gt;
      &lt;td&gt;103.0&lt;/td&gt;
      &lt;td&gt;283.0&lt;/td&gt;
      &lt;td&gt;0.363958&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;12&lt;/th&gt;
      &lt;td&gt;406.0&lt;/td&gt;
      &lt;td&gt;1118.0&lt;/td&gt;
      &lt;td&gt;0.363148&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Bottom 5 realike ratios.&lt;/span&gt;
data.sort_values(by=&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;, ascending=&lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;)[:&lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;# Likes on Pic&lt;/th&gt;
      &lt;th&gt;# Friends&lt;/th&gt;
      &lt;th&gt;Ratio&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;92&lt;/th&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;125.0&lt;/td&gt;
      &lt;td&gt;0.000000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;40&lt;/th&gt;
      &lt;td&gt;0.0&lt;/td&gt;
      &lt;td&gt;117.0&lt;/td&gt;
      &lt;td&gt;0.000000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;299&lt;/th&gt;
      &lt;td&gt;1.0&lt;/td&gt;
      &lt;td&gt;370.0&lt;/td&gt;
      &lt;td&gt;0.002703&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;57&lt;/th&gt;
      &lt;td&gt;2.0&lt;/td&gt;
      &lt;td&gt;539.0&lt;/td&gt;
      &lt;td&gt;0.003711&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;89&lt;/th&gt;
      &lt;td&gt;6.0&lt;/td&gt;
      &lt;td&gt;826.0&lt;/td&gt;
      &lt;td&gt;0.007264&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;&lt;p&gt;Viewing the lowest 5 realike ratios reveals that those with the lowest friend counts do &lt;em&gt;not&lt;/em&gt; have the lowest realike ratios.&lt;/p&gt;&lt;h4&gt;Does Friend Count Matter?&lt;/h4&gt;&lt;p&gt;I then took a look at the distributions for users with more than 1000 friends compared to users with fewer than 1000 friends.&lt;/p&gt;&lt;p&gt;It&#39;s important to note that there are significantly more users with fewer than 1000 friends in my data set.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;gt1000 = data.loc[data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;] &gt;= &lt;span class=&quot;hljs-number&quot;&gt;1000&lt;/span&gt;]
lt1000 = data.loc[data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;] &amp;#x3C; &lt;span class=&quot;hljs-number&quot;&gt;1000&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(gt1000)
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;gt1000[&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;].describe()
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-apache&quot;&gt;&lt;span class=&quot;hljs-attribute&quot;&gt;count&lt;/span&gt;    &lt;span class=&quot;hljs-number&quot;&gt;44&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;000000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;mean&lt;/span&gt;      &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;173164&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;std&lt;/span&gt;       &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;084129&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;min&lt;/span&gt;       &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;008739&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;25&lt;/span&gt;%       &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;116832&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;50&lt;/span&gt;%       &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;180046&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;75&lt;/span&gt;%       &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;219244&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;max&lt;/span&gt;       &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;363148&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;Name&lt;/span&gt;: Ratio, dtype: float&lt;span class=&quot;hljs-number&quot;&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;lt1000[&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;].describe()
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-apache&quot;&gt;&lt;span class=&quot;hljs-attribute&quot;&gt;count&lt;/span&gt;    &lt;span class=&quot;hljs-number&quot;&gt;234&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;000000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;mean&lt;/span&gt;       &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;156139&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;std&lt;/span&gt;        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;094783&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;min&lt;/span&gt;        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;000000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;25&lt;/span&gt;%        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;072971&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;50&lt;/span&gt;%        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;155958&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;75&lt;/span&gt;%        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;220952&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;max&lt;/span&gt;        &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;492114&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;Name&lt;/span&gt;: Ratio, dtype: float&lt;span class=&quot;hljs-number&quot;&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The mean ratio for those with &gt; 1000 friends is a little bit larger than those without, as is the median.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;%matplotlib inline

plt.figure(figsize=(&lt;span class=&quot;hljs-number&quot;&gt;12&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;))

plt.subplot(&lt;span class=&quot;hljs-number&quot;&gt;121&lt;/span&gt;)
plt.plot(lt1000[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;], lt1000[&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;], &lt;span class=&quot;hljs-string&quot;&gt;&#39;ro&#39;&lt;/span&gt;)
plt.plot(gt1000[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;] - &lt;span class=&quot;hljs-number&quot;&gt;1000&lt;/span&gt;, gt1000[&lt;span class=&quot;hljs-string&quot;&gt;&#39;Ratio&#39;&lt;/span&gt;], &lt;span class=&quot;hljs-string&quot;&gt;&#39;bo&#39;&lt;/span&gt;)

plt.xlabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;)
plt.ylabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;Realike Ratio&#39;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-mipsasm&quot;&gt;&amp;#x3C;matplotlib&lt;span class=&quot;hljs-meta&quot;&gt;.text&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;.Text&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x1140b42e8&lt;/span&gt;&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;img src=&quot;https://naitian.org/assets/img/output_25_1.png&quot; alt=&quot;&quot; /&gt;&lt;p&gt;This plot might be a little bit confusing. The red dots represents users with fewer than 1000 friends. The blue dots represents users with 1000 or more friends, but the dots are scaled so as to align with the red dots (by subtracting 1000 from the friend count).&lt;/p&gt;&lt;p&gt;What does this reveal? Not much. There are more red dots in the upper right corner than blue dots, but the points are spread evenly enough where this is insignificant.&lt;/p&gt;&lt;h3&gt;Looking at Friend Counts&lt;/h3&gt;&lt;p&gt;As an aside, I took a look at the distribution of friend counts.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;].describe()
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-apache&quot;&gt;&lt;span class=&quot;hljs-attribute&quot;&gt;count&lt;/span&gt;     &lt;span class=&quot;hljs-number&quot;&gt;278&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;000000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;mean&lt;/span&gt;      &lt;span class=&quot;hljs-number&quot;&gt;656&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;589928&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;std&lt;/span&gt;       &lt;span class=&quot;hljs-number&quot;&gt;395&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;612176&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;min&lt;/span&gt;        &lt;span class=&quot;hljs-number&quot;&gt;22&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;000000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;25&lt;/span&gt;%       &lt;span class=&quot;hljs-number&quot;&gt;371&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;750000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;50&lt;/span&gt;%       &lt;span class=&quot;hljs-number&quot;&gt;564&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;500000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;75&lt;/span&gt;%       &lt;span class=&quot;hljs-number&quot;&gt;841&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;750000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;max&lt;/span&gt;      &lt;span class=&quot;hljs-number&quot;&gt;2403&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;000000&lt;/span&gt;
&lt;span class=&quot;hljs-attribute&quot;&gt;Name&lt;/span&gt;: # Friends, dtype: float&lt;span class=&quot;hljs-number&quot;&gt;64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Conclusion? My friends, on average, have twice as many friends as I do. Sad.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;plt.figure(figsize=(&lt;span class=&quot;hljs-number&quot;&gt;16&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;8&lt;/span&gt;))

plt.subplot(&lt;span class=&quot;hljs-number&quot;&gt;121&lt;/span&gt;)
plt.boxplot(data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;])
plt.ylabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;)

plt.subplot(&lt;span class=&quot;hljs-number&quot;&gt;122&lt;/span&gt;)
plt.hist(data[&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;], bins=&lt;span class=&quot;hljs-number&quot;&gt;20&lt;/span&gt;)
plt.ylabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;Freq.&#39;&lt;/span&gt;)
plt.xlabel(&lt;span class=&quot;hljs-string&quot;&gt;&#39;# Friends&#39;&lt;/span&gt;)
plt.title(&lt;span class=&quot;hljs-string&quot;&gt;&#39;How Many Friends My Friends Have&#39;&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-mipsasm&quot;&gt;&amp;#x3C;matplotlib&lt;span class=&quot;hljs-meta&quot;&gt;.text&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;.Text&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0x114f552b0&lt;/span&gt;&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;fullwidth&quot;&gt;
&lt;img src=&quot;https://naitian.org/assets/img/output_30_1.png&quot; alt=&quot;Graph of friend count distributions.&quot; /&gt;
&lt;figcaption&gt;Distribution of my friends&#39; friend counts&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;As shown by the box plot and, perhaps more obviously, by the histogram, the distribution of friend counts is skewed right, accounting for the large difference between mean friend count and median friend count. Either way, I look to be pretty anti-social.&lt;/p&gt;&lt;h3&gt;Conclusions?&lt;/h3&gt;&lt;p&gt;I can&#39;t really draw any statistically significant conclusions from these data. That said, there were some trends that were insightful or interesting to some extent.&lt;/p&gt;&lt;h4&gt;Quality over Quantity&lt;/h4&gt;&lt;p&gt;It&#39;s apparent that having a higher friend count does not necessarily result in a higher realike ratio. For 4 of the top 5 ranked realike users, the friend count was below the third quartile. In fact, the user with the highest friend count (2403 friends) had one of the lowest ratios (.8%)&lt;/p&gt;&lt;p&gt;That said, by examining the bottom 5, almost all were below the median friend count. This seems to imply that having too few friends is also not ideal.&lt;/p&gt;&lt;p&gt;Given these very broad generalizations, one can make the logical ssumption that there is a &quot;Goldilocks zone&quot; of friend count that yields that highest ratio. However, the data is probably much to scattered to be able to actually generate a useful model.&lt;/p&gt;&lt;h4&gt;An Individualized Analysis&lt;/h4&gt;&lt;p&gt;This data set was composed of only my friends. This meant the data set was tailored uniquely to my choice of friends, which are mostly high schoolers in the NOVA area.&lt;/p&gt;&lt;h4&gt;Next Steps&lt;/h4&gt;&lt;p&gt;There are quite a few paths in which I can proceed with this little experiment, if I want to. For one thing, it would be great to acquire more data, and, now that I think of it, generally profile pictures and friend counts are public, so I could expand the data set to beyond my friends.&lt;/p&gt;&lt;p&gt;Looking at the contents of the profile picture would also be interesting. For example, in pictures that were especially popular, were there multiple people? What is the gender / age / etc of the subject? However, this will be a much more nontrivial task.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>The Blue Lagoon</title>
		<link href="https://naitian.org/blog/2017/04/13/The-Blue-Lagoon/" />
		<updated>2017-04-13T07:00:00Z</updated>
		<id>https://naitian.org/blog/2017/04/13/The-Blue-Lagoon/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;The Blue Lagoon&lt;/h2&gt;&lt;p&gt;&lt;em&gt;&quot;The Blue Lagoon is a 1980 American romance and adventure film directed by
Randal Kleiser&quot;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;This phrase is stuck in my head. Not because I&#39;m a huge fan of poorly rated
movies, but because it&#39;s a test phrase that Google likes to use to show off its
speech synthesis algorithms. Speech synthesis has kinda been stuck in my head
too.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Tacotron Yum&lt;/h2&gt;&lt;p&gt;Recently, researchers at Google published a paper describing a text-to-speech
generation model called “Tacotron”. It uses deep learning to learn how to
generate audio based on input text. Besides catching my attention due to the
delicious sounding title, the paper intrigued me because of the problems that
arise when trying to synthesize speech from text. Current speech synthesis
models in production rely primarily on concatenation of pre-recorded words, with
some smoothing to make the words flow together more. The problem with this
method is that the length of words and intonation are not taken fully into
consideration, causing the synthesized audio to sound robotic and unnatural.&lt;/p&gt;&lt;p&gt;Synthesizing speech is a non-trivial problem, mainly because there is a
lot of interpolation involved. Raw text does not provide a lot of clues for the
tone, inflection, and expressiveness. The inflection in asking a question, such
as &quot;It&#39;s your birthay today?&quot;, is significantly different from that in a statement
such as &quot;It&#39;s your birthday today!&quot; In addition, individual voices,
obviously, differ by a lot, based on gender, nationality, etc. It&#39;s hard to
teach a computer to generalize the important parts.&lt;/p&gt;&lt;p&gt;Tacotron takes a different approach from the current concatenative
methods: it uses an “end-to-end” approach, wherein it learns from text/speech
pairs to determine how to directly generate the raw spectrogram given an input
text. This allows for it to include features such as a natural rhythm of speech,
incorporate stress and intonation. The strength of a deep learning model is that
it can naturally incorporate features that may otherwise go overlooked. Since it
learns from recordings, for example, and uses that to generate speech, the
generated audio also includes mouth-sounds and breathing that make the speech
sound more human.&lt;/p&gt;&lt;p&gt;Speech synthesis is an incredibly relevant application of computer
science, which is why I found the topic so interesting. Text to speech could be
used to automatically generate audiobooks, create dialogue procedurally, and
provide accurate verbal translations. Personal assistant applications that use a
conversational interface would require natural speech synthesis for a more
immersive user experience.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Additional Reading&lt;/h2&gt;&lt;p&gt;You can read the Tacotron paper &lt;a href=&quot;https://arxiv.org/abs/1703.10135&quot;&gt;here&lt;/a&gt; (arxiv
1703.10135).&lt;/p&gt;&lt;p&gt;You can read about another one of Google&#39;s speech synthesis projects, WaveNet,
&lt;a href=&quot;https://deepmind.com/blog/wavenet-generative-model-raw-audio/&quot;&gt;here&lt;/a&gt; (website)
or &lt;a href=&quot;https://arxiv.org/abs/1609.03499&quot;&gt;here&lt;/a&gt; (paper; arxiv 1609.03499).&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>About this Site - Design</title>
		<link href="https://naitian.org/blog/2017/03/05/About-this-Site-Design/" />
		<updated>2017-03-05T08:00:00Z</updated>
		<id>https://naitian.org/blog/2017/03/05/About-this-Site-Design/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Getting Started&lt;/h2&gt;&lt;p&gt;After getting an idea of what I wanted to accomplish with the site (which I
detailed in the previous post), I was ready to begin designing.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/03/05/About-this-Site-Design/#sketching&quot;&gt;Sketching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/03/05/About-this-Site-Design/#mockups&quot;&gt;Mockups&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/03/05/About-this-Site-Design/#home&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/03/05/About-this-Site-Design/#about&quot;&gt;About&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/03/05/About-this-Site-Design/#art&quot;&gt;Art&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/03/05/About-this-Site-Design/#blog&quot;&gt;Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/03/05/About-this-Site-Design/#projects&quot;&gt;Projects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/03/05/About-this-Site-Design/#post-mortem&quot;&gt;Post Mortem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Sketching&lt;/h2&gt;&lt;p&gt;I normally start out with sketching some ideas. Conveniently, I was going to
Seattle for winter break, so the hours on the flight sans internet was
well-used.&lt;/p&gt;&lt;p&gt;I find sketching to be useful for figuring out layout and the flow of content. I
was now ready to start making some mockups.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Mockups&lt;/h2&gt;&lt;p&gt;I use &lt;a href=&quot;https://affinity.serif.com/en-us/designer/&quot;&gt;Affinity Designer&lt;/a&gt; for all of
my computer graphics work. I used to use Adobe Illustrator before I switched
computers, and the overall workflow is very similar, which meant a pretty low
learning curve for the transition.&lt;/p&gt;&lt;h3&gt;Home&lt;/h3&gt;&lt;p&gt;I started with the home page. I tried to keep it simple, and allow it to act as
a hub to all of the other pages.&lt;/p&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/home_mock.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;The index of the site&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;I also wanted to keep the terminal, and ultimately decided on adding a little
flip tab to reveal the &quot;inside&quot; of the site.&lt;/p&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/home_unveiled_mock.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;The hidden
terminal.&lt;/figcaption&gt;
&lt;/figure&gt;&lt;h3&gt;About&lt;/h3&gt;&lt;p&gt;One of the first conditions for the About page was that I had to include a
picture of myself. However, images always raise the risk of disrupting the
stylistic consistency (especially when the photo isn&#39;t that good). I
eventually decided to add an overlay of the theme color.&lt;/p&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/about_mock.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;Both the desktop and mobile
layouts&lt;/figcaption&gt;
&lt;/figure&gt;&lt;h3&gt;Art&lt;/h3&gt;&lt;p&gt;A huge reason for the redesign of the site was because I wanted a place for me
to show off the things that I draw and design. This is where the design things
got interesting.&lt;/p&gt;&lt;p&gt;For the home page of the Art section, I wanted to keep it as a simple mosaic
layout, without any text. In fact, in the original design, I had envisioned
tiled and interlocking blocks. The goal was to have a wall of art, and clicking
on one would lead you to a page explaining the piece in greater detail.&lt;/p&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/art_mock.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;Mockup for home page of art&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;This detail page was more interesting to work with. I wanted to cast attention
primarily upon the work, so I chose a dark background. The piece is displayed
prominently as the first item, but underneath is the same layout as a blog post.&lt;/p&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/art_detail_mock.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;Detail page for a
specific page. Note the unappealing background color.&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;This is probably the least polished part of the site. Some concerns I have about
the details page is how the colors might clash. The current color is far from
neutral.&lt;/p&gt;&lt;h3&gt;Blog&lt;/h3&gt;&lt;p&gt;I wanted to keep the blog as a separate entity from the rest of the site. This
informed some of my decisions, such as having the navigation at the root of the
blog be a &quot;go to website&quot; button, instead of the nav bar as shown on the rest of
the site.&lt;/p&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/blog_toc_mock.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;Table of Contents for
the blog. Probably page that changed the least from design to development&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;The blog is mainly text-based, so I stuck to a black and white color scheme,
like ink on paper. I&#39;m satisfied with the very minimalist aesthetic.&lt;/p&gt;&lt;p&gt;I struggled more with the page of an article. I had a couple of choices to make.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Typeface:
&lt;ul&gt;
&lt;li&gt;I planned on initially using two typefaces: Open Sans for headers, and a
serif typeface for body text. However, it looked kind of busy, so I
ultimately decided against it. I may revisit the idea in the future,
though, because I kind of like the look.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cover photo:
&lt;ul&gt;
&lt;li&gt;I was unsure of how I would handle cover images. Initially, I planned on
making the cover images fit into the width of the article, but I ended up
preferring the expansive feeling of having the image stretch across the
entire width of the screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/blog_post_mock.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;Mockup of a blog post&lt;/figcaption&gt;
&lt;/figure&gt;&lt;h3&gt;Projects&lt;/h3&gt;&lt;p&gt;I probably struggled with the Projects page the most. I tried 5 or 6 different
card designs before settling on one that I liked. I played around with working
project-specific colors into each card, but I figured that would be too busy.&lt;/p&gt;&lt;figure class=&quot;figure&quot;&gt;
    &lt;img src=&quot;https://naitian.org/assets/img/project_mock.png&quot; /&gt;
    &lt;figcaption class=&quot;img-caption&quot;&gt;So many variations of the
card.&lt;/figcaption&gt;
&lt;/figure&gt;&lt;p&gt;I added a subtle drop shadow just to keep things interesting.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Post Mortem&lt;/h2&gt;&lt;p&gt;Overall, I&#39;m very satisfied with the design of this site. Nonetheless, there are
still a couple of things that I may change in the future.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Art Detail Page
&lt;ul&gt;
&lt;li&gt;As I previously alluded to, I&#39;m not entirely satisfied with the design of
this page. I have two main concerns.&lt;/li&gt;
&lt;li&gt;I&#39;m not happy with the &lt;strong&gt;color choice&lt;/strong&gt;. It looks kind of muddy, and doesn&#39;t
really allow the pieces to stand out that much.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;presentation of additional images&lt;/strong&gt; is flawed, especially since some
images don&#39;t contrast as well against the background, and they&#39;re
currently very small without a way to zoom in on them.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Project Cards
&lt;ul&gt;
&lt;li&gt;I&#39;m still not entirely sold on the design of the project cards. I think the
&lt;strong&gt;presentation is a bit too plain&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Blog Post
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Font color&lt;/strong&gt; is something I&#39;m still working on with the blog. The color of
links is harsh, and stands out too much. The pure black text on a pure
white background also seems jarring. However, I like how sharp it feels
with that much contrast.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Table of Contents&lt;/strong&gt; needs to be dealt with to make it more interesting,
or at least more visually appealing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>About this Site - Intro</title>
		<link href="https://naitian.org/blog/2017/02/14/About-this-Site-(Part-1)/" />
		<updated>2017-02-14T08:00:00Z</updated>
		<id>https://naitian.org/blog/2017/02/14/About-this-Site-(Part-1)/</id>
		<content xml:lang="en" type="html"
			>&lt;p&gt;&lt;em&gt;Edited 3/6/17 to add in new links and change title.&lt;/em&gt;&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;p&gt;I spent the better part of my winter break revamping my personal website (of
which this blog is a component). You can view the old site here:
&lt;a href=&quot;https://naitian.github.io/&quot;&gt;naitian.github.io&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you want to skip to another part of this walkthrough, I have links to all of
the available parts listed for you here:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://naitian.org/blog/2017-03-05-About-this-Site---Design/&quot;&gt;Design&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Setting Goals&lt;/h2&gt;&lt;p&gt;I think it&#39;s important to consider what the goals, desires, and requirements are
for every project.&lt;/p&gt;&lt;p&gt;While I was generally satisfied with the old website, there were some issues that I felt
needed addressing.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;The overabundance of colors pulled from
&lt;a href=&quot;http://flatuicolors.com/&quot;&gt;flatuicolors.com&lt;/a&gt; was busy, and seemed like it
wasn&#39;t well thought out.&lt;/li&gt;
&lt;li&gt;The terminal in the background never worked very well, and ultimately
didn&#39;t do everything I wanted it to. &lt;strong&gt;I wanted a dynamic &quot;terminal&quot; through
which you could basically browse the entire website&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;I had gotten tired of the one-page layout, after also using for the &lt;a href=&quot;https://tjdev.club/&quot;&gt;Dev
Club Website&lt;/a&gt;, so &lt;strong&gt;I wanted to challenge myself with a
new type of layout&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;I wanted to start up the blog again, and the original Jekyll blog was kind
of a pain to work with. &lt;strong&gt;I wanted to minimize the friction involved with
publishing new posts&lt;/strong&gt;, which would in turn encourage me to write more.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Okay, so those were the things that I took issue with. However, there were some
aspects of the site that I wanted to keep.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;I liked the terminal; it&#39;s fun and nerdy. So I wanted to keep it, but maybe
make it a bit more subtle.&lt;/li&gt;
&lt;li&gt;I liked having distinct colors for the different sections.&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Fizz Buzz</title>
		<link href="https://naitian.org/blog/2017/01/26/Fizz-Buzz/" />
		<updated>2017-01-26T08:00:00Z</updated>
		<id>https://naitian.org/blog/2017/01/26/Fizz-Buzz/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Fizz Buzz? How trivial.&lt;/h2&gt;&lt;p&gt;Recently, I needed to submit a fizz-buzz program as part of my application for a
summer internship (hi Dagger Analytics!). I&#39;ve decided to take advantage of that
to talk about why sometimes, the most elegant code isn&#39;t the best code.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Cutting to the chase&lt;/h2&gt;&lt;p&gt;Here is my Fizz-Buzz code:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-javascript&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// Javascript solution&lt;/span&gt;

&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; i = &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;; i &amp;#x3C; &lt;span class=&quot;hljs-number&quot;&gt;101&lt;/span&gt;; i++) {
   &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; string = &lt;span class=&quot;hljs-string&quot;&gt;&#39;&#39;&lt;/span&gt;;
   &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i % &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; === &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {
      string += &lt;span class=&quot;hljs-string&quot;&gt;&#39;fizz&#39;&lt;/span&gt;;
   }
   &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i % &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; === &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) {
      string += &lt;span class=&quot;hljs-string&quot;&gt;&#39;buzz&#39;&lt;/span&gt;;
   }
   &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (string === &lt;span class=&quot;hljs-string&quot;&gt;&#39;&#39;&lt;/span&gt;) {
      string = &lt;span class=&quot;hljs-built_in&quot;&gt;parseInt&lt;/span&gt;(i);
   }
   &lt;span class=&quot;hljs-built_in&quot;&gt;console&lt;/span&gt;.log(string)
}
&lt;/code&gt;&lt;/pre&gt;&lt;div id=&quot;output&quot;&gt;
&lt;br /&gt;
&lt;b style=&quot;cursor: pointer&quot;&gt;Click to Toggle Output&lt;/b&gt;
&lt;div style=&quot;overflow: hidden&quot; id=&quot;actualOutput&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;script&gt;

window.onload = function () {
   let open = false;
   let out = document.querySelector(&#39;#actualOutput&#39;);
   out.style.height = 0;
   document.querySelector(&#39;#output &gt; b&#39;).addEventListener(&#39;click&#39;, () =&gt; {
      if (open) {
         out.style.height = 0;
      } else {
         out.style.height = &#39;100%&#39;;
      }
      open = !open;
   })
   for(let i = 1; i &lt; 101; i++) {
      let string = &#39;&#39;;
      if (i % 3 === 0) {
         string += &#39;fizz&#39;;
      }
      if (i % 5 === 0) {
         string += &#39;buzz&#39;;
      }
      if (string === &#39;&#39;) {
         string = parseInt(i);
      }
      out.innerHTML += &quot;&lt;br /&gt;&quot; + string;
      console.log(string);
   }
}

&lt;/script&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Post-mortem (the good part)&lt;/h2&gt;&lt;p&gt;Ok, so now that you have viewed this solution, you may have some questions. I
can hear them right now.&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;Naitian, why would you use Javascript? Why are you using 13 lines to write
something this simple? Etc, etc.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Well to address the elephant in the room, I used Javascript because it was the
most convenient thing for me to write in. But to satisfy you, here&#39;s a solution
in Python.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;101&lt;/span&gt;):
    string = &lt;span class=&quot;hljs-string&quot;&gt;&#39;&#39;&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; i % &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;:
        string += &lt;span class=&quot;hljs-string&quot;&gt;&#39;fizz&#39;&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; i % &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;:
        string += &lt;span class=&quot;hljs-string&quot;&gt;&#39;buzz&#39;&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; string == &lt;span class=&quot;hljs-string&quot;&gt;&#39;&#39;&lt;/span&gt;:
        string = &lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;(i)
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(string)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As you can see, it&#39;s the &lt;strong&gt;exact same thing&lt;/strong&gt;. Alright, cool. So why didn&#39;t I do
something totally rad, like this list comprehension!?&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; line &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; [&lt;span class=&quot;hljs-built_in&quot;&gt;str&lt;/span&gt;(i) &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i % &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; != &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; i % &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; != &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;fizz&#39;&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i % &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt; == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;buzz&#39;&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (i % &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt; == &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;fizzbuzz&#39;&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;range&lt;/span&gt;(&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;101&lt;/span&gt;)]:
    &lt;span class=&quot;hljs-built_in&quot;&gt;print&lt;/span&gt;(line)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See, it&#39;s only 2 lines and does the exact same thing! It also showcases my l33t
h4x0r skills! Well, yeah, but you tell me what&#39;s going on in that mess.&lt;/p&gt;&lt;p&gt;When writing code, especially when it&#39;s a one-off sort of thing, it&#39;s often easy
to get stuck trying to get a more &quot;elegant&quot; solution. But I think it&#39;s good to
keep in mind that the technically superior solution is not necessarily the best
solution. Sure, the list comprehension is &lt;a href=&quot;http://stackoverflow.com/questions/22108488/are-list-comprehensions-and-functional-functions-faster-than-for-loops&quot;&gt;arguably
faster&lt;/a&gt;, but you shouldn&#39;t sacrifice that for readability, especially at such small scales.&lt;/p&gt;&lt;p&gt;That&#39;s not to say you shouldn&#39;t try to write good, performant code, but instead
you should focus on writing maintainable, bug-free code, which ends up being a
much more valuable skill in the real world.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Getting Cozy with Jekyll</title>
		<link href="https://naitian.org/blog/2017/01/14/Getting-Cozy-With-Jekyll/" />
		<updated>2017-01-14T08:00:00Z</updated>
		<id>https://naitian.org/blog/2017/01/14/Getting-Cozy-With-Jekyll/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;The Problem&lt;/h2&gt;&lt;p&gt;I&#39;ve been having lots of fun with this blog, and Jekyll makes it easy to write
posts. I love the simplicity involved in creating a post and publishing it.
However, there were some irritations involved when starting to write a post: I
had to write the front matter manually every single time. As it turns out, I was
basically copying and pasting the front matter and changing values every time.
There must be a better way!&lt;/p&gt;&lt;p&gt;There isn&#39;t an easy fix for this. Since the front matter is specific to every
post, there&#39;s nothing I can specify in the Jekyll configuration. So the question
was: what do?&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The Solution&lt;/h2&gt;&lt;p&gt;After a little bit of research into preexisting solutions, I decided it would be
easiest to just write my own little script. I have a special set up, where, in
addition to just blog posts, I also have art and project posts that I want to
semi-automate the generation of also.&lt;/p&gt;&lt;p&gt;I ended up writing a Python script that basically walks me through the front
matter requirements for each post. The interface looks a little bit like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-sql_more&quot;&gt;blog &gt; title: Getting Cozy &lt;span class=&quot;hljs-keyword&quot;&gt;with&lt;/span&gt; Jekykll
blog &gt; author(Naitian Zhou):
blog &gt; cover(&lt;span class=&quot;hljs-keyword&quot;&gt;required&lt;/span&gt;): TODO
blog &gt; &lt;span class=&quot;hljs-keyword&quot;&gt;desc&lt;/span&gt;(A blog post): A &lt;span class=&quot;hljs-keyword&quot;&gt;quick&lt;/span&gt; guide &lt;span class=&quot;hljs-keyword&quot;&gt;to&lt;/span&gt; easliy generating &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; Jekyll psts &lt;span class=&quot;hljs-keyword&quot;&gt;with&lt;/span&gt; Python &lt;span class=&quot;hljs-keyword&quot;&gt;and&lt;/span&gt; Mustache
Would you &lt;span class=&quot;hljs-keyword&quot;&gt;like&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;add&lt;/span&gt; a tag? (y/N)y
blog &gt; tag &gt; &lt;span class=&quot;hljs-keyword&quot;&gt;name&lt;/span&gt;: Python
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This generates a file &lt;code&gt;_drafts/getting-cozy-with-jekyll.md&lt;/code&gt; with the following
content:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;title:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Getting&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Cozy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Jekyll&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;author:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Naitian&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Zhou&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;cover:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/assets/TODO&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;quick&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;guide&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;easily&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;generating&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Jekyll&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;posts&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Python&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Mustache&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;tags:&lt;/span&gt;
    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Python&lt;/span&gt;
&lt;span class=&quot;hljs-meta&quot;&gt;---
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A couple of interesting notes: I implemented very basic default values, which
allowed me to leave the &lt;code&gt;Author: &lt;/code&gt; field blank, and included the ability to add
lists to the front matter.&lt;/p&gt;&lt;p&gt;In fact, I even made it so that I could specify more JSON schemas for posts and
the script would automatically be able to handle those as well. Here&#39;s the
relevant directory structure:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-haml&quot;&gt; -&lt;span class=&quot;ruby&quot;&gt; /&lt;span class=&quot;hljs-regexp&quot;&gt;/other Jekyll files
&lt;/span&gt;&lt;/span&gt; -&lt;span class=&quot;ruby&quot;&gt;&lt;span class=&quot;hljs-regexp&quot;&gt; _templates/&lt;/span&gt;
&lt;/span&gt;   -&lt;span class=&quot;ruby&quot;&gt; schemas.json
&lt;/span&gt;   -&lt;span class=&quot;ruby&quot;&gt; art.mustache
&lt;/span&gt;   -&lt;span class=&quot;ruby&quot;&gt; blog.mustache
&lt;/span&gt;   -&lt;span class=&quot;ruby&quot;&gt; project.mustache
&lt;/span&gt; -&lt;span class=&quot;ruby&quot;&gt; _utils/
&lt;/span&gt;   -&lt;span class=&quot;ruby&quot;&gt; help.py
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I used the mustache templating language for easy templating. The art.mustache
file looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;title:&lt;/span&gt; {{&lt;span class=&quot;hljs-string&quot;&gt;title&lt;/span&gt;}}
&lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; {{&lt;span class=&quot;hljs-string&quot;&gt;img&lt;/span&gt;}}
{{&lt;span class=&quot;hljs-comment&quot;&gt;#other}}&lt;/span&gt;
&lt;span class=&quot;hljs-attr&quot;&gt;others:&lt;/span&gt;
{{&lt;span class=&quot;hljs-string&quot;&gt;/other&lt;/span&gt;}}
{{&lt;span class=&quot;hljs-comment&quot;&gt;#other}}&lt;/span&gt;
   &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; {{&lt;span class=&quot;hljs-string&quot;&gt;file&lt;/span&gt;}}
{{&lt;span class=&quot;hljs-string&quot;&gt;/other&lt;/span&gt;}}
&lt;span class=&quot;hljs-attr&quot;&gt;description:&lt;/span&gt; {{&lt;span class=&quot;hljs-string&quot;&gt;desc&lt;/span&gt;}}
&lt;span class=&quot;hljs-meta&quot;&gt;---
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This method gives me a lot of flexibility to flesh out the templates in the
future. I could even add content into the body text, in addition to the front
matter.&lt;/p&gt;&lt;p&gt;I used Python and the &lt;code&gt;pystache&lt;/code&gt; library to take the input and render out the
correct files.&lt;/p&gt;&lt;p&gt;To take input, I wrote a recursive function that looks at the schema specified
by the &lt;code&gt;schemas.json&lt;/code&gt; file.&lt;/p&gt;&lt;p&gt;Here is the entirety of the schemas file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-json&quot;&gt;{
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;blog&quot;&lt;/span&gt;: {
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;title&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;required&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;author&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;Naitian Zhou&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;cover&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;required&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;desc&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;A blog post&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;tag&quot;&lt;/span&gt;: [
            {&lt;span class=&quot;hljs-attr&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;}
        ]
    },
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;art&quot;&lt;/span&gt;: {
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;title&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;required&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;img&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;required&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;desc&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;An art piece&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;other&quot;&lt;/span&gt;: [
            {&lt;span class=&quot;hljs-attr&quot;&gt;&quot;file&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;}
        ]
    },
    &lt;span class=&quot;hljs-attr&quot;&gt;&quot;project&quot;&lt;/span&gt;: {
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;title&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;thumb&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;desc&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;A project page&quot;&lt;/span&gt;,
        &lt;span class=&quot;hljs-attr&quot;&gt;&quot;tech&quot;&lt;/span&gt;: [
            {&lt;span class=&quot;hljs-attr&quot;&gt;&quot;name&quot;&lt;/span&gt;: &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;}
        ]
    }    
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The function looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-python&quot;&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;prompt&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;title, obj&lt;/span&gt;):&lt;/span&gt;
    &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&quot;Prompt for input

    :obj: Empty Object
    :returns: Filled-in object

    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; key &lt;span class=&quot;hljs-keyword&quot;&gt;in&lt;/span&gt; obj:
        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;type&lt;/span&gt;(obj[key]) &lt;span class=&quot;hljs-keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;list&lt;/span&gt;:
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&#39;Would you like to add a {}? (y/N)&#39;&lt;/span&gt;.&lt;span class=&quot;hljs-built_in&quot;&gt;format&lt;/span&gt;(key)) == &lt;span class=&quot;hljs-string&quot;&gt;&#39;y&#39;&lt;/span&gt;:
                &lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;True&lt;/span&gt;:
                    obj[key].append(prompt(&lt;span class=&quot;hljs-string&quot;&gt;&#39;{} &gt; {}&#39;&lt;/span&gt;.&lt;span class=&quot;hljs-built_in&quot;&gt;format&lt;/span&gt;(title, key), copy.deepcopy(obj[key][&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;])))
                    &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;&#39;Finished? (y/N)&#39;&lt;/span&gt;) == &lt;span class=&quot;hljs-string&quot;&gt;&#39;y&#39;&lt;/span&gt;:
                        &lt;span class=&quot;hljs-keyword&quot;&gt;break&lt;/span&gt;
            obj[key] = obj[key][&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;:] &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;len&lt;/span&gt;(obj[key]) &gt;= &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;None&lt;/span&gt;
        &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:
            message = &lt;span class=&quot;hljs-string&quot;&gt;&#39;{} &gt; {}: &#39;&lt;/span&gt;.&lt;span class=&quot;hljs-built_in&quot;&gt;format&lt;/span&gt;(title, key) &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; obj[key] == &lt;span class=&quot;hljs-string&quot;&gt;&#39;&#39;&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&#39;{} &gt; {}({}): &#39;&lt;/span&gt;.&lt;span class=&quot;hljs-built_in&quot;&gt;format&lt;/span&gt;(title, key, obj[key])
            val = &lt;span class=&quot;hljs-built_in&quot;&gt;input&lt;/span&gt;(message)
            &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; val != &lt;span class=&quot;hljs-string&quot;&gt;&#39;&#39;&lt;/span&gt;:
                obj[key] = val
    &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; obj
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It prompts you for the requisite values (and keeps the default if you don&#39;t
enter anything), and recursively goes into lists if lists are present. It will
then return an &lt;code&gt;OrderedDict&lt;/code&gt; that we can feed into &lt;code&gt;pystache.render()&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Now whenever I want to write a new blog post, I can just call&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;hljs language-vim&quot;&gt;$ _utils/&lt;span class=&quot;hljs-keyword&quot;&gt;help&lt;/span&gt;.&lt;span class=&quot;hljs-keyword&quot;&gt;py&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;new&lt;/span&gt; blog
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and it will hold my hand as we navigate through the front matter options.&lt;/p&gt;&lt;p&gt;You can find all of the files on the &lt;a href=&quot;https://github.com/naitian/PV2&quot;&gt;Github for my blog&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;More specifically, here are the &lt;a href=&quot;https://github.com/naitian/PV2/blob/master/_util/help.py&quot;&gt;Python
script&lt;/a&gt; and the
&lt;a href=&quot;https://github.com/naitian/PV2/tree/master/_templates&quot;&gt;template directory&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Oops! and Why I Use Vim</title>
		<link href="https://naitian.org/blog/2017/01/09/Oops/" />
		<updated>2017-01-09T08:00:00Z</updated>
		<id>https://naitian.org/blog/2017/01/09/Oops/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;A Quick Apology&lt;/h2&gt;&lt;p&gt;So a little over a week ago, I wrote my first post of the year, detailing a
couple of my goals, one of which was to hopefully release a blog post every
week. Oops... That lasted for a total of one week...&lt;/p&gt;&lt;p&gt;Anyway.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;An Unhealthy Obsession&lt;/h2&gt;&lt;p&gt;A couple of months ago, I switched to using Vim full-time to do all of my text
editing (coding and writing Markdown... I still use MS Word for rich text
editing).&lt;/p&gt;&lt;p&gt;When I say I can&#39;t go back to Sublime Text anymore, it&#39;s not because I&#39;m in love
with everything about Vim. It&#39;s not even that (despite what some people may say)
Vim has shown me the flaws of all of the other graphical text editors in the
world. In fact, I sometimes find myself missing all of the thoughtful,
plug-and-play aspects of Sublime Text, like how easy theming it is, or how
seamless the autocompletion is, or how package manager (with Package Control)
&quot;just works&quot;.&lt;/p&gt;&lt;p&gt;The real reason I can&#39;t go back to Sublime anymore is because, whenever I want
to save a file, I end up typing &quot;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&quot; before I realize I needed to
press Command-S. Oops.&lt;p&gt;&lt;/p&gt;&lt;p&gt;So you may be wondering to yourself, &lt;em&gt;Why would Naitian ever have wanted to use
Vim then?&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Good question.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;An Unlikely Romance (OoooOOOOoooo)&lt;/h2&gt;&lt;p&gt;The original motive was not to become a l33t hax0r that lives in the terminal.
Oops. My experience with the command line has been one of slow, begrudging
acceptance. I like to imagine it as a buddy film where the initial mutual
disdain slowly blooms into a wonderful friendship.&lt;/p&gt;&lt;p&gt;Movie analogies aside, the true reason I chose to use Vim was because I could
use Vim with tmux, which meant I had full control over how my text editor and
terminal emulator meshed together. It was like a tiling window manager except I
didn&#39;t need to install a tiling wm. Is that a weird, convoluted excuse to use
vim? Yes, but that be the truth.&lt;/p&gt;&lt;p&gt;Well, after I played around with the &lt;code&gt;vimrc&lt;/code&gt; for a little bit, I was hooked on
how configurable vim was (I&#39;m a sucker for config files), and the rest is
history.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;The Happy Ending&lt;/h2&gt;&lt;p&gt;So now I use Vim every day to do everything from writing this sentence to
making my website to doing my AI labs.&lt;/p&gt;&lt;p&gt;Expect a post on how I use Vim coming up soon (hopefully next week when I
&lt;em&gt;don&#39;t&lt;/em&gt; forget to post...)&lt;/p&gt;&lt;p&gt;Also! You know what would make the ending even happier? If you used that handy
dandy RSS link in that footer down there to subscribe to this blog and read all
of these mildly amusing posts!&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>New Year, New Blog, and New Bugs</title>
		<link href="https://naitian.org/blog/2017/01/01/New-Years-New-Bugs/" />
		<updated>2017-01-01T08:00:00Z</updated>
		<id>https://naitian.org/blog/2017/01/01/New-Years-New-Bugs/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Organizing My Thoughts&lt;/h2&gt;&lt;p&gt;I&#39;m writing this blog post on New Year&#39;s Day, bracing myself for the violent
reentry into my hectic school life in less than 2 days. I think this is a good
opportunity for me to take a step back and organize my thoughts while I still
have the time (and patience), so here goes.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Table of Contents&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/01/01/New-Years-New-Bugs/#this-website&quot;&gt;This Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/01/01/New-Years-New-Bugs/#this-blog&quot;&gt;This Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/01/01/New-Years-New-Bugs/#this-life-mine-not-yours&quot;&gt;This Life (Mine, Not Yours)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://naitian.org/blog/2017/01/01/New-Years-New-Bugs/#speaking-of-being-updated&quot;&gt;Speaking of Being Updated...&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;This Website&lt;/h2&gt;&lt;p&gt;I&#39;ve spent the majority of my winter break working on this website. It&#39;s built
with blood, sweat, and tears, except instead of blood I used Jekyll, and instead
of sweat and tears I used Sass and HTML.&lt;/p&gt;&lt;p&gt;This was also my first time working with Sass, so definitely expect something
about that experience soon. In fact, I didn&#39;t expect to be using Sass, until my
hand was basically forced when I wanted to use any type of asset pipeline for
minimizing and optimizing my assets.&lt;/p&gt;&lt;p&gt;There&#39;s still lots of work to be done, particularly in the little &quot;terminal&quot;
easter egg on the home page, but I&#39;m very happy with the site.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;This Blog&lt;/h2&gt;&lt;p&gt;After finishing the first version of the blog sometime in May of &lt;strike&gt;this
year&lt;/strike&gt; last year, I uploaded my first post (about Chrome Dev Tools), and
then promptly ignored it for the rest of the year. I definitely plan on posting
more, and hopefully at least once every week, with either tidbits of my personal
life or technical advice.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;This Life (Mine, Not Yours)&lt;/h2&gt;&lt;p&gt;I expect that, once I enter the halls of Thomas Jefferson High School for
Science and Technology, I will once again be faced with the challenges of
balancing schoolwork with everything else that I want to do, including Dev Club,
this blog, band, and so much more. So how do I plan on staying afloat? If only I
knew. That said, I&#39;ll take to heart Dory&#39;s advice of &quot;Just keep swimming&quot;, and
keep you guys updated.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Speaking of Being Updated...&lt;/h2&gt;&lt;p&gt;Subscribe to this blog using the RSS feed!&lt;/p&gt;&lt;p&gt;Anyway, Happy New Year&#39;s, and I hope you&#39;re as excited as I am (despite my
moaning and groaning) to start this year off strong.&lt;/p&gt;&lt;/section&gt;</content
		>
	</entry>
	<entry>
		<title>Chrome Developer Tools</title>
		<link href="https://naitian.org/blog/2016/05/30/Chrome-Dev-Tools/" />
		<updated>2016-05-30T07:00:00Z</updated>
		<id>https://naitian.org/blog/2016/05/30/Chrome-Dev-Tools/</id>
		<content xml:lang="en" type="html"
			>&lt;section&gt;&lt;h2&gt;Chrome Dev Tools&lt;/h2&gt;&lt;p&gt;A good grasp of how to use Chrome (or equivalent) Dev Tools are one of the most fundamental skills a web developer must have. From monitoring network calls to debugging Javascript to testing out CSS style changes, Dev Tools provides a useful repertoire of functions to help you develop, test, and optimize a web page.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Why Chrome?&lt;/h2&gt;&lt;p&gt;There is not a particular reason why I chose Chrome Dev Tools over other browsers, other than that I use Chrome and Chrome Dev Tools more than other browsers. Chrome Dev Tools does offer a lot of useful features, some of which may apply to cutting-edge web development standards, that may not be present on other browsers.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Opening Chrome Dev Tools&lt;/h2&gt;&lt;p&gt;Windows: F12 or Ctrl+Shift+I
Linux: Ctrl+Shift+I
Mac: Cmd+Opt+I&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;CDT and the DOM&lt;/h2&gt;&lt;p&gt;DOM stands for Document Object Model. It&#39;s a convention for representing and manipulating objects in HTML, XML, and XHTML documents (characterized by the angle brackets).&lt;/p&gt;&lt;h3&gt;What can I do?&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Inspect any element&lt;/li&gt;
&lt;li&gt;View and change CSS rules&lt;/li&gt;
&lt;li&gt;View the element&#39;s box model&lt;/li&gt;
&lt;/ol&gt;&lt;h3&gt;Inspecting Elements&lt;/h3&gt;&lt;p&gt;There are several ways to select and inspect a particular element. One can:&lt;/p&gt;&lt;p&gt;Click on the element selection tool, then click on an element to jump to that position in the document.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/cursor-deselected.png&quot; height=&quot;200&quot; /&gt;&lt;p&gt;Click on a specific element in the Dev Tools &lt;em&gt;Elements&lt;/em&gt; view.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/click-element.png&quot; height=&quot;200&quot; /&gt;&lt;h3&gt;What Can I Do With These Elements?&lt;/h3&gt;&lt;p&gt;Now that you have selected an element, you can right-click on the element to see some of the actions you can do:&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/actions.png&quot; height=&quot;200&quot; /&gt;&lt;p&gt;Especially notable is the ability to toggle states such as active, hover, etc.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Styling&lt;/h2&gt;&lt;p&gt;One of the most useful aspects of Dev Tools is the ability to change styles easily.&lt;/p&gt;&lt;p&gt;With an element selected, you can easily view its styles.&lt;/p&gt;&lt;p&gt;The &quot;Styles&quot; tab contains all of the CSS rules that govern the selected element.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/styles-tab.png&quot; height=&quot;400&quot; /&gt;&lt;p&gt;We can see that the selected element has an id of &quot;overlay&quot;, and a class of &quot;shell&quot;, and that there are CSS rules defined for those selectors. The overridden styles are struck through. You can also toggle element state in this tab.&lt;/p&gt;&lt;p&gt;If you have animations or transitions with a timing function defined, you can also use the cubic bezier editor to help you with your animations.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/bezier.png&quot; height=&quot;200&quot; /&gt;&lt;h3&gt;Box Model&lt;/h3&gt;&lt;p&gt;The Computed Box Model provides the final computed values of margin, padding, width, height, etc. This is particularly useful when creating responsive layouts, or when there&#39;s an awkward gap in your layout that you can&#39;t find the source of. You can access this view by clicking on the computed tab.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/computed.png&quot; height=&quot;400&quot; /&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Network&lt;/h2&gt;&lt;p&gt;Another very useful aspect of Dev Tools is the &lt;em&gt;Network&lt;/em&gt; tab. This allows you to view all requests made from this webpage. This includes requests for images, files, fonts, scripts, etc.&lt;/p&gt;&lt;p&gt;It also helps you determine if there is a major bottleneck to page load times. In this image, try to find at least one request of each of the following types:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;HTML Document&lt;/li&gt;
&lt;li&gt;Font&lt;/li&gt;
&lt;li&gt;Stylesheet&lt;/li&gt;
&lt;li&gt;Javascript File&lt;/li&gt;
&lt;li&gt;Image&lt;/li&gt;
&lt;/ol&gt;&lt;img src=&quot;https://naitian.org/assets/network-tab.png&quot; height=&quot;400&quot; /&gt;&lt;h3&gt;Example Case Study&lt;/h3&gt;&lt;p&gt;Cubemania is a Rubik&#39;s Cube timing website that allows users to save their times. I use it a lot. Let&#39;s analyze some of the requests it makes, specifically when a user logs in.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/cubemania-home.png&quot; height=&quot;200&quot; alt=&quot;Cubemania Home Screen&quot; /&gt;&lt;p&gt;Now let&#39;s open up Chrome Dev Tools and switch over to the Network Tab.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/cubemania-pre.png&quot; height=&quot;200&quot; /&gt;&lt;p&gt;Make sure that the red &quot;record&quot; button in the top left is active.&lt;/p&gt;&lt;p&gt;Now I&#39;ll click log in and see what requests are made.&lt;/p&gt;&lt;p&gt;We&#39;re hit by a barrage of requests. Let&#39;s look at the most interesting ones...&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/cubemania-barrage.png&quot; height=&quot;200&quot; /&gt;&lt;p&gt;There&#39;s a POST request at the very top. Usually these are for form submissions. Let&#39;s click it open and take a more detailed look.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/cubemania-post-1.png&quot; height=&quot;200&quot; /&gt;&lt;p&gt;This a lot of information! We can deduce some things about how Cubemania works on the server side! For example, we now know that this POST request is making a call to the &lt;code&gt;http://www.cubemania.org/session&lt;/code&gt; endpoint, and that our session is stored in a &lt;code&gt;_Cubemania_session&lt;/code&gt; cookie. We can also see all of our request headers, which we might be able to use to recreate this request manually. If we scroll further down, we see the really interesting bit: the form data.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/cubemania-post-form.png&quot; height=&quot;200&quot; /&gt;&lt;p&gt;Now, I blacked out my password, of course, but as you can see, we know exactly what fields are passed into the POST request! Now, you might notice that there is also an &lt;code&gt;authenticity_token&lt;/code&gt; field. This is generated on the server side to try to make sure that you cannot spoof these requests. A bit of light Googling reveals that this is common in Ruby on Rails web apps. However, if we access the contents of the HTML first, we will be able to find the token and pass it into the POST request.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Resources Tab&lt;/h2&gt;&lt;p&gt;The resources tab contains information on the majority of client-side storage options. This includes local storage and cookies.&lt;/p&gt;&lt;h3&gt;Local Storage&lt;/h3&gt;&lt;p&gt;If we click open the local storage section, we can find that Cubemania stores all of my times in the local storage.&lt;/p&gt;&lt;img src=&quot;https://naitian.org/assets/cubemania-storage.png&quot; height=&quot;400px&quot; /&gt;&lt;h3&gt;Cookies&lt;/h3&gt;&lt;p&gt;We can also view the cookies that Cubemania has stored. In here we do indeed see the &lt;code&gt;_Cubemania_session&lt;/code&gt; cookie we saw mentioned previously.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Exercises&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Go on the &lt;a href=&quot;http://www.cubemania.org/&quot;&gt;Cubemania&lt;/a&gt; website and answer these questions:&lt;/li&gt;
&lt;/ol&gt;&lt;ul&gt;
&lt;li&gt;Click on the &#39;Users&#39; tab. What type of CSS selector is used to apply the yellow background on hover effect?&lt;/li&gt;
&lt;li&gt;Search for &quot;naitian&quot; in the search box. Monitor the network traffic. What is/are the query string parameter(s) of the search query? What is/are the value(s) of the parameter? Is this request a GET request or POST request? Why does that make sense?&lt;/li&gt;
&lt;/ul&gt;&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Visit this wonderful lawn care website: &lt;a href=&quot;http://kamronsoldozy.github.io/&quot;&gt;http://kamronsoldozy.github.io&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;ul&gt;
&lt;li&gt;Look in the Console. What are some errors? Are any of these errors related to each other?&lt;/li&gt;
&lt;li&gt;Based on these errors, what part of the home page is broken? What is it supposed to do?&lt;/li&gt;
&lt;li&gt;How can we fix this?&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Bonus) Solve a Rubik&#39;s cube in under 30 seconds.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Further Reading&lt;/h2&gt;&lt;p&gt;Chrome Developer Tools has a lot more to offer than just what we covered here. If you&#39;d like to find out more, here are some materials to keep you occupied.&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/web/tools/chrome-devtools/?hl=en&quot;&gt;Google Official Dev Tools Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/channel/UCnUYZLuoy1rq1aVMwx4aTzw&quot;&gt;Chrome Developers YouTube Channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/web/shows/ttt/?hl=en&quot;&gt;Totally Tooling Tips&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;Exercise Answers&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;1a.) &lt;code&gt;#content a&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;
&lt;p&gt;1b.) Parameter: &lt;code&gt;q&lt;/code&gt;, Value: &lt;code&gt;naitian&lt;/code&gt;, &lt;code&gt;GET&lt;/code&gt; request, There is no need for a &lt;code&gt;POST&lt;/code&gt; request, since this value does not need to be kept confidential.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;
&lt;p&gt;2a.) There are three errors. The failure to load &lt;code&gt;jquery.min.js&lt;/code&gt; is directly tied to the &lt;code&gt;Uncaught ReferenceError: $ not defined&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;
&lt;p&gt;2b.) By viewing the details of the &lt;code&gt;ReferenceError&lt;/code&gt;, we see that we need jQuery in image_slide.js, which is supposed to provide an image slider.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;
&lt;p&gt;2c.) If we load in jQuery, the image slider &lt;em&gt;should&lt;/em&gt; no longer be broken, and will alternate between the 2 images.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/section&gt;</content
		>
	</entry>
</feed>
