𐑑𐑕

πŸ“ Portfolio 🎢 Music 🎨 Art 🍳 Recipies πŸ“œ Blog

Software Projects

../ software


All of my available software projects can be viewed on GitHub! You can view them on github.com/joshuaspann/

simuLauncher

Remote Control VNC Client for Sim Lab Devices simuLauncher

We were promised a lot of stuff from vendors: remote controlling simulators, single unified experiences, etc. None of them delivered. I sought to fix that, especially when COVID was creeping around. I found that RDP was too limiting for our devices that needed to have the screen unlocked for patient monitors. I also found that VNC was perfect, but too complex for everyday nurses that know nothing about tech. I also discovered that Windows didn't like the fact that I created a Haxe app that ran shell commands to auto-launch said VNC software.

I did what any sane person would do and decided to build my own VNC app. I started in Haxe until I learned that core libraries and functions were nothing more than empty declarations. I then decided to use what I know would work: Java. I took some abandoned VNC client's source code and modified it to work in 2020's Java. I simplified the interface and made it call a server config file for mapping everyday names to device hostnames. I also made it to where it would poll the same server for updates and auto-update if there were any. What was born was a VNC app that acted like a mobile app, but was made so simple that nurses could use it.

Vimulator

The Healthcare Simulator Vimulator

The world of healthcare simulation is rife with the latest craze and full of buzzwords like VR and AR. A big focus has been on creating virtual simulation software. Problem is that nothing seemed to do it right, except for Body Interact. I wanted something that was a mix between that and Laerdal's vSim, something that could interface with anything and was highly configurable.

Enter Vimulator, a really lame name that reminds me of my favorite text editor. It seeks to keep as close of a hands-on approach as possible to simulation. In full 3d, the user can navigate the space and perform basic assessment skills on the virtual patient. The goal of the software is to have easily configurable UD settings allowing quick and dynamic development of home-grown virtual scenarios. Think LLEAP and vSim mixed with the beauty of BodyInteract.

Mihxi

Haxe Tool for Writing MIDI Data

Haxe is great for writing libraries. Why? Because transpiling. Write once in Haxe, transpile to anything, run on every target available. I wanted a flexible solution that allowed me to create a fairly portable app. The app pulls music data from a QBasic/TempleOS string and writes it to a proper MIDI file that can be played, listened to, or used in music software. Haxe provided that solution.

I made an open-source app that writes MIDI data based off of specific objects. The objects represent note data and MIDI info in an understandable and flexible way. Then the data is translated to match the MIDI specification and turns the data to a raw byte stream organized as a MIDI file. The files generated work with Windows Media Player, FLStudio20, and MuseScore3. There are still some bugs and some extra work to make it more customizable and compliant with all of the MIDI specs.

To check out the project, visit https://github.com/JoshuaSpann/mihxi/.

SimMonitor: A Web-Based Patient Monitor

Created to provide a fairly versatile and open-source vital signs monitor that can be used in simulation. It is intended to be customizable, extensible, and cross-platform so it can be utilized in a variety of situations from simulation and training to photography and art.

Due to limitations and costly licenses of simulation vendor software, as well as highly fragmented and platform-locked options, the need arose to have a more flexible solution. The vendor's vitals monitor application was limited in styling and customization. It also was not flexible enough to allow multiple monitor instances (with different target vitals and monitor layouts) be connected to the same simulator, creating duplicates on every connected monitor instance. Freeware options were limited to a small number of platforms and did not provide the freedom to improve and extend the baseline software to meet specific needs (ie, yet another phone app).

This project attempts to allow customization first, with feature-parity after. Created as a web app, it allows full and easy control over vital signs and layouts, also allowing users to extend it with their own custom assets. The goal is to have it draw and animate vital signs and waveforms in an easy, user-defined way.

To check out the project, visit https://github.com/JoshuaSpann/sim-monitor.

LoveSong: A random melody generator inspired by the GodSong utility from TempleOS.

Sometimes a creative person needs a little nudge in the right direction. The goal of the library is to randomly generate music for the user that they can have as a starting point for creating music and melodies.

There is a procedural music generator for TempleOS named GodSong. The user is met with a dialog that allows them to set options like melody complexity, whether the melody will contain rests, and the octave the melody should be on. The next screen has a timer that increments in hexadecimal format. After a certain number of clicks a monophonic melody is generated.

Inspired by the above functionality, LoveSong attempts to go a bit further and create savable data. The melodies can be saved in numeric format, based off of the note number in the western chromatic scale, or in alphabetic format, using the note letters instead. The data will also attempt to be exported to MIDI data that can be used in musical application.

Parameters will also be set controlling the key signature, accidentals, and melody length if the user would like to. Options will also allow the melody generation to follow basic rules and principles of music theory. By creating the library in Haxe, it will make it easier to port it to a variety of software applications, though a bit unoptimized.

To see the latest changes and experiments with the project, you can examine the repo at github.com/JoshuaSpann/love-song.

Charte: The Open-Source EMR-Simulator Web App

Because every other charting system didn't fit my specific needs. Paid ones were locked down, more manual, dated-looking, and offered no freedom or control. Free ones focused on being a comprehensive solution that was too much for basic sim needs. Something simple was needed for simulations; something simple and free that institutions outside of hospitals could afford.

The web app is an attempt to create a basic "flowsheet" view that can be read and temporarily modified from a nurse's perspective. I decided to make it highly flexible and cross-platform as well as work perfectly fine on its own when there is network downtime. A typo made "charte", which can mean "Chart Emulator".

The project is a web-app that is built to run on a local hard disk first, then communicate with a variety of servers to access and update charting data. The system heavily relies on JavaScript and JSON to create a data model and controller. Though JSON would be the preferred format for configuration files and data models, the files are stored as JavaScript files instead of JSON files. This is to allow the app to run on a web browser with no cross-site issues that arise when trying to access files and resources.

The app is intended to run offline and sync with specified servers when online. It will call multile servers to merge various charting data objects so there can be better allocation and sharing of simulated charting data. This also allows integration with other solutions while still allowing full customization.

It's meant for learning usage to help follow and apply the workflow behind common digital charting systems, such as EMRs/EHRs.

To see my latest changes and experiments with the project, you can examine my repo at github.com/joshuaspann/charte.

Qualtrics Asset Usage Form

A simple qualtrics survey extended with custom JavaScript to ease data recording and entry. Default Qualtrics has no way of storing date fields, though you can use the marketplace. If your organization locks down the marketplace, you can't download those nicely over-engineered calendar plugins. We had such a scenario and I got tired of entering manual dates on a phone, especially in a MM/DD/YYYY format with leading 0s. Luckily we had scripting capabilities with our plan.

A default HTML date field was added for optimized date selection via the web browser. Once a date was entered or the field's value changed, the date would be formatted into the requisite format that Qualtrics desires, including the pesky leading 0s. The formatted date would then be pushed to the actual date field, which was hidden until an error occured which would expose all fields. The time of year, Spring Summer or Fall, along with the entered date's year were also needed. A custom dropdown and a few event listeners allowed me to create a string on the change of the dropdown or the date fields. The listener generated a needed string/text that would be put into the actual hidden Qualtrics field.

JOSH: The Java Object Shell

Inspired in part by the original concepts behind Powershell with a bit of TempleOS for good fun. The shell is an attempt to handle Java objects natively instead of piping text back and forth between apps. The name of JOSH is purely coencidental; I'm not that egotistical to name it after me. The name came from the initial project goal, having an operating java shell. I wanted the name to be easy to say and catchy like "bash" and thought up "The Java Operating Shell". I thought of how to compact it down and got "JOSH" as a result.

JOSH is an attempt to make certain features and ideas easier to implement. It focuses on experimenting with new ways to handle data as well as navigation and commands. There is the concept of "nodes", where numbers represent the counted node in the working directory. You can use nodes in interesting ways, though the shell will default to files or folders with numbers in the name if they exist.

The shell attempts to guess the intentions behind commands to shorten them. You enter a string suffixed with a file delimiter and it attempts to change to the directory. You can also enter a node number to imply the same.

If you start a command with a number, it will attempt to iterate the following command that many times. If the number is followed by numbers, then it is assumed to change to those directories. The commands are intended to work as standalone applications or they can be used as intended as a part of JOSH.

To see my latest changes and experiments with the project, you can examine my repo at github.com/joshuaspann/josh.

Taskbar: Added Features

Added functionality to the original Taskbar repo. I noticed that it did not have the ability to customize the 'start menu' icon outside of two embedded images within the app. I added the ability to allow the user to specify if they desired to use a custom image from their phone. If the setting was checked and a file specified, the taskbar would update with the custom image the user chose via a filepicker.

To see my latest changes and experiments with the project, you can examine my fork at github.com/joshuaspann/taskbar.

cklist: A Minimalist Checklist Manager

A simple command-line checklist application that manages lists through files and folders. It is basically a merged reimplementation of common Unix commands like touch, mkdir, ls, and rm -rf. The concept came as a way to reduce keystrokes while managing checklists made from files. The project page is at github.com/joshuaspann/cklist

Raspy LCDriver: Controlling a Character LCD from the Pi

An excercise to get familiar with the Raspberry Pi's GPIO pins on Linux. Inspired by some 8-Bit Guy YouTube videos, I reimplemented David's solution on a RaspberryPi 3 instead of a Commodore64. It started as an 8-bit counter up to 256 values with just LEDs. I added python code to parse a given character to the character code on the LCD. I did a lot of research and created my own circuit to manage and control a large character LCD. After printing out many characters in a row, some tweaks were made to have the LCD print messages.

I then started creating a shell in Python, which would take in keystrokes and parse commands like bash or any other shell. The difference was to have it save each character and send the LCD code to the screen in real time. It was almost complete but was abandoned with an increased workload and wedding planning. It is currently two separate applications that have yet to interface with one another.

timec: A Simple Time Converter

A command-line calculator that converts given times into different formats. It started to simply convert a mm:ss format to a decimal formatting of mm but grew with more needs. I added the ability to make it convert times from 24-hour to 12-hour formatting.

The need also arose to find the time difference between two times in a mm:ss format, so I added that as well. Out of curiosity, as a benchmark to compare multiple languages, I rewrote it in Haxe then in Python to compare how each platform performed. I also looked at compiling it to C++ via Haxe's utilities and Cython. Rewriting it helped me to find areas to improve the software and give me ideas of additional functionality.

The project page is at github.com/joshuaspann/timec

Arch-Linux Node: A Persistent Live USB

A series of steps and commands to make a persistent Arch-Linux install on a USB stick. It is bootable, while files can be accessed by all platforms without the need to boot. It boots on most i386 and amd64 processors in both BIOS and UEFI modes. It originally used a UDF-formatted drive but concerns led me to partition the drive to have a shared partition which improved filesystem resiliency for the OS partiton while keeping the open, cross-platform-compatible idea.

The shorthand notes/instructions can be found at github.com/JoshuaSpann/help/blob/master/linux/portable-arch-usb-install.htm

Simulation Checklist: A Mobile Management App

A quick project to get familiar with the Flutter framework and Dart language. It was intended to display a list of checklists that could be individually viewed and modified. The changes would not be persistant outside of adding/deleting items. Due to personal time constraints and Flutter feeling like Google's take on ReactNative, the project has since been abandoned. It is missing the ability to save or modify checklist items, though it is usable.

Daily Droid: A Smartphone Journaling App

A configurable, multi-activity Android applicatioin that acts as a glorified text editor. It was concieved as a response to my dissatisfaction of having to remember everything and handwrite it at the end of each day. I would lose 2-4 hours of sleep writing in my journal. Diction significantly reduced the time, but it was hard to convert to text accurately and took up significantly more space. Not to mention, trying to search an audio file for something was very impractical (especially if you forgot the date). Typing at the end of the day was better, but everything was just bundled into a large amount of time wasted. It was built due to other text editors being slow, rife with ads, or counterintuitive.

It creates text files named by the timestamp created. It uses quick buttons to navigate and add markdown to the text files. If the user specifies so, the app can also auto-log incoming and outgoing calls as markdown. Users can also persistently change colors of the current text file to one of many preset colors for easier organizing and customization.

I was inspired by the default Memo app on Samsung smartphones, but put off that it exported to PDF. I wanted timestamps, markdown, the ability to navigate the document with a few taps. I had to start from scratch, so I wrote my own. It started as a "Text File Writer" that simply allowed a user to save text files via a single activity. It had the ablity to not only create text files, but add time stamps at the tap of a button.

The need for enhanced navigation caused more buttons to be added, allowing navigation between the beginning and end of a file. I made it autosave as long as characters are added, allowing accidental deletions to be undone. The default scroll behavior was not fluid and did not traverse well, so I reconfigured that. I then added the ability to colorized given text files as a way to visually categorize them. I made it capable of automatically log incoming and outgoing calls by inserting timestamps with the basic call information into the text file. I added the ability to manually and hot-refresh the file to ensure that no up-to-date changes were lost in the background. The app also allows users to adjust settings, such as syntax highlighting for markdown support or the ability to control whether calls are auto-logged.

The project page is at github.com/joshuaspann/daily-droid

LLEAP Patient Info Plugin: An Instructor Application Extension

A simple extension to the LLEAP Instructor App (IA) that allowed the viewing of patient info given in scenario files. It obtains the patient data and display it in the IA interface as a window that can be added/modified. Certain tweaks have to be made to the scenario file with UD variables as the Laerdal SDK does not support all patient info like the patient name, birthday, etc. It also was bundled into a self-extracting executable that would extract a copy of all DLL files and the plugin to the proper Laerdal directories. It was additionally improved to load up pages from the SIMS "charting" system in the default web browser.

Dot QR: An Inkscape Plugin

A customization of the base barcode extension in Inkscape. A checkbox for using dots instead of squares was added to the QR Code GUI's .inx and the rendered QR code would be rendered in a pretty, dotted format too. This reduced manual, time-consuming work to the instant check of a checkbox and click of a button.

You can download a zip file of DotQR here.

Video Text Balancer: A Plugin to Ease Video Editing in Blender

A Blender3D UI customization in Python to help speed up video development. A button was added in the VSE to loop through all selected text objects in the video editor, make them have a minimum specified length, and then space them apart so they do not overlap.

Auto-Flag RMA Opportunity Trigger

Because a workflow didn't allow the Opportunity Stage field to be modified via the workflow. An apex trigger was used instead. The trigger ran on the creation of new records only. If there was a certain country code (US or UK) that was chosen for the record, the Opportunity's Stage would be auto-updated to a custom RMA picklist value. The need was to help expadite the Salesforce proccess of the client and to better match their business process.

RMA Mass Automation Scheduled Apex Job

A massive scheduled Apex class that automated the RMA process daily. Automated emails would be sent 2 days after the owning Case's follow-up date and the final email would vary when it was sent. The final email depended on the RMA type being old process or new process. Checks would be run to determine if the emails, phone tasks, and all other tasks were completed before progressing. The first email would be sent, then if it was a phone task would be assigned to a user. If the (standard process) phone task was assigned and then completed, the RMA would be flagged as charged and a final email would be sent. If the final email was sent, then the case would auto close (if old process) or a task would be assigned to close the owning case (if standard process).

The automated apex emails were also linked to the owning Case's activity history and open activites. This project had a lot of scope creep since its onset, where my company was willing to add changes since the client did not have a standard payment process. It evolved from a simple email and phone?call checker to a data factory that also closed orders and further made the functionality dynamic; requiring multiple records from great grandparent and great great grandchildren objects that were out of the normal Salesforce limits on generational data to object traversal.

Teamwork API Callout Connector

A quick pet project to provide basic GET and POST functionality provided via HTTP REST callouts. Custom fields and tables were made to match the structure of a Teamwork Projects organization. API tokens and authentication was dynamically handled and allowed the posting of time entries from Salesforce to Teamwork. The project utilized callout classes and triggers to fire off correctly whenever a time entry was made or updated. The connector also was created as a Salesforce App that ran in the traditional layout as well as Lightning and the Salesforce1 mobile app. This allowed for time entries to be tracked and reported in Salesforce to run a greater variety of reports than Teamwork provided. The goal was to gain more knowledge of both the Teamwork API as well as direct Salesforce integration with other web applications.

Flag Project Details

This was a form customization that utilized the base project form deeply stripped of its excess functionality. The form was made simple, to load all projects that met a date range, or met a project code, or met a project code within a given date range. The form was the first customization at my company where an updatable BAQ was linked to a form customization and updated via an impl on the adapter business object. The BAQ would then flag certain fields that met the criteria given in the form and update via the BAQ. However, the BAQ ran on a table that did not call the correct methods and had issues inserting more than 50 records to the database. The limitations slowed down the system and a method directive was decided to be the best approach moving forward.

Credit Card Management Integration

A project where a previous middleware company left broken and unfinished code on a client's Salesforce organization. The default code was improved upon and I was able to complete it and make it fully functional. The program also had some improvements for displaying error messages and error handling. The code was then modified to work with new use case requirements that required an extension on the existing apex code.

There were 3 major pages involved: credit card selection, credit card entry, and a credit card assignment page. The selection page allowed selection from a listing of valid credit cards assigned to the account. The entry page allowed entry of a credit card or modification of an existing one. The assignment page allowed credit cards to be assigned to accounts.

Each page also had controller extensions linking to the existing credit card utility classes. A custom javascript button was used to prevent API submission of orders for certain RMAs that did not have a valid credit card. Validation was done by a HTTP Callout class that received major credit card information from credit card companies. The callout would verify that the credit card number existed in the earlier form entries. If no credit card was assigned or had expired, then the javascript button would alert the users.

TSQL to Excel Reporting Data Dump

A simple application that performed financial lookups and reporting on a SQL Server database. The lookups filtered inventory and tracked costs per warehouse as well as per region and overall. The financial report would also perform complex business calculations and then write to Excel. SSRS was not perferred by the project manager, so elevated permissions and outdated techniques were used to dump the data to an Excel file.

A concept application was also made as a backup and would perform the same as a standalone C# app that ran as a cron job. The TSQL would then be set to run on scheduled intervals every few days, but not as a stored procedure. The Excel file would be written but not overwritten once created. New files would be added for each run to provide a better snapshot for the client. Excel templates were also created to meet the client's needs.

Price Listing Inquiry Form

A client requested an extension to the Epicor base Price List Inquiry form. The extension required a custom sheet that allowed quick addition of Quotes or Orders with a miniature form that would load new or existing entry forms. The forms would auto?populate based off of the parameters launched from the other form. I was the first in my organization to implement such functionality. The Quote/Order forms would populate billing and shipping information differently and had to be extended to support the data sent from the PLI form. Quotes required the same bill-to and ship-to address as the customer's address. Orders would defult to the standard billing/shipping addresses, but would also auto select a proper warehouse to link to the order.

API Usage Reporting

A Scribe platform application that allowed reporting to be done in Scribe on the Scribe organization's usage history. This called the Scribe API to pull organization usage and details for each child organization. It would also calculate times spent processing records as well as errors encountered. I initially started the project, swapped between development projects, and trained other developers to get them up to speed with the project.

RMA Replacement Order Forms

A custom RMA replacement order page was created, almost identically matching the Create Free Part RMA Order Visualforce Page project. This form, however, looked at all products. Another difference was the ability to see all products or only products meeting certain groups or other criteria. The criteria would be the RMA type as well as user?selected radio buttons.

The page would also have the ability to filter products by their associated pricebook entries. All pricebooks were set to a picklist which was then defaulted to the Retail pricebook, or any pricebook with "retail" in its name if there was no lone "Retail" pricebook. The selected pricebook would not only filter the products available, but it would also change the prices accordingly. Only pricebooks from the RMA account's default pricebook group were shown.

If there was any invalid data, a custom Javascript button would fire off an alert message and prevent the user from continuing to the page. Apex extensions were used with the standard controller to provide a robust experience.

Defect Entry Customization

A project breifly picked up by me after another developer could not work on it for a while. I took an existing form customization layout and added in the functionality to allow the entry and modification of defect entries as well as defect details per entry all in the same form customization. The trick was to allow out?of?the?box Epicor functionality but create the same grid display results as a BAQ (Business Activity Query). The issue was working with the Epi Data View and having to code around default issues with utilizing a child data view in a parent.

The child was a UD (User?Defined) extenstion of the parent table. The similarity of Key fields required careful planning and a creative workaround in the code. The child UD data view was integrated instead of a BAQ to allow direct Paste to Excel functionality which was a must for the client.

Job Part Bundling Utilities

My first Epicor project. On the Job Entry Form, when the job was flagged as engineered, all 1st level Subassemblies and Raw Materials would be grouped into unbundled parts. The unbundled parts showed up on a custom sheet on a bottom grid. A user could then select multiple Job Assemblies and Materials from the grid and bundle them at once. Bundled parts will be transferred to an upper grid, where advanced calculations are done to determine remaining quantity. Any bundled parts exceeding the required quantity (resulting in negative quantity in bottom row) will flag rows to be marked as red.

The user could update, add, delete parts from a bundle. BPMs fired off to successfully and efficiently manipulate data much faster than an adapter or impl would provide. After bundling parts, the user will move to a 100% custom Bundle Management (Bundle Shipping) form. The custom form would allow bundles to be flagged as completed.

A user can also flag a job as completed by shipping it. Default values are auto assigned for more rapid bundling and shipping. Bundles can be assigned to a load master with an auto?generated bill of lading number if the user decides to do so.

Create Free Part RMA Order Visualforce Page

My first Salesforce project, the Free Part RMA (Return Material Authorization) Page utilized the Salesforce MVC pattern using traditional tools. The RMA was a custom object implemented to track returns in Salesforce. The page allowed onlt products flagged as "Free Part Eligible" to be selected from a page block table with a specified quantity and grouped together for an RMA order. The layout used two grids where the products were selected from the bottom table and assigned to the top table. Each row in the page block table had a Select button that pulled the product from the bottom grid to the top grid. Products could be removed from an order (top grid) by clicking a page link while the quantity and RMA reasons could be modified for each individual free part order record.

API Subscription Checker

My first Scribe API project, the subscription checker was built into an already extensive application that covered two versions of an API to integrate with. The checker would sent a web callout to a SQL Server instance that would return queried key values and information like key expiration dates and key hashes. These values would then be evaluated on the Scibe client side and prevent organization access if the subscription key was invalid or expired.

The server-side portion of the Scribe API Subscription Checker used a custom database that was created to work with an old, existing IIS API. The IIS app was updated and the database would hash, salt, and securely store user data as well as subscription keys. It would then return the needed values through SOAP.

SIUE Senior Project Presentation

A simple presentation in the form of a playable minigame. As I was graduating the School of Business, I needed to give a presentation that sold my skillset. I found a unique way to mix business presentation with computer systems and art in the videogame medium.

The presentation was built with the Blender Game Engine in the Blender 3D software. The player is a rolling ball with a fedora hat (my signature look) that rolls to different parts of a platform. The player can view basic presentation content in any order they desire or they can simply roll around the stage.

You can download a zipfile of my presentation here.

Customer Contacts Tracker

A small extended customization of an existing template database and form structure. The system was architected and built initially to work exactly as the client specified but project management decided that form was perferred over function. As sole developer I had to write complex queries and VBA code to extend the template to meet the use case requirements. Much of the existing template fields were replaced and programmatically populated from the VBA code extensions and Macros.

Irresistorable

A script that gives you the value of a traditional 3-band resistor based on the bands' colors. It was made as I was starting out with electronics to help me quickly get resistor values until I could remember the color values myself. The script ran a command-line app that prompted for specific values: