Monday, May 03, 2021

F# under the covers XVIII -- lambdas and closures

Consider this code, using named and anonymous inner functions

  let F1 l =
    let aux i = i + 1

    let FI li =
      let rec FII lii acc =
        match lii with
        | [] -> acc
        | x :: xs -> FII xs (aux acc)
      FII li 0
    l |> List.map (fun i -> (string i).Length)

The inner functions are compiled as FSharpFunc objects, with values closed over being injected as constructor arguments.

Before .net 5.0.200, this would make function F1 look like

public static FSharpList<int> F1<a>(FSharpList<a> l)
{
	FSharpFunc<int, int> aux = new aux@9();
	FSharpTypeFunc FI = (FSharpTypeFunc)(object)new FI@11(aux);
	return ListModule.Map<a, int>((FSharpFunc<a, int>)new F1@17<a>(), l);
}

With .net 5.0.200, the fact that some of the inner functions -- like aux above -- are pure, closing over nothing, has been taken account of, and needless new object creation is avoided, in the same way that C# lambdas have long been cached after first use.

public static FSharpList<int> F1<a>(FSharpList<a> l)
{
	FSharpFunc<int, int> aux = aux@9.@_instance;
	FSharpTypeFunc FI = (FSharpTypeFunc)(object)new FI@11(aux);
	return ListModule.Map<a, int>((FSharpFunc<a, int>)F1@17<a>.@_instance, l);
}

where the aux and F1@17 functions -- the latter being the anonymous function used by List.map -- are referenced through a class internal static readonly value, rather than having to create a new instance every time.

String processing as a fold

Having occasion recently to ensure that text in XML/HTML containing non-ASCII (high-bit set) characters, but no control codes aside from line breaks, was presenting them as character references, the obvious algorithm in C#, using a StringBuilder, sb, was

  foreach( char ch in text )
  {
    if ( ch < 127 ) 
      { sb.Append(ch); }
    else
      { sb.AppendFormat( "&#x{0:X4}", (int) ch ); }
  }

In F# though, the obvious direct Seq.iter translation ends up needing |> ignore the results of the append operations. Since this is actually an accumulation operation into the StringBuilder, the better functional representation would be more like

  let sb = Seq.fold (fun (b:StringBuilder)
                         (c:char) -> let ic = int c
                                     if ic >= 127
                                     then b.AppendFormat( "&#x{0:X4};", ic )
                                     else b.Append(c))
              (StringBuilder(text.Length + extra)) // estimate the expansion up front
              text

which lets the StringBuilder flow naturally through the process, rather than closing over it and having to discard the value of the if expression. This could be done in C#, too along the lines of

  var sb = text.Aggregate(new StringBuilder(), (b, c) =>
                                     if (c >= 127) 
                                       {return b.AppendFormat("&#x{0:X4};", c);}
                                     else 
                                       {return b.Append(c);});

only here the returns have to be explicit.

Saturday, April 10, 2021

Anime roundup '21Q1 -- Shin Eva and others

So, yeah, there'll be spoilers for the new Evangelion movie, after the run-down of other watching.

The Q1 line-up was fairly thin, with Yuru Camp△ 2 the only title I'd marked as a definite watch, and only a handful more of "might look for to watch if well received". Yuru Camp△ 2 was not as good as the previous season -- being less about the equipping and camping, and more of a Google StreetView journey around tourist spots (including one instance of the Google watermarking not being adequately removed in the transformation from photo to anime background) -- but was pleasant enough all the same.

The surprise hit of the season, though, was Pui Pui Molcar, a series of whimsical stop-motion shorts about giant guinea-pigs that are also cute semi-autonomous vehicles

after which, most other new titles paled into insignificance.

On the rewatch front, I completed Tegami Bachi and the Koihime Musou sequels, plus Modern-Day Magic for Dummies, which all held up reasonably; and also Noir, which is indeed an decent enough actioner but which is pushed over the top by the sound track.

From the backlog, I did finish Fate/kaleid liner Prisma☆Illya 2wei Herz, which was definitely not as good as the previous season.

In the tried-and-dropped pile are the new Mamoru Oshii comedy Vlad Love, which, alas, wore out its welcome very quickly, the GTO OVA, and Cowboy Bebop (which as the OP indicated, felt like just another of those 1970s noir actioners, usually starring either Roger Moore or Tony Curtis, which I watched back in the day -- which maybe explains the popularity as being accessible for newcomers to Japanimation -- also with bouts of not funny humour). One episode each was quite enough, thank you.

Continuing are Digimon Adventure: and the original Digimon Adventure, and rewatches of THE UNLIMITED Hyobu Kyosuke, Yuru Camp△ and Saki.

OK, Shin Evangelion spoilers time now, so avert your eyes.

Having originally been set for its release last summer, and after two holds for Corona-chan, the long awaited final Evangelion movie released on the 8th of March. With curfews still in place, in lieu of a midnight showing, the first fifteen minutes -- the first action scene and the opening credits -- were streamed on YouTube, much as the short opening action scene had been televised for the previous movie.

This then caused a demonstration that computer security is hard. As part of its accessibility arrangements, a smartphone app had been provided with sub-titles for the hard of hearing and audio description for the partially sighted, to be cued by the movie sound-track playing. Armed with a capture of the YouTube stream, little work was then needed to obtain a complete set of subtitle images -- sufficiently little that they were being passed around before lights went down for the 07:30 JST premiere. The next day, in a display of belatedly bolting the stable door, the movie was pulled from the app, inconveniencing only the people in Japan who actually needed the assistive technology.

I really mean it about the spoilers now -- skip to after the picture to continue if you wish.

So yes, this movie does wrap everything up with a nice bow and a "That's All, Folks!".

Cutting to the chase, it ends with a title and sub-title drop, before Shinj wakes up in the real world, on the station platform in Anno's home town of Ube, where he is greeted by someone identified as "Large breasts, nice girl." with whom he proceeds to run out of the station and into the wide world beyond, thus sinking all the usual ships, especially the ones from the party line of "EoE was a hopeful end, with the two lovebirds on the beach together." Now, I know NGE prided itself on disregarding anime clichés, like "first girl wins" or "the boy who walks in on a girl changing suffers extreme physical violence at her hands", but taking a story that was about immanentizing the eschaton on the surface, and overcoming depression as a subtext, treating it as a harem show was always going to be misguided.

Right now, I'm feeling vindicated on a number of accounts, having proposed a Shinji/Mari end even before the second movie came out, that Mari would stand for Moyoco (to Hideaki's Shinji), having my own diagnosis of what Shinji needed validated by

Shikinami: What the brat needs is not a lover, it's a mother.

and that, of the named cast, that Kensuke would be a better fit for Asuka.

Elesewhere, the post-credits opening sequence sounds very mellow, and the provision at last of some of Asuka's Shikinami's Instrumentality-cum-back-story, a nice idea, albeit possibly a bit too much, too late.

Still, after all these years, this is the bit that makes it difficult for me to decided to actually watch any of these movies after the first. The first suffered enough from making everyone seem miserable all the time, in distinct contrast to the original episodes which it reworked, and being sufficiently off-putting that the introduction of a 5th Child and Gerry Anderson spaceships in the trailers for the next movie were net negative, even before the appearance of a new character that was wearing Asuka as a skin-suit. Maybe when it becomes feasible to deep-fake the whole thing with a different character -- maybe a green-haired girl with green outfits and Eva unit -- and different name instead.

Post spoilers bit starts here.

But enough about how I feel that the Rebuilds fall into an uncanny valley near the original, even if it is only the authors' all being older and somewhat wiser, trying to revisit characters from their youth, and on to a related subject. Following the release, NHK put out a documentary about Hideaki Anno, and the four years post-Shin Godzilla that were the making of 3.0+1.0, which proved interesting viewing -- especially the parts where Anno kept trying and failing to delegate to the team, before going on to do "if you want a job done properly..." I know that feel.

Well worth seeking out if you have any interest in the behind the scenes and the people involved. And it's not too spoilery -- so much got dropped and rewritten that it's not obvious what in the documentary ends up in the film, or what it means if it does.

Thursday, April 01, 2021

Q1 cycling

On the winter bike, from 17608.7 to 17833.4, and on the two hot days leading up to Easter, the summer bike from 3583.1 to 3610.9, plus 13.9 unmetered for a total of 266.4 miles. January was generally not nice, so I logged only one 8 mile ride that month; February was better and accounted for 107 miles, including two almost 20-milers; then despite the wet and windy mid-month, managed a lot of shorter rides, and a couple of 20 milers on the summer bike.

The flooding that marked the end of the year was slow to recede, but the roads at least were dry, even if brooks and ditches remained high -- and occasional waterlogged fields stayed that way

Thursday, March 04, 2021

F# and XAML and OpenSilver ctd.

Last time, we concluded that what we really want is a reimplementation of the Silverlight System.Windows.Application.LoadComponent, whereas what we have at the moment is generated C# code built from the XAML.

In practice, those generated InitializeComponent methods are a compile-time version of what the runtime component load would give us. This leads to a next step that takes us in the direction of what our ideal would be, and is in any case closer to the initial manual code-only approach.

Start with a new OpenSilver application, and add an F# netstandard2.0 library like last time. This time, however, make this assembly depend on the primary OpenSilver project, and the .Simulation and .Browser projects depend on the F# library. Add OpenSilver to the F# library project, as a nuget package, but this time there's no need to add any ExcludeAssets qualifier, nor to static link the F# core library.

The F# library now contains the Page (or UserControl) and Application classes that you would want to write, but their XAML goes into the C# project that it builds against. In the XAML project, remove everything in the initial classes after the // Enter construction logic here... comments. In the .Simulation project, point the debug parameters at the F# library, and in the .Browser project's RunApplication method, construct the F# Application type. This is important, otherwise nothing will show when you try to run the application!

We can now go one of two ways to invoke the InitializeComponent methods into the F# code.

First, we can treat the generated InitializeComponent code as almost the static utility LoadComponent method we would desire; in which case, in the F# library, the Application leeches from the corresponding generated code by

    member this.InitializeComponent() =
        let prototype = Inversion.App()
        this.Resources <- prototype.Resources

and the Page similarly

    member this.InitializeComponent() =
       let prototype = Inversion.MainPage()
       prototype.InitializeComponent()
       this.Content <- prototype.Content
       let hack = typeof.GetField("_nameScopeDictionary",
                                                System.Reflection.BindingFlags.Instance |||
                                                System.Reflection.BindingFlags.NonPublic)

       hack
       |> Option.ofObj
       |> Option.map ((fun f -> f.GetValue prototype) >> Option.ofObj)
       |> Option.flatten
       |> Option.map(fun o -> o :?> System.Collections.Generic.Dictionary<string, Object>)
       |> Option.iter (fun dict ->
             dict
             |> Seq.iter (fun kvp ->>this.RegisterName(kvp.Key, kvp.Value)))

takes the work from its pre-processed XAML, here using an over-engineered construction to get at the private name registration dictionary while avoiding any hint of NRE. These methods should then be called from the respective F# type constructors.

Alternatively, we remove the sealed qualifier from the generated Application, mark it and the MainPage class abstract, and let the F# types directly subclass the skeleton types in the C# library; this case needs no F# level InitializeComponent methods as the code we're interested in already gets called during the base class constructor call.

If this starts with the same application code as previous -- here my original Silverlight ephemeris clock -- we get the same visual appearance as with the previous approach, so no extra pictures in this post.

F# and XAML and OpenSilver

Emboldened by yesterday's success, what happens when we try to emulate the next steps?

First off, when pasting the F# code into the project, we see that System.Windows.Application.LoadComponent isn't present. Adding the XAML file has that subsumed by the OpenSilver environment, to appear as a <Page/> element in the project file that generates C# code that also fails at compile time. That latter can be switched off by modifying the package reference to look like

    <PackageReference Include="OpenSilver" Version="1.0.0-alpha-007">
      <ExcludeAssets>build; native; contentfiles; analyzers</ExcludeAssets>
    </PackageReference>

but we still don't have the runtime-generated model that System.Windows.Application.LoadComponent would give us.

Without that support, we can still use the hybrid approach of the early F# Silverlight days.

In this case, start with a new OpenSilver project and add an F# netstandard2.0 library as a dependencyand add the modified package reference to the new F# library, to allow access to the GUI types. The C# project gets the project-related XAML file, with the necessary modifications for porting to OpenSilver, and the F# code now, rather than subclassing a UI element, works by composition and delegation, much as for the F#/Silverlight3.0 template for VS2008.

The F# type, rather than subclassing a UI type now takes one as a construction argument, and the C# initializer, having constructed the main control and initialized the UI tree can simply pass that object to the F# type constructor, storing the instance as a member variable. Any event handlers can then delegate to the F# object as well.

  public partial class MainPage : Page
  {
    private Astroclock.AstroPage carry;

    public MainPage()
    {
      this.InitializeComponent();

      var temp = new Astroclock.AstroPage(this);
      temp.Begin();
      carry = temp;
    }
  ...

At this point, attempting a build fails in the C# layer with

2>MSBUILD : error : C#/XAML for HTML5: BeforeXamlPreprocessor (pass 1) failed: System.IO.FileNotFoundException: Could not load file or assembly 'FSharp.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

so we go back and add

    <OtherFlags>--standalone</OtherFlags>  

to the top-level Property Group on the F# project, and suddenly things start working.

For an example at this stage, I've ported the full applet to OpenSilver here. The other significant change to mention is that rather than just being a UserControl embedded into HTML, this is now a Page with the static HTML text included as TextBlock elements instead, but that is a generic OpenSilver behaviour I've just gone with the flow on, not something F# specific. Nor, I suspect, are the not quite circular circles...

Of course what we really want is a reimplementation of the Silverlight System.Windows.Application.LoadComponent. It's just a pity that that dives into native code in agcore.dll to do the interesting bits.

Also, alas, as currently implemented the browser version doesn't update even though the simulator does. Maybe if the updates were an event driven thing, like the button in the previous example?

Update: Events did the trick -- removing the sleepy BackgroundWorkers from the F# code, and instead adding a DispatcherTimer to fire the relevant UpdateXxx methods once a second unblocked the browser behaviour. The timer can be in either the C# or the F# layer. Again, I suspect that this is generic OpenSilver/Blazor behaviour, not anything F# specific.

Next -- A more LoadComponent-like approach with other benefits.

Wednesday, March 03, 2021

F# and OpenSilver -- first steps

This set of lab notes turned into a series of 3 posts.


Many years ago, I made a series of posts experimenting with F# (then still in preview) and Silverlight

  • documenting some of the hacks required to get it to work. Now, more than a decade later, WASM is the new in-browser hotness, with many approaches to getting your non-JS code to run in browser.

    One of these is OpenSilver, which is intended as a near as possible drop-in replacement for Silverlight. Like the original, it assumes C# and XAML with code-behind first, but let's see what we can do about that...

    Assuming you have OpenSilver set up, then the equivalent of the first post above is relatively simple. Make a new OpenSilver application solution, then replace the actual application project with a new netstandard2.0 F# library (in the solution and as a project reference in the two helper projects). Add OpenSilver as a nuget package to the F# project, then paste in the code from the same first working example to replace the initial stub code. In the .Browser project, fix the type of the App class -- new SilverLightFSharp.MyApp(); -- and then run whichever helper.

    It should look like this :--

    in the simulator after you click the button.

    Next -- Adding XAML, initial attempts

    Sunday, February 21, 2021

    Kappa "Kami-cat" Kamina 23-Oct-2007 - 21-Feb-2021

    Kami looking innocent

    A cat of remarkable practical intelligence, especially where food was concerned -- "food in a can with the rip-off cap on top of what's left? Easy -- hoik the lid out and start scooping!", and a master of the art of holding things still with one paw, or even just a single toe, while licking them clean.

    Kami foraging

    The runt of the litter, he was always at the bottom of the heap at least around the food bowls, so that may have contributed to his readiness to forage for might-be-edibles (which long-term may have been his downfall) and to hunt -- I remember having to excuse myself from a phone meeting to take him and his pigeon outside. When he no longer had his sister keeping him down, he came into himself, being the one to inhale his own late evening treat of wet food (initially a ruse to get the cats inside and downstairs at the end of the day) and steal Pip's.

    And then one evening he didn't come squealing as was his wont. A stay at the vets, a special diet, and he seemed to be on the mend -- once more squeaking for his evening treat, then in the morning happily climbing unassisted to his usual basking spot; but by Thursday evening he was off his food again. Friday morning, he was huddled miserable in a corner, so off again to the vets, where he declined, underlying cause not determined.

    Monday, January 04, 2021

    Anime round-up 2020 and a bit

    Never got around to doing an "end of the 2010s" summary a year ago, mainly because of the new titles that quarter I only watched the Youjo Senki movie (which is just more of Tanya being her loveable self in the desert and on the Eastern front -- if you liked the series,...) and one episode of Chihayafuru 3.

    And what with that, and other world events, I ended up watching very little that was new the whole of 2020, with a bunch of backlog clearing and rewatches.

    I stumbled across the raw of the Lensman movie on YouTube, so out of morbid curiosity -- having heard nothing good about this take on the classic space opera -- I sat down and watched it. On the plus side, it's clearly animated on a movie budget, and generally makes good use of what was for the time high-end CGI (except in one bizarre TronxPacMan-style sequence), and generally has high production values. On the other hand, it pastes a few names from the source onto a Star Wars meets Dirty Pair sci-fi comedy thriller, with random slapstick, and even more random disco scenes. Interesting to have seen, but that's about the limit of it.

    Also finished Chobits, having abandoned it years ago. This was another of these "complete" manga adaptations that finish while the manga itself is still wrapping up (see also Planetes, Bokurano, etc, ad naus), so could only approximate the canonical end, with the most obvious difference being that Chi's inconveniently located reset switch never actually factored into the anime's resolution. Because 1 cour shows weren't really a thing back around the turn of the century, it also had to spread itself out, so that, as well as overly extending the one chapter gag about Chi's pantsu to a whole episode, about a quarter of the episodes were completely anime-original SoL. In the adaptation, too, it brings home the generational change in technology in the years since, even more than the manga, which I reread a few months ago -- smartphones haven't quite become "it", but that's only for lack of the sexbot chassis.

    Overall, very dated in style as well as subject, and having seen it all, I'm happy to cross that off the backlog, even if I was right in dropping it after the first disk, back in the pre-broadband days when it would not have been dated. Verdict -- of historical interest only.

    Of similar historical interest was Tezuka's Firebird 2772, a very stange mix of distopia with interludes that wanted to be in Disney's Fantasia when they grew up. Rock Schlock, indeed. Plus the legendary 1985 OVA Twinkle Nora Rock Me. Yes, that one. The one where they saved money by not doing any in-betweening. Entirely harmless fluff, but Nora herself stands as an example of a character with potential wasted by the rest of the production.

    I also caught up with Saint October, a series which, apart from killing off every fansub group that attempted it, started off being something very whimsical, somewhere in the vicinity of Scooby-Doo, style-wise, with cartoonish villains ranged against the magical-girl Goth Loli detectives. I'd seen about the first third before subs seemed to have completely stalled, so I was pleased to see the first cour end with what seemed to be a darker turn. It was slightly disappointing that the next episode, the only vestige of that event was in the new OP animation, but from that point the stakes did slowly build all the way to a rather well handled dénouement, which was better than the potential angst-fest that the midpoint seemed to be setting up. In all a surprisingly good series that I am glad finally got subbed, despite the rather patchy nature of those subs. Verdict -- well worth watching.

    Also watched Fafner and Fafner : Heaven and Earth, both of which were OK, but nothing spectacular; in particular I didn't notice any significant difference after the writer change part-way through, which is something usually mentioned about the first series. In retrospect, having started with Exodus, and then gone back, may have been the right thing to do.

    I had a bit of a Gundam kick, including F91, which was fairly weak, even allowing for it having been edited down to fit a movie, with sudden jumps after which characters had changed sides. Even the Char was a let-down. OTOH, G-Reco was not as bad as I'd been led to believe by the threads for when it aired -- it's just that everyone has factions (except the Gondwanese, who we never see, only hear of), several of the high-ranking military are clearly unfit for command on account of being sub-rational, and the ending just happens, after catching up on the Tomino kill-quota. And what was that random bit of "let's visit Japan" with a Tomino cameo after? I've not seen them in Japan in a UC Gundam before.

    Also from the backlog, Fist of the Blue Sky - Regenesis, being a sequel to the autumn '06 Fist of the Blue Sky, which I never finished for lack of subs at the time. For a show about larger than life manly martial artists having two-fisted adventures, the somewhat janky CG animation is tolerable. In the end it was was a decent enough hokey martial arts fest, with new ultimate techniques being handed out almost every episode. On the down side, you do have to simply ignore the sudden retcon of the maguffin after the mid-point timeskip, not worry too much about the chronology, and sigh deeply when the scene cuts from some tense action to the comic relief villains left over from the previous series. And why is it that the mid-season change of OP/ED is always for the worse?

    Samurai Flamenco was a fun love letter to toku, along the same lines as Gurrent Lagann was for super-robot, as well as being one of those rare series where the main cast are all adults well past their school days.

    Picked up on a whim from having seen favourable mention years past, Blast of Tempest served the job of occupying a few dark evenings, but as a shonen series, having the two high-school leads out mind-gaming the adults was just going to be part of the territory, even if it had the grace to stay out of school. The mid series plot-twist was handled elegantly enough, though, as was the guy who by rights ought to have been the big bad. That the main girl falls for the "literally me" character was only to be expected.

    In the guilty pleasures pile, I watched all three seasons of Overlord, a harmless diversion which proved to be quite amusing, with all the "Oh, shit!!" moments, just before the over-confident NPCs get kerb-stomped by our dorkish MC or his entourage.

    On hold are Heroic Age, a sort-of mechs-in-space (or, rather, Attack on Titan in Space) from the Fafner crew, which had the misfortune of airing at the time as Gurren Lagann, and Bamboo Blade, also from '07. Also on hold, as only the first couple of episodes seem to have been subbed is Six Heart Princess, another rather different magical girl series, Different, as in it opens like this

    with the use of ships as projectile weapons like that last seen in End of Evangelion.

    Dropped after 4 episodes, Galilei Donna reminded me very much of RerideD, even though none of the lead staff on the one worked on the other, which was enough for me to declare it another Noitamina dud.

    Amongst rewatches, Fafner Exodus, which I think benefited from now being able to tell more of the Hiraiface characters apart (good robot series, you should watch it); Long Riders (twice), during the winter and the early lockdown (a generally charming cute girls do outdoor activity show), Kemono Friends (tanoshii!!), GaruPan and Minami Kamakura Girls' High School Cycling Club plus OVA, for the vicarious miles on the road, mixed in with fluffy stuff like Vividred Operation, Konohana Kitan, Flying Witch and Toji no Miko. Also Rewatched YuYuYu both seasons, with the Hero Club part of S2 being much better when a) one knows that the developments being trailed in the Kusunoki Mebuki wa Yuusha de aru LN were scrapped and b) when watched with better subs than the "electronic brain pancake crystal elderly"-tier Amazon effort.

    Q1 did bring the short-short Heya Camp△ which was entirely harmless; and Kirara Asteroid a "cute girls doing things" in the same sort of vein option, but that didn't impress -- the curse of 4koma source material strikes again, I guess. Somali looked pretty, but the endearing small girl antics were too much to take.

    On the positive side, Railgun T was a known quantity, and there was also the rather off-beat Eizouken. Not only is this another Yuasa anime, it's an adaptation of a manga which I first became aware of due to some moaning about some of the typesetting in the scanlation --

    but in the end, it did itself a disservice by not just fading to black when they put the DVD of their Comiket anime into the drive, rather than ending with what was the most underwhelming of the three pieces they animated. The best bits were the girls interacting, with Kanamori being the voice of reason amongst all the flights of fancy -- the process rather than the outcome.

    Railgun T ended up spread over the first three quarters of the year due to production difficulties (Spring season in general was badly hit by Corona-chan), and was the mixture as usual, right up to the parts where you just have to say "Honestly now!" -- "Bust Upper", indeed!

    In the end, Chihayafuru 3 was an interesting change of pace after the first two series -- much of the time Chihaya wasn't playing cards, being either away on a school trip, worrying about what career to follow after high-school, or in the audience watching 2nd and 3rd tier cast members playing each other in the Master and Queen tournaments. And there was even about an episode's worth of progression of the romance triangle scattered into the mix, before another cliffhanger ending.

    The Toji no Miko OVA was little more than a reminder advertisement for the mobage, to showcase some of the in-game characters. Entirely harmless, but a bit of a let down compared with the series. Even the sword fights seemed mainly to be going through the motions.

    And finally, this year I did finish the one Q4 show I started -- Iwa Kakeru was an adequate "cute girls do cute climbing things" offering, but no more. The quirky rivals from the other schools were mostly Chekov guns that never fired, with only Asuka Kurusu Anne being given much development, and again the curse of the 12 episode season hit -- the Nationals could have benefited from spreading over two episodes and leaving a little space to catch breath after the results were announced.

    Continuing are Digimon Adventure: 2020, and rewatches of Tegami Bachi and the Koihime Musou sequels

    Friday, January 01, 2021

    December Cycling

    On the winter bike only, from 17522.7 to 17608.7 for a total of 86 miles, going out for fresh air on the few bright days in the month. For the year that was 1008.4 miles on the winter bike, 1366.3 on the summer bike (2216.8 to 3583.1) and 17.64 to 48.18 = 30.5 on the folder, giving a total of 2405.2 for the year, way up on what I thought I might do.

    The weather was rather wet all month, especially in the days before Christmas -- water meadows all flooded, and in places roads, like the above turn-around-and-go-back interruption to my Christmas Eve ride, where the Bourn brook had burst its banks near Toft.