diff --git a/articles.html b/articles.html index fd3bbb8..f2ec048 100644 --- a/articles.html +++ b/articles.html @@ -6,45 +6,10 @@ - - - - - - + + + @@ -75,6 +40,38 @@ Although I don't generally write much, sometimes I'll find something interesting, or something that I notice a significant number of people could benefit from reading about. In that case, it'll most likely end up on this page as an article.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DateArticle
A Beginner's Guide to Searching with Lucene
DSH - Easier Scripting in D
The D Programming Language: Does it have a future?
Spring's Open-Session-in-View & Transactions
2D Games with Java & Swing
diff --git a/articles/beginner-guide-to-apache-lucene.html b/articles/beginner-guide-to-apache-lucene.html index 75a57b6..ffc1af7 100644 --- a/articles/beginner-guide-to-apache-lucene.html +++ b/articles/beginner-guide-to-apache-lucene.html @@ -4,13 +4,39 @@ A Beginner's Guide to Searching With Lucene + - - - + + + + + + + + + +

A Beginner's Guide to Searching With Lucene

@@ -27,7 +53,7 @@

-

The Use Case

+

The Use Case

Before we dive into the code, it's important to make sure that you actually need an indexing and searching tool that goes beyond simple SQL queries.

@@ -42,7 +68,7 @@
-

Indexing and Searching Basics

+

Indexing and Searching Basics

No matter what searching solution you end up choosing, they all generally follow the same approach:

@@ -64,7 +90,7 @@
-

Setting Up a New Project

+

Setting Up a New Project

In this guide, I'll be creating a small Java program for searching over a huge set of airports which is available for free here: https://ourairports.com/data/. The full source code for this project is available on GitHub, if you'd like to take a look.

@@ -94,7 +120,7 @@
-

Parsing the Data

+

Parsing the Data

First of all, we need to parse the CSV data into a programming construct that we can use elsewhere in our code. In this case, I've defined the Airport record like so:

@@ -131,7 +157,7 @@
-

Indexing

+

Indexing

In order to efficiently search over a massive set of data, we need to prepare a special set of index files that Lucene can read during searches. To do that, we need to create a new directory for the index to live in, construct a new IndexWriter, and create a Document for each airport we're indexing.

@@ -187,7 +213,7 @@
-

Searching

+

Searching

Now that we've built an index from our dataset, we can search over it to find the most relevant results for a user's query.

@@ -260,12 +286,9 @@

Once again, my sample code is available on GitHub here.

-
- - - Back to Dev Discussions +
+ Back to Articles
- - + diff --git a/articles/d-prospects-for-future.html b/articles/d-prospects-for-future.html index 661b641..7384878 100644 --- a/articles/d-prospects-for-future.html +++ b/articles/d-prospects-for-future.html @@ -4,13 +4,39 @@ The D Programming Language: Does it have a future? + - - - + + + + + + + + + +

The D Programming Language: Does it have a future?

@@ -25,7 +51,7 @@ a radical stance, and contrast those ideals with some harsh realities.
-

The Potential

+

The Potential

Because it was designed many years after the advent of most of the main programming languages that form the backbone of our software (C, C++, Java, Python, etc.), D has the benefit of 20/20 hindsight that it uses to @@ -95,13 +121,13 @@

-

Why Isn't D Popular?

+

Why Isn't D Popular?

You'd think that all these benefits, developers would be flocking in droves to D. But clearly in the real world, that's not the case. Why? This section outlines some of the reasons why the language hasn't attained the same level of popularity as others.

-

Late to the Party

+

Late to the Party

Despite their modern-day popularity, all of the major programming languages are several decades old: Java was created in 1995, Python in 1991, C++ in 1985, and so on. D was first conceived in 2001, giving all of @@ -111,7 +137,7 @@ from there. So we're dealing with a relatively immature language as of yet, which still needs to prove its worthiness in various disciplines before it gains popularity.

-

Paradoxical Loneliness

+

Paradoxical Loneliness

One fatal issue which affects many software projects is this: the project receives little attention from new users, so it is not promoted to new users. Therefore, the project yet again receives little attention from @@ -122,7 +148,7 @@ languages but instead offers smaller meaningful, incremental improvements, it's also not the most flashy new language for individual developers to rave about in the free time.

-

A New Ecosystem

+

A New Ecosystem

Stemming from the other reasons mentioned above, because D is relatively new, its software ecosystem is still growing, and lacks some of the mature, standard libraries we've come to expect from a general-purpose @@ -131,9 +157,8 @@ robust library of modules that rivals the Java and C++ ecosystems.

- Back to Dev Discussions + Back to Articles
- - + diff --git a/articles/dsh-easier-scripting-in-d.html b/articles/dsh-easier-scripting-in-d.html index 976efbf..06d8927 100644 --- a/articles/dsh-easier-scripting-in-d.html +++ b/articles/dsh-easier-scripting-in-d.html @@ -4,12 +4,37 @@ DSH - Easier Scripting in D + - - - + + + + + + + + +
@@ -27,7 +52,7 @@

-

Why write scripts in D?

+

Why write scripts in D?

While many people are used to scripting in languages that have been built over the years specifically for that use case, this introduces extra complexity into projects that are mainly built using some other language. In an ideal world, we'd use one single language to describe everything about our app, from the way it looks, to how we compile and distribute it. DSH is my attempt to make this a reality, at least for applications written in D. When developing D programs that require some auxiliary scripts, you don't have to make a cognitive jump to another language; just keep writing code in the environment you're most efficient in. This way, we reap the benefits of specializing in becoming an expert in a single language and its ecosystem.

@@ -36,7 +61,7 @@

-

Writing Your Script

+

Writing Your Script

There are two main ways to write scripts using DSH:

@@ -86,12 +111,12 @@
-

Helper Functions

+

Helper Functions

While dshutil is a handy tool on its own, the real benefit of using DSH is its library of helper functions which are designed specifically for scripting tasks.

-

File Utilities

+

File Utilities

DSH offers quite a few helpful functions that reduce the verbosity of your IO operations. Below is a sampling of some of the most prominent functions.

@@ -108,7 +133,7 @@ } -

Process Utilities

+

Process Utilities

In addition to the functions in D's std.process module, DSH provides some shortcuts for scripts to make it easy to manage processes.

@@ -126,9 +151,8 @@ Also included is a ProcessBuilder class with which you can use a fluent method interface to construct processes with custom input and output sources and environments.

- Back to Dev Discussions + Back to Articles
- - + diff --git a/articles/java-swing-2d-game.html b/articles/java-swing-2d-game.html index a58c0a5..5029781 100644 --- a/articles/java-swing-2d-game.html +++ b/articles/java-swing-2d-game.html @@ -4,13 +4,39 @@ Java + Swing 2D Games + - - - + + + + + + + + + +

2D Game Development with Java and Swing

@@ -35,7 +61,7 @@
-

Model-View-Control Design

+

Model-View-Control Design

At first, it's super easy to make a new JFrame and start drawing on it, and you can add action listeners everywhere, whenever they're needed. If you ever plan on expanding beyond a simple 20-line drawing method however, you should organize your code using the Model-View-Controller pattern. For example, in my Before Asteroids sample game, I have split up my code into a few different packages.

@@ -54,7 +80,7 @@

-

Setting up a Swing GUI

+

Setting up a Swing GUI

Making a Swing GUI usually consists of two basic components: the JFrame that acts as your application's window, and a JPanel that is used for actually drawing your model. Usually we start by defining our own frame to extend from the base JFrame, and set its properties in a constructor.

@@ -105,7 +131,7 @@
-

The Game Loop

+

The Game Loop

First of all, this guide won't go too in-depth about the details of game loops in general, but focuses specifically on their implementation with Java/Swing. For more information, you can read this excellent article on the subject.

@@ -202,7 +228,7 @@
-

Listeners and Control

+

Listeners and Control

Most often, you'll want something to happen when the player presses a key or clicks the mouse. To do this, you should create your own class which extends from KeyAdapter or MouseAdapter, depending on what you want to do.
@@ -244,9 +270,8 @@

In this example, I show both checking which button was pressed, and also checking where the button was pressed. getX() and getY() return the x- and y-coordinates relative to the source component, which will most often be the JFrame or JPanel that the user clicked on.
- Back to Dev Discussions + Back to Articles
- - + diff --git a/articles/spring-osiv-transactions.html b/articles/spring-osiv-transactions.html index 0013752..22558ae 100644 --- a/articles/spring-osiv-transactions.html +++ b/articles/spring-osiv-transactions.html @@ -4,12 +4,37 @@ Spring's Open-Session-in-View & Transactions + - - - + + + + + + + + +
@@ -27,7 +52,7 @@

-

Don't Send Entities to Your View

+

Don't Send Entities to Your View

At first, many of the simple tutorials you'll read online will have you passing your entity models to Thymeleaf or JSP templates to render a web page for your application. This convenience is what leads developers to use OSIV in the first place, because they start fetching attributes of their entity which were not initially loaded. This is fine for the most simple "Hello World" starter projects, but as soon as you add any real complexity, this "convenience" breaks down into an unorganized mess, where it is not clear at a glance where data will be fetched from the database.

@@ -49,7 +74,7 @@

-

Transactions

+

Transactions

The Spring framework allows you to annotate a service's method as @Transactional, which means that at runtime, when your method is called, a proxy method is wrapped around it which starts a transaction (and thus a Hibernate session to go with it) that persists for the duration of the method. Inside this method, you are free to fetch lazy-loaded attributes from an entity, without having to deal with LazyInitializationExceptions.

@@ -73,9 +98,8 @@ However, the flexibility of being able to use lazy-loaded attributes the easy way more than makes up for the strict encapsulation rules, and by structuring your project around service methods as black-box operations, you'll be able to build huge projects while keeping your sanity mostly intact.

- Back to Dev Discussions + Back to Articles
- - + diff --git a/articles/template.html b/articles/template.html index 8707721..49c89f0 100644 --- a/articles/template.html +++ b/articles/template.html @@ -4,50 +4,16 @@ {{TEMPLATE_TITLE}} + + - - - - - - - + + + + - @@ -118,7 +84,8 @@ + Back to Articles - + diff --git a/contact.html b/contact.html index f5f744c..8644ea0 100644 --- a/contact.html +++ b/contact.html @@ -6,45 +6,10 @@ - - - - - - + + + diff --git a/index.html b/index.html index 86136d0..4672d2b 100644 --- a/index.html +++ b/index.html @@ -6,45 +6,10 @@ + - - + - - - @@ -79,7 +44,7 @@

About this Site

- This page was written by me, Andrew Lalis, to be my personal website on the world-wide-web. It's got all the usual stuff that a personal site should have, like important links and contact details, plus a little series of articles I've written about my experiences with programming, lifting, gaming, or anything else of interest. + This page was hand-written by me, Andrew Lalis, to be my personal website on the world-wide-web. It's got all the usual stuff that a personal site should have, like important links and contact details, plus a little series of articles I've written about my experiences with programming, lifting, gaming, or anything else of interest.

As you can see, I'm a fan of the "plain HTML is responsive" school of thought. This website is intentionally very simple in its structure, styling, and interactivity. This is because I believe that the vast majority of the internet's most popular websites sacrifice usability and accessibility to make a flashier product. By using a simpler design, we can help to make the internet more accessible to all, regardless of their physical ability or device's processing power. diff --git a/projects.html b/projects.html index d39c372..5d6121a 100644 --- a/projects.html +++ b/projects.html @@ -6,46 +6,12 @@ - - - - - - + + + + diff --git a/scripts/themes.js b/scripts/themes.js new file mode 100644 index 0000000..d5a8199 --- /dev/null +++ b/scripts/themes.js @@ -0,0 +1,30 @@ +const THEMES = ["light", "dark"]; + +function getPreferredTheme() { + const storedTheme = localStorage.getItem("theme"); + if (storedTheme !== null && THEMES.includes(storedTheme)) return storedTheme; + if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) { + return "dark"; + } + return "light"; +} + +function setPreferredTheme(theme) { + document.documentElement.className = theme; + localStorage.setItem("theme", theme); +} + +setPreferredTheme(getPreferredTheme()); +window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", event => { + const newTheme = event.matches ? "dark" : "light"; + setPreferredTheme(newTheme); +}); +document.addEventListener("DOMContentLoaded", event => { + const themeToggleButton = document.getElementById("themeToggleButton"); + themeToggleButton.onclick = clickEvent => { + const currentTheme = getPreferredTheme(); + const idx = THEMES.indexOf(currentTheme); + const nextIdx = idx === THEMES.length - 1 ? 0 : idx + 1; + setPreferredTheme(THEMES[nextIdx]); + }; +}); \ No newline at end of file diff --git a/scripts/themes.min.js b/scripts/themes.min.js new file mode 100644 index 0000000..9c20a60 --- /dev/null +++ b/scripts/themes.min.js @@ -0,0 +1 @@ +const THEMES=["light","dark"];function getPreferredTheme(){const e=localStorage.getItem("theme");return null!==e&&THEMES.includes(e)?e:window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function setPreferredTheme(e){document.documentElement.className=e,localStorage.setItem("theme",e)}setPreferredTheme(getPreferredTheme()),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",(e=>{setPreferredTheme(e.matches?"dark":"light")})),document.addEventListener("DOMContentLoaded",(e=>{document.getElementById("themeToggleButton").onclick=e=>{const t=getPreferredTheme(),r=THEMES.indexOf(t),d=r===THEMES.length-1?0:r+1;setPreferredTheme(THEMES[d])}})); \ No newline at end of file diff --git a/styles/article.css b/styles/article.css index 3f4433e..73033ca 100644 --- a/styles/article.css +++ b/styles/article.css @@ -1,5 +1,11 @@ article { background-color: var(--background-color-2); + padding: 0.5em 1em; +} + +article h1 { + margin-top: 0; + font-size: xx-large; } figure { diff --git a/styles/style.css b/styles/style.css index 7e1e3c8..7092c7f 100644 --- a/styles/style.css +++ b/styles/style.css @@ -46,7 +46,6 @@ code { background-color: var(--background-color-2); width: 100%; border-collapse: collapse; - border: 1px solid blue; } .stats-table th { @@ -79,3 +78,22 @@ code { .page-header-selected { text-decoration: underline !important; } + +.basic-table { + background-color: var(--background-color-2); + width: 100%; + border-collapse: collapse; +} + +.basic-table th { + text-align: center; + border: 1px solid var(--background-color-3); + padding: 0.5em; +} + +.basic-table td { + font-family: "IBM Plex Sans"; + text-align: start; + border: 1px solid var(--background-color-3); + padding: 0.25em; +} diff --git a/training.html b/training.html index 83b8853..265d687 100644 --- a/training.html +++ b/training.html @@ -6,45 +6,10 @@ - - - - - - + + + diff --git a/upload.sh b/upload.sh index 82452bb..8b3815c 100755 --- a/upload.sh +++ b/upload.sh @@ -3,7 +3,7 @@ # Helper script that copies files to the server. # You need to have authenticated access to the server via SSH to use this. -rsync -rav -e ssh \ +rsync -rav -e ssh --delete \ --exclude .git/ --exclude *.sh --exclude README.md \ ./ \ root@andrewlalis.com:/var/www/andrewlalis.com/html