<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Ross Kelso</title>
    <subtitle>Notes and things I collect as I tinker.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://www.rosskelso.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://www.rosskelso.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-02-14T00:00:00+00:00</updated>
    <id>https://www.rosskelso.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Downloads</title>
        <published>2025-02-14T00:00:00+00:00</published>
        <updated>2025-02-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.rosskelso.com/downloads/"/>
        <id>https://www.rosskelso.com/downloads/</id>
        
        <content type="html" xml:base="https://www.rosskelso.com/downloads/">&lt;p&gt;A few files worth keeping around.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cv&quot;&gt;CV&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;files&#x2F;cv.pdf&quot;&gt;CV (PDF)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;university-reports&quot;&gt;University Reports&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;files&#x2F;university-reports&#x2F;computer-vision-in-cue-sports.pdf&quot;&gt;Computer Vision in Cue Sports (PDF)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;files&#x2F;university-reports&#x2F;synthetic-gps-traces-for-privacy-protection.pdf&quot;&gt;Synthetic GPS Traces for Privacy Protection (PDF)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;games&quot;&gt;Games&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;files&#x2F;gmtk-2025&#x2F;Archive.zip&quot;&gt;GMTK Game Jam 2025 (ZIP)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Starfinder 2e - Star Ship Encounter Sub-system</title>
        <published>2025-02-14T00:00:00+00:00</published>
        <updated>2025-02-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.rosskelso.com/starfinder/starship-encounter/"/>
        <id>https://www.rosskelso.com/starfinder/starship-encounter/</id>
        
        <content type="html" xml:base="https://www.rosskelso.com/starfinder/starship-encounter/">&lt;h1 id=&quot;starfinder-2e-star-ship-encounter-sub-system&quot;&gt;Starfinder 2e - Star Ship Encounter Sub-system&lt;&#x2F;h1&gt;
&lt;p&gt;This is a sub-system for running starship combat using player led ability checks in Starfinder 2e. By &#x27;player led&#x27; I mean all checks will be rolled by the players and they make all the decisions.&lt;&#x2F;p&gt;
&lt;p&gt;Broadly this sub-system codifies specific skill checks and their outcomes for starship based encounters. This allows everyone to have shared expectations. There is no tactical positioning, instead a bonus&#x2F;penalty called &#x27;encounter advantage&#x27; is used to track which side has the upper hand moment to moment.&lt;&#x2F;p&gt;
&lt;p&gt;This sub-system is very loose and the GM will often have to make a call on what a DC should be or the outcome of a check.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;narrative-explanation&quot;&gt;Narrative Explanation&lt;&#x2F;h2&gt;
&lt;p&gt;Here is a narrative explanation of each starship system which informs the design of the skill checks.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Helm&lt;&#x2F;strong&gt;: The pilot&#x27;s primary responsibility is maneuvering the ship to avoid incoming weapons fire, their secondary responsibility is to out manuever the enemy ship(s) in order to get the upper hand.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Weapons&lt;&#x2F;strong&gt;: The gunners&#x27; primary responsibility is to destroy the enemy vessels, they can also lay down covering fire to try to gain the upper hand.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Astro-navigation&lt;&#x2F;strong&gt;: In order to go into FTL and flee an encounter you must plot a course. Typically 3 astro-navigation successes are required to plot a course. It is possible for the enemy to hack into your systems and copy your plotted course (or vice-versa). Each course is from a specific origin to a specific destination, if the origin or destination changes you must plot a new course. Once you have computed a course you may jump whenever you like as a free action.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Shields&lt;&#x2F;strong&gt;: The shields are used to deflect incoming weapons fire. Shields on a star ship have a number of layers each of which can take 1 hit. Engineers maintain the shields and recharge them to protect the ship. If the engineers critically succeed they can recharge the shields by 2 layers and up to 1 layer better than the typical maximum.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Scanners&lt;&#x2F;strong&gt;: The scanners are used to learn about the enemy vessels&#x27; capabilities and whether they are attempting to scan or hack you.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Escape Pods&lt;&#x2F;strong&gt;: the escape pods are an emergency escape mechanism allowing the player characters to survive their ship being destroyed. If you you eject you escape pods while surrounded by enemy combatants chances are you are going to be captured.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;encounter-advantage&quot;&gt;Encounter Advantage&lt;&#x2F;h2&gt;
&lt;p&gt;During a starship combat encounter keep track of the current &#x27;encounter advantage&#x27; this is an untyped bonus&#x2F;penalty the players can add to all of their checks in the encounter. This is intended to represent who has the upper hand in the encounter. Laying down covering fire, intimidating the enemy or maneuvering to a better position may increase the player&#x27;s encounter advantage.&lt;&#x2F;p&gt;
&lt;p&gt;Encounter advantage can be from +3 to -3 and it&#x27;s initial value depends on how the encounter starts. If the players ambush their enemy it may start at +2. If the players are out gunned it may start at -1.&lt;&#x2F;p&gt;
&lt;p&gt;Before a player makes a check they may choose to forgo one degree of success (i.e. a crit success is a success, a success is a failure etc.) in order to gain one encounter advantage on what would have been a success. They must be able to describe how the action they want to take hinders their enemy. E.g. &lt;strong&gt;Attack&lt;&#x2F;strong&gt; compared to &lt;strong&gt;Covering Fire&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A player may also choose to make a check solely to increase encounter advantage (which they must justify), on a success they increase encounter advantage by 1, on a crit success they increase encounter advantage by 2.&lt;&#x2F;p&gt;
&lt;p&gt;This concept of encounter advantage can also be applied to other social and skill encounters.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-players-ship&quot;&gt;The Players&#x27; Ship&lt;&#x2F;h2&gt;
&lt;p&gt;The recommended player ship has 3 hit points, 1 shield layer (2 on a crit) 2 gun turrets and a 3 point FTL system (it takes successes to jump).&lt;&#x2F;p&gt;
&lt;p&gt;When the players are hit (due to a failed evasion check) they first lose a shield points and then lose a hull points. They can regenerate their shields by succeeding on a crafting&#x2F;engineering lore check against their enemy&#x27;s DC. Hull points can only be regenerated by making repairs at a port.&lt;&#x2F;p&gt;
&lt;p&gt;The players can jump into FTL and escape the fight if they get 3 successes on astro-navigation checks.&lt;&#x2F;p&gt;
&lt;p&gt;Only 1 player can make piloting checks in a round. Only 2 players may make attack checks in a single round.&lt;&#x2F;p&gt;
&lt;p&gt;The player ship is equipped with escape pods which they can use to abandon ship in an emergency.&lt;&#x2F;p&gt;
&lt;p&gt;This can grow and change throughout the course of the campaign.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;encounter-difficulty&quot;&gt;Encounter Difficulty&lt;&#x2F;h2&gt;
&lt;p&gt;Throughout the difficulty of checks is set using the level of the enemy threat. Use a DC based on an appropriate level for the enemy. For appropriate DCs see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;2e.aonprd.com&#x2F;Rules.aspx?ID=2629&quot;&gt;Level-Based DCs&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;2e.aonprd.com&#x2F;Rules.aspx?ID=2874&quot;&gt;Building Creatures&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If there are multiple enemy ships this is modelled by a higher DC that goes down as these enemies are defeated. See &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;2e.aonprd.com&#x2F;Rules.aspx?ID=2630&quot;&gt;Adjusting Difficulty&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Each enemy ship should have a level (to base DCs on) and a number of hit points they can take before being destroyed. The GM should also decide which &#x27;actions&#x27; an enemy vessel will take each round. For a simple encounter this should be gunnery (i.e. shoot the players).&lt;&#x2F;p&gt;
&lt;p&gt;More complex encounters may have the enemy have regenerating shields, scan the players to gain encounter advantage or have more complex weapon hit effects.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;standard-checks&quot;&gt;Standard Checks&lt;&#x2F;h2&gt;
&lt;p&gt;During a round the players can make any check they can justify. However these checks are always or often available:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Maneuver&lt;&#x2F;strong&gt;: make a piloting check against the enemy attack DC to gain encounter advantage
&lt;ul&gt;
&lt;li&gt;Critical success: gain 2 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Success: gain 1 encounter advantage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Attack&lt;&#x2F;strong&gt;: make a gunnery check (simple weapons bonus + dex) against the enemy AC
&lt;ul&gt;
&lt;li&gt;Critical success: the enemy takes 2 damage&lt;&#x2F;li&gt;
&lt;li&gt;Success: the enemy takes 1 damage&lt;&#x2F;li&gt;
&lt;li&gt;Critical failure: the enemy is free to maneuver, lose 1 encounter advantage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Covering Fire&lt;&#x2F;strong&gt;: make a gunnery check (simple weapons bonus + dex) against the enemy piloting DC
&lt;ul&gt;
&lt;li&gt;Critical success: the enemy takes 1 damage and you gain 1 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Success: you gain 1 encounter advantage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Astro-Navigate&lt;&#x2F;strong&gt;: make a computers&#x2F;drift lore check against the enemy&#x27;s DC to attempt to charge the FTL drive, you must state your destination (choosing a new destination resets your FTL to 0 charges). Once you have computed a course (you have 3 charges) you may jump whenever you like as a free action.
&lt;ul&gt;
&lt;li&gt;Critical success: the FTL drive gains 2 charges&lt;&#x2F;li&gt;
&lt;li&gt;Success: the FTL drive gains 1 charge&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Risky Astro-Navigation&lt;&#x2F;strong&gt;: make a computers&#x2F;drift lore check against the enemy&#x27;s DC to attempt to charge the FTL drive, you will jump to a random point in space (GM&#x27;s choice)
&lt;ul&gt;
&lt;li&gt;Critical success: the FTL drive gains 3 charges, you may immediately jump&lt;&#x2F;li&gt;
&lt;li&gt;Success: the FTL drive gains 2 charges&lt;&#x2F;li&gt;
&lt;li&gt;Critical failure: you gain no FTL charges, any existing course plotted is now to a random location (i.e. you ust start over or continue to use &lt;strong&gt;Risky Astro-Navigation&lt;&#x2F;strong&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Regenerate Shields&lt;&#x2F;strong&gt;: make crafting or engineering lore against the enemy&#x27;s DC to attempt to recharge the shields. Shields cannot be charged beyond their maximum (recommended 1) unless on a critical success where they overcharge to 1 extra point
&lt;ul&gt;
&lt;li&gt;Critical success: the shields gain 2 charges&lt;&#x2F;li&gt;
&lt;li&gt;Success: the shields gain 1 charge&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Communicate&lt;&#x2F;strong&gt;: use social skills to intimidate, deceive or placate the enemy
&lt;ul&gt;
&lt;li&gt;Critical success: gain 2 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Success: gain 1 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Critical failure: lose one encounter advantage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Identify Weaknesses&lt;&#x2F;strong&gt;: scan the enemy ship for weaknesses, make a perception check against the enemy&#x27;s DC to gain encounter advantage
&lt;ul&gt;
&lt;li&gt;Critical success: gain 2 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Success: gain 1 encounter advantage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Scan&lt;&#x2F;strong&gt; &lt;code&gt;secret&lt;&#x2F;code&gt;: make a perception check against the enemy&#x27;s deception DC to identify strategic information
&lt;ul&gt;
&lt;li&gt;Critical success: learn the player&#x27;s choice of information and it&#x27;s matching maximum&#x2F;current value.&lt;&#x2F;li&gt;
&lt;li&gt;Success: learn 1 of the following (player&#x27;s choice), if there is nothing to learn gain 1 encounter advantage
&lt;ul&gt;
&lt;li&gt;enemy current hit points&lt;&#x2F;li&gt;
&lt;li&gt;enemy maximum hit points&lt;&#x2F;li&gt;
&lt;li&gt;enemy current shields&lt;&#x2F;li&gt;
&lt;li&gt;enemy maximum shields&lt;&#x2F;li&gt;
&lt;li&gt;enemy current FTL charge&lt;&#x2F;li&gt;
&lt;li&gt;enemy FTL maximum charge&lt;&#x2F;li&gt;
&lt;li&gt;whether the enemy is attempting to scan or hack the player ship and the obfuscate or cover tracks action should be taken&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Critical failure: learn incorrect information&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Pursue&lt;&#x2F;strong&gt; &lt;code&gt;secret&lt;&#x2F;code&gt;: make a computers or thievery check against the enemy&#x27;s deception DC to attempt to follow them through FTL
&lt;ul&gt;
&lt;li&gt;Critical success: your FTL system is set to the same level as the enemy&#x27;s on the same course&lt;&#x2F;li&gt;
&lt;li&gt;Success: you learn where the enemy is attempting to go (i.e. you can now manually astro-navigate to pursue)&lt;&#x2F;li&gt;
&lt;li&gt;Critical failure: the enemy deceives you, you learn a false destination&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Hack&lt;&#x2F;strong&gt;: make a computers or thievery check to attempt to hack the enemy&#x27;s systems
&lt;ul&gt;
&lt;li&gt;Critical success: gain 2 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Success: gain 1 encounter advantage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Abandon Ship&lt;&#x2F;strong&gt;: make a reflex saving throw against the enemy&#x27;s attack DC to make it to escape pods before the ship explodes (automatic success if the ship is not about to be destroyed)
&lt;ul&gt;
&lt;li&gt;Critical success: the player character reaches an escape pod and survives, they may save another character&lt;&#x2F;li&gt;
&lt;li&gt;Success: the player character reaches an escape pod and survives&lt;&#x2F;li&gt;
&lt;li&gt;Failure: the player character dies (unless saved)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;example-enemy-actions&quot;&gt;Example Enemy &#x27;Actions&#x27;&lt;&#x2F;h2&gt;
&lt;p&gt;Players are always the active participant so these are phrased as actions the players can take to counter-act the enemy acting.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Evade&lt;&#x2F;strong&gt;: make a piloting check to avoid the enemy weapons fire
&lt;ul&gt;
&lt;li&gt;Critical success: take no damage and gain 1 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Success: take no damage&lt;&#x2F;li&gt;
&lt;li&gt;Failure: take 1 damage (first to shields then to hull) or lose 1 encounter advantage (depending on whether you where evading &lt;strong&gt;Covering Fire&lt;&#x2F;strong&gt; or &lt;strong&gt;Attack&lt;&#x2F;strong&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Critical failure: take 2 damage (first to shields then to hull) or take 1 damage and lose 1 encounter advantage (depending on whether you where evading &lt;strong&gt;Covering Fire&lt;&#x2F;strong&gt; or &lt;strong&gt;Attack&lt;&#x2F;strong&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Obfuscate&lt;&#x2F;strong&gt;: make a stealth or deception check against the enemy&#x27;s DC to hide strategic information from enemy scans (the players may take this action even if the enemy ship is not scanning them, in which case there is no failure effects and any success effect applies the next time the enemy scans)
&lt;ul&gt;
&lt;li&gt;Critical success: gain 1 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Success: no effect (prevent enemy scan)&lt;&#x2F;li&gt;
&lt;li&gt;Failure: lose 1 encounter advantage&lt;&#x2F;li&gt;
&lt;li&gt;Critical failure: lose 2 encounter advantage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Cover Tracks&lt;&#x2F;strong&gt;: (trigger: the player ship is about to jump, this check must be made by someone who has not taken their turn this round) make a computers or deception check against the enemy&#x27;s DC to prevent them pursuing you through FTL
&lt;ul&gt;
&lt;li&gt;Critical success: the enemy attempts to pursue but jumps to a random location (or a location of your choosing if you have plotted an additional fake course requiring 3 successful astro-navigation checks)&lt;&#x2F;li&gt;
&lt;li&gt;Success: enemy is prevented from pursuing&lt;&#x2F;li&gt;
&lt;li&gt;Failure: enemy copies your astro-navigation calculations and can pursue you through your FTL jump. They are delayed by 1 round.&lt;&#x2F;li&gt;
&lt;li&gt;Critical failure: as with failure but with no delay&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Auto-success &#x27;actions&#x27;. Some enemy abilities make more sense as automatic effects that the players need to keep on top of. These can occur at the end of a round.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Regenerating Shields&lt;&#x2F;strong&gt;: enemy shields regenerate back to 1 point every round (or every other round). Essentially players must hit twice per round to be effective&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;FTL Jammer&lt;&#x2F;strong&gt;: the players lose 1 point of FTL charge every round (or every other round).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Astro-Navigate&lt;&#x2F;strong&gt;: charge FTL every round and attempt to flee&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;!-- 
Weapon ideas

- Clamping weapons to prevent the player ship from moving (roid removers)
- 

 --&gt;
&lt;h2 id=&quot;structure-of-a-round&quot;&gt;Structure of a Round&lt;&#x2F;h2&gt;
&lt;p&gt;Starship combat typically starts with social challenges, if these challenges go well combat may be avoided entirely. If either side starts to take offensive action I recommend structuring checks in rounds.&lt;&#x2F;p&gt;
&lt;p&gt;Each round the GM announces checks the players must make in response to enemy actions (if they choose not to then they critically fail). Each player makes a skill check, either one the GM called for, a standard one or something they suggest (if it can be justified). They may also try to use any abilities or spells they have if they can justify why they work in the scenario. The players may go in any order.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;destruction&quot;&gt;Destruction&lt;&#x2F;h2&gt;
&lt;p&gt;If the players ship reaches 0 hit points it and its contents are destroyed. The players must attempt to &lt;strong&gt;Abandon Ship&lt;&#x2F;strong&gt; or be killed.&lt;&#x2F;p&gt;
&lt;p&gt;A player may expend all of their hero points (at least 1) to survive the ships destruction on 0HP but stable and adrift in space.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>CV</title>
        <published>2025-02-13T00:00:00+00:00</published>
        <updated>2025-02-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.rosskelso.com/cv/"/>
        <id>https://www.rosskelso.com/cv/</id>
        
        <content type="html" xml:base="https://www.rosskelso.com/cv/">&lt;h2&gt;Ross Kelso &amp;nbsp; &lt;a class=&quot;fa fa-github&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RossRKK&quot;&gt;&lt;&#x2F;a&gt;  &lt;a class=&quot;fa fa-linkedin&quot; href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;ross-kelso&#x2F;&quot;&gt;&lt;&#x2F;a&gt;&lt;a class=&quot;fa fa-download&quot; href=&quot;&#x2F;files&#x2F;cv.pdf&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;mailto:ross@rosskelso.com&quot;&gt;ross@rosskelso.com&lt;&#x2F;a&gt; Edinburgh, Scotland&lt;&#x2F;p&gt;
&lt;p&gt;Software developer with 5 years&#x27; experience in full-stack development and a first class MSci in Computer Science from St Andrews.&lt;br&#x2F;&gt;
Specialized in rapid development of data analysis and visualisation systems using &lt;code&gt;c#&lt;&#x2F;code&gt;, &lt;code&gt;python&lt;&#x2F;code&gt;, and &lt;code&gt;javascript&lt;&#x2F;code&gt;, with a background in machine learning, computer vision, and industrial software.&lt;br&#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3&gt;Technical Skills&lt;&#x2F;h3&gt;
&lt;p&gt;Languages &amp;amp; Frameworks: &lt;code&gt;c#&lt;&#x2F;code&gt;, &lt;code&gt;python&lt;&#x2F;code&gt;, &lt;code&gt;javascript&lt;&#x2F;code&gt;, &lt;code&gt;typescript&lt;&#x2F;code&gt;, &lt;code&gt;.net&lt;&#x2F;code&gt;, &lt;code&gt;angular&lt;&#x2F;code&gt;, &lt;code&gt;react&lt;&#x2F;code&gt;, &lt;code&gt;sql&lt;&#x2F;code&gt;, &lt;code&gt;rust&lt;&#x2F;code&gt;&lt;br&#x2F;&gt;
Technologies: &lt;code&gt;elasticsearch&lt;&#x2F;code&gt;, &lt;code&gt;git&lt;&#x2F;code&gt;, &lt;code&gt;azure&lt;&#x2F;code&gt;, &lt;code&gt;aws&lt;&#x2F;code&gt;, &lt;code&gt;docker&lt;&#x2F;code&gt;, &lt;code&gt;kubernetes&lt;&#x2F;code&gt;, &lt;code&gt;tensorflow&lt;&#x2F;code&gt;, &lt;code&gt;nodejs&lt;&#x2F;code&gt;, &lt;code&gt;windows&lt;&#x2F;code&gt;, &lt;code&gt;linux&lt;&#x2F;code&gt;, &lt;code&gt;ci&#x2F;cd&lt;&#x2F;code&gt;&lt;br&#x2F;&gt;
Concepts: Machine Learning, Data Engineering, Cloud Architecture, Computer Vision&lt;&#x2F;p&gt;
&lt;h2&gt;Work Experience&lt;&#x2F;h2&gt;
&lt;h3&gt;Cintra HR &amp; Payroll - Software Developer (since June 2025)&lt;&#x2F;h3&gt;
Creating HR &amp; payroll management software. 
&lt;p&gt;&lt;code&gt;c#&lt;&#x2F;code&gt; &lt;code&gt;typescript&lt;&#x2F;code&gt; &lt;code&gt;angular&lt;&#x2F;code&gt; &lt;code&gt;ci&#x2F;cd&lt;&#x2F;code&gt; &lt;code&gt;aws&lt;&#x2F;code&gt; &lt;code&gt;docker&lt;&#x2F;code&gt; &lt;code&gt;terraform&lt;&#x2F;code&gt; &lt;code&gt;python&lt;&#x2F;code&gt; &lt;code&gt;mcp&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Delivered new cloud-based pensions UI with Angular and .NET ahead of schedule, focusing on UX improvements, validation logic, and data integrity when integrating with legacy database tables.&lt;&#x2F;li&gt;
&lt;li&gt;Identified and fixed critical validation middleware bug where premature type conversion caused required field and date validation to silently fail. Modified application-wide middleware to validate against loosely-typed request bodies, preventing entire classes of validation errors.&lt;&#x2F;li&gt;
&lt;li&gt;Designed and implemented load testing strategy using k6, then diagnosed and resolved database deadlocks caused by inefficient triggers. Refactored triggers by unrolling dynamic SQL and adding strategic indices, achieving 5x throughput improvement.&lt;&#x2F;li&gt;
&lt;li&gt;Work full-stack with emphasis on backend development in a cross-functional team of 4 developers, 1 PM, and 2 designers.&lt;&#x2F;li&gt;
&lt;li&gt;Developed a Model Context Protocol (MCP) server enabling AI coding assistants to search and retrieve relevant code across full-stack codebases and understand complex database relatonships and constraints, improving context accuracy for LLM-assisted development.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Intelligent Plant - Software Developer (2021-2025), Intern (University Holidays 2017-2021)&lt;&#x2F;h3&gt;
Creating data storage, analysis and visualisation solutions for the energy industry.
&lt;p&gt;Lead developer for the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;appstore.intelligentplant.com&#x2F;Home&#x2F;AppProfile?appId=40d7a49722f84be4986318bb5cc98cf3&quot;&gt;Industrial App Store API Python Client&lt;&#x2F;a&gt; &lt;code&gt;python&lt;&#x2F;code&gt; &lt;code&gt;pandas&lt;&#x2F;code&gt; &lt;code&gt;django&lt;&#x2F;code&gt; &lt;code&gt;tensorflow&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Designed and implemented a Python SDK to simplify OAuth authentication and data access for the Industrial App Store API, automatically converting API responses to pandas DataFrames for data science workflows.&lt;&#x2F;li&gt;
&lt;li&gt;Set up and maintained JupyterHub instance in Kubernetes for internal and client data science work.&lt;&#x2F;li&gt;
&lt;li&gt;Created demonstration notebooks showing time series prediction with TensorFlow, used by industrial clients and university research partners.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lead developer for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;appstore.intelligentplant.com&#x2F;Home&#x2F;AppProfile?appId=f3175c7a68774ef1ae96de5e8c16900e&quot;&gt;Sequence of Events Explorer&lt;&#x2F;a&gt; &lt;code&gt;c#&lt;&#x2F;code&gt; &lt;code&gt;javascript&lt;&#x2F;code&gt; &lt;code&gt;html&lt;&#x2F;code&gt; &lt;code&gt;css&lt;&#x2F;code&gt; &lt;code&gt;elasticsearch&lt;&#x2F;code&gt; &lt;code&gt;ci&lt;&#x2F;code&gt; &lt;code&gt;azure&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Built application from MVP to production as sole developer, becoming the company&#x27;s 3rd largest product and sold to every client with alarm analysis capabilities.&lt;&#x2F;li&gt;
&lt;li&gt;Designed intuitive drag-and-drop query interface allowing users to build complex filters for industrial alarm event logs, dramatically reducing noise in sequence-of-events analysis.&lt;&#x2F;li&gt;
&lt;li&gt;Mentored junior developers through code reviews and maintained code quality standards as project technical lead.&lt;&#x2F;li&gt;
&lt;li&gt;Developed custom domain-specific query language with parser to translate user queries into Elasticsearch queries.&lt;&#x2F;li&gt;
&lt;li&gt;Architected frontend using clear MVC pattern with state-driven DOM updates, minimizing state synchronization issues and contributing to application stability.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Developer for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;appstore.intelligentplant.com&#x2F;Home&#x2F;AppProfile?appId=d2322b59ff334c97b49760e40000d28e&quot;&gt;Alarm Analysis&lt;&#x2F;a&gt; and Intelligent Plant Historian  &lt;code&gt;c#&lt;&#x2F;code&gt; &lt;code&gt;elasticsearch&lt;&#x2F;code&gt; &lt;code&gt;machine learning&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Created novel Hidden Markov Model approach to parse non-standard semi-structured alarm data from industrial sources with inconsistent formats (interleaved JSON, CSV, and fixed-width tables).&lt;&#x2F;li&gt;
&lt;li&gt;Built interactive web interface allowing domain experts to iteratively refine the model&#x27;s field boundary detection and labelling.&lt;&#x2F;li&gt;
&lt;li&gt;Upgraded Elasticsearch from version 2 to 7, doubling query throughput at 1-second latency and achieving 10x improvement at 5-second latency through index optimization and breaking change migrations.&lt;&#x2F;li&gt;
&lt;li&gt;Worked directly with clients for on-site installations and support.&lt;&#x2F;li&gt;
&lt;li&gt;Developed and maintained a backend for performing complex data aggregations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Developer for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;appstore.intelligentplant.com&#x2F;Home&#x2F;AppProfile?appId=2a59ca294ce2464cb14694b682294de5&quot;&gt;Gestalt (PnID &amp;amp; Trend)&lt;&#x2F;a&gt; &lt;code&gt;c#&lt;&#x2F;code&gt; &lt;code&gt;sql&lt;&#x2F;code&gt; &lt;code&gt;javascript&lt;&#x2F;code&gt; &lt;code&gt;azure&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Led architectural separation of monolithic API into distinct application and data components, enabling independent deployment cycles and reducing downtime.&lt;&#x2F;li&gt;
&lt;li&gt;Replaced file system storage with SQL database implementing hierarchical folder structure through relational model, enabling Azure App Service deployment with blue-green deployment strategy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Experimental projects involving the application of AI and large language models to our software &lt;code&gt;python&lt;&#x2F;code&gt; &lt;code&gt;docker&lt;&#x2F;code&gt; &lt;code&gt;tensorflow&lt;&#x2F;code&gt; &lt;code&gt;ollama&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Deployed internal AI inference APIs for proposal writing and proof-of-concept industrial automation applications.&lt;&#x2F;li&gt;
&lt;li&gt;Developed locally-hosted coding assistants to maintain IP security while exploring LLM integration opportunities.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lead developer for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;appstore.intelligentplant.com&#x2F;Home&#x2F;AppProfile?appId=064fa04abe624c70a982e377a6c72850&quot;&gt;Power BI Industrial Connector&lt;&#x2F;a&gt; &lt;code&gt;c#&lt;&#x2F;code&gt; &lt;code&gt;power query m&lt;&#x2F;code&gt; &lt;code&gt;react&lt;&#x2F;code&gt; &lt;code&gt;yarp&lt;&#x2F;code&gt; &lt;code&gt;azure&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Replaced custom endpoint controllers with YARP proxy implementing licensing middleware.&lt;&#x2F;li&gt;
&lt;li&gt;Maintained 100% backwards compatibility while fixing incorrectly named legacy functions.&lt;&#x2F;li&gt;
&lt;li&gt;Re-architected connector removing reverse proxy data transformation dependency, enabling direct connection to on-premises installations and simplifying NTLM authentication.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Optimized the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;appstore.intelligentplant.com&#x2F;Home&#x2F;AppProfile?appId=60e8ea6fc28a4abb902ce0b7b03b215b&quot;&gt;Excel Data Query Add-in&lt;&#x2F;a&gt;, reducing query time from minutes to seconds. &lt;code&gt;c#&lt;&#x2F;code&gt; &lt;code&gt;excel-dna&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Implemented async request processing to prevent UI blocking during data queries.&lt;&#x2F;li&gt;
&lt;li&gt;Designed intelligent request batching system bundling compatible queries reducing hundreds of individual requests to single batched calls.&lt;&#x2F;li&gt;
&lt;li&gt;Reduced typical query completion from 30+ seconds to near-instantaneous with responsive UI.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2&gt;Education&lt;&#x2F;h2&gt;
&lt;h3&gt;University of St Andrews - Computer Science MSci First Class (2016-2021)&lt;&#x2F;h3&gt;
&lt;p&gt;Deans&#x27; List, for academic excellence 2017&#x2F;18, 2018&#x2F;19, 2019&#x2F;20&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Masters Thesis&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;files&#x2F;university-reports&#x2F;synthetic-gps-traces-for-privacy-protection.pdf&quot;&gt;Synthetic GPS Traces for Privacy Protection&lt;&#x2F;a&gt;
&lt;code&gt;python&lt;&#x2F;code&gt; &lt;code&gt;tensorflow&lt;&#x2F;code&gt; &lt;code&gt;pandas&lt;&#x2F;code&gt; &lt;code&gt;numpy&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Applied Markov Models and Convolutional Generative Adversarial Networks to synthesize realistic GPS movement data indistinguishable from real traces while preserving statistical properties like speed and path-following behavior.&lt;&#x2F;li&gt;
&lt;li&gt;Evaluated model accuracy and effectiveness in preserving statistical properties of real-world movement data.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Senior Honours Project&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;files&#x2F;university-reports&#x2F;computer-vision-in-cue-sports.pdf&quot;&gt;Computer Vision in Cue Sports&lt;&#x2F;a&gt;
&lt;code&gt;opencv&lt;&#x2F;code&gt; &lt;code&gt;python&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Designed computer vision system for unconstrained pool table analysis, handling arbitrary camera angles and partial occlusion without the need for calibration markers.&lt;&#x2F;li&gt;
&lt;li&gt;Implemented perspective transformation and object detection achieving millimeter-scale ball position accuracy,&lt;&#x2F;li&gt;
&lt;li&gt;Developed snooker detection algorithm and generated 3D table models enabling arbitrary viewpoint rendering.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Junior Honours Project&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Group software engineering project to create an encrypted wireless network of embedded devices
&lt;code&gt;c&lt;&#x2F;code&gt; &lt;code&gt;nodejs&lt;&#x2F;code&gt; &lt;code&gt;python&lt;&#x2F;code&gt; &lt;code&gt;git&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Led protocol design team coordinating inter-group standards for encrypted mesh network communication on Micro:bit devices.&lt;&#x2F;li&gt;
&lt;li&gt;Implemented RSA encryption from scratch in C, Python, and JavaScript to enable secure interoperability across devices, gateways, and web services.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3&gt;Side Projects&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Game Design&lt;&#x2F;strong&gt;
&lt;code&gt;rust&lt;&#x2F;code&gt; &lt;code&gt;bevy&lt;&#x2F;code&gt; &lt;code&gt;godot&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Competed in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rossrkk.itch.io&#x2F;red-or-black&quot;&gt;GMTK Game Jam 2025&lt;&#x2F;a&gt; using &lt;code&gt;godot&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Implemented a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RossRKK&#x2F;tetris&quot;&gt;Tetris clone&lt;&#x2F;a&gt; in &lt;code&gt;rust&lt;&#x2F;code&gt; using &lt;code&gt;SDL2&lt;&#x2F;code&gt; including a simple software synthesizer to play the classic music.&lt;&#x2F;p&gt;
&lt;p&gt;Implemented a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RossRKK&#x2F;bevy-bird&quot;&gt;Flappy Bird clone&lt;&#x2F;a&gt; in &lt;code&gt;rust&lt;&#x2F;code&gt; using &lt;code&gt;bevy&lt;&#x2F;code&gt; game engine.&lt;&#x2F;p&gt;
&lt;!-- **Other Modules**

* Algorithms and data structures `java`
* Artificial intelligence and machine learning `python` `java`
* Information Visualisation `python`
* Operating systems `c`
* Advanced programming projects `haskell` `python` --&gt;
&lt;!-- **Internet of Things**
`c` `python` `nodejs`
 * Created a network of micro-controllers that recorded temperature data around my flat to an Intelligent Plant Historian
 * Created a website showing whether communal items in my flat had run out, updated by an ESP-32 stuck to the fridge. --&gt;
&lt;!-- **Starfinder&#x2F;D&amp;D**
Game Master (since 2024)
* Coordinated and led a group of players through an immersive and engaging story, ensuring a cohesive and enjoyable experience for all participants.
* Designed challenging scenarios that required players to think critically and strategically to overcome.
* Improvised and responded to unexpected player choices or rule interpretations, using creative problem-solving and diplomacy to resolve conflicts and maintain a positive game environment. --&gt;
&lt;!-- **Pool Society**
Vice-president, Social Rep, Publicity and Fundraising Rep (2017-2021)
* Managed day-to-day operations, including equipment maintenance, weekly sessions and recruiting new members.
* Promoted the society through social media channels and organized fundraisers, including live streams of semesterly Finals Day events.
* Represented the university at several pool competitions, including 5 BUCS tournaments. --&gt;
&lt;!-- **Utilities Mod for Minecraft (2013)**
 * Taught myself how to develop a Minecraft mod using `java` and forge resulting in over 700 downloads --&gt;
&lt;!-- 
**The &#x27;Walk&#x27; App**
`swift`
 * Created an app that interfaces with the Apple health app to track walking progress compared to a pre-set rate
 * This resulted in me walking 3,000km in 2024


**Games Room**
`nodejs` `python` `javascript` `html` `css`
* Developed a framework for creating online group games, such as Killer, using a variety of technologies.
* Collaborated with team members to design and implement the framework.

**Killer Web App**
Developer (2018) `nodejs` `html` `javascript` `css`
* Created a web app to simulate the cards used in the pool game &quot;Killer&quot; using client-side JavaScript.
* Developed a new version using Bootstrap, Node.js, WebSockets, and Heroku, allowing for multi-device spectating and control.

**Utilities Mod for Minecraft**
 * Developed a minecraft mod using Java and forge resulting in over 700 downloads
 * Revisited the mod and rebuilt the core features using Fabric

 --&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Sims 3 on Deck</title>
        <published>2025-02-13T00:00:00+00:00</published>
        <updated>2025-02-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.rosskelso.com/guides/sims3/"/>
        <id>https://www.rosskelso.com/guides/sims3/</id>
        
        <summary type="html">&lt;p&gt;How to install the Sims 3 and it&#x27;s expansions on a steam deck from the DVDs using Lutris.&lt;&#x2F;p&gt;</summary>
        
    </entry>
</feed>
