Monday, October 7, 2019

Reflecting on my activities at CCSC:MW 2019

This past weekend, I attended the annual conference of the Consortium for Computing Sciences in Colleges, Midwest. I have been involved with this organization for many years, and I wanted to take a moment to share an overview of how I was involved at this conference.

Student Showcase

I am in charge of the Student Showcase. Many years ago, it was a Student Poster Competition, but it felt to me that this format gave inordinate status to the scholarship of discovery. When I took it over, I revised the format to have two tracks inspired by Boyer's Scholarship model: traditional "research" goes into the Discovery track, and interesting applications of computing goes into the Applications track. This year, we had six Applications track presentations and three Discovery track.

There are practically always Ball State students in the Showcase, and so rather than judge the event myself, I organize volunteer judges. The students are told ahead of time that they will be judged on the same six categories recommended by Glassick et al.; specifically, they are told they will be evaluated on the following:
  • Clear Goals (“What is the goal of this work? What problem are you solving?”)
  • Adequate Preparation (“How did you get ready to do this work?”)
  • Appropriate Methods (“How did you solve your problem? Why did you approach the problem in this way?”)
  • Significant Results (“What was the result of this work? Who is affected by this work?”)
  • Effective Presentation (“How well does this poster or demonstration communicate what is important about this work?”)
  • Reflective Critique (“What would you do differently? What does this mean for you and your career?”)
Over the years, I have fiddled with the judging form with varying degrees of success. This year, I asked each judge to rate presenters on a 1-5 scale for each presentation and each category, and there were no hitches. The scale I provided was Poor (1), Below Average (2), Satisfactory (3), Good (4), and Excellent (5). I have also put the actual judging form online, in case anyone would like to see it.

To determine the winners, I simply take the medians across the six categories and sum them. This led to a clear winner in Discovery and Application tracks as well as a clear Honorable Mention (the third highest overall score), so those are the prizes we awarded. I am proud that my own Canning Heroes team presented and won the Applications track award this year.

Tutorial: Unreal Engine 4 for Computer Scientists

Since getting into Unreal Engine 4 a few years ago, I have noticed many interesting manifestations of Computer Science concepts. I decided to run a tutorial session this year at CCSC:MW to show these to the attendees. However, it did not go as well as I had hoped. I did not have machines that could run UE4, nor could I expect attendees to have adequate laptops, so I designed the tutorial as a sort of Show and Tell. Then I was scheduled for 8:30AM on Saturday, which meant that attendees would be tired and very few students would be there. The room we were given was really awkward: it was a lab, which meant everybody was behind monitors where I could not make eye contact. To make it worse, there was no station where I could stand and work at my laptop, so I was seated and, because of HDMI cabling, facing away from the attendees. To top it all off, I was traveling with family, and my son got sick that morning at the hotel, so I was distracted and unfocused.

Suffice it to say, I would not be surprised if the session were poorly reviewed. Heck, I would poorly review it. I would like to do something like this again, but in a more controlled environment. Perhaps I will move forward with writing up an actual paper about some of the interesting manifestations, and then be able to give a shorter show-and-tell in a future year.

On a positive note, preparing for the tutorial gave me several new ideas for video tutorials. In fact, I could take my tutorial outline, chop it up, and have a pretty good series. Now, it's a matter of determining which ideas have sufficient weight to merit the time required to do the video. (For those who don't know, I have a YouTube playlist of game programming tutorial videos. In fact, I have written up this blog post while rendering my latest video in Blender.)

WIP: Mapping Game Design Learning Outcomes to CS2013

I presented in the Works-in-Progress session what I have shared here on my blog about mapping game design learning outcomes to the ACM/IEEE CS Body of Knowledge. I think it was well received. I have made the slides available online for anyone who wishes to see them, but as usual, my slides do not make a lot of sense without the stories to go with them.

I think the audience assembled for the WIP session was happy to hear my story, and they seemed to understand my frustration. I think they appreciated seeing how one becomes more critical of CS2013 as one digs deeper into the recommendations. One mentioned that his institution had given up on CS2013 and simply used instructor consensus. Ball State is really the largest school in the region that regularly participates in CCSC:MW though, and most of the attendees were in very small departments at private liberal arts schools. 

Wednesday, September 25, 2019

Learning objectives for introductory game design: Continuing comparison against CS2013

I am giving a presentation in the Works-In-Progress session of the upcoming CCSC:Midwest conference. This short talk is connected to my post from April about mapping learning outcomes of game design to learning outcomes of Computer Science. Conversation on Facebook led me to understand that I had not fully explained my goals in that post, in large part because I had skipped the first part of the mapping: the learning objectives of introductory game design.

As far as I know, there is no standards body or recognized formal recommendations for game design curricula as there are with Computer Science, where we have the ACM/IEEE CS2013 curriculum recommendations. However, if you look at all the various introductory texts on game design, you will find significant overlap, although these are by their nature written along the lines of content rather than objectives. Each time I have taught game design as an Honors Colloquium or a Computer Science seminar, I have had to articulate the learning outcomes of the course; what I did this morning is reflect on this process in an attempt to pull out my current thoughts about what a student should learn from an introductory course. Here is my proposal:

After taking my introductory course in game design, a successful student will be able to:
  • Apply common analytical tools to existing games, examples being MDA (Hunicke), Formal vs Dramatic elements (Fullerton), and Interactive Forms (Burgun).
  • Identify positive and negative feedback loops in a game.
  • Critically analyze existing games in order to understand their component parts and describe their interactions, including such components as rules, theme, and narrative
  • Describe, apply, and justify iterative prototyping models to produce an original game.
  • Describe and apply formal techniques of playtesting.
  • Compose and present status reports.
I think this is a good number and granularity of items for how I like to introduce game design. Furthermore, having taught such courses for years, I think it's a good representation of the skills that students develop.

As I reflected on this list, though, I realized that there's another layer to the learning objectives. There are objectives that are implicit—objectives that are hiding in the cracks and in the details. Here's what I came up with as the shadow objectives:

A successful student will be able to

  • Read, understand, and critique book chapters, essays, and articles on game design.
  • Articulate specific, measurable design goals from ambiguous constraints and inspiration.
  • Incorporate feedback to improve a prototype and reflect on that process.
  • Incorporate feedback to improve analytical, compositional, and creative skills and reflect on that process.
The first one here is not to be overlooked. When I look at the design and goals of introductory computer science, learning how to read does not come up at all. I believe it also to be completely absent from CS2013. However, this is a crucial skill for someone who wants to be a lifetime learner.

The second is, perhaps, the most important skill that someone can learn in this class, and its transferable to any other creative domain. By "creative domain" here, I mean any that require creativity in the technical sense—the development of new ideas—so we can include all the sciences, engineering, and education along with the arts and humanities. More specifically, it is exactly this skill I want to see strengthened for nascent software developers and computer scientists: every day we have to manage ambiguity, transforming it into measurable goals and progress. Again, however, CS2013 has very little to say about this except for a couple of hours of requirements engineering. It may simply be a case that CS2013 is too deep into the weeds, but that's kind of my point: stepping back from the weeds, managing ambiguity and turning into concrete communications is something that a computer scientist does daily, but it's also something that is often ignored in curriculum and assessement, in my experience.

The third item is a clarification of the objective to apply playtesting techniques, but as above, there is something more potent here than just playtesting: it's about closing feedback loops to improve a product. Reflecting on this led me to compose the fourth bullet point, that it's not just about the feedback loops of the game but the feedback loops of the person. Maybe you might just call this "learning", yet I think there's not enough of this going on across our campus. For example, for a course to be considered a writing intensive course here has required that a student complete at least one draft-feedback-revise cycle. In my department, there are a few places where we practice this explicitly, and all of these are places that I have touched, which would not have this otherwise.

My next step in preparing for the presentation is to take this list, look back at my earlier post, and turn again to CS2013 to make sure that my points are clear. Right now, I have a feeling like the things I want to be emphasized by CS2013 are simply not in it at all, or at least not explicitly. It will be interesting to see the reactions of the generally-conventional conference attendees.

Wednesday, September 18, 2019

Revisiting the state analysis of Every Extend

Back in 2007, my first Computer Science education research paper was published in the proceedings of SIGCSE. The paper provides an overview of how game programming can be used as a motivating context for learning design patterns. One of the examples in the paper, which I have used for years, is the behavior of the player-controlled bombs in the inimitable Every Extend, which can be used to explain the State Design Pattern. In the paper, I argue that the player's pawn can be described by a state machine like the following.
In yesterday's meeting with my CS315 Game Programming students, I was inspired to create a UE4 tutorial video about using state machines for state management. In particular, I wanted to show how an enumeration can be used to define the possible states, and then behavior can be switched depending on the current state. This is not, of course, the State Design Pattern, but it's a heck of a lot better than an ad hoc collection of Boolean variables. It also follows from Michael Allar's Gamemakin' UE4 Style Guide that is mandatory for my students, which says:
Do not use booleans to represent complex and/or dependent states. This makes state adding and removing complex and no longer easily readable. Use an enumeration instead.
To prepare for the video, I have spent a few hours the last two days building a simple playable framework similar to Every Extend. Over a decade ago, I did a similar exercise in Java to produce EEClone. This time, I did it in UE4. (A bit of an aside: Every Extend is like my kata for new game programming frameworks. I use the essential gameplay of it as a case study to understand how game engine functions. Of course, then, when I first started learning UE4, I tried making an Every Extend clone, but it went quite poorly. After a few years of working with UE4, it's become a lot easier to get the game up and running!)

With my gameplay framework in place, I started working on the diagram shown above to use in my series of game programming tutorial videos. However, as I looked at the diagram, I realized I had a rather fundamental problem: these are not the states of the player bomb. It's true that these are, abstractly, states of the game, but they are not the states of a single stateful object. Instead, what I had programmed was leading into the following state model:
That is, a player bomb is created, which has it play a spawning animation. When that is completed, then the player becomes vulnerable to collisions but can also press Space to explode. However, unlike in the initial analysis, there are no other states after this. If the player presses Space or is hit by an obstacle, the player's bomb is destroyed: that actor—that object—no longer exists. It is the game mode that either counts down to respawn or waits until a chain of explosions is complete and then counts down to respawn. These states are not part of the player pawn.

This observation shoots a hole in my plan to make a video using the Every Extend example. I still want to make a video about state analysis, but I need to find a better example—one where a single actor's state is interesting enough to be modeled but simple enough to fit into a tutorial video. Please feel free to share your suggestions in the comments.

Monday, September 16, 2019

Muncie DevFest 2019

I was invited to speak at DevFest Muncie 2019, an event hosted by my friend and colleague Chris Turvey, who runs the Muncie Google Developer Group. I've known about DevFest for a few years, but this was the first time I had the chance to attend. My oldest son and I went together, and it was fun to share the day with him. The morning speakers included talks about playing music over a 300-baud modem on a C128, how to design custom circuit boards, smart cities, developing experimental audio systems using Javascript and Firebase, along with my own humble contribution, a brief discussion of Kaiju Kaboom.

One of the reasons I'm writing this post is simply to share a link to my slides. Like most of my presentations, the slides will not make a whole lot of sense without the stories to support them, but I want to make them available nonetheless. The slide showing my sales got a hearty applause when I explained that there is no animation or anything—that's just the chart.

In the afternoon, my son and I joined a workshop introducing Particle products and services. It was the first time I have gotten my hands dirty with IoT technology or, really, with anything in that hardware hacker space. The integration of their technology is really amazing to me, since I understand at least the theory of how each part works. And yet, despite this, it took us over an hour to get an LED to blink on a board. As for me, I think I'll stay in softwareland, but it does seem that my son's interest was piqued. Thanks to the sponsorship of Particle, we were able to take the boards home with us, so as soon as I get them rigged up to my home Wi-Fi network, he should be able to tinker some more.

Thanks to Chris and the rest of his co-organizers, as well as the MadJax staff and the other sponsors. It was a nice day to share with developers of all experience levels from the region.

Sunday, September 8, 2019

Painting Lord of the Rings Journeys in Middle Earth

My brother got me excited enough about Lord of the Rings: Journeys in Middle Earth (JiME) that I pre-ordered it not long before it was scheduled to be released. The idea at the time was that it would make a great summer painting project, and that my sons and I could get into the campaign in those quiet summer evenings. Turns out, I did not get as much painting done this summer as I hoped to. Instead, almost all my creative energy went into Kaiju Kaboom. It wasn't until today that I finally finished painting the JiME miniatures.
Box Art
Several of the techniques and color palettes that I used were taken from Sorastro's series. For most of the mob characters, I took a new approach to try to speed them up. I zenithally primed them via airbrush and then used thin paints in single coats followed by a wash to darken the recesses. This allowed me to let the zenithal highlights show through the paint. One thing I learned using this approach is that one has to be much more careful with the individual layers than I normally am with the first coat. When taking more time with each layer, it actually matters less if the first one or two run into each other, since it will be touched up. However, with this approach, a little slip of the brush can lead to a contamination of one area with the wrong color. There were some parts of the following figures where I added manual highlights and shades, but they were primarily done with single thin coats and washes.

Ruffians
Goblin Scouts

Orc Marauders
Orc Archers
Getting through all these was pretty quick. The results are certainly adequate though a bit unsaturated or washed-out looking. You can probably tell by a quick glance here that I had some fun mixing different flesh tones for both the humans and the goblins & orcs.

I painted the wargs in a similar way, just spending a bit more time on some of the highlights. I also added glowing red eyes. Now that I look at the eyes, I'm a bit ambivalent about it as a visual effect. It seems to be a common design in illustrations of the wargs. I spent a few minutes trying to determine if it was canonical or not, but it's still inconclusive.
Wargs
The wights were mostly one color, and I gave them a little more attention than the orcs and goblins, though still working rather rapidly. These were the only ones in the set where I added some weathering, namely, mud on the cloaks. I did this with drybrushing, although in retrospect, I wonder if I should have just painted it on more boldly. I still struggle with weathering. I love watching painters make figures look like they are part of their environment, but I personally feel lost somewhere between not being good at it and not wanting to risk ruining an otherwise good paint job.
Wights
You cannot actually see the weathering so well from the front, so here's a rear view.
Wight, Back
You cannot see it so much there either—hence my comment about drybrushing perhaps being the wrong path here. That said, I am pretty happy with the weathering on the sword and armor: they look old and corroded.

The last of the villains is the Big Bad of this set: the Hill Troll. I like the way it turned out. I used wet blending to get nice transitions between its two skin tones, and some purple glazes add nice color variation around the face and neck.
Hill Troll, Front

Hill Troll, Back
With the villains out of the way, I moved on to the heroes. I'll show them in the order I painted them, starting with the elves.
Legolas, Front
Legolas, Back
Elena, Front
Elena, Back
Legolas and Elena both use essentially the same palette since I figured they probably have the same tailor. For basically all the heroes, my standard approach was to use basecoat, wash, and highlight for everything but the cloaks. The cloaks were basecoated, then the shadows and highlights painted in using two-brush blending.

Given Tolkein's elven names like Legolas, Glorfindel, Elladan, and Luthien, I wonder who at FFG decided that a great name for an extended universe elf would be "Elena?" So mysterious! So otherworldly!

Berevor, Front 
Berevor, Back
I started Berevor and Aragorn at the same time, giving them the same base skin tone. I intended to do a similar palette-sharing as with Legolas and Elena. However, as I started working with Berevor, I found I was content to just buckle down and work on this one figure. I think she turned out quite nicely. Although she is not an original Tolkein character, I have a special fondness for her as she is the ranger in Middle Earth Quest, which I finished painting earlier this year. It's interesting to compare the figures to see how Fantasy Flight Games' philosophy regarding miniatures has changed to match popular demand. The MEQ figure is fine for what it is, but the JiME one is much more interesting. It also benefits from being a larger scale, about a head taller.

Aragorn, Front
Aragorn, Back
I tried to make Aragorn look a little more mature, his hair starting to grey. I think I have conceived of Aragorn as progressively older as I have gotten older. It's been over a decade (maybe two) since I've read Lord of the Rings. So many things to read and so little time. Anyway, I was partially inspired by watching Ghool's Quick Tip video on painting graying hair. I didn't follow his approach, but the video did get me thinking about trying to get that aesthetic.

I will mention here that all the heroes above have very similar earthy tones, being almost entirely greens and browns. I kept each one internally consistent so that the same colors are used, and I think this helps them look coherent without being too bland. I dressed up Aragorn a bit by painting the trim on his leather accessories in multiple colors, which may draw too much attention when rangering around Bree-land. I figure that for his sculpture, he wore his dress leathers.

Bilbo, Front
Bilbo, Back
Bilbo's red vest and gold buttons gave a much-needed reprieve from the greens and browns of his companions. I should mention that I still haven't played the game, and I find myself quite curious how their story will get Bilbo Baggins—only three feet tall!—to do any adventuring after his experiences in The Hobbit.

Gimli, Front

Gimli, Back
Dwarves. I swear, there must be some kind of curse upon them, or maybe sculptors just really don't like sculpting them. The card art for Gimli has him wearing a very reasonable chainmail jerkin with leather bracers and belt. The miniature, on the other hand, has... well, I guess it's a leather shirt over chainmail jammies, and a plate mail belt, with massive steel pauldrons and bracers. On his right arm, you can even see that the sculptor had to run the bracer and pauldron together, which just goes to show how unreasonable this would be in combat. I understand that sculpting to scale must be really hard, but look at the size of his hands! It's all very strange. Yet, I have a suspicion one my sons will be very excited to play an axe-swinging goblin-smiter, so I'll have to get used to seeing him on the table.

For the many metallic parts of this figure, I busted out my P3 Armor Wash, which really is like magic for this kind of figure. The highlights on the hair are just zenithal highlights showing through thinned paint. I thought about darkening his hair, but basically all the other heroes have such dark hair that I wanted someone besides Bilbo to have different colored locks.

I based all the figures in this set using the same technique. I prepared some rocks by cutting pieces off of a cork trivet that I saved from the trash many years ago; these pieces I painted a neutral grey and set on a corner of my painting desk. I started basing with an application of Vallejo Brown Earth basing paste, embedding some rocks into it. had ordered the basing paste after watching Sorastro's Star Wars Legion painting series. When I first applied it to one of the ruffians, I was shocked and disappointed in how red it appeared. I decided to work with it to see what I could do. After drybrushing the rocks, I mixed a wash using black and sepia inks, and this served to tone it down a bit. Then I applied flock using my usual approach: dab some glue, sprinkle some flock, wait for it to dry, repeat with a different material. After finishing my test model, I wondered what would happen if I just mixed all my flocking material together, so I did.
Mixed Flock
That container holds a mix of black tea, burnt grass fine turf, and medium green fine turf. I sprinkled this on to the other figures over dabs of thinned white glue—except for the wights, which used a less green mixture—and it saved me a bit of time and mess. After varnishing, I then added the green static grass. The results were pretty quick and look fine for a wilderness setting. At least, I think they will; I will find out for sure when we finally get the game to the table.

Here's a picture to help compare the size difference of the Hill Troll and the other characters. The Big Bad here is not as big as some of them I have painted, yet I think he's plenty big to be intimidating.

Aragorn and the Hill Troll

Finally, here are some group shots.

Fellowship of the Fanfic Prequel
A Medley of Villainy
Thanks for reading!

Thursday, September 5, 2019

How I might teach using the Working Software Cycle

I've been out of teaching CS222 for several semesters now, but it still occupies my mind from time to time. This afternoon, I read the latest blog post by Ron Jeffries, which concludes with this:

There is a particular trick to the working software cycle, as I prefer to do it. It goes like this:
  1. Start with working software. Ideally an “End Card”, ideally bug-free, but something that runs. Your existing legacy product will do if that’s all you’ve got.
  2. Select a very simple next feature to do. No, that’s too big, even simpler. There you go.
  3. Write an automated example that will fail until that feature works, and then succeed. If it requires more than one example, go back to #2.
  4. Start programming: Run the example; add some code; run the example; every time the example runs, refine and improve the code a bit. When you’re satisfied with the example and code quality, that bit of feature is ready to ship.
  5. You’re back to working software, with a new feature. Go to 2.

It made me think about the nine-week project in CS222 and its three three-week iterations. Students always struggle with getting a productive rhythm of software development. Next time I teach the course, I need to think about Jeffries' idea instead. That is, rather than ask them to write up plans for what to have done in three weeks, have them come up with something to have done, say, by tomorrow. Make the loop even tighter so they can both expose their misunderstanding about planning and feel what its like to be productive. (Of course, they should also start in a bug-free condition, which is also a challenge for them!)

Also, putting this together makes me think I should write more often. We're wrapping up the third week of the semester, and I feel like I've been thrashing. That usually means its time to schedule reflection and writing time and hold myself accountable to the schedule.

Friday, July 26, 2019

Summer 2019 Course Revisions

My main focus this summer was my first commercial game project, but I have always kept in the back of my head that I had some serious work to do to get ready for Fall semester. In fact, I was feeling a bit stressed about it a few weeks ago and took some time off of Kaiju Kaboom to sketch out plans for my game programming and game design classes. My third class for Fall is scheduled to be CS445/545 Human-Computer Interaction, but it is right on the edge of being underenrolled; if it doesn't make minimum enrollment, the dean's office will cut it and I'll be deployed somewhere else with very little notice. However, because my time to work on course prep is drawing to a close, I devoted the day to sorting out as much of that course as I can.

In today's blog post, I'll give some highlights for my three courses. This will be shorter than in some previous years, so I'm condensing it all into one.

CS315: Game Programming

I'm excited to be teaching game programming again, since this year we actually did get new machines in the lab—machines that are capable of running UE4. Last Fall's course went well, and so I am keeping most of the plan as-is, but trying to keep a pedagogic eye on how I can use in-class examples and workshops to drive some of the lessons home. I expect that we will do three to four mini-projects followed by a larger team project. This year, I have dropped the achievements, since I think the course is already quite full of places where students can make meaningful decisions about what to pursue. I am keeping both the specifications grading and the project reports, both of which served their purposes last year. I have been tempted to set up some kind of team role system or other accountability system for the final project, to prevent the case where one student carries the rest, but I am still unsure how to do this; perhaps I should turn that question around to the students and have them contribute to setting the rules.

Here is the draft course plan. Only the first of the mini-projects is posted, but I expect to re-use my progression from last Fall, where we went essentially from 1D to 2D to 3D across three projects.

CS439: Introduction to Game Design

I do not have an immersive learning project lined up for this academic year. Instead, I am using the year to try to intentionally explore how I can integrate some of the work I've done through immersive learning into formalized Computer Science department offerings. One step in this direction is offering a version of my game design course—which I have taught for several years as an honors colloquium—as a Computer Science elective that anyone can take. The easiest way to do this was with our "seminar" course, although this is not ideal for marketing the course, since it still shows up in the catalog as a 400-level CS elective. Still, I look forward to teaching this and seeing how the audience compares to the honors colloquium.

One way that I have made this "computer science-y" is to require our intro programming course as a prerequisite. This is not because I expect to do much programming, but rather because I want to be able to draw upon metaphors of computational thinking when looking at games system design. This seemed like a good idea at the time, but I have questioned this the more I've worked on it. Indeed, in my random sketching of how I would consider proposing this as a formal service course in my department, I've strongly considered dropping any prerequisite.

As for the course structure, here is the draft course plan. It is based strongly on what I have done in previous years. Even though the examples in the free online text we use are showing their age, I like both the presentation and the price. Once students build a core vocabulary, they can make use of the exhaustive supplemental information that is discoverable online. Without a community partner via immersive learning, the students will be working on projects of their own design without external constraints, which I haven't done in a class like this since roughly 2008. I'm eager to see what they pursue. As before, we'll spend the first half of the semester studying fundamentals and then the second half of the semester building projects. Some of the students who have enrolled are ones with whom I really enjoy working, and so I'm looking forward to spending time with them again too.

CS445/545: Human-Computer Interaction

The last academic year, I taught this course both semesters in a collaboration with the David Owsley Museum of Art. I had a fruitful meeting with their education director several weeks ago as we debriefed the experience. I am glad to say that we are continuing our collaboration, but we are narrowing the focus toward one specific problem: helping visitors navigate the physical museum. This means that my students won't have to do so much problem discovery, but I think that's OK. They really struggled with the idea of finding a legitimate problem vs. inventing a problem and then justifying their work. I think this new focus will help them get into the solution design part of the course, which is really more important for our single, elective course on HCI.

Knowing that this will be a relatively low-enrollment class allows me to treat it as a studio class. We will start with some common readings and structured exercises, but then I would like to move quickly into tackling this navigability problem, using my familiar tactics of just-in-time teaching and reflective practice to have a meaningful learning experience. The draft course plan only lays out activities for the first three weeks or so of class, after which I can work with the students to assess our situation and move forward as needed. It does mean there is kind of a hole around the grading policy of the course, and I hope that this does not cause the students any undue stress. My plan is to work with them to develop a methodology that embeds assessments into it, which I think they will enjoy and learn from.

A word about the sites

Careful readers may have noticed that my course web sites have undergone a visual overhaul. This is related to my learning lit-element, as I wrote about earlier this summer. Whereas my sites were previously based on the polymer starter kit, now I am using the PWA starter kit prerelease. I had to do a bit of finagling to get it to work on our departmental Apache server, but once that was done, I could easily replicate it across the three sites.