commit 04c50be3ac40b58d01dc54684fe59bf1cdaaa7d6
parent 75d5ba32dd8d67c2d56c2f88c6f875df974d5315
Author: William Lindholm <william_lindholm@outlook.com>
Date: Mon, 21 Sep 2026 19:23:56 +0200
Added duration calculation
Diffstat:
6 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
@@ -47,6 +47,7 @@ Use this structure:
└── app/
├── main.py
├── Dockerfile
+ ├── requirements.txt
├── index.html
└── style.css
```
diff --git a/app/Dockerfile b/app/Dockerfile
@@ -4,7 +4,8 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
WORKDIR /app
-RUN pip install --no-cache-dir Flask==3.1.2 waitress==3.0.2 \
+COPY requirements.txt ./
+RUN pip install --no-cache-dir -r requirements.txt \
&& useradd --uid 10001 --create-home resume \
&& chown resume:resume /app
diff --git a/app/index.html b/app/index.html
@@ -33,27 +33,27 @@
<h2 id="experience">Work experience</h2>
<article>
<h3>Software developer · Combitech</h3>
- <p class="entry-meta">August 2025 - present</p>
+ <p class="entry-meta">{{ duration("2025-08") }}</p>
<p>Developing software in a security-sensitive environment using Python and C#, alongside hardware-oriented programming in C++.</p>
</article>
<article>
<h3>Software developer (summer position) · Volvo Group</h3>
- <p class="entry-meta">June - August 2025</p>
+ <p class="entry-meta">{{ duration("2025-06", "2025-08") }}</p>
<p>Continued the migration of a legacy system used to control automated guided vehicles (AGVs). Mentored two new summer developers in technologies and working practices including Scrum, test automation, .NET and Git.</p>
</article>
<article>
<h3>Bachelor’s thesis · Combitech</h3>
- <p class="entry-meta">January - June 2025</p>
+ <p class="entry-meta">{{ duration("2025-01", "2025-06") }}</p>
<p>Completed a 30-credit bachelor’s thesis in collaboration with Combitech, applying and evaluating image anomaly detection algorithms for drone imagery of forest environments.</p>
</article>
<article>
<h3>Software developer (summer position) · Volvo Group</h3>
- <p class="entry-meta">June - August 2024</p>
+ <p class="entry-meta">{{ duration("2024-06", "2024-08") }}</p>
<p>Modernized a legacy AGV control system using .NET Blazor, introduced API integration testing, reduced UI test execution time by approximately 55%, and helped establish new GitHub workflows.</p>
</article>
<article>
<h3>Software developer (summer position) · Volvo Group</h3>
- <p class="entry-meta">June - August 2023</p>
+ <p class="entry-meta">{{ duration("2023-06", "2023-08") }}</p>
<p>Modernized a legacy web interface using Blazor, with Azure DevOps and TFVC for organisation and planning. Implemented a visual identity now used in several internal applications.</p>
</article>
</section>
@@ -61,7 +61,7 @@
<section aria-labelledby="education">
<h2 id="education">Education</h2>
<h3>BSc in Computer Science · University of Skövde</h3>
- <p class="entry-meta">August 2022 - June 2025</p>
+ <p class="entry-meta">{{ duration("2022-08", "2025-06") }}</p>
<ul>
<li>Studied abroad at the University of Limerick, Ireland, in autumn 2024.</li>
<li>Served as industry relations representative on the board of SKILLS, the student union section for IT students, organising collaborations with companies.</li>
@@ -79,7 +79,7 @@
<article>
<h3>Anomaly detection for forest monitoring using UAV imagery</h3>
<p>Applied and evaluated image anomaly detection algorithms for drone imagery of forest environments in a bachelor’s thesis carried out with Combitech. <a href="https://urn.kb.se/resolve?urn=urn:nbn:se:his:diva-25550">Read the thesis on DiVA</a>.</p>
- <p class="entry-meta">2025 · Computer vision · Image anomaly detection</p>
+ <p class="entry-meta">Computer vision · Image anomaly detection</p>
</article>
</section>
@@ -89,7 +89,7 @@
<dt>Languages & frameworks</dt>
<dd>Python, .NET, Blazor, Angular, C++</dd>
<dt>Tools & platforms</dt>
- <dd>Git, Docker, Linux</dd>
+ <dd>Git, Docker, Linux, Proxmox</dd>
<dt>Areas & practices</dt>
<dd>Hardware programming, software-defined radio, web development, REST APIs, test automation, integration and UI testing, Scrum</dd>
</dl>
diff --git a/app/main.py b/app/main.py
@@ -1,13 +1,16 @@
"""Serve the résumé document and its stylesheet."""
-from flask import Flask, send_from_directory
+from datetime import date
-app = Flask(__name__, static_folder=None)
+from flask import Flask, render_template, send_from_directory
+from markupsafe import Markup
+
+app = Flask(__name__, static_folder=None, template_folder=".")
@app.get("/")
def resume():
- return send_from_directory(app.root_path, "index.html")
+ return render_template("index.html", duration=duration)
@app.get("/style.css")
@@ -15,6 +18,22 @@ def stylesheet():
return send_from_directory(app.root_path, "style.css")
+def duration(start, end=None):
+ start = date.fromisoformat(f"{start}-01")
+ finish = date.fromisoformat(f"{end}-01") if end else date.today()
+
+ months = (finish.year - start.year) * 12 + finish.month - start.month + 1
+ years, months = divmod(months, 12)
+
+ parts = [
+ f"{years} year{'s' if years != 1 else ''}" if years else "",
+ f"{months} month{'s' if months != 1 else ''}" if months else "",
+ ]
+ length = ", ".join(filter(None, parts))
+
+ return Markup(f'<time datetime="{start:%Y-%m}">{start.year}</time> · {length}')
+
+
if __name__ == "__main__":
from waitress import serve
diff --git a/app/requirements.txt b/app/requirements.txt
@@ -0,0 +1,2 @@
+Flask==3.1.2
+waitress==3.0.2
diff --git a/docker-compose.yml b/docker-compose.yml
@@ -28,3 +28,5 @@ services:
target: /app/style.css
- action: rebuild
path: ./app/Dockerfile
+ - action: rebuild
+ path: ./app/requirements.txt