trafficlights/README.md

7.6 KiB
Raw Permalink Blame History

Traffic Light System

Problem Description

Summary

This test is a take home test, please return once completed

Requirements

In this test we would like you to implement a traffic light system. We are required to have 4 sets of lights, as follows.

  • Lights 1: Traffic is travelling south
  • Lights 2: Traffic is travelling west
  • Lights 3: Traffic is travelling north
  • Lights 4: Traffic is travelling east

The lights in which traffic is travelling on the same axis can be green at the same time. During normal hours all lights stay green for 20 seconds, but during peak times north and south lights are green for 40 seconds while west and east are green for 10 seconds. Peak hours are 0800 to 1000 and 1700 to 1900. Yellow lights are shown for 5 seconds before red lights are shown. Red lights stay on until the cross-traffic is red for at least 4 seconds, once a red light goes off then the green is shown for the required time(eg the sequence is reset).

Bonus: At this intersection north bound traffic has a green right-turn signal, which stops the south bound traffic and allows north bound traffic to turn right. This is green at the end of north/south green light and stays green for 10 seconds. During this time north bound is green, north right-turn is green and all other lights are red.

Implementation/Outcomes

  1. Implement a front-end and backend (you can use dotnet new templates of your choice)
  2. The backend will contain the logic and state of the running traffic lights. The front-end will be a visual representation of the traffic lights, with the data served from the backend.
  3. Theres no need to have a perfect design on the front end, something simple and functional is fine (unless this is an area of strength you would like to show off). Noting* we will review the client side code.
  4. Theres no need to implement entity framework (or similar) to store the data in a database, a in-memory store is fine
  5. Code needs to follow architecture & best practices for enterprise grade systems

Note: Code will be evaluated not just for function, but on the quality of the code.

Design

Algorithmic Assumptions

The problem clearly specifies a kind of timed "simulation" with a decoupled front- and back-ends. The problem has been approached on that basis.

Additionally:

  • The algorithm uses the term period to denote specific timing profiles (e.g. off-peak vs peak period). Within each period is a single implicit sequence that itself is comprised of a set of timed states that each fully specify the colour of each light. These are stored in JSON format in the file periods.json.
  • The problem description does not specify behaviour on period change (i.e. transitioning from normal timing to period timing). One would assume that an instantaneous change would easily create unpredictable and unsafe conditions for any hypothetical drivers, and so in this implementation the current full sequence is allowed to complete before transitioning to the next period. For this example, a full cycle should not last longer than approximately 80 seconds and therefore this is the expected maximum delay between period transitions.

Period data is configurable/stored in periods.json. The implementation algorithm is found in simulation/simulation_thread.py.

Environment and Infrastructure

The wording of the problem description clearly implies the use of C#/.NET, however given my lack of up-to-date knowledge with modern C# frameworks I have chosen Python/Django instead. Django is a modern web framework for Python that includes many more features than are required for this simple project, but again has been chosen for familiarity. A web front-end was chosen due to the broad use of HTML/CSS/JavaScript and the ease with which it can be changed or updated according to need. It would also lend itself particularly well to a scenario where the front- and back-ends would exist on different machines.

However, despite it's large feature set, Django has no native support for long background threads (though modern versions have some asynchronous call support). For this purpose it is generally recommended to use the Celery library which then communicates with the main Django server via multiprocess pipes. This is, however, overkill for this problem and so a simple thread is used instead. This however means that the simulation thread relies on the Django webserver for its own existence. In an Enterprise environment, it would be more desirable to have the traffic light control to operate independently, which would then encourage the use of a separate process such as provided by Celery.

The UI is a simple web page that calls polls for updates from the server. Due to the use of locks to avoid race conditions, this can induced minor delays (milliseconds at worse) in the processing and updates of traffic light information in the simulation thread. The main loop is designed in such a way that this will not cause cumulative delays in traffic light timing. However, it is worth considering that another approach may be desirable (such as pushed client updates rather than polling) if, for instance, many clients were expected to be making simultaneous requests of the server.

The main frontend web page, including the JavaScript polling code, is specified in its entirety in trafficlightfrontend/templates/trafficlightfrontend/index.html. The code responsible for encoding and dispatching responses can be found in trafficlightfrontend/views.py. Other files not described in this README are largely Django default scaffolding.

Installation and Usage

Pre-requisites

The project requires Python 3.8 and Django 4.2. A virtual environment is recommended, but is only required when it is undesirable to install Django into your main Python package repository (most real-life cases, to avoid different Django version conflicts). Basic instructions for virtual environments can be found here. Once the virtual environment has been created and activated, the following command will install the version used in the project:

pip install -r requirements.txt

Python 3.11.2 and Django 4.2.6 during development. Django 4.2 supports Python 3.8 to 3.11 inclusive. It should be noted that 3.12 introduces a number of syntax extensions that might cause problems when using 4.2.6. Version 4.2.7 is expected to support Python 3.12 in future.

Execution

Django can be run in a production environment, but this project is runnable and testable using the local debug server. This can be invoked using the following command, executed in the top-level directory:

python manage.py runserver 0.0.0.0:8000

This server can then be accessed via http://localhost:8000/frontend/, and can be terminated from the command-line using Ctrl-C.

Configuration

Project settings are in the standard Django location, trafflights/settings.py. Much of this file is default Django scaffolding. Of interest for this specific project are the following:

  1. SIMULATION_DATA_FILE: The file containining the period/state data for traffic light behaviour.
  2. SIMULATION_START_TIME: The internal time at which the simulation starts, in ISO text format. By default this is 07:59 for demonstration purposes.
  3. SIMULATION_TIME_FACTOR: The time "acceleration" factor (floating point) for the simulation. A factor of 1.0 will run in real-time, and higher factors will run faster. Default is 4.0.