Coursework Projects (Technical)
Selected academic projects from software development and HCI coursework at the University of Sydney.
A selection of coursework from my Bachelor of Advanced Computing at the University of Sydney, spanning systems programming, software engineering, security, HCI, and project management. Each section covers the key projects and the skills they demonstrate.
INFO1110: Introduction to Programming
Built a simulated mobile operating system in Python called Dorrigo OS, modelling the core software layer of a smartphone. The system managed battery life, network connectivity, signal strength, a contact list, and per-contact chat history, all implemented from scratch using object-oriented design across two classes: DorrigoMobile and DorrigoContact.
The assignment imposed deliberate constraints: no imports, no for loops, no dictionaries, and no several built-in functions. This forced reasoning about data structure design and recursive or while-loop-based logic at a low level. Contact management enforced capacity limits, phone state guards, and deep copy semantics. The messaging system implemented a circular overwrite buffer capped at 20 messages per contact.
Tech stack: Python · Object-oriented programming · List-based data structures · Recursive logic · Deep copy implementation without standard library
INFO1112: OS and Network Platforms
Assignment 1: Cron Job Scheduler
Implemented a Unix-style cron daemon in Python consisting of two programs: runner.py, a background daemon that reads a configuration file and executes programs at scheduled times, and runstatus.py, a status client that sends a SIGUSR1 signal to the daemon and reads its written status output. The system supported both one-time and recurring schedules across specific days and times.
The daemon wrote its PID to a file on startup and maintained a live status log of past and upcoming runs. Inter-process communication was handled entirely through OS signals and shared files, no sockets or pipes. Error handling covered malformed config lines, missing files, fork/exec failures, and 5-second status timeouts. Test cases were written as Bash scripts using diff-based output comparison.
Tech stack: Python · os / sys / signal / time / re · fork and exec · SIGUSR1 inter-process signalling · Daemon process architecture · PEP-8 style
Assignment 2: MinCGI Web Server
Built a multi-connection HTTP/1.1 web server in Python that served static files and executed CGI programs. The server parsed a configuration file specifying static file root, CGI binary directory, port, and executor path. Incoming GET requests were parsed for method, resource, query strings, and headers, which were then mapped to CGI environment variables (REQUEST_METHOD, QUERY_STRING, HTTP_HOST, REMOTE_ADDRESS, etc.) before forking and executing the CGI program.
Static file serving handled content-type mapping by file extension (html, css, js, png, jpg, xml) and returned appropriate 200, 404, or 500 responses. CGI programs communicated via stdin/stdout; the server piped the request body in and relayed the output back as an HTTP response, normalising any custom Status-Code headers. Concurrency was achieved by forking each accepted connection. Test cases used curl and diff against expected output files.
Tech stack: Python · Socket programming · HTTP/1.1 parsing · CGI/1.1 specification · fork and exec · Environment variable injection · Content-type mapping · Bash test scripts with curl
INFO1113: Object-Oriented Programming
Assignment 1: Flight Scheduler
Built a command-line flight scheduling application in Java with three core classes: FlightScheduler (main entry point), Flight (flight data and pricing logic), and Location (airport with arriving/departing flight lists). The schedule is weekly (Monday to Sunday, repeating), and each location has a single runway, meaning no two flights can arrive or depart within one hour of each other at the same location.
Ticket pricing was dynamic: a base rate of $30 per 100km (adjusted by the demand coefficient differential between origin and destination) multiplied by a fill-level curve, prices decrease linearly to 80% as the flight reaches half full, then rise back to 100% at 70% capacity, then follow an inverse-tan curve up to 110% at full. Distances were computed using the Haversine formula.
The TRAVEL command implemented multi-stop route search with up to 3 stopovers, supporting 5 sort modes: minimum cost, total duration, stopovers, layover time, and flight time. The weekly wraparound (Sunday connecting to Monday) was handled explicitly. CSV import/export was supported for both flights and locations.
Tech stack: Java · Object-oriented design (encapsulation, class composition) · Haversine formula · Graph-based route search · Dynamic pricing model · CSV I/O · Command-line parsing
Assignment 2: Delayed Stack and Queue
Implemented two generic data structures in Java: MyStack<T> (implementing a DelayedStack interface) and MyQueue<T> (implementing a DelayedQueue interface). Both structures work like their standard counterparts, LIFO for the stack, FIFO for the queue, but enforce a delay condition: remove operations are blocked until a minimum number of add operations have occurred since the last remove sequence. Once the threshold is reached, any number of removes can run; the delay resets when the next add operation occurs after a remove.
The delay maximum could be updated at runtime via setMaximumDelay(), but the new value only takes effect at the next delay reset. A delay of 0 or below means no restriction. Both classes were implemented without any imports from the Java standard library, all internal storage used raw arrays with manual resizing. JUnit 4 test suites (MyStackTest.java and MyQueueTest.java) covered edge cases including empty-structure exceptions, delay boundary transitions, and mid-sequence setMaximumDelay() calls.
Tech stack: Java · Generics · Custom array-backed data structures · DelayedStack / DelayedQueue interface contracts · JUnit 4 · Google Java Style Guide
INFO2222: Usability and Security
A semester-long group project to design and build a discussion forum and real-time chat application for computing students. The project was assessed in two phases: a usability report covering the full UX design process, and a security report covering the implementation of authentication and encrypted messaging.
Usability
The usability phase followed a structured design process from user research through to hi-fi prototype. The team conducted a 19-response survey and 6 user interviews targeting undergraduate computing students, then applied PACT analysis (People, Activities, Context, Technology) to define the target user and use context. Card sorting with 20 features across 4 categories informed the site map and information architecture, with deliberate departures from the majority vote: for example, placing "forgot password" under Home (accessible before login) and "remove contact" under Chat (grouped with "add contact" for discoverability).
Two rounds of lo-fi prototyping and guerrilla testing refined the design before two hi-fi prototypes were built and evaluated against WCAG accessibility criteria. Implemented features included anonymous and public posting, commenting, upvote/downvote, tag-based information hierarchy, admin roles (mute/delete users and posts), file uploading, code blocks, and rich text formatting.
Security
The security phase hardened the web app against five criteria. Passwords were stored as salted hashes using werkzeug.security (PBKDF2-SHA256), with server-side validation enforcing minimum length, username-password mismatch, and password strength classification (weak/medium/strong). A self-signed TLS certificate was generated and hardcoded as a trusted root CA, enabling HTTPS. Login returned a constant error message regardless of whether the username or password was wrong, preventing username enumeration.
End-to-end encryption for chat was implemented using the Web Crypto API. On registration, each client generated two asymmetric key pairs: RSA-OAEP for encrypting and decrypting message content, and RSA-PSS for signing and verifying message integrity. Public keys were sent to the server and stored with user records; private keys stayed in the browser's IndexedDB. When two users became friends via a friend-request handshake over Socket.io, they exchanged public keys: allowing each to encrypt outgoing messages with the recipient's public key. A digital signature was attached to every message; if the ciphertext or signature was tampered with in transit, the receiver saw an error alert. The server relayed messages without being able to read them.
Bonus features included a CAPTCHA on registration (client-side, resets on correct entry or page refresh) to mitigate DoS on the signup endpoint, and per-message timestamps.
Tech stack: Python · Flask · Socket.io · SQLAlchemy · werkzeug.security · JavaScript · Web Crypto API (RSA-OAEP, RSA-PSS) · IndexedDB · HTTPS with self-signed TLS · HTML/CSS
ISYS2120 · Data and Information Management
ISYS2120 covered relational database design, SQL querying, and database-backed web development. The course built on the fundamentals of entity-relationship modelling and relational theory, culminating in a group project building a full-stack media server using Flask and PostgreSQL.
For Assignment 3, our team of four built a web application on top of an existing PostgreSQL schema spanning media items, metadata, user accounts, and playlists. We wrote 10 SQL queries covering login authentication with bcrypt password hashing (via pgcrypto’s crypt()), playlist and in-progress media retrieval, and metadata reads for songs, albums, TV shows, and podcasts. Movie search used PostgreSQL’s regex operator (~) for case-insensitive matching, and the genre browser unified songs, podcasts, and films in a single UNION query across heterogeneous media types.
Our group’s new functionality was User Management and Security: replacing plain-text password storage with bcrypt hashing and salting via gen_salt(’bf’). We built a change-password flow with session-gated routes, a user profile page displaying contact details, and add/delete contact operations — all wired through Flask routes and Jinja2 templates.
Tech stack: Python · Flask · PostgreSQL · SQL · Jinja2 · pgcrypto
INFO3315: Human-Computer Interaction
A semester-long group project to design IntelliDoc, an AI-powered health chatbot application that lets patients self-diagnose using symptom descriptions and book video consultations with doctors. The project addressed the UN Sustainable Development Goal of good health and well-being, motivated by evidence that out-of-pocket healthcare costs push hundreds of millions into poverty. The course required both an initial requirements report and a final design-and-evaluation report.
Part 1: Requirements Report
The requirements phase began with a literature review of existing self-diagnosis tools (including Avey, which gave single-answer diagnoses, and NLP-based chatbots that prioritised conversation over accuracy). The key gap identified: existing apps either over-indexed on AI model accuracy at the expense of usability, or disappeared from the market entirely. IntelliDoc aimed to surface multiple diagnostic possibilities with confidence percentages rather than a single answer, addressing both accuracy perception and user trust.
User research used two methods: a survey targeting both healthcare professionals and general public, and two in-person focus group sessions lasting approximately 90 minutes each. Focus group participants were recruited across three profiles: technology enthusiasts, health enthusiasts, and non-health enthusiasts: to capture adoption barriers across the full user spectrum. Key findings: 94.5% of potential users were aged 18-35, 76% had used similar health apps before, and privacy around health data was a recurring concern. These findings directly shaped the decision to include an anonymous video call option.
Requirements were prioritised as must-have (AI chatbot diagnosis, video consultation, anonymity), should-have (appointment scheduling, medical history), and nice-to-have (health news, Medicare payment integration). User groups were initially framed as patients and researchers, but were revised to patients and doctors after the research phase confirmed that human clinical oversight is necessary for diagnosis accuracy.
Part 2: Final Report: Design and Evaluation
The design process moved through lo-fi wireframes, think-aloud testing, hi-fi prototypes, cognitive walkthroughs, and usability testing. Lo-fi wireframes were built in Figma and evaluated during a Week 9 workshop using think-aloud sessions with members from another group. This revealed two issues: missing login confirmation feedback, and a back button (a plain black circle) that users did not recognise as navigation. Both were fixed before moving to hi-fi.
The hi-fi prototype added a dedicated doctor-side interface (absent from the initial lo-fi scope), a symptom icon-based doctor search feature (added after a user struggled to find a specialist for cold symptoms), and an anonymous video call mode that overlaid a digital avatar on the user's face to address privacy concerns raised in the focus groups. Two cognitive walkthrough sessions evaluated core patient flows (login, appointment booking, chatbot diagnosis, medical history) and uncovered further navigation simplification opportunities.
Usability testing sessions collected both task success rate and think-aloud feedback. The evaluation research plan outlined a future pilot study using a mixed-methods protocol: SUS questionnaire for quantitative usability scores and semi-structured interviews for qualitative insights: to validate design changes at scale.
Methods: PACT Analysis · Survey · Focus Groups · Persona Development · Figma (Lo-Fi and Hi-Fi) · Think-Aloud Testing · Cognitive Walkthrough · Usability Testing · SUS Questionnaire
SOFT2201: Software Construction and Design 1
Three assignments building progressively on the same domain: a JavaFX pool game: moving from UML modelling through design pattern application to codebase analysis. Each assignment required written justification of design decisions against OOP, SOLID, and GRASP principles.
Assignment 1: UML Modelling
Designed a pool table game application model in UML. The game is single-player on a rectangular table: colored balls are randomly placed, the player hits the cue ball via mouse input, and the game ends when the cue ball is pocketed. The model included a Use Case Diagram (player, stakeholders, system functions), a Sequence Diagram illustrating the ball-hit interaction, and a Class Diagram covering the main classes Ball, Table, and Player with their attributes, methods, associations, and dependencies. Design decisions were justified against OO theory including Abstraction, Encapsulation, Inheritance, and Polymorphism.
Assignment 2: Design Pattern Application
Redesigned the pool game application to incorporate three GoF design patterns. The Factory Method Pattern used a Factory interface with BallFactory and TableFactory as concrete creators, producing Ball and Table objects via a shared GameInstance interface: decoupling object creation from the game logic and enabling new game instances to be added without modifying existing factories. The Builder Pattern used a BallBuilder interface with a concrete BallBuilder and a BallDirector, separating ball construction (setting colour, mass, position, velocity, strategy) from the client: making Ball construction readable and eliminating constructors with many parameters.
The Strategy Pattern used a BallStrategy interface with concrete strategies BlueBallStrategy, RedBallStrategy, and WhiteBallStrategy, assigned per-ball during construction via the Builder. This eliminated chains of if-else logic for ball-type-specific behaviour and allowed new ball types to be added by writing a new strategy class without touching existing code. GUI and mouse input handling were consolidated into GameWindow, removing them from the Player class. SOLID and GRASP principles were used to justify and critique each pattern choice.
Assignment 3: Codebase Review
Reviewed an existing pool game codebase for adherence to OOP, SOLID, GRASP, and design pattern correctness. Encapsulation was largely upheld through consistent getter/setter usage, with several attributes (colour, mass, radius) intentionally read-only by omitting setters. Inheritance and polymorphism were demonstrated through the PocketStrategy abstract class, which defined reset() as abstract to force subclass override: an example of runtime polymorphism via method overriding.
SOLID analysis identified two SRP violations: BallReader.java handled both config file parsing and Builder pattern direction (two responsibilities), and App.java validated the config file path rather than delegating that to GameManager. The Open-Closed and Dependency Inversion Principles were satisfied through the Factory Method and Strategy patterns. The codebase used three design patterns: Factory Method (ReaderFactory with BallReaderFactory and TableReaderFactory), Builder (BallBuilder interface implemented by PoolBallBuilder, directed by BallReader), and Strategy (PocketStrategy with BlueStrategy and BallStrategy as concrete implementations). GRASP analysis confirmed GameManager as the Information Expert and identified high cohesion through the joint Factory Method and Builder usage.
Tech stack: Java · JavaFX · UML (Use Case, Sequence, Class diagrams) · GoF Design Patterns (Factory Method, Builder, Strategy) · SOLID principles · GRASP principles
SOFT2412: Agile Software Development Practices
Two assignments applying agile tooling and Scrum methodology to software development projects. The first built a JavaFX Currency Converter using industry-standard DevOps tools; the second used the full Scrum framework to deliver a JavaFX Vending Machine application across multiple sprints.
Assignment 1: Tools for Agile Software Development
Built a JavaFX Currency Converter application and applied agile tooling throughout the development process. The app supported admin login, a popular currencies view, a currency summary table, and data loading from both CSV and TXT file sources. The project was managed through a GitHub repository with a structured branching strategy: a main production branch, a dev integration branch, and per-feature branches merged via pull requests with linked issues. A GitHub Kanban board tracked work items through To Do, In Progress, and Done columns.
Gradle was used as the build tool, supporting init, build, run, test, and clean lifecycle commands. JUnit 5 unit tests were written for five classes: PopularCurrency (loading and parsing currency data), Calculator (conversion logic), CSV (CSV file reading), ReadDate (date parsing), and TXT (TXT file reading). Tests validated both expected outputs and edge cases including malformed input. Jenkins CI was configured to automatically run the full test suite on each push, with build status visible through the repository. The pipeline enforced that no broken build reached the main branch.
Tech stack: Java · JavaFX · Gradle · JUnit 5 · GitHub (branching, issues, PRs, Kanban) · Jenkins CI
Assignment 2: Scrum Software Development Project
Applied the full Scrum framework to design and build a JavaFX Vending Machine application supporting four user roles: Customer, Seller, Cashier, and Owner. The team of five filled three Scrum roles: Product Owner (responsible for the backlog, stakeholder communication, and requirement prioritisation), Scrum Master (bridging the Product Owner and Development Team, facilitating sprint planning and enforcing Scrum practices), and three developers implementing features sprint by sprint.
A stakeholder register mapped six stakeholder groups (Buyer, Seller, Cashier, Machine Owner, Product Owner, Scrum Master, and Development Team) by role, impact, and project phase. The team created 44 user stories across all four roles: covering product browsing by category, multi-item selection, cash and card payment with AUD denominations, change optimisation (notes to coins, dollars to cents), idle timeout cancellation, purchase history (personal and anonymous), role-based account management, and reporting for cashiers and owners. Stories were written in "As a [role], I want [action], so that [benefit]" format with explicit acceptance criteria, story points, ideal time, and elapsed time.'),
Story point estimation used Planning Poker via the planITpocker tool, where all five team members voted simultaneously to avoid anchoring bias. The average of votes became the official story point value. The GitHub Kanban board managed sprint flow across five columns: Product Backlog, Sprint 1 To Do, Sprint 1 In Progress, Sprint 1 Testing, and Sprint 1 Done. The Product Owner prioritised backlog items into Sprint 1, the Scrum Master assigned tasks to developers, and work items moved across the board as features progressed through development and testing.
Tech stack: Java · JavaFX · GitHub (Kanban, issues, PRs) · Planning Poker (planITpocker) · Scrum (Product Owner, Scrum Master, Development Team) · Sprint planning · Stakeholder register · User story mapping
INFO3333: Computing 3 Management
A group project applying IT project management frameworks to plan (but not build) NatureNexus, an AR-powered mobile intelligent planting system. The project combined market research, literature review, work breakdown, schedule and cost modelling, risk management, and communication planning across a simulated 365-day delivery timeline. Katherine served as Project Manager, responsible for overseeing the project charter, budget, timeline, and stakeholder communication.
Product: NatureNexus
NatureNexus aimed to address the challenges of urban gardening through a mobile AR application that guides users in planning, planting, and maintaining gardens. Core features included AR-powered virtual plant placement and spacing to visualise garden layouts before planting, AI/ML-based plant identification and personalised recommendations, IoT sensor integration for real-time environmental monitoring (soil quality, temperature, moisture), push notifications for watering and fertilising schedules, and a curated plant database covering edible crops and plants safe for pets. The design was inclusive: targeting both novice home gardeners and people in healthcare settings where gardening has therapeutic benefit.
Literature Review
The team reviewed 11 papers across three domains: urban planting challenges, Augmented Reality technology, and the intersection of AR with IoT for precision farming. The literature established that home gardeners lack access to expert knowledge about pests, spacing, and plant compatibility; that existing AR apps suffered from technical unreliability and irrelevant content; and that AR-IoT systems had demonstrated real-world feasibility in precision agriculture. Key design implications drawn from the review: the system should keep cognitive load low, support culturally diverse plant varieties, use AI/ML for context-aware recommendations, and provide IoT interfaces for future environmental monitoring.
Work Breakdown Structure
The WBS decomposed the project into six phases: Market Research (competitor analysis, survey design, data collection and analysis), App Design (requirements gathering, UI/UX wireframing, prototype development, usability testing, and design iterations), AR and IoT Integration (AR tool selection, AR development, IoT connectivity setup, data integration, AR-IoT functionality testing, and system validation), Database Creation (data source selection, extraction, cleansing, schema design, indexing, and validation), AI/ML Implementation (algorithm selection, training data collection, model training and evaluation, and model integration), and User Testing and Feedback (test plan, recruiting, usability sessions, result analysis, and improvement iterations). Total planned duration: 365 days.
Cost Modelling
The project budget was modelled at $330,500 across all six phases, billed at $150/hour for most roles and $200/hour for AI/ML specialists. The largest cost centre was AI/ML Implementation ($80,000: 24% of total), driven by the 100-hour model training task and the cost of acquiring training data. AR and IoT Integration was the second largest ($76,500: 23%), reflecting the complexity of AR development (150 hours) and AR-IoT integration testing. Database Creation ($55,500) and App Design ($46,500) followed. Cost types included direct costs (salaries, tools), tangible costs (hardware, software licences), and intangible costs (time spent learning new AR/IoT technologies, data cleansing overhead, and potential model retraining effort). A cost baseline table tracked spending across all 12 months.
Risk Management
Five risks were identified and rated. Personal Data Security (Technology, HIGH impact, LOW likelihood): the app scans physical spaces and models them, requiring a secure data channel; mitigation included biometric verification and database encryption. Competition from similar products (Market, MEDIUM impact, HIGH likelihood): mitigated by conducting competitive analysis upfront and differentiating on unique AR-IoT features. Budget overrun (Financial, HIGH impact, LOW likelihood): managed through phased fund monitoring and contingency plans to narrow scope. Resignation of core developers (People, MEDIUM impact, LOW likelihood): mitigated through work contracts and team wellbeing monitoring. Inefficient AR recognition (Process, MEDIUM impact, LOW likelihood): mitigated through iterative modelling tests post-development.
Methods: Project Charter · WBS · Gantt Chart · Cost Baseline · Risk Register · Communication Management Plan · Literature Review (11 papers) · AR · IoT · AI/ML
SOFT3202: Software Construction and Design 2
Two assignments set in the fictional Brawndo company's SalesPerson Front-End Application (SPFEA) system. The first focused on test-driven quality assurance, writing a micro/unit test suite and implementing a module so it passed independently. The second focused on design pattern application to a real legacy codebase suffering from performance, maintainability, and class explosion problems.
Assignment 1: Testing
Built a test suite against a public-facing Java API for the SPFEA system, with no access to the concrete implementations being tested (the test suite was run against several different unknown implementations to detect bugs). Two modules were targeted: the ToDo Module and the SPFEAFacade.
For the ToDo Module, wrote micro/unit tests for three classes: ToDoListImpl (implements ToDoList), ToDoFactory, and TaskImpl (implements Task): covering only methods declared in the public API, including both their expected behaviour and their defensive programming behaviour (precondition enforcement). Tests had to be written without knowledge of the concrete implementation, relying purely on the Javadoc-specified pre- and postconditions. Also implemented the ToDo Module itself so it passed a provided known-working test suite.
For SPFEAFacadeImpl, wrote a test suite using Mockito mock objects to simulate the ToDo module dependency: the tests could not instantiate the real ToDo implementation to set up fixtures, forcing test isolation through mocking. This tested the facade behaviour independently of the module it depended on.
Tech stack: Java · JUnit 5 · Mockito (mock doubles, stubbing) · Defensive programming · API-driven testing · Gradle
Assignment 2: Design Patterns
Diagnosed and refactored six design problems in a pre-existing Brawndo ERP/SPFEA Java codebase. The codebase had accumulated technical debt from years of rushed delivery: all functional tests passed but non-functional requirements (memory usage, performance, maintainability) had deteriorated. The constraint was strict: the public API of the spfea package could not change, out-of-scope packages could not be touched, and all existing tests had to continue passing throughout: no breaking changes allowed.
RAM Issue: the Product class was loading and storing excessive data. Applied the Flyweight Pattern to share intrinsic product data across instances, reducing per-object memory overhead without changing the Product interface. Too Many Orders: the system had 264 order subclasses (66 discount types × 2 order types × 2 subscription types). Applied the Bridge Pattern to separate the order abstraction from its implementation axes, replacing the class explosion with a composable structure. Bulky Contact Method: ContactHandler.sendInvoice() was an unmaintainable chain of conditional logic. Refactored using the Command Pattern to encapsulate each contact method as a discrete command object, making the handler open for extension and easier to maintain.'),
System Lag: loading a full Customer object from the database even when only the ID field was needed caused significant latency. Applied the Proxy Pattern to defer full customer loading until fields beyond the key were actually accessed, mitigating the database overhead in software without changing the Customer interface. Hard to Compare Products: Products lacked a consistent primary key, causing equality checks to compare many fields in code. Overrode equals() and hashCode() based on a stable combination of product attributes to make comparisons consistent and correct. Slow Order Creation: each change to an order before finalization triggered a slow database operation. Applied the Builder Pattern to accumulate order state in memory and defer all database writes until the order was explicitly finalized.
Tech stack: Java · GoF Design Patterns (Flyweight, Bridge, Command, Proxy, Builder) · Gradle · JUnit 5 · Refactoring under constraint · Code documentation (Javadoc, Google Style Guide)



