Apple Vision Pro Demo Impressions

I tried out the Apple Vision Pro (AVP) hardware in an Apple store today. The ball was in Apple’s court. I really wanted to be impressed by the hardware and put me over the edge to pick one up and develop apps for it. I’ve released Day 1 apps for the Apple Watch & ARKit (iOS 11), and I believe in the future of AR for productivity.

Not Sharp

Unfortunately, when I wore the AVP, the content (text, images, etc.) was not razor sharp. I could use the device and navigate the OS without an issue, but I was expecting next-gen sharpness on the AVP displays.

My guess is I could try different distances (closer or further) from the screen to find the distance where all the content is sharp and crisp. Probably try different light seals. I couldn’t achieve the level of sharpness that I expect from any 2020 device (phone, HD monitor, etc).

Also, there was an opening at the bottom of my headset (towards my nose). I thought the light seals were supposed to block 360 degrees of light around the headset and not leave a small gap. That gap was normal per the Apple rep.

Demo

Apple did a great job with the demo. The demo was seated (smart) and focused on VR content, not passthrough use cases.

The OS (visionOS) was simple to use. Pinching to drag around or press buttons worked fine with hand gestures. When I tried to resize windows (bottom corners) or use two hands to pull apart, I ran into problems with certain apps where it wouldn’t work.

Content (2D vs 3D)

My imagined ideal use case would be having several large macOS screens in front of me to get work done. However, Apple marketing seems to be focused on entertainment (big TV in front of you) as their selling point.

The problem (in my opinion) is that the content was not great. Spatial content, shot on what I presumed are iPhone 15 Pro Maxes or AVPs, seemed low resolution to me. Enlarging an iPhone photo to fill up your entire room’s wall doesn’t work that well. It lacked detail. Even viewing a Panorama (shot on iPhone? not sure), the resolution was not great when viewed at such a large size.

Part of the demos included immersive environments. The environments were impressive since they were built natively for the device and 3D rendered. Viewing a photo from the moon environment was great since the nearby 3D rocks on the ground really sell the illusion.

I personally felt the other content fell apart. Spatial videos (shot with iPhone 15 PM?) were fun but it didn’t feel immersive to me since moving around lacked the convincing parallax experience you get from viewing things in your every day life.

While internet AVP users seem to enjoy viewing 2D movies on a giant, virtual screen, I think there is a huge opportunity for companies to build 3D immersive environments or games for users to be in (and interact with). Using the AVP’s state of the art hardware to view 2D images is like watching television without sound – a missed opportunity.

Takeaway

Despite the hardware issues (I suspect the light seal), I’d be interested in making AR apps for the AVP. Paying almost $4K to buy a dev kit and develop for Apple is a tough sell for an indie developer. I honestly think Apple should have a program for developers to borrow AVPs and build apps.

Paris November 2023 Trip Report

During Thanksgiving week, we went to Paris. This is a review of how things went traveling as a family with young kids in a city without strollers.

Flight: French Bee

I wasn’t sure what to expect flying this budget airline. They changed our flight months before from [Saturday to Saturday] to [Sunday to Sunday]. This was annoying but we dealt with it by updating hotel plans. The outbound flight was good. The airplane was a modern Airbus plane and we could watch movies from a limited selection. While we had meal service pre-purchased, they only offered water with our meal. Anything besides water cost extra. Not a deal breaker but kind of odd? The prepaid pasta entree was not good.

On the inbound flight, our plane had an issue. This was very concerning as it wasn’t clear if we were going to be able to fly home on Sunday. After a few hours delay, they switched us to another plane (from partner Air Caraïbes) and we were flying home. Despite this significant delay on the return flight, I would be open to flying French Bee again as long as the price is low enough.

Hotel: Hyatt Regency Paris Étoile

We stayed a week in the 17th arrondissement on points. No cash cost for a suite (actually a family room: 2 connected rooms) with a great view of the Eiffel Tower and lounge access. Our kids enjoyed the lounge and we took advantage of the lounge to eat breakfast. The location is not central, so doing stuff “in Paris” meant taking the subway for 20 minutes one way, doing stuff, and then coming back another 25 minutes.

I enjoyed our stay here. There are plenty of other hotels in more central or vibrant locations which would have been more conducive to a mid day rest. This Hyatt had convenient subway access and a great view of the city.

Transportation

We flew into Orly airport and were lucky that our trip lined up with the Navigo weekly pass. It was hard to purchase the weekly pass since we had to find a manned booth at the “5th” bus stop area outside Terminal 4. Regular public transit machines did not sell the weekly pass. For 30 euros, you get a pass that works exactly from Monday to Sunday for metro, train, RER, express tram, tram and bus. This means you can take unlimited Paris subway, train to Versaille, city buses, etc. rides all for 1 low price.

When it made sense to, I did supplement with Taxi rides via the G7 Paris Taxi app. Not all taxis can hold 4 passengers so hailing a taxi is hit or miss. Also when taking a large passenger van official taxi (with the taxi light on top), I ran into upcharges for luggage and stuff even though the fare from the airport to Paris was supposed to be a lower flat fee. It’s unclear how much of these fees are valid or the taxi driver tacking on extra charges.

Weather: cold & challenging

So this isn’t unexpected, but it’s worth mentioning. The weather during Thanksgiving week is very cold. Even when my iPhone Weather app says today is “cloudy and not raining”, some days would still have drizzle or rain. This made sightseeing or walking around VERY difficult with young kids.

Itinerary

We had 5 full days to sight see. Jetlag was a real challenge during the trip and even after the trip.

  1. Tues – Eiffel Tower summit, Le Bon Marché department store, Tuileries Garden Christmas market. The Eiffel Tower was pretty awful with cloudy & rainy weather, but we had pre-purchased tickets. The Tuileries Christmas market was fun with lots of carnival games.
  2. Weds – Louvre, Sacré-Cœur de Montmartre. The Louvre was good as we saw the famous art and ate at Cafe Angelina inside. There was also a kids studio in the basement of the Louvre with crafts. For dinner, we ate at Bouillon Pigalle which was pretty awful, my fault for picking a lower end place.
  3. Thur – Versailles palace, Bateaux-Mouches Seine river boat cruise. In Versailles, the weather was pretty bad with drizzle. Since we have young kids, there was no way to walk around the whole estate, so we rented a golf cart which was fun. The boat cruise was definitely worth it to see the city of lights at night.
  4. Fri – Shopping (La Samaritaine, BHV Marais), walking around (Île de la Cité). We made a pit stop at Boulangerie BO&MIE which had excellent pastries. For dinner, we ate at Grand Brasserie. Our kids were really tired. The beef quality in France seems worse than the US. Obviously the wine, cheese, bread, etc. are all top notch in Paris.
  5. Sat – More shopping (Printemps Haussmann, Galeries Lafayette Haussmann), Saint Germain Christmas Market. The rooftop of the Printemps was not anywhere as amazing as the Galeries Lafayette. Since this was a Saturday and “Black Friday” shopping, the crowds at Galeries Lafayette Haussmann was just too crowded. I wanted to look around more for kids stuff, but there were way too many people. Also the Saint Germain Christmas Market was a few stalls alongside the road – not worth checking out.

Overall

Despite the weather and time difference, we enjoyed the trip. The kids already want to go back to Paris. While we can’t go back right away (the trip just happened), it will be fun to come back eventually and spend time doing other things (walking around, eating, shopping, and not visiting the Louvre or Eiffel tower). It was good to take an international trip, expose our kids to a different culture/language, and challenge ourselves visiting a major European city (instead of a more typical Hawaii vacation at the beach/resort).

Installing Ruby 2.X on Intel macOS Monterey (12.6)

In this guide, we’ll be using rvm & homebrew to install Ruby 2.X on our Intel Mac. The key is to specify the location of openssl.

First, make sure you have Xcode Command Line Tools installed on your mac. You can install it with

        xcode-select --install

Then install openssl (v1.1):

        brew install openssl@1.1

To install Ruby on my Mac, I’ve had to specify the openssl directory when compiling Ruby. Make sure to replace “2.7.8” with your target Ruby version.

        rvm install 2.7.8 --with-openssl-dir=`brew --prefix openssl@1.1`

You can set this version of Ruby as your default version with rvm:

        rvm use --default 2.7.8

That’s it! Installing older versions of Ruby isn’t too tough.

Updating web app from Rails 4 to Rails 7

A few months ago, certbot gave me the warning “Your system is not supported by certbot-auto anymore.”. With my Rails 4 app running on old Ubuntu 14.04, it was time to update the app & environment.

Since I’m using Digital Ocean’s droplets, it was easy to spin up a new droplet, setup the new droplet, and then destroy the old droplet. This is way better than operating in situ.

This blog post will provide a high level overview of update steps & pitfalls encountered.

  1. Spin up a Ruby on Rails (v7.0.4.2, OS Ubuntu 22.04) droplet https://marketplace.digitalocean.com/apps/ruby-on-rails This also involved setting up a SSH key to access the new droplet server.

  2. Exfiltrate the example Rails 7 app from the server to my local machine scp -r root@{SERVER_IP}:/home/rails/example .

  3. Create a new private GitHub repo for this example Rails 7 app

  4. Run the new example Rails 7 app locally This step should be super simple, but it was not. Getting RVM to run Ruby 3.2.0 with OpenSSL was not trivial on my Intel Mac. Here’s what I ran to setup Ruby 3.2.0 locally:

    sudo -i
    cd /usr/local/src
    curl -O https://www.openssl.org/source/openssl-1.0.2t.tar.gz
    tar xzf openssl-1.0.2t.tar.gz
    cd openssl-1.0.2t
    ./Configure darwin64-x86_64-cc
    make
    make install

    rvm reinstall 3.2.0 --with-openssl-dir=/usr/local/ssl

  5. In the new Rails 7 app, I moved my psql DB migrations over by hand. I copied the files and had to update the ActiveRecord::Migration with ActiveRecord::Migration[7.0].

  6. Draw the rest of the owl. I had to port lots of Rails files over from my Rails 4 to the target Rails 7 app.

    I ran into an issue with a model validation callback. To fix my issue, I created a migration to add uniqueness validation at the postgres layer and removed the uniqueness check in my model.

    This also include various site fixes. Such as Open Street Map tiles, using 3rd party APIs, and Font Awesome icons.

  7. Setup deployment to the server using Capistrano.

    Setting up Capistrano with Puma on Digital Ocean was not trivial at all. I followed this guide by Matthew Hoelter https://www.matthewhoelter.com/2020/11/10/deploying-ruby-on-rails-for-ubuntu-2004.html

    In my config/deploy.rb file, I had to add this set :branch, :main

    In my root Capfile, I had to use install_plugin Capistrano::Puma::Systemd due to using Puma 5.6.5.

    After a ton of trial and error, I had setup my nginx config at /etc/nginx/sites-available/rails.

    There was a ton of issues with the .sock file from Puma not getting generated.

    Setting up the secret_key_base is a newer Rails convention. Luckily Matthew’s blog post goes into detail on how to set it up in /etc/environment

    Using systemctl, I got puma setup to run the command bundle exec puma -C /home/rails/apps/[APP_NAME]/shared/puma.rb.

    Also, due to running on Digital Ocean, I had to update permissions for the rails user. cd /home; chmod o=rx rails. See Stack Overflow for details https://stackoverflow.com/questions/70028324/nginx-permission-denied-accessing-puma-socket-that-does-exist-in-the-correct-loc Without running this, I was getting a 502 (Bad Gateway) error, even though everything else was setup. I can see traffic in my nginx.access.log, but I was still getting the 502 (before running this command).

  8. Move psql data over. This step is going to vary a lot on your setup. I was able to run pg_dump to export my data and import data using psql APP_NAME_production < latest_pg_dump.sql.

  9. Update A record. In order to point my domain to my new droplet, I went into Digital Ocean and updated the A record from my old IP to my new IP. This is going to vary depending who you’re using for domain names.

  10. Run certbot. Running certbot for SSL was super easy. https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal

  11. Destroy old droplet. When you’ve verified everything is working with your new Rails 7 app, you can destroy the old droplet in Digital Ocean.

My app, GeoGraph, is now running on Rails 7 and lets anyone bookmark their location.

Disney California Adventure (CA) Trip Report – June 2023

Our family went to Disney CA on a weekday in early June. I read online there would be lots of graduating high school students, but I didn’t anecdotally feel like the park was filled with students.

We opted for 1 day of intensity instead of going to Disneyland over multiple days. Since we haven’t been to Disney CA in a while, I opted for the paid fast pass (Genie+ Lightning Lane). The Lightning Lane proved helpful since you can skip some long lines.

The Disneyland Genie+ Lightning Lane (G+LL) system is confusing. As of June 2023, there was 1 paid ride that was not part of the G+LL pass: Radiator Springs Racers (RSR). RSR has its own paid Individual Lightning Lane, which we did not buy. With the G+LL, you can book another Lightning Lane (LL) every 2 hours or after you scan in your LL pass at the ride entrance.

8am – Rope Drop

We went for the rope drop. However we hit some bad traffic on the highway driving down. So after parking in the Toy Story parking lot, we got to the rope drop area at 7:45a. We were stuck in the back of the rope drop crowd. Everyone was heading towards Radiator Springs Racers.

8:10a – Radiator Springs Racers

90 minute posted wait. Actual wait was ~80 minutes. We rope dropped this ride since I didn’t want to pay for the Individual Lightning Lane. I enjoyed the Cars Land area decorations, but I didn’t think RSR was a great ride. For whatever reason, the car we sat in didn’t even race another car. There was simply no car next to us, so we went through the ride just cruising around the track by ourselves. I honestly don’t see what all the hype is about.

9:40a – Web Slingers

45 minute posted, 45 minute actual wait. I think this was a decent ride. The ride broke down on us a couple times while on the ride. Overall, it was fun with young kids to shoot webs and go for high value targets.

10:40a – Guardians of the Galaxy – Mission Breakout (LL)

80 minute posted. 30 minute actual wait with LL reservations. The Lightning Lane queue wasn’t moving when we checked in. So even with a LL, it can take a while to get on the ride. This ride was one of the best rides of the day. I wanted to go on it again, but the line throughout the day was just long. And you can’t use LL twice on 1 ride in a day.

11:40a – Lunch

We went to Pacific Wharf Café and had clam chowder bowls. I had low expectations, but the bread (and the soup) was pretty good.

For the next LL ride, I wanted to give us enough space to walk around, eat lunch, and take a breather from rushing to 3 heavy hitting rides in the morning. I didn’t want to have to cut lunch short in order to make a LL reservation.

12:50p – Mike & Sulley to the Rescue! (LL)

35 minute posted. 9 minute wait with LL. So I booked this LL when the ride was showing up as down. It didn’t work as the ride came back up eventually. If the ride didn’t come back up in time for our LL, then we would have a pass to use at another similar tier ride. I think this ride was OK. It’s a ride for kids who really love Monster’s Inc.

1:20p – Animation Academy

This was a 2 for 1. There’s a bunch of attractions in the Animation Academy. Each has different waits. We took the Learn the Secrets of Drawing class and it was fun to draw Dumbo. However, we also waited for the Frozen meet and greet (Royal Welcome) and that wasn’t a great use of our time. No issues with the character we met, but the line was just way too long and not worth meeting a character for 30 seconds.

2:35p – Redwood Creek Challenge Trail

This was our resting period for the day. The kids ran around the play area and we were able to sit for a little bit.

3:20p – Grizzly River Run (Single Rider)

70 minute posted wait, actual wait 9 minutes. While other members were at the challenge trail, I rode the Grizzly River Run as a single rider. The ride was fun and the tube spun around a lot. While I was in the Single Rider line, I saw a party of 2 (parent and child?) try to use the Single Rider line to go on the ride together. The Disney CM called them out for it, but ultimately the 2 were able to go on the ride together.

4:10p – Incredicoaster (Single Rider – did not ride)

55 minute posted wait. Did not actually ride it at 4pm. So the Single Rider line for Incredicoaster was pretty long and not moving with any regularity. I think the 2+2 seating doesn’t lend itself well to single riding. I waited for 20 minutes and left since the line wasn’t moving.

4:30p – Jessie’s Critter Carousel

10 minute posted wait. 5 minute actual wait. This ride is pretty self explanatory. It’s a carousel for young kids. The short wait helps.

4:45p – Toy Story Midway Mania (LL)

40 minute posted wait. 15 actual wait with LL. This was a fun ride. Shooting targets for a high score was fun for the family.

5:15p – Emotional Whirlwind Inside Out

30 minute posted wait. 20 minute actual wait. This ride was OK. We recently watched Inside Out so I figured this would be a fun ride to go on. Note: Bing Bong’s Sweet Stuff nearby has some sweet (pun intended) treats!

5:45p – Pixar Pal-A-Round (Swinging)

30 minute posted wait on the physical entrance sign. The app said 60 minute wait. Actual wait was 25 minutes. This was a fun ride. I wasn’t sure if we were able to fit it in our schedule. The Swinging version is no joke. The Swinging was more than I expected, but it was fun. Also seeing various Pixar characters on the Ferris wheel pods was fun.

7p – Soarin’ Around the World (LL)

55 minute posted wait. 15 minute actual wait with LL. We enjoyed this ride. I’m not sure when the ride soars around the world VS California. We went on a world tour and it was really fun.

7:30p – Cozy Cone Motel

Dinner was fine. I wanted something fast casual. Using the Disney app to order in advance definitely saved a lot of time (vs waiting in line to order food). Also as already mentioned, I really like the Cars Land theming/decor.

8p – Goofy’s Sky School (LL)

50 minute posted wait. 10 minute actual wait. The LL really helped here. I don’t think this ride was a must ride, but it’s included in the LL so why not ride it? At this point, we had used the LL on almost all the LL eligible rides. This was a bumpy/rough and fun kids roller coaster.

8:15p – The Little Mermaid: Ariel’s Undersea Adventure

10 minute posted wait. 5 minute actual wait. This ride wasn’t running earlier in the day. But it was up and running throughout the day. During the afternoon, the posted wait was long so I didn’t go on it. At night, there was practically no line. This was a fun ride for our kids since we also recently saw the classic animated The Little Mermaid movie.

8:30p/9p – World of Color ONE (WoC)

My family got in line at the designated seating area for WoC around 8:30p. I left for the Incredicoaster and came back by 9pm to watch the show. I would say the show is OK. Some people really enjoyed it, but I wasn’t personally invested in light projection on water meant to invoke classic Disney/Marvel/etc memories.

8:40p – Incredicoaster (LL)

45 minute posted wait. No wait while using LL. As I walked to the Incredicoaster ride, I could see the Single Rider line still really long. With the LL reservation, I walked all the way onto the ride. This ride was amazing. Definitely one of my top rides in California Adventure.

9:30p to Close

We walked around the shops to get some last minute souvenirs. Honestly, I prefer the Main Street shops in Disneyland more. I think CA park is great if you want very specific stuff (Avengers, Spider-Man, Pixar, etc gear), but otherwise I felt the selection in Disneyland main street was much greater.

Takeaways

At rides, the posted wait time changes constantly and really doesn’t tell you exactly how long the wait is.

Walking around Disney CA is a challenge. I usually had to take the long way and walk through a ton of the park to get where I wanted to go. The layout of Disney CA doesn’t lend itself well to doing stuff nearby when I’m trying to also use Lightning Lane for rides that are often on the other side of the park.

On our weekday, there were some rides down in the morning and throughout the day. I think most or all of them were back and running later in the day. I think Zephyr kept going down but was up every now and then. The good news is that just because I saw a ride being unavailable at rope drop, it didn’t mean the ride was down for the whole day.

I think 1 day is enough to see Disney California Adventure with the G+LL constantly used. Compared to Disneyland, I think Disneyland is the top tier park and Disney California Adventure is the second choice. So depending on how many days you want to spend at Disney: if you only have 1 day, go to Disneyland. If you have 2 or more days, you can do 1 day Disneyland, 1 day California Adventure, etc. I personally don’t buy the park hopper, but park hopper seems like a popular add-on.

P.S. – I can’t help but feel like posting content to the internet is just feeding LLMs (ChatGPT, etc.).

Installing Windows 11 on a new PC built from scratch

I recently built a PC from parts I got at my local MicroCenter and online. Building the PC was tough, but there were no surprises.

Installing Windows 11 Pro was really, really difficult. I’m shocked since installing software (especially a prominent offering of Microsoft) is supposed to be trivial and work everywhere.

With my PC parts put together, I was able to see the BIOS screen on my monitor. I made sure CSM (Compatibility Support Module) was off and UEFI (Unified Extensible Firmware Interface) was enabled.

I restarted my computer and plugged in my Windows 11 installation USB drive. (Sidenote: I recommend creating the installation USB from Microsoft’s Media Creation Tool on a Windows PC. I tried to create a USB install stick from macOS and it did not work.)

Going through the menu options, I was getting cryptic errors: “Windows could not prepare the computer to boot into the next phase of installation. To install windows, restart the installation“. The error message was unhelpful so I spent time googling for answers and restarting my computer countless times.

From what I can tell, my copy of Windows 11 Pro cannot install from a USB drive. This is surprising since using a USB drive is the de facto installation method in 2023. Almost nobody has a CD/DVD drive to install Windows like we used to 10 years ago.

I had to use command line tools in the Windows installation process to create a local SSD partition, copy Windows 11 from my USB to the new partition, and install Windows from the SSD. This was extremely not user friendly and took me well over 3 hours of trial and error to eventually come up with a solution to install Windows. What gives Microsoft? Is installing Windows from a USB drive seamlessly not a priority?

Here are the commands I ran to install Windows 11. My notes (after the # below) are my best guesses as to what is happening. Note: this will format/wipe/erase your drive. PROCEED AT YOUR OWN RISK.

You can get to the command line interface from the disk selection screen. Press Shift + F10 to open and enter.

# enter diskpart tool
diskpart

# view your disks
list disk 

# selects the 1st disk (make sure you select your primary SSD)
select disk 0 

# wipe the selected disk
clean 

# set the selected disk to GPT format. this is important!
convert gpt 

create partition primary size=52000 
# the size (52000) varies. Just make sure it fits Windows 11 and is within the size of your SSD

# format the selected disk to NTFS
format fs=ntfs 

# assign a drive letter to the selected disk
assign 

# view your list of volumes
list volume 
# make a note of the letters for your new SSD partition & USB stick

# exit diskpart
exit 

# change to your flash drive. Use the correct letter (may or may not be E:)
cd E:

# copy from USB to your new SSD partition
# Use the correct letters (e: & c:) below
xcopy e: c:/s /e /h /c

exit

After following the steps above, you have now created a partition on your SSD with a copy of the install USB contents. It is important to EXIT the Windows installer. Do NOT continue with the Windows menus.

Restart your computer. When your computer is off (during the restart), make sure to remove the USB stick. You want your computer to boot from your new partition and not the USB stick.

If everything goes well, you should be able to install Windows 11 successfully.

During the Windows setup, I had to run a command (OOBE\BYPASSNRO) to install Windows without connecting to the internet. This was a chicken and egg problem since I didn’t have any WiFi firmware setup on my computer, so I couldn’t easily get any firmware updates. Also Windows wasn’t even setup yet, so I couldn’t use Windows to install the WiFi firmware either.

As a final step, I wanted to remove the disk partition created during the Windows install process (above). It’s all been a blur given how hard it was to install Windows 11 in the first place. Thankfully, after Windows 11 was already installed on my computer, I was able to re-run the Windows 11 setup process, remove the partition, and install Windows without an issue.

How I cleaned up 3M spam comments in a WordPress blog

Tl;dr: delete them.

Last week, I received an alert, my blog’s database was too large (> 3GB) and had to be upgraded to a premium plan. Paying a new monthly fee for something I don’t need made no sense, so I looked into the database.

Most of the space was used by two WP tables: wp_comments & wp_commentmeta. Their sizes being roughly 2.2 GB & 1.8 GB respectively.

Upon logging into the WP admin panel, I could see a long neglected blog. There were 3.1M comments, and somehow 2.7M were approved.

3M comments (the vast majority are assumed to be spam)

My first approach was to use akismet (Automattic’s spam filtering service) to process the comments. I went into my MySQL database and marked the comments from late 2019 (arbitrary cutoff date) from approved (comment_approved=1) to pending (comment_approved=0).

WordPress’s comments section has a handy button to Check For Spam with Akismet. I tried this, but it was taking too long. I honestly think it would take a month to check my ~3M comments. Since the browser would time out, this process had to be manually monitored (not practical).

While your comments section may have lots of legitimate comments, my understanding of my comments is that they are 99.999% spam for the past few years. This is because my blog has been largely ignored and is no longer current. In fact, searching for my blog doesn’t even show up on Google. The lack of HTTPS (now fixed) and endless spam comments probably pushed the SEO so low that *only* spammers know about the site to post comments.

With the assumption of nearly 3M comments as spam, here’s how I cleaned it up:

  1. As mentioned above, I moved all the comments from late 2019 to pending (comment_approved=0). I tried using phpMyAdmin but had to eventually use a GUI (TablePlus on Mac) to run SQL.
    UPDATE wp_comments set comment_approved = '0' WHERE comment_date > '2019-10-01' AND comment_approved = '1';
  2. Delete all my pending comments:
    DELETE FROM wp_comments WHERE comment_approved = '0';
  3. Clean up my meta comments table (wp_commentmeta):
    DELETE FROM wp_commentmeta WHERE comment_id NOT IN ( SELECT comment_id FROM wp_comments );
  4. Clean up table overhead. Overhead was making my tables still take up GBs of space even though the vast majority of comments were deleted.
    OPTIMIZE TABLE wp_comments;
    OPTIMIZE TABLE wp_commentmeta;

Using a desktop GUI to run MySQL was fast and efficient. Before and after I executed my SQL clean up commands, I checked the row counts so I could have some confidence in the executed commands.

I still have ~10K comments left on my site. Some are legitimate, some are spam. I’m letting Akismet take a pass through these 10K comments, and then I’ll clean up the rest manually.

Setting up your Mac to create a Playdate app

This guide is written on macOS Monterey (v12.3).

playdate simulator

Here are instructions on setting up & running the most barebones app possible on macOS. There are probably better ways to do this, but here’s one way that works for me.

  1. Download & install the SDK via https://play.date/dev/

  2. Update your ~/.zshrc file with the following line:

    export PLAYDATE_SDK_PATH=/Users/rex/Developer/PlaydateSDK

    Obviously you want to replace “rex” with your username.

  3. Create a new folder for your project (anywhere)
    mkdir playdate_hello_world
    cd playdate_hello_world

  4. Create a VS Code folder & settings file
    mkdir .vscode
    touch .vscode/settings.json


  5. Put the following into your new settings.json file. Make sure to replace the 2 instances of “rex” with your username

    {
    "Lua.runtime.version": "Lua 5.4",
    "Lua.diagnostics.disable": [
    "undefined-global",
    "lowercase-global"
    ],
    "Lua.diagnostics.globals": [
    "playdate",
    "import"
    ],
    "Lua.runtime.nonstandardSymbol": [
    "+=",
    "-=",
    "*=",
    "/="
    ],
    "Lua.workspace.library": [
    "/Users/rex/Developer/PlaydateSDK/CoreLibs"
    ],
    "Lua.workspace.preloadFileSize": 1000,
    "playdate.sdkPath": "/Users/rex/Developer/PlaydateSDK"
    }


    (Apologies for the formatting. WordPress & code doesn’t mix well). You can copy & paste above (and make sure to replace the 2 “rex”s)

  6. Create a simple file for your app
    mkdir source
    touch source/main.lua

    Copy the following into main.lua:

    import "CoreLibs/object"
    import "CoreLibs/graphics"
    import "CoreLibs/sprites"
    import "CoreLibs/timer"

    function playdate.update()
    print "Hello world"
    end


    Obviously this code does not do very much. It’s super, super basic, but it compiles & runs!

  7. Install the following VS Code extensions (sumneko.lua, jep-a.lua-plus, and Orta.playdate)

  8. Run your app on the Playdate Simulator with VS Code.

    Press Cmd + Shift + P and select & run [Run app in Playdate simulator]

  9. That’s it! Your app is now running on the Playdate sim. You can view print statements by using Window > Console.

For more comprehensive details, refer to the SDK documentation: https://sdk.play.date/1.10.0/

For the sample files discussed here, see repo: https://github.com/xta/playdate_hello_world

Legoland 2022 1-Day Trip Review

We went for a day in March during spring break. With young kids, we had some height restrictions, but most rides were available since Legoland is for young kids. The park was busier than I expected, but overall it was much better (less crowded) than summer time.

Legoland sells VIP access to skip lines, but I wasn’t interested. Plus, we’ve already been to Legoland a handful of times so I didn’t see the need to pay extra.

I downloaded the official Legoland app, which was extremely helpful in looking at estimated ride wait times. Too bad their app doesn’t let you order food like Disneyland’s app does.

While picking rides in the park, I focused on rides with shorter wait times & rides that were nearby. If there was a ride nearby with a short line, I definitely took my kids to check it out.

Attractions List with comments

Junior Driving School / Driving School

  • This is fun for kids to drive around

Sky Patrol

  • basic helicopter ride. what you see is what you get. fun

Fun Town Police and Fire Academy

  • this was a competitive ride (competing against other groups). pumping (to move the truck) was harder than expected

Skipper School

  • this boat ride was fun, but the line was really long. the wait wasn’t worth it

Legoland Express

  • simple train ride for toddlers. it’s fun, and no wait is awesome

DUPLO Playtown

  • this was ok. kids can play in the playground. the Duplos were scarce (COVID safety precaution?)

Queen Watevra’s Carousel

  • it’s a basic carousel ride. you either like it or you don’t

LEGO Movie 2 Experience

  • this simple walkthrough is cool for Lego set piece nerds, but it might not be interesting for everyone

Coast Cruise

  • simple, boat tour. I feel bad for the tour guides since they have to repeat the same pun jokes over and over

The Royal Joust

  • this thing always has a long line? it works well for the kids to wait in line while I get food nearby…

Knights’ Smokehouse BBQ

  • the lunch options are decent. typical, pricey theme park food, but the BBQ itself is not bad. if you get here during lunch hours, be prepared to wait in a long line

Cargo Ace

  • simple, kid friendly plane ride

Bionicle Blaster

  • these saucers spin around fast. shorter/younger children can’t ride it

Ninjago the Ride

  • our family isn’t super into Ninjago. the ride was OK, but I think my sensor hand placement was off since it wasn’t working well

Eglor’s Build-a-Boat

  • it’s legoland, so there’s different lego stations for kids. this one was a decent distraction. the Legos didn’t seem to be that clean considering the amount of water they are exposed to

Fairy Tale Brook

  • this ride is awesome. the decor is standard fare. I always enjoy this simple boat ride with almost no wait

LEGO Factory Tour

  • we walked through some Lego factory machines and the kids were able to build with Legos. this was more of a time sink

LEGO City Deep Sea Adventure

  • this sub ride was ok. there was no line, and I’m not a huge fan of the treasure hunt activity (spot things in the water)

The Hideaways

  • this play ground at the top of the theme park was fun for the kids to run around. I have to assume due to COVID, all the tube slides were closed (sealed at top & bottom). No slides makes getting around the vertical playground a bit odd

The Big Shop

  • always packed at the end of the day. The shop is OK. I think most stuff you can find online at a similar or better price. I didn’t find any notable exclusive Legos this day. If you show them your Lego.com VIP, you get a small discount

Legoland is fun for young kids, but it’s easy to run out of things to do after your 1st day. Costco has a 2 day ticket promo (with 2nd visit in 14 days of 1st visit), but that’s more Legoland than we need.

Disneyland 2021 1-Day Trip Review

We went for 1 day in August with young kids, meaning we couldn’t go on all the rides (height restriction). When we went, there was no park-wide fast pass system, so I didn’t have to worry about optimizing the next fast pass.

Before going, I downloaded the official Disneyland app (with my account & tickets set up). This is important since it lets you join boarding groups (Rise of the Resistance) at 7 am (outside the park) or 12 noon (in the park). If you are trying to join a boarding group, make sure you try exactly when it turns 7a (or 12). The official app also makes ordering food easy.

Some helpful tips: 1.) Go early. Try to get there when the park opens (like 8am) or even before they open (line up for rope drop). This will let you go a number of rides early in the day when lines are shorter. 2.) With tip #1, go on rides with longer lines first. Here’s a site showing sample wait times.

Ride List with comments

  • Jungle Cruise
    • alright. The guide was good, but the scripted dad jokes were soso
  • Pirates of the Caribbean
    • decent. This is classic Disneyland
  • Haunted Mansion
    • decent. This is classic Disneyland
  • The Many Adventures of Winnie the Pooh
    • fun for young kids
  • Mad Tea Party
    • decent. your typical spinning kid ride
  • King Arthur Carousel
    • decent. your typical carousel ride
  • Star Wars: Rise Of The Resistance
    • decent. It wasn’t the best thing ever. I enjoyed the impressive set pieces. This ride broke down twice on us (used Rider Switch) and ate up much of our afternoon.
  • It’s a Small World
    • good. This is classic Disneyland
  • Autopia
    • good, but they need to make the cars electric. The gas fumes are awful
  • Buzz Lightyear Astro Blasters
    • good, but it’s hard to tell where you are aiming
  • Mickey’s Mix Magic (9pm)
    • decent. Instead of a parade, they projected a show onto the castle and lit up a ton of fireworks

Food List with comments

  • Mickey-shaped Beignets @ [Mint Julep Bar, New Orleans Square]
    • mediocre. we were hungry in the morning, but these did not knock my socks off
  • New Orleans Mint Julep @ [Mint Julep Bar, New Orleans Square]
    • tasty, non-alcoholic drink
  • hand-dipped corn dogs @ [Stage Door Café, Frontierland]
    • tasty, but I was feeling fried food overdose
  • chicken tenders kids meal @ [Stage Door Café, Frontierland]
    • alright. your typical generic theme park kids meal. including a mandarin orange was good
  • Dole Whip Soft Serve @ [Tiki Juice Bar, Adventureland]
    • good, but I prefer the float! Don’t @ me
  • Dole Whip Float @ [Tiki Juice Bar, Adventureland]
    • amazing. Dole whip floats are always great, even more so on a hot day
  • frozen cherry lemonade @ [Fantasyland cart]
    • not good. the cherry flavoring didn’t remind me of cherry
  • blue milk @ [Milk Stand, Star Wars: Galaxy’s Edge]
    • good. this may have been an acquired taste. The tropical flavor was delicious
  • green milk @ [Milk Stand, Star Wars: Galaxy’s Edge]
    • average. I tried the citrus flavor, but it didn’t remind me of citrus and didn’t hit the spot

Disneyland was a fun-filled day for our family. Since we don’t go often, I try to do as much as possible. This is tough with kids, but we had strollers and took a break in the middle of the day to let the kids rest.

Having secured the Rise of the Resistance boarding group at noon, I think we accomplished more than enough. If we had more time in the afternoon, there were plenty of rides in Fantasyland to try or Mickey’s Toontown to visit.