# Welcome

This is where you can find Code for Life resources and publications.

We are a not-for-profit, open-source initiative that provides educators with the resources they need to inspire the next generation of computer scientists. In addition to its educational resources, Code for Life engages with schools and educational institutions to provide career-based activities, coding club packs, robotics workshops, certificates, progress tracking and much, much more. Here is also where we document our various processes and how our system's services work.&#x20;

#### Games and Resources

We offer two coding games and a suite of free teaching resources. If you want access to free slides, videos, assessments, solutions and lesson plans, please [register as a teacher](https://www.codeforlife.education/register_form). If you want to learn at home, [register as an Independent student](https://www.codeforlife.education/register_form). This Community site gives you access to various additional resources to support your Python teaching and learning journeys with Code for life.

#### Contribute to the project

Check out [this page](/become-a-contributor) on how to contribute to the Code for Life project and help us to support coding in schools. Please read through the sections to understand how you can contribute as a developer.&#x20;

If you wish to contribute as a designer, product manager or a researcher, please [email us](mailto:codeforlife@ocado.com) directly to find out more.

As we are [open-source](https://github.com/ocadotechnology/codeforlife-workspace), anyone following our guidelines is welcome to [contribute to the project](/become-a-contributor). &#x20;

Additional docs can be found in our [reading list](/repositories-and-packages).

If you have any feedback on how we can improve our docs, please reach out to <codeforlife@ocado.com>.

{% hint style="info" %}
To learn more about the Code for Life mission, [check out our site](https://www.codeforlife.education/about).
{% endhint %}


# Release Notes

Everything we release appears here! Changes released per version.

## Thursday 30 April 2026

**codeforlife-portal: 8.10.0, rapid-router: 7.7.3**

Users can now see their user IDs in the user dropdown and the registration-related emails. The Freshdesk widget is now pre-populated with the user's name and email address and a subject line prompting them to share their user ID.

## Wednesday 25 March 2026

**codeforlife-portal: 8.9.32, rapid-router: 7.7.2**

## Saturday 14 March 2026

**codeforlife-portal: 8.9.31, rapid-router: 7.7.0**

Fundamentally reinvented the way we track "attempts" within Rapid Router and Python Den. Moved on from the old Attempt model (completely deleted it), and instead, aggregated the data from the old Attempt table and migrated it to two new tables: LevelMetrics and DailyActivity. These two tables keep track of the same core data we need around user attempts of the game per level, i.e. score, time spent and number of attempts. Main achievement from this: massive reduction of the database's size (91.5% reduction) from 71GB to 6GB which equates to huge cost saving.&#x20;

## Saturday 7 March 2026

**codeforlife-portal: 8.9.29 rapid-router: 7.6.27**

"Moved" most models from the cfl\_common app to the codeforlife.user app. Faked and subsequently deleted all migrations in portal, common and game and reinitialised the migrations in game and common. Main achievement from this: create our own User model to use across the application instead of the Django's auth.User model, which is a huge step in our effort to breaking the circular dependencies.

## Wednesday 25 February 2026

**codeforlife-portal: 8.9.24, rapid-router: 7.6.24**

* Multiple security updates
* Added a warning message on the Level Creator popups about the failing road building feature

## Tuesday 11 November 2025

**codeforlife-portal: 8.9.8, rapid-router: 7.6.8**

* Upgraded from Django 5.1.13 to 5.1.14
* Upgraded from django-otp 1.6.1 to 1.6.3

## Monday 27 October 2025

**codeforlife-portal: 8.9.6, rapid-router: 7.6.6**

Shoutout to [@evalawther-ocado](https://github.com/evalawther-ocado): Moved the "Max fuel" input to the Character tab and made it automatically update to "battery" or "moves" depending on the character selected for the level.

## Friday 22 August 2025

**codeforlife-portal: 8.9.4, rapid-router: 7.6.3**

* Embedded the Raspberry Pi IDE and our Gitbook content to the worksheet levels in Python Den
* Fixed links to the club packs in Gitbook to ensure only logged in teachers had access to the full Python club pack content
* Fixed issues with the header layout in various browsers across devices (mainly Safari)

## Friday 15 August 2025

**codeforlife-portal: 8.8.3, rapid-router: 7.5.23**

Renamed level 34 from "Multiple Ifs" to "If and bends".

## Friday 8 August 2025

**codeforlife-portal: 8.8.1, rapid-router: 7.5.20**

* Updated solutions to levels 34, 35, 36, 37, 40, 41, 44, 45, 46, 48 and 49 to favour the use of `if...else if... else` instead of `if...else if...else if`
* Level solutions are now consistently loaded without needing to move the canvas

## Thursday 12 June 2025

**codeforlife-portal: 8.7.5, rapid-router: 7.5.13**

* Enforced backend checks against special characters in custom level fields
* School names can no longer contain special characters

## Tuesday 3 June 2025

**codeforlife-portal: 8.7.1, rapid-router: 7.5.10**

* Updated Contribute page to include newer Gitbook thumbnail
* Added CFL community space link to footer
* Added pwnedpassword CloudFlare cookie to the privacy notice
* Only admin teachers can invite other teachers, resend and delete invitations

## Friday 25 April 2025

**codeforlife-portal: 8.6.6, rapid-router: 7.5.4**

Shoutout to [@Bailey-Hodge](https://github.com/Bailey-Hodge): Updated links in Teach page to national curricula Gitbook pages.

## Wednesday 9 April 2025

**codeforlife-portal: 8.6.5, rapid-router: 7.5.3**

* Shoutout to [@Bailey-Hodge](https://github.com/Bailey-Hodge): Updated Register button to say "Register for free"
* Shoutout to [@Bailey-Hodge](https://github.com/Bailey-Hodge): Updated text in register form to highlight free nature of the accounts
* Shoutout to [@Bailey-Hodge](https://github.com/Bailey-Hodge): Fixed layout responsiveness issue in Contribute page
* Upgraded from Django 4.2.20 to 5.1.8

## Wednesday 26 March 2025

**codeforlife-portal: 8.5.1, rapid-router: 7.4.7**

Added list of individual cookies to the privacy notice.

## Thursday 20 March 2025

**rapid-router: 7.4.5**

Now counting number of times users play Rapid Router and Python Den using GTM.

## Tuesday 18 March 2025

**codeforlife-portal: 8.4.10, rapid-router: 7.4.4**

* Most Rapid Router and Python Den levels can now be accessed only by logged in users
* Embedded Gitbook videos no longer keep playing in the background after closing the popup

## Tuesday 11 March 2025

**codeforlife-portal: 8.4.4, rapid-router: 7.3.6**

* Students can now play their own custom level even if it still hasn't been approved by their teacher
* Added missing `my_van.deliver()`command to the Python commands popup in PD level 40

## Friday 7 March 2025

**codeforlife-portal: 8.4.3, rapid-router: 7.3.4**

* Shoutout to [@bella054](https://github.com/bella054): Added new sound effects for Santa in Rapid Router
* Shoutout to [@bella054](https://github.com/bella054): Fixed the syntax in the Python Den's split levels so the generated Python is consistent with the commands presented in the Python-only levels
* Fixed a bug in the level access control feature where Episode 8 (Procedures) couldn't be unlocked

## Thursday 27 February 2025

**codeforlife-portal: 8.4.0, rapid-router: 7.3.2**

* Shoutout to [@bella054](https://github.com/bella054): Added introduction video to variable-type blocks in Python Den level 7
* Linked the "Opportunities with Code for Life" document in the footer and Get Involved page
* Links to PDF docs now point to Gitbook URLs instead of GCP assets bucket
* Retired our use of Mouseflow
* Added a new button in the Play page banner to direct users to the Python Den
* Reworded the buttons on the Play page from "Play" to "Try"
* Made the level moderation feature proactive instead of reactive, meaning students now need to have custom levels approved by their teacher because they can be shared with others

## Wednesday 19 February 2025

**codeforlife-portal: 8.2.2**

* Class names can no longer contain special characters
* Update to privacy notice around GA4 data collection

## Monday 10 February 2025

**codeforlife-portal: 8.2.0, rapid-router: 7.2.9**

Improved Python error feedback in Python Den console log.

## Thursday 30 January 2025

**codeforlife-portal: 8.1.3, rapid-router: 7.2.8**

* Shoutout to [@NoahBakr](https://github.com/Noah-Bakr): Teachers outside of a school can now create and save custom levels
* Removed trial "Donate" button

## Friday 18 January 2025

**codeforlife-portal: 8.1.2, rapid-router: 7.2.7**

* Added link to download our [2024 Impact Report](broken://spaces/FpoODWoLebPGDHgekgrk/pages/QjZOLODnnvi3610SWYR6) in the footer
* Fixed small ordering and layout issues in Python Den's episodes accordion

## Monday 16 December 2024

**codeforlife-portal: 8.0.5, rapid-router: 7.2.5**

* Shoutout to [@RaihanRasheedApurbo](https://github.com/RaihanRasheedApurbo): Fixed strange highlighting bug when placing cows
* Improve input sanitisation on subtitle, description and hint fields in the Level Editor

## Monday 9 December 2024

**codeforlife-portal: 8.0.3, rapid-router: 7.2.3**

Allow for Python Den worksheets to be locked from the teacher's level control form.

## Wednesday 27 November 2024

**codeforlife-portal: 8.0.1, rapid-router: 7.1.0**

Released Python Den worksheets on 2D lists and Procedures and Functions.

## Tuesday 12 November 2024

**codeforlife-portal: 8.0.0, rapid-router: 7.0.1**

* BREAKING CHANGE: Upgrade from Django 3.2 to 4.2.<br>
* Shoutout to [@RaihanRasheedApurbo](https://github.com/RaihanRasheedApurbo): Cows can now be placed on non-road squares as scenery!

## Thursday 7 November 2024

**codeforlife-portal: 7.4.9**

* Shoutout to [@sebp999](https://github.com/sebp999): Fixed broken website bar on Safari and tablet devices
* Shoutout to [@sebp999](https://github.com/sebp999): Students' custom levels are no longer still shared with their ex-teacher and classmates after being released from the school
* Fixed broken edit account details forms

## Saturday 2 November 2024

**codeforlife-portal: 7.4.6, rapid-router: 6.7.1**

* Switched to PostgreSQL 16 from MySQL 5.7
* Transferred all data for all 3 environments to the new instance on GCP

## Monday 28 October 2024

**codeforlife-portal: 7.4.4, rapid-router: 6.7.0**

* Shoutout to [@razvan-pro](https://github.com/razvan-pro): Removed the direct drive arrows in Rapid Router
* Shoutout to [@besque](https://github.com/besque): Fixed the broken JS elements in the registration form for invited teachers
* Updated the Coding Clubs page to match new structure after Python Den release
* Updated the marketing video for the Python Den on the Teach page
* Removed the temporary redirect to the Python Den from the old Rapid Router levels
* Included the Python Den in our Terms of Use
* Fixed the broken level moderation page, teachers can now view and delete custom levels again

## Tuesday 15 October 2024

**codeforlife-portal: 7.4.0**

* Updated Home Learning page to reflect Rapid Router changes following Python Den release
* Added a tester Donate button to the header which links to a contact list in DotDigital

## Tuesday 8 October 2024

**rapid-router: 6.6.0**

* Released Blockly translations for Bulgarian, Polish, Brazilian Portuguese and Russian.
* Amended Python Den level 15 to accept more solutions.

## Monday 30 September 2024

**codeforlife-portal: 7.3.7, rapid-router: 6.5.3**

* Fixed "days left" data binding in inactivity reminder emails
* Fixed broken links to the old CSR page, now redirecting to the Sustainability page
* Updated migrations to be Postgres-compatible

## Wednesday 18 September 2024

**rapid-router: 6.5.2**

Fixed column alignment issue in Python Den scoreboard.

## Wednesday 11 September 2024

**codeforlife-portal: 7.3.3, rapid-router: 6.5.1**

* Update Python Den web pages to ensure title says "Python Den" instead of "Rapid Router"
* Mark some MUI icons in the login dropdown as `data-nosnippet` to see if search engines stop rendering their text version

## Tuesday 10 September 2024

**codeforlife-portal: 7.3.2, rapid-router: 6.5.0**

* Shoutout to [@Ridwanah](https://github.com/Ridwanah): Going back to the levels page from within a Rapid Router / Python Den level using the browser's back arrow now only takes one click instead of several
* Added the scoreboard feature to the Python Den
* Fixed link to Blockly phrasebook in Play page
* Allow admin teachers to move students from any class in their school

## Thursday 5 September 2024

**rapid-router: 6.4.4**

* Replaced cows with pigeons in City theme
* Added solar panel options for Snow and City themes
* Fixed Python Den banners to match Rapid Router banner height
* Fixed links to Blockly phrasebook and Python guides

## Tuesday 3 September 2024

**codeforlife-portal: 7.2.1, rapid-router: 6.3.7**

Upgraded to Python 3.12

## Thursday 29 August 2024

**codeforlife-portal: 7.2.0, rapid-router: 6.3.5**

* <mark style="color:purple;">**Released Python Den**</mark>
* Changed colour of upper-left hand corner text in Rapid Router game view from black to white.

## Friday 9 August 2024

**codeforlife-portal: 7.1.1, rapid-router: 6.0.2**

* Shoutout to [@Ridwanah](https://github.com/Ridwanah): Show failure popup when trying to deliver at a non-destination square.
* Fixed the "exploding flying van bug" where using an action block / command in front of a cow would cause a crash.

## Tuesday 6 August 2024

**codeforlife-portal: 7.1.0**

Added three email alerts for users who haven't been active in a while, warning them that their account is about to be anonymised. The first reminder happens 2 years since last activity, the second 2 years and 8 months, and the final reminder 2 years and 11 months, 1 month before the anonymisation happens at 3 years of inactivity.

## Thursday 1 August 2024

**codeforlife-portal: 7.0.0, rapid-router: 6.0.0**

* BREAKING CHANGE: Removed everything Kurono-related, including game dashboard functionality, Kurono-related text, images and videos and deregistered the URLs for Kurono.<br>
* Added a migration to clean dirty class data, i.e. to nullify the `creation_time` of the few classes that inexplicably had a `creation_time` set to before we actually started tracking that data.
* Reintroduced the missing buttons to the "Overwrite" popup in Rapid Router's level editor.
* Enabled the `is_animal_crossing()` and `sound_horn()` commands in Python levels.
* Gave the "sound horn" action a wait time equal to all other action animations, allowing for the highlighting of the "sound horn" block or the `sound_horn()` command to be visible.

## Wednesday 31 July 2024

**rapid-router: 5.27.0**

Shoutout to [@Ridwanah](https://github.com/Ridwanah): Updated the Python commands modal so it only shows the commands relevant to the level that's being played.

## Friday 19 July 2024

**codeforlife-portal: 6.46.0, rapid-router: 5.26.1**

* Introduced functional cookie to save a user's preferred language in Rapid Router.
* Functional cookies are now automatically deleted from the browser after a user withdraws their consent and navigates back to Rapid Router.
* 10 years celebration page is under construction!

## Friday 5 July 2024

Reintroduce the 2 email reminders for unverified users before their account gets anonymised.

## Monday 1 July 2024

**rapid-router: 5.25.0**

* Added a sounded effect for when the Electric Van starts.
* Added a "battery gauge" for the Electric Van, similar to the fuel gauge for the classic van.

## Thursday 27 June 2024

**rapid-router: 5.23.1**

Level subtitle, description and hint can now be customised with creating a level in the level editor.

## Wednesday 19 June 2024

**rapid-router: 5.22.0**

* Scenery (cows and traffic lights) can now be dragged directly from the sidebar in the level editor!
* Added solar panels to grass and farm scenery!
* Added the electric van as a character option!
* Blocks can now be translated into Catalan and Spanish.

## Thursday 6 June 2024

**rapid-router: 5.19.0**

* Scenery (trees, bushes and ponds) can now be dragged directly from the sidebar in the level editor!
* Disabled algorithm score for all custom levels
* Fix cow placement so they cannot be put on start or destination blocks

## Thursday 30 May 2024

**codeforlife-portal: 6.45.1, rapid-router: 5.18.2**

* Shoutout to [Jibran1998](https://github.com/Jibran1998): Updated the Gmail button links to search for our new email service domain
* Added missing translations for the "Do" block
* Clarified verification email that gets sent to released school students
* De-verify students when they are released as verification of their new email address is required
* Clarified error text when requesting to join a class that doesn't exist or isn't accepting join requests

## Thursday 23 May 2024

**aimmo: 2.11.3, codeforlife-portal: 6.44.9, rapid-router: 5.18.1**

Fixed level 36 so the van now drives under the trees instead of over them.

## Monday 20 May 2024

**codeforlife-portal: 6.44.5, rapid-router: 5.18.0**

* Introduced a translation feature for the blocks in Rapid Router! Initial deployment includes English (UK), English (US), French and Hindi.
* Updated the level editor to allow for creation of multiple destinations (houses)
* Fixed the "wonky" level editor layout
* Added the Gmail and Outlook redirection buttons to the password reset request sent page
* Updated the contribute page with more up to date figures

## Thursday 9 May 2024

**codeforlife-portal: 6.44.3, rapid-router: 5.16.25**

* Transferred all the other emails to DotDigital
* Ran migrations to clean illogical data states:
  * Anonymised "typeless" users
  * Anonymised empty schools
  * Verified all returning users
* All students are now automatically verified upon their first login
* Updated footer layout with social media icons

## Tuesday 23 April 2024

**codeforlife-portal: 6.41.12**

Moved the jQuery script tag higher up in the DOM - seems to have fixed, or at least warded off, the ghost bug.

## Friday 19 April 2024

**codeforlife-portal: 6.41.11, rapid-router: 5.16.24**

Host js-reverse script directly instead of downloading as an attempt to fix the jQuery ghost bug - turned out to be unrelated.

## Friday 12 April 2024

**codeforlife-portal: 6.41.10, rapid-router: 5.16.21**

* Transferred some of our email messages from AWS to DotDigital to help with email authentication:
  * Email address verification on account creation
  * Email address verification on account email change
  * Email address update notification
  * Parent's / Guardian's email address verification on account creation for independent user under 13
  * Email address verification first reminder
  * Email address verification second reminder
  * Forgotten password reset
* Updated Privacy Notice to highlight the use of YouTube embedded videos
* Fixed broken Mouseflow cookie

## Thursday 21 March 2024

**aimmo: 2.11.2, codeforlife-portal: 6.41.5, rapid-router: 5.16.21**

* Updated main logo to its trademarked version.
* Fixed broken mute cookie.

## Friday 15 March 2024

**codeforlife-portal: 6.41.3, rapid-router: 5.16.20**

* Updated text on email verification and reset password pages to highlight need to check spam folder.
* Updated solutions to levels 106-109 to replace `n` variable with `number`.

## Friday 1 March 2024

**codeforlife-portal: 6.41.2, rapid-router: 5.16.19**

Fixed issues relating to max scores in Rapid Router.

## Monday 19 February 2024

**aimmo: 2.11.1, codeforlife-portal: 6.41.1, rapid-router: 5.16.15**

* Added a button which links to Outlook on the email verification page.
* Added the 10-year badge image to the footer.
* Slightly amended level and episode names to make them consistent.
* Teachers can no longer select Episodes that aren't ready in the scoreboard.
* The scoreboard now properly shows the results for all Episodes to the teachers.

## Friday 2 February 2024

**codeforlife-portal: 6.40.0**

Added a link to the 2023 Impact Report in the footer.

## Tuesday 23 January 2024

**rapid-router: 5.16.12**

* Shoutout to [AbdelrahmanDeghedy](https://github.com/AbdelrahmanDeghedy): Fixed the saving functionality of level workspaces.
* Shoutout to [akurtle](https://github.com/akurtle): Removed level 14's solution's random block on the side of the workspace.

## Thursday 18 January 2024

**codeforlife-portal: 6.39.10, rapid-router: 5.16.10**

Shoutout to [AbdelrahmanDeghedy](https://github.com/AbdelrahmanDeghedy): The Start block now always spawns at the same location in the game, instead of a random location sometimes too close to the edge.

## Monday 8 January 2024

**rapid-router: 5.16.9**

Shoutout to [AbdelrahmanDeghedy](https://github.com/AbdelrahmanDeghedy): Dee no longer appears in the intro popup for level 116.

## Thursday 21 December 2023

**codeforlife-portal: 6.39.9, rapid-router: 5.16.8**

* Shoutout to [benbacardi](https://github.com/benbacardi): fixed the broken student login link in the level editor popups.
* Shoutout to [sebp999](https://github.com/sebp999): fixed the level editor so the "level language" setting persists through saving & loading.

## Tuesday 19 December 2023

**rapid-router: 5.16.6**

* Shoutout to [AbdelrahmanDeghedy](https://github.com/AbdelrahmanDeghedy): videos in Rapid Router popups now stop playing when the popup is closed.
* Shoutout to [juandesenvolvedor](https://github.com/juandesenvolvedor): renamed level 36 to include `else if` concept.

## Monday 11 December 2023

**rapid-router: 5.16.4**

* Replaced the van with the sleigh in the Start block during the Christmas theme.
* Updated the description of level 36 to show example code and cog icon.
* The level selection page now remembers which Episode the user was last on and opens that accordion by default.

## Thursday 30 November 2023

**aimmo: 2.11.0, rapid-router: 5.16.1**

* Imports in Kurono are now restricted to the ones used in the worksheets.
* Cows are now always visible in Rapid Router.
* The van now needs to be on the square directly before a cow in order to honk the horn to make it disappear, instead of two squares away.

## Tuesday 28 November 2023

**aimmo: 2.10.15, codeforlife-portal: 6.39.8, rapid-router: 5.15.13**

* Introduced `else` in Level 36 (in level intro and solution)
* Fixed and updated styles of missing Level Editor popup buttons

## Wednesday 15 November 2023

**aimmo: 2.10.12, codeforlife-portal: 6.39.4**

* No longer gathering and processing school postcodes
* School countries are now optional
* UK schools can be linked to a county, which is also optional
* Fixed and issue with the flow for changing emails addresses
* Now tracking worksheet usage, worksheet badges and game load time in Kurono

## Friday 3 November 2023

**aimmo: 2.10.9, codeforlife-portal: 6.38.1, rapid-router: 5.15.5**

* Created levels 110-122 in Rapid Router, within Episode 12 as an introduction to While Loops.
* Added episodes 13-15 to the levels list and marked them as coming soon.
* Added a formal method to capture volunteer acceptance of contributing terms.
* Password fields in forms now have a "reveal password" icon.
* Removed autocomplete for some password fields.
* Increased the size of the Rapid Router level map so it takes up the whole section.
* Updated the button styles for the hint and level failure / completion popups in Rapid Router.

## Tuesday 17 October 2023

**aimmo: 2.10.7, codeforlife-portal: 6.37.1, rapid-router: 5.12.3**

* Introduced cows to levels 38, 39 and 47
* Removed the game-creator and moved its logic to the Django aimmo app

## Wednesday 20 September 2023

**codeforlife-portal: 6.37.0**

* Unverified users are now anonymised instead of deleted.
* Keep track of daily and total unverified users anonymisations.

## Tuesday 19 September 2023

**codeforlife-portal: 6.36.2**

Implemented a quick fix for the 2FA bug.

## Thursday 7 September 2023

**codeforlife-portal: 6.36.0**

Keep track of total registrations.

## Tuesday 5 September 2023

**codeforlife-portal: 6.35.3, rapid-router: 5.11.3**

* Added a comma in some of the Rapid Router levels instructions for better readability.
* Only the selected road type in the level editor has a border now to improve user experience.
* Created two automated email verification reminders for unverified users who registered 7 days ago and 14 days ago.
* Created an automated deletion job which deletes unverified users who have registered over 19 days ago.

## Monday 14 August 2023

**aimmo: 2.10.6, codeforlife-portal: 6.34.1**

* UK schools are now linked to a county.
* Kurono games are now stopped immediately upon deletion.
* Implemented a max limit of 15 for concurrent Kurono running games. Attempting to create or start a 16th game will show the user a friendly error message.
* Updated the starter code for worksheet 2 to reflect changes on Gitbook.

## Thursday 20 July 2023

**aimmo: 2.9.1, codeforlife-portal: 6.33.6, rapid-router: 5.11.1**

* Fixed a bug with the password strength indicator on password reset.
* Fixed a bug with the password reset email form.

## Thursday 29 June 2023

**rapid-router: 5.11.0**

Enabled secure boot for GKE nodes.

## Wednesday 28 June 2023

**aimmo: 2.9.0, codeforlife-portal: 6.33.0**

* Upgraded to Python 3.8.
* Added a check for commonly used passwords upon registration.

## Friday 16 June 2023

**aimmo: 2.8.7, codeforlife-portal: 6.31.1**

* Removed intermediate Teaching Resources pages, dropdowns now link directly to Gitbook.
* Shortened email verification links.
* Fixed Kurono cross-worksheet badges trigger bug.
* Testing out new GA4 script.

## Wednesday 31 May 2023

**codeforlife-portal: 6.30.11**

Fixed mistakenly removed riveted.js library.

## Thursday 25 May 2023

**aimmo: 2.8.5, codeforlife-portal: 6.30.10, rapid-router: 5.10.6**

Updated an outdated JS library.

## Sunday 30 April 2023

**aimmo: 2.7.0, codeforlife-portal: 6.30.4**

* Updated Kubernetes to 1.26 and Agones to 1.31.
* Addressed a number of security issues related to the clusters and node pools.
* Added a custom action in the Django admin panel allowing admins to bulk stop Kurono games.
* Added text in Terms of Use describing the school admin powers.

## Wednesday 26 April 2023

**aimmo: 2.5.20, codeforlife-portal: 6.30.2**

Implemented JWT tokens for the registration process, allowing users to have simultaneous valid email verification tokens on registration.

## Wednesday 12 April 2023

**aimmo: 2.5.19, codeforlife-portal: 6.29.9, rapid-router: 5.10.5**

* Fixed Avatar auth token generation when creating an Avatar in Kurono.
* Teachers can now access the account settings page even if they don't have a school.
* Updated the solution for level 43.
* Matched the green in the level editor sidebar to the one in the actual game.
* Verification emails are now sent before the newsletter confirmation emails.

## Tuesday 21 March 2023

**aimmo: 2.5.18, codeforlife-portal: 6.29.4**

* Updated text and padding of the Get Involved page.
* Added a "pause" functionality to the Kurono game - users can now pause their avatar, effectively stopping their code and the logs while the rest of the game carries on.

## Monday 13 March 2023

**aimmo: 2.5.16**

Updated the Kurono avatar marker - made it bigger, changed the model to the Kurono logo and added a bounce animation.

## Friday 10 March 2023

**rapid-router: 5.10.4**

* Reverted an issue introduced in the previous deployment which made the map no longer scrollable on tablets.
* Fixed the broken coin image that appears in the Episode title when all levels have been completed.

## Wednesday 8 March 2023

**rapid-router: 5.10.2**

Fixed some issues with the zoom buttons in Rapid Router, namely, the game doesn't randomly zoom in on the first input, and the buttons remain in the screen for all screen sizes.

## Tuesday 21 February 2023

**rapid-router: 5.10.1**

Fixed scoreboard bug whereby custom level names prevented the page from loading.

## Friday 17 February 2023

**aimmo: 2.5.15, codeforlife-portal: 6.29.3, rapid-router: 5.10.0**

* Fixed level editor disappearing scenery bug
* Updated introductory videos order in Rapid Router

## Wednesday 15 February 2023

**aimmo: 2.5.12, codeforlife-portal: 6.29.2, rapid-router: 5.9.1**

Fixed a broken DB migration.

## Monday 6 February 2023

**codeforlife-portal: 6.29.0**

Added ratelimit to the student login as well as the tracking for the lockout reset mechanic.

## Wednesday 25 January 2023

**codeforlife-portal: 6.28.3, rapid-router: 5.8.1**

Updated Privacy Notice with updated text and correct personal data information.

## Thursday 19 January 2023

**aimmo: 2.5.11, codeforlife-portal: 6.28.0, rapid-router: 5.8.0**

* Added cows and cow-related blocks to Rapid Router
* Implemented a data tracker for when users reset their passwords to unlock their accounts (teachers and independent students only)
* Having no nearby artefacts in worksheet 4 no longer raises an error which blocks the user from progressing, instead it prints out a more user-friendly warning.

## Wednesday 4 January 2023

**codeforlife-portal: 6.27.8, rapid-router: 5.7.4**

* Removed the snow in Rapid Router.
* Coding club page link now opens in the same tab as expected.

## Monday 19 December 2022

**codeforlife-portal: 6.27.7**

* Updated instructions for level control and added a usage tracker for it.
* Fixed broken independent student newsletter subscription.
* Added a link to the coding clubs page on the Get Involved page.

## Tuesday 6 December 2022

**codeforlife-portal: 6.27.3, rapid-router: 5.7.3**

* Brought back Rapid Rudolph
* Updated incorrect email address in privacy policy.
* Update Rapid Router UI including previous and next level buttons.

## Wednesday 16 November 2022

**aimmo: 2.5.10, codeforlife-portal: 6.27.1, rapid-router: 5.6.1**

* Teachers can now control which levels of Rapid Router are available on a per-class basis.
* Fixed missing padding in level editor.

## Monday 31 October 2022

**aimmo: 2.5.7, codeforlife-portal: 6.24.1**

Fixed a bug where old games would show in the Kurono games table.

## Tuesday 25 October 2022

**aimmo: 2.5.6, codeforlife-portal: 6.23.1, rapid-router: 5.5.2**

* Upgraded Kubernetes to version 1.23 on all Kurono resources.
* Admin teachers can now create Kurono games for their colleagues.
* Updated Rapid Router Python levels styles.

## Thursday 13 October 2022

**aimmo: 2.5.2, codeforlife-portal: 6.22.1, rapid-router: 5.5.1**

* Made the alert banner on the homepage dynamic.
* Fixed some bugs in the level editor.
* Admin teachers can now see, play, edit and delete any Kurono game in their school.

## Friday 7 October 2022

**codeforlife-portal: 6.21.0, rapid-router: 5.5.0**

Admin teachers can now see, play and share any custom level in their school.

## Friday 30 September 2022

**codeforlife-portal: 6.20.3**

Updated the Data Protection Officer's email address in the Privacy Policy.

## Wednesday 21 September 2022

**codeforlife-portal: 6.20.2**

Removed the Kurono maintenance banner.

## Thursday 15 September 2022

**codeforlife-portal: 6.20.1, rapid-router: 5.4.3**

* Fixed missing cookie banner and settings
* Fixed some UI bugs in Rapid Router

## Friday 9 September 2022

**codeforlife-portal: 6.19.1**

* Added code clubs page with free downloadable content
* Updated text to registration forms
* Fixed issue where the Kurono preview video would not load on the independent student dashboard

## Tuesday 6 September 2022

**aimmo: 2.4.6, codeforlife-portal: 6.18.3, rapid-router: 5.4.2**

* Fixed a major issue where deployment was broken by removing the legacy django-autoconfig package
* Added a banner on the homepage to warn users of ongoing issues with Kurono
* Updated session timeout to 30 minutes and added a 2 minute countdown to warn users of it
* Fixed some issues with Rapid Router button designs
* Users can now see their scores for custom levels on the scoreboard page

## Friday 5 August 2022

**codeforlife-portal: 6.16.0, rapid-router: 5.3.1**

* Admin teachers can now see and moderate all custom levels in their school
* Admin teachers can now see, accept and reject all external requests to their school's classes
* Updated Rapid Router icons
* Updated Rapid Router Python levels design and made each component resizable

## Wednesday 27 July 2022

**aimmo: 2.4.3, codeforlife-portal: 6.15.4**

* Admin teachers can now see, edit and delete all the classes in their school
* Admin teachers can now create a class for a fellow teacher
* Updated the "Make admin" popup

## Thursday 14 July 2022

**aimmo: 2.4.1, codeforlife-portal: 6.15.3, rapid-router: 5.1.0**

* Updated Rapid Router levels design
* Removed Dee from Python levels
* Added Bav the Brain to brainteaser levels
* Admin teachers can now see all classes in their school
* Gave admin teachers the ability to create classes for other teachers
* Updated the "Make teacher admin" popup
* Created child-friendly versions of the Privacy Policy and Terms of Use
* Independent students under 13 now need to provide their parents' or guardian's email address

## Friday 1 July 2022

**aimmo: 2.4.0, codeforlife-portal: 6.12.4, rapid-router: 4.4.1**

* Gave admin teachers the possibility to invite other teachers directly to their school
* Removed the ability to join another teacher's school by looking it up and sending a join request
* Added a confirmation popup to the independent student account deletion process
* Updated the teacher registration form and added a consent checkbox
* Added a one hour screen time warning popup
* Made the Rapid Router scoreboard clearer and easier to work with

## Tuesday 21 June 2022

**aimmo: 2.3.5, codeforlife-portal: 6.8.9**

* Removed newsletter signup for independent students
* Fixed registration boxes width

## Friday 17 June 2022

**aimmo: 2.3.4, codeforlife-portal: 6.8.8, rapid-router: 4.3.0**

* Added badges for challenge 1 in Kurono
* Independent students can now delete their accounts
* Signing up for the newsletter using the footer form now requires the user to be over 18
* Rapid Router solutions for levels 101-104 now have a main() method
* Teachers can now re-share the levels that are shared with them
* Fixed deleting workspaces in Rapid Router
* In Kurono, when moving towards is blocked by an avatar, a message is now displayed in logs
* Security updates

## Thursday 19 May 2022

**aimmo: 2.1.2, codeforlife-portal: 6.8.2**

* Add worksheet 4 for Kurono
* Security updates

## Thursday 12 May 2022

**codeforlife-portal: 6.6.0, rapid-router: 4.1.0**

* Update Rapid Router level 48 to include multiple houses
* Anonymise schools and classes without any active teachers

## Thursday 5 May 2022

**codeforlife-portal: 6.5.2**

* School is now anonymised when the last admin leaves and marked as inactive
* Fix email display and link

## Friday 29 April 2022

**aimmo: 2.0.4, codeforlife-portal: 6.4.4, rapid-router: 4.0.9**

* Anonymise classes instead of deleting them
* Update style and content of emails sent to users
* Update Pyodide to fix Kurono issue running on certain browsers
* Rename `v` variable in Rapid Router to `my_van`
* Fix multiple start blocks bug in Rapid Router

## Friday 8 April 2022

**codeforlife-portal: 6.3.1, rapid-router: 4.0.4**

* Delete account functionality for teacher
* Admin role is passed to the next teacher when admin account is deleted
* Fix bugs where deleted teachers were showing
* Update image credits and alt texts

## Friday 18 March 2022

**rapid-router: 4.0.2**

* Fixed Rapid Router not loading properly

## Friday 18 March 2022

**aimmo: 2.0.1, codeforlife-portal: 6.0.1, rapid-router: 4.0.1**

* Upgraded Django to version 3.2

## Monday 14 March 2022

**codeforlife-portal: 5.42.0**

* Independent student and login update to use email only and no username
* Added videos to Educate and Play pages

## Tuesday 8 March 2022

**rapid-router: 3.8.9**

Fixed student scoreboard not showing data.

## Friday 4 March 2022

**codeforlife-portal: 5.40.0**

Added Dotmailer address books integration on registration / newsletter subscription (user types).

## Thursday 3 March 2022

**codeforlife-portal: 5.39.1, aimmo: 1.4.11, rapid-router: 3.8.8**

* Scoreboard now does not display everything on page load
* Kurono student dashboard update
* Fixed Rapid Router freeze issue when using fast play
* Fixed Crowdin resources that were blocked

## Tuesday 1 March 2022

**rapid-router: 3.8.5**

Fixed Crowdin's In-Context translation tool.

## Monday 28 February 2022

**rapid-router: 3.8.3**

Fixed bug introduced with previous level 74 improvement.

## Friday 25 February 2022

**rapid-router: 3.8.2**

Improved Rapid Router level 74 solution.

## Thursday 24 February 2022

**codeforlife-portal: 5.37.2, aimmo: 1.4.10, rapid-router: 3.8.1**

* Thickened road divider lines in Rapid Router
* Updated remove / leave teacher page

## Wednesday 23 February 2022

**codeforlife-portal: 5.36.1, aimmo: 1.4.9, rapid-router: 3.8.0**

* Improved registration process
* Disabled local storage in Rapid Router

## Thursday 17 February 2022

**codeforlife-portal: 5.35.1, aimmo: 1.4.7, rapid-router: 3.7.8**

* Ensure no duplication of email when releasing student
* Cookies updates

## Monday 14 February 2022

**codeforlife-portal: 5.34.3, aimmo: 1.4.6**

* Data tracking for join and release of student
* Updated starter code for Kurono worksheet 3

## Wednesday 9 February 2022

**codeforlife-portal: 5.33.3**

Cleaned up some teacher and independent student accounts that had the same email.

## Monday 7 February 2022

**codeforlife-portal: 5.33.0**

User sessions will now expire on browser close.

## Thursday 3 February 2022

**codeforlife-portal: 5.32.3**

* Updated 2FA pages
* New registration for independent student or teacher now require unique email across the different account types

## Friday 28 January 2022

**rapid-router: 3.7.1**

Removed snow from Rapid Router.

## Thursday 27 January 2022

**aimmo: 1.4.5, codeforlife-portal: 5.32.0, rapid-router: 3.7.0**

* Updated OneTrust instance for cookie management
* Added scrollbar in Python pane in Rapid Router Python levels
* Made Python pane resizeable in Rapid Router Python levels
* Made email verification link expiry time explicit on verification page
* Redesigned password reset and email verification pages
* Redesigned Kurono teacher dashboard
* Redesigned level moderation page
* Fixed level moderation delete level bug
* Scoreboard page now loads all classes and levels data by default
* Deleting Kurono games now archives them instead of deleting them completely
* Upgraded to Kubernetes 21.7.0
* Tidied up independent student duplicate accounts with the same email

## Thursday 13 January 2022

**aimmo: 1.3.3, codeforlife-portal: 5.28.1, rapid-router: 3.5.7**

* Account details page updates
* Registration page update
* Kurono worksheet 2 starter code update
* Crashing, running a red light and running out of fuel in Rapid Router now count as an attempt
* Scoreboard filter update

## Friday 7 January 2022

**codeforlife-portal: 5.27.9, rapid-router: 3.5.5**

Fix scoreboard loading issues.

## Wednesday 5 January 2022

**codeforlife-portal: 5.27.8, rapid-router: 3.5.4**

* Fix alignment and text issues in edit class pages
* Fix scoreboard spacing and functional issues
* Allow logged in users to view other login pages

## Friday 31 December 2021

**codeforlife-portal: 5.27.5, rapid-router: 3.5.3**

* Update Scoreboard page with new designs and Improvements table
* Update all class edit pages

## Monday 20 December 2021

**aimmo: 1.3.2, codeforlife-portal: 5.26.14, rapid-router: 3.4.5**

* Remove Wagtail
* Align pages to container width
* Fix 2FA QR code not showing bug
* Fix 2FA banner bug
* Stick website footer to bottom of the screen
* Remove all Rapid Router resource pages and link to Gitbook instead
* Fix heading sizes on Play page

## Thursday 9 December 2021

**codeforlife-portal: 5.26.3, rapid-router: 3.4.4**

* Student login details CSV now includes student passwords and class link
* Fix for class code login issue
* Rapid Router functions renaming to be more descriptive
* Data and error logging

## Friday 3 December 2021

**codeforlife-portal: 5.24.2, rapid-router: 3.4.3**

* Enabled Rapid Rudolph :christmas\_tree:
* Updated Educate page
* Updated Play page
* Updated teacher and independent student navigation bars&#x20;
* Fixed alignment issues on student Kurono dashboard
* Fixed alignment of header and footer
* Fixed teacher dashboard and Kurono page
* Fixed size of table buttons

## Friday 26 November 2021

**codeforlife-portal: 5.21.3, rapid-router: 3.4.1**

Further CSP fixes.

## Thursday 25 November 2021

**aimmo: 1.3.0, codeforlife-portal: 5.21.2, rapid-router: 3.4.0**

* Home Learning page update and Independent student resources
* Fix for deleted students appearing at places
* Class code is now case insensitive plus related fixes
* Implemented CSP header
* Kurono worksheet updates - moved from model to a data file
* Privacy policy and Terms of use pages design updates

## Friday 19 November 2021

**codeforlife-portal: 5.17.1, rapid-router: 3.3.1**

* Updated Rapid Router level selection page
* Removed django-hijack

## Friday 12 November 2021

**codeforlife-portal: 5.17.0**

Added student login type data.

## Friday 5 November 2021

**rapid-router: 3.2.0, codeforlife-portal: 5.16.3**

* Moved and linked Kurono resources to Gitbook
* Updated teacher onboarding pages
* Updated About Us page
* Updated student dashboard including independent student
* Updated lockout page
* Removed Ocado logos from in-game images
* Added functionality to import students from CSV file
* Fix for class deletion

## Wednesday 20 October 2021

**rapid-router: 3.1.0, codeforlife-portal: 5.10.0**

* Updated most of the Rapid Router level help texts (morning)
* Updated student deletion data (afternoon)

## Monday 18 October 2021

**codeforlife-portal: 5.9.0**

Added school and class creation time and data.

## Friday 15 October 2021

**aimmo: 1.1.0, codeforlife-portal: 5.8.0**

* Updated reminder cards design
* Replaced `IndexError` of `scan_nearby` returned list with a more meaningful error
* Fixed "Update account details" in the account dropdown
* Added login metrics
* Upgraded reportlab and pillow libraries

## Monday 11 October 2021

**codeforlife-portal: 5.6.1, rapid-router: 3.0.5**

* Student login updated - option with class code or with direct link
* Updated page with student login details
* Updated class code format and student password policy
* Split teacher dashboard in 3 tabs and updated designs
* Updated teacher password policy
* Updated login pages to have branding shapes

## Monday 27 September 2021

Updated Dotmailer's "Thanks for staying" campaign ID env var to point to the new one, which is aligned to the new design.

## Thursday 23 September 2021

**codeforlife-portal: 5.2.3, rapid-router: 3.0.4**

* Fixed some issues with page banners and header styles
* Improved 2FA pages UI to match new styles
* Disabled Turkish language localisation in Rapid Router after reports of it causing issues in classrooms

## Wednesday 15 September 2021

**codeforlife-portal: 5.2.1, rapid-router: 3.0.3**

* [@sebp999](https://github.com/sebp999): Fixed bug with deleting Rapid Router custom level
* Added index to Terms of Use
* Removed country flag from Update School form
* Header image repositioning and other header updates

## Friday 10 September 2021

**codeforlife-portal: 5.0.1**

Button and table display fixes.

## Monday 6 September 2021

**aimmo: 1.0.0, codeforlife-portal: 5.0.0, rapid-router: 3.0.0**

* Updated website logo, design and style
* Removed teacher title
* Updated privacy policy

![New website design](/files/-MivIkS9SJl5eZAkLuMX)

## Monday 23 August 2021

**codeforlife-portal: 4.34.0, rapid-router: 2.7.14**

* [@sebp999](https://github.com/sebp999): Disable saving and loading of workspace when user is not logged in
* [@sebp999](https://github.com/sebp999): Disable save and load buttons in the game template when user is not logged in

## Thursday 5 August 2021

**codeforlife-portal: 4.33.0**

Added Get Involved and Contributor pages.

## Monday 26 July 2021

**aimmo: 0.69.19, codeforlife-portal: 4.32.4, rapid-router: 2.7.13**

Improved user experience of login forms.

## Thursday 22 July 2021

**aimmo: 0.69.18, codeforlife-portal: 4.32.3**

* Kurono games now stop properly
* Fixed empty game name bug
* Dockerised portal for development

## Wednesday 7 July 2021

**aimmo: 0.69.14, codeforlife-portal: 4.31.4, rapid-router: 2.7.12**

* Changed Kurono game load text to be more informative
* Improved load time of Kurono games

## Monday 28 June 2021

**codeforlife-portal: 4.31.2**

Enforced account's email verification on login.

## Friday 25 June 2021

**codeforlife-portal: 4.31.1, rapid-router: 2.7.11**

* Additional hint text for Rapid Router level 80 onwards
* Top navigation bar fix on onboarding phase

## Wednesday 23 June 2021

**codeforlife-portal: 4.30.13, rapid-router: 2.7.10**

* Display updates to the Rapid Router 'if else' block: clearer separation, clearer hints
* Security header update

## Thursday 17 June 2021

**codeforlife-portal: 4.30.12, rapid-router: 2.7.7, aimmo: 0.69.11**

* Upgrade to Django 2.2.24
* Prevent changing an account's email address to that of another account's

## Thursday 10 June 2021

**codeforlife-portal: 4.30.8, rapid-router: 2.7.5, aimmo: 0.69.8**

* Prevent concurrent login sessions for the same user
* Security fixes and documentation updates

## **Friday 21 May 2021**

**codeforlife-portal: 4.29.2, rapid-router: 2.7.4, aimmo: 0.69.3**

* Added ability to edit saved custom levels
* Fixed invalid character bug

## **Friday 21 May 2021**

* Fixed ReCaptcha bypass issue
* Added ratelimit to sensitive forms and re-implemented 24 hour lockout
* Fixed session not invalidated after password change issue
* Removed autocomplete from forms
* Added warning banner for email verification

![](https://assets.sutori.com/user-uploads/image/b2d431a5-aaa4-403d-91be-e5e0aa4e050d/cybersecurity-vs-information-security-illustration.jpeg)

## **Friday 7 May 2021**

Security fixes and JavaScript updates

![](https://assets.sutori.com/user-uploads/image/629c4170-70ca-4c42-aeb2-0b47785728b6/kisscc0-cute-lock-icons-5b37078a752296.5931807415303330664798.png)

## **Thursday 22 April 2021**

* Added Dotmailer consent renewal form
* Fixed interchangeable GETs/POSTs issues

![](https://assets.sutori.com/user-uploads/image/43cc7bae-a80f-422d-8018-84f8b4434d67/Selection_357.png)

## **Monday 19 April 2021**

* OneTrust Cookie Management
* Updated Privacy Policy

![](https://assets.sutori.com/user-uploads/image/c5b25772-ce88-4661-9f80-43d8875f401f/Screenshot%20from%202021-04-19%2017-16-44.png)

## **Thursday 15 April 2021**

Removed the admin login page! Admin access now requires a superuser profile with 2FA enabled.

![](https://assets.sutori.com/user-uploads/image/44fc94fd-33a8-4a43-addc-048a0f24337f/shutterstock_346773854.jpeg)

## **Friday 9 April 2021**

* Fixed a link in the Worksheet 3 resources.
* Made portal only send Google Analytics events in prod environment.

![](https://assets.sutori.com/user-uploads/image/d86474b6-359f-4ff2-a81d-c63673c4dc3d/Screenshot%20from%202021-04-15%2017-45-30.png)

## **Thursday 1 April 2021**

* Released Kurono Challenge 3!
* Added MoveTowardsAction and scan\_nearby methods to Kurono.
* Challenge 3 has a new theme and two new different artefacts.
* PDFs and solutions file have been updated with Challenge 3.
* Not an April Fools, the above actually happened 🙂

![](https://assets.sutori.com/user-uploads/image/f06a2806-b6ba-468f-b558-ae52d7259e13/ancient_active\[1].png)

## **Friday 26 March 2021**

* Fixed worksheet selection bug.
* Fixed Recaptcha dual-script bug.

![](https://assets.sutori.com/user-uploads/image/9600b544-ae30-47df-b31b-bee186683723/Selection_346.png)

## **Monday 8 March 2021**

* Revamped the admin login page.
* Added 2FA to the admin login form for accounts with 2FA.

![](https://assets.sutori.com/user-uploads/image/3f1eac09-9c7a-4a40-9c6c-1475813510cd/Selection_321.png)

## **Friday 5 March 2021**

Fixed pickups not spawning.

![](https://assets.sutori.com/user-uploads/image/1b2c624f-f723-4734-9fbe-95c18b3d0daf/Screenshot%20from%202021-03-09%2013-26-22.png)

## **Monday 1 March 2021**

Navigation and text updates on Kurono pages.

![](https://assets.sutori.com/user-uploads/image/b2f2ccb3-0be3-4c30-b4bf-eadde6937d56/Screenshot%202021-03-02%20at%2014.57.07.png)

## **Monday 1 March 2021**

Consent data when signing up to newsletter is now saved.

![](https://assets.sutori.com/user-uploads/image/c71a68ac-8aa0-42a6-8603-c579e869e979/Selection_297.png)

## **Monday 1 March 2021**

Agones has been integrated to improve game creation and loading.

![](https://assets.sutori.com/user-uploads/image/5db142ce-c6dc-4a07-ae32-3f715ea5966d/Screenshot%202021-03-02%20at%2014.53.42.png)

## **Monday 1 March 2021**&#x20;

* Stats on Home and About page updated with the latest data.
* Copyright year in the footer now updates automatically.

![](https://assets.sutori.com/user-uploads/image/9807bfd0-2832-433d-bbe9-dbcf7217b589/Selection_296.png)

## **Monday 1 March 2021**

Console update to increase font size and make colour contrast more accessible.

![](https://assets.sutori.com/user-uploads/image/3356b514-6e03-4ba5-89be-6cff4ac403b4/Screenshot%202021-03-01%20at%2018.30.06.png)

## **Tuesday 9 February 2021**

Fixed the "Trash Can" bug.

![](https://assets.sutori.com/user-uploads/image/af4a35d9-d95e-4f98-9872-ab0ce5ebb6b7/Selection_268.png)

## **Tuesday 2 February 2021**

* Finished updating games table on Teacher Kurono Dashboard page.
* Added the Kurono solutions file to the Kurono Packs page.

![](https://assets.sutori.com/user-uploads/image/51d02723-360d-44d7-a3e3-4a4e10fe2f47/Selection_260.png)

## **Friday 29 January 2021**

* Updated the Teacher Kurono Dashboard page by simplifying the resources section and add the "Add Class" and "Challenge" dropdowns.
* Updated Recaptcha script in hope to fix Recaptcha issues in certain countries.

![](https://assets.sutori.com/user-uploads/image/5ff6c843-a099-4991-87a7-1a6ba9ca7890/screencapture-codeforlife-education-teach-kurono-dashboard-2021-02-01-15_49_01.png)

## **Thursday 21 January 2021**

* Added Kurono Resources.
* Added Kurono Teaching Packs.
* Reset Code has been fixed in Kurono - it now resets the code to the Worksheet's starter code.

![](https://assets.sutori.com/user-uploads/image/e110007e-dbf0-4d44-985e-57c3b7bd1d78/Screenshot%202021-01-21%20120430.jpeg)

## **Wednesday 30 December 2020**

The sub nav has been fixed - it is now visible on mobile!

![Subnav on mobile](https://assets.sutori.com/user-uploads/image/80fd5cfb-0892-4537-86d4-fa72ab460301/Selection_215.png)

## **Wednesday 23 December 2020**

We upgraded to Django 2.2!&#x20;

![](https://assets.sutori.com/user-uploads/image/b5bcb426-acc5-4322-8e42-90ba8bcb223f/django2.png)

## **Monday 14 December 2020**

Rapid Rudolph has returned!

![](https://assets.sutori.com/user-uploads/image/255ae519-015d-4ca4-8db7-72527aee9501/Selection_205.png)

## **Monday 14 December 2020**

The Kurono "Add Game" form was improved by clarifying the labels


# Project Management

Manage epics and tasks in Code for Life.

## GitHub

Code for Life is managed using [GitHub Issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/learning-about-issues/about-issues) and [GitHub Projects](https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects).

### [Issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/learning-about-issues/about-issues)

An issue is a task (most common) or epic that is assigned to a repo ([see issue types](#issue-relationships-and-types)).

{% hint style="info" %}
All of Code for Life's repos are prefixed with "codeforlife-" ([see](https://github.com/orgs/ocadotechnology/repositories?q=codeforlife-)), except for [rapid-router](https://github.com/ocadotechnology/rapid-router).
{% endhint %}

### [Projects](https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects)

Simply put, a GitHub project allows you to collect issues from one or more repos, visualize them in a [variety of views](#project-views), and create your own [custom workflows](#automated-workflows). From GitHub's docs:

> A project is an adaptable table, board, and roadmap that integrates with your issues and pull requests on GitHub to help you plan and track your work effectively at the user or organization level. You can create and customize multiple views by filtering, sorting, slicing, and grouping your issues and pull requests to manage your team backlogs and roadmaps, visualize work with configurable charts, add custom fields to track metadata specific to your team, create templates, share status updates, and automate your projects.

## Custom Project Fields

GitHub Projects supports creating [custom fields](https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields) to track different values per issue. Below are the custom fields we define.

<figure><img src="/files/HXxctbyUs8meFe0XFW8Z" alt="" width="331"><figcaption><p>How the CFL project-card appears on an issue</p></figcaption></figure>

### Status

\[[single select](https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields/about-single-select-fields)] The current status of a [task](#tasks) in our [Definition of Done](#definition-of-done).

**Options:**

1. [**To Do**](#id-2.-to-do) - To be completed but haven't started yet.
2. [**In Progress**](#id-3.-in-progress) - Actively being worked on (unless blocked).
3. [**Ready For Review**](#id-4.-ready-for-review) - Ready to be reviewed but haven't started yet.
4. [**In Review**](#id-5.-in-review) - Actively being reviewed.
5. [**Staging**](#id-6.-staging) - Has been deployed to staging and needs testing.
6. [**Production**](#id-7.-production) - Has been deployed to production and needs testing.
7. [**Closed**](#id-8.-closed) - Has been completed.

### Size

\[[single select](https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields/about-single-select-fields)] Approximately how many [man-hours](https://en.wikipedia.org/wiki/Man-hour) is needed to close a [task](#tasks).

{% hint style="danger" %}
[Epics](#epics) should NOT be sized; their size may be inferred by summing the sizes of their sub-issues.
{% endhint %}

**Options:**

1. **XS** - Extra small (approx. 2hrs / ¼ working day).
2. **S** - Small (approx. 4hrs / ½ working day).
3. **M** - Medium (approx. 8hrs / 1 working day).
4. **L** - Large (approx. 16hrs / 2 working days).
5. **XL** - Extra large (approx. 24hrs / 3 working days).

{% hint style="warning" %}
If a [task](#tasks) is larger than an **XL**, it should be broken down into an [epic](#epics) with smaller tasks. Avoid "mega" tasks.
{% endhint %}

### Sprint

\[[iteration](https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields/about-iteration-fields)] The [sprint](https://www.atlassian.com/agile/scrum/sprints) the [task](#tasks) is scheduled to be worked on. Our sprints are 2-week intervals.

{% hint style="danger" %}
[Epics](#epics) should NOT be assigned to a sprint.
{% endhint %}

### Est. start

\[[date](https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields/about-date-fields)] The estimated start-date of an [epic](#epics). Used in our [Epic Roadmap](#epic-roadmap).

{% hint style="success" %}
ONLY [epics'](#epics) timelines should be estimated when [roadmapping](#epic-roadmap).
{% endhint %}

### Est. end

\[[date](https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields/about-date-fields)] The estimated end-date of an [epic](#epics). Used in our [Epic Roadmap](#epic-roadmap).

{% hint style="success" %}
ONLY [epics'](#epics) timelines should be estimated when [roadmapping](#epic-roadmap).
{% endhint %}

### Category

\[[single select](https://docs.github.com/en/issues/planning-and-tracking-with-projects/understanding-fields/about-single-select-fields)] The type of work involved in a [task](#tasks).

{% hint style="danger" %}
&#x20;[Epics](#epics) should NOT be categorized; sub-issues may span multiple categories.
{% endhint %}

**Options:**

1. :computer: ( a.k.a. **:computer:** ) - Software development.
2. :art: ( a.k.a. **:art:** ) - Design.
3. :mag: ( a.k.a. **:mag:** ) - Research.
4. :books: ( a.k.a. **:books:** ) - Educational resources.
5. :gear: ( a.k.a. **:gear:** ) - Operations.

<details>

<summary>Examples of tasks per category</summary>

:computer: develop a new feature.

:computer: squash a bug.

:computer: deploy a service.

:computer: fix a security vulnerability.

:art: design a user interface component.

:art: design a page layout.

:art: design some imagery/iconography/branding.

:art: design some marketing/event materials.

:mag: conduct market/competitor research.

:mag: consolidate feedback provided in user-support tickets.

:mag: actively seek feedback on existing functionality.

:mag: investigate which feature to develop next.

:books: write a lesson plan.

:books: plan a game level.

:books: write a brain teaser.

:books: write a coding-club pack.

:gear: consult with a legal professional about a concern.

:gear: make a payment/budget.

:gear: create & schedule a marketing campaign.

:gear: organize an event.

</details>

## Definition of Done

Our [Definition of Done](https://www.atlassian.com/agile/project-management/definition-of-done) is defined using our custom [Status](#status) field. The order of the statuses matter as each subsequent status is one step closer to a [task](#tasks) being "[closed](#id-8.-closed)". As seen on our [Task Board](#task-board), the leftmost/first ([No Status](#id-1.-no-status)) column is where you find newly created tasks and the rightmost column is where you find [Closed](#id-8.-closed) tasks; the general idea is to move the tasks from the left side of the board to the right.

<figure><img src="/files/CGVolnGr9UzIk2Z3UdX2" alt=""><figcaption><p>The status columns in order (from left to right)</p></figcaption></figure>

Here's a high-level overview of how tasks move throughout the columns (not all possible paths).

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]" %}

Below are the statuses in order, each with:

* a description of the conditions under which a [task](#tasks) qualifies for the status;
* general do's & do-not's for [tasks](#tasks) in this status;
* a list of acceptable previous/next status changes.

### 1. No Status

Technically this is the absence of a status and not an actual status. Newly created [tasks](#tasks) go here.

When a [task](#tasks) is first created, it should NOT be allocated a status.

<p align="center"><strong>Acceptable status changes:</strong></p>

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

NS --> IP
NS --> C

style NS stroke:#E0004D,stroke-width:4px
linkStyle 0,9,10 stroke:#E0004D,stroke-width:4px" %}

* :arrow\_right: [**To Do**](#id-2.-to-do) - if a [task](#tasks) is assigned to the current sprint or a previous sprint.
* :arrow\_right: [**In Progress**](#id-3.-in-progress) - if a [task](#tasks) is actively being worked on, regardless of sprint.
* :arrow\_right: [**Closed**](#id-8.-closed) - if a [task](#tasks) is closed, no longer relevant or a duplicate of another [task](#tasks).

### 2. To Do

[Tasks](#tasks) that have [been prioritized for this sprint](#sprint-planner) and are aimed to be completed by end-of-sprint. [Tasks](#tasks) not started from previous sprints will remain in this column.

<p align="center"><strong>Acceptable status changes:</strong></p>

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

TD --> NS
TD --> C

style TD stroke:#E0004D,stroke-width:4px
linkStyle 1,9,10 stroke:#E0004D,stroke-width:4px" %}

* [**No Status**](#id-1.-no-status) :arrow\_left: - if a [task](#tasks) is unassigned from the current sprint or assigned to a future sprint.
* :arrow\_right: [**In Progress**](#id-3.-in-progress) - if a [task](#tasks) is actively being worked on, regardless of sprint.
* :arrow\_right: [**Closed**](#id-8.-closed) - if a [task](#tasks) is closed, no longer relevant or a duplicate of another [task](#tasks).

### 3. In Progress

[Tasks](#tasks) actively being worked on, regardless if they're assigned to a sprint or not.

If a [task](#tasks) is blocked, by which we mean it cannot be progressed by the assignee(s), it should be labelled with (search "blocked" in labels to find these):

* ":octagonal\_sign:" if the [task](#tasks) can be unblocked by someone *inside of Ocado;*
* ":earth\_africa::octagonal\_sign:" if the [task](#tasks) can ONLY be unblocked by someone *outside of Ocado*.

<p align="center"><strong>Acceptable status changes:</strong></p>

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

IP --> NS
IP --> TD
IP --> C

style IP stroke:#E0004D,stroke-width:4px
linkStyle 2,9,10,11 stroke:#E0004D,stroke-width:4px" %}

* [**No Status**](#id-1.-no-status) :arrow\_left: - if a [task](#tasks) is no longer being worked on and was unassigned from the current sprint or assigned to a future sprint.
* [**To Do**](#id-2.-to-do) :arrow\_left: - if a [task](#tasks) is no longer being worked on and is assigned to the current sprint.
* :arrow\_right: [**Ready For Review**](#id-4.-ready-for-review) - if a [task's](#tasks) assignee(s) believe they have delivered the requirements.
* :arrow\_right: [**Closed**](#id-8.-closed) - if a [task](#tasks) is closed, no longer relevant or a duplicate of another [task](#tasks).

### 4. Ready For Review

[Tasks](#tasks) that are ready to be reviewed but haven't started being reviewed yet.

<p align="center"><strong>Acceptable status changes:</strong></p>

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

RFR --> IP
RFR --> C

style RFR stroke:#E0004D,stroke-width:4px
linkStyle 3,9,10 stroke:#E0004D,stroke-width:4px" %}

* [**In Progress**](#id-3.-in-progress) :arrow\_left: - if a [task's](#tasks) assignee(s) realize that changes are required to the deliverables.
* :arrow\_right: [**In Review**](#id-5.-in-review) - if a reviewer has started reviewing a [task's](#tasks) deliverables.
* :arrow\_right: [**Closed**](#id-8.-closed) - if a [task](#tasks) is closed, no longer relevant or a duplicate of another [task](#tasks).

### 5. In Review

[Tasks](#tasks) that are actively being reviewed.

Assignees should NOT review their own [task](#tasks); we do peer reviewing.

When a [task](#tasks) is reviewed, the [task's](#tasks) deliverables will either be accepted or the reviewer will request changes. If changes are requested, the [task](#tasks) will go back to [In Progress](#id-3.-in-progress) and the assignee(s) must [request another review](#id-4.-ready-for-review). It's normal for a [task](#tasks) to go through multiple *rounds of review* before its deliverables are accepted. If a reviewer accepts, they should comment "LGTM" (an acronym for "looks good to me").

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

subgraph review\_round \["Review Round"]
IP
RFR
IR
end" %}

<p align="center"><strong>Acceptable status changes:</strong></p>

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

style IR stroke:#E0004D,stroke-width:4px
linkStyle 4,5,6 stroke:#E0004D,stroke-width:4px" %}

* [**In Progress**](#id-3.-in-progress) :arrow\_left: - if a reviewer requests changes on a [task's](#tasks) deliverables.
* :arrow\_right: [**Staging**](#id-6.-staging) - if a [dev-task](#category) (:computer:) was accepted and has been deployed to our staging environment.
* :arrow\_right: [**Closed**](#id-8.-closed) - if a [task](#tasks) is closed, no longer relevant or a duplicate of another [task](#tasks).

### 6. Staging

[Dev-tasks](#category) (:computer:) that have been deployed to our [staging environment](https://staging-dot-decent-digit-629.appspot.com/) and require manual testing.

A clear description of how to manually test a [task's](#tasks) deliverables should be provided by the assignee(s) in a comment. At least 2 different testers (not including the assignees) should test the [task's](#tasks) deliverables. If a tester approves, they should comment "LGTM" (an acronym for "looks good to me").

<p align="center"><strong>Acceptable status changes:</strong></p>

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

S --> IP
S --> C

style S stroke:#E0004D,stroke-width:4px
linkStyle 7,9,10 stroke:#E0004D,stroke-width:4px" %}

* [**In Progress**](#id-3.-in-progress) :arrow\_left: - if a bug or missing requirement managed to slip through the reviews.
* :arrow\_right: [**Production**](#id-7.-production) - if a [dev-task](#category) (:computer:) was accepted in our staging environment.
* :arrow\_right: [**Closed**](#id-8.-closed) - if a [task](#tasks) is closed, no longer relevant or a duplicate of another [task](#tasks).

### 7. Production

[Dev-tasks](#category) (:computer:) that have been deployed to our [production environment](https://www.codeforlife.education/) and require manual testing.

A clear description of how to manually test a [task's](#tasks) deliverables should be provided by the assignee(s) in a comment. At least 2 different testers (not including the assignees) should test the [task's](#tasks) deliverables. If a tester approves, they should comment "LGTM" (an acronym for "looks good to me").

<p align="center"><strong>Acceptable status changes:</strong></p>

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

P --> IP

style P stroke:#E0004D,stroke-width:4px
linkStyle 8,9 stroke:#E0004D,stroke-width:4px" %}

* [**In Progress**](#id-3.-in-progress) :arrow\_left: - if a bug or missing requirement managed to slip through the reviews.
* :arrow\_right: [**Closed**](#id-8.-closed) - if a [task](#tasks) is closed, no longer relevant or a duplicate of another [task](#tasks).

### 8. Closed

[Tasks](#tasks) that have been completed.

<p align="center"><strong>Acceptable status changes:</strong></p>

{% @mermaid/diagram content="graph LR
NS\["No Status"] --> TD\["To Do"]
TD --> IP\["In Progress"]
IP --> RFR\["Ready For Review"]
RFR --> IR\["In Review"]
IR --> IP
IR --> C
IR --💻--> S\["Staging"]
S --> P\["Production"]
P --> C\["Closed"]

C --> NS
C --> TD
C --> IP

style C stroke:#E0004D,stroke-width:4px
linkStyle 9,10,11 stroke:#E0004D,stroke-width:4px" %}

* [**No Status**](#id-1.-no-status) :arrow\_left: - if a [task's](#tasks) requirements weren't delivered and aren't scheduled in the current sprint.
* [**To Do**](#id-2.-to-do) :arrow\_left: - if a [task's](#tasks) requirements weren't delivered and are scheduled in the current sprint.
* [**In Progress**](#id-3.-in-progress) :arrow\_left: - if a [task's](#tasks) requirements weren't delivered and are actively being worked on.

## Issue Relationships & Types

As documented by GitHub, you can [add sub-issues to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/adding-sub-issues) which creates a child & parent relationship between issues. Depending on these relationships, we define different types of issues.

{% hint style="info" %}
The terms "sub-issue" and "child-issue" are interchangeable.
{% endhint %}

Below is an example relationship-graph between various issues.

**Legend:**

* **--**:octagonal\_sign:**-- >** = blocking relationship ("this issue is blocking that issue").
* **—**:baby:**— >** = child relationship ("this issue has that issue as a child").

{% @mermaid/diagram content="graph TD
A --👶--> B
B --👶--> C
B --👶--> D
B --👶--> E
C -.🛑.-> D
D -.🛑.-> E
A --👶--> F
G --👶--> H
G --👶--> I
J
K
subgraph epics \["Epics"]
B
subgraph root\_epics \["Top Epics"]
A
G
end
end
subgraph tasks \["Tasks"]
C
D
E
F
H
I
subgraph orphan\_tasks \["Orphan Tasks"]
J
K
end
end" fullWidth="false" %}

### Epics

&#x20;**(In graph: A, B, G)** Issues that...

* ...do have a sub-issue.

Epics are not tasks to be completed in themselves. Rather, epics represent *initiatives* that comprise multiple tasks. Epics are closed by closing all the sub-issues within them.

#### Top \[Level] Epics

**(In graph: A, G)** Issues that...

* ...do have a sub-issue...
* ...and do NOT have a parent-issue.

Top-level epics contain sub-epics and/or [tasks](#tasks). These are useful for breaking down larger initiatives into smaller ones, each with their own [tasks](#tasks).

### Tasks

**(In graph: C, D, E, F, H, I, J, K)** Issues that...

* ...do NOT have a sub-issue.

Tasks are the actual work that needs to be completed.

#### Orphan Tasks

**(In graph: J, K)** Issues that...

* ...do NOT have a sub-issue...
* ...and do NOT have a parent-issue.

Orphan tasks are one-off tasks that are NOT part of an [epic](#epics).

{% hint style="warning" %}
Ideally, we should have few of these; we want tasks to work towards initiatives set out in our [roadmap](#epic-roadmap).
{% endhint %}

#### [Blocking Tasks](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/creating-issue-dependencies#marking-an-issue-as-blocked-by-or-blocking-another-issue)

**(In graph: C, D)** Issues that...

* ...do NOT have a sub-issue...
* ...and are blocking another issue.

Blocking tasks define a sequence in which tasks must be [closed](#id-8.-closed) ("this task must be done before that task").

#### [Blocked Tasks](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/creating-issue-dependencies#marking-an-issue-as-blocked-by-or-blocking-another-issue)

**(In graph: D, E)** Issues that...

* ...do NOT have a sub-issue...
* ...and are being blocked by another issue.

Blocked tasks define a sequence in which tasks must be [closed](#id-8.-closed) ("this task must be done after that task").

## Project Views

In GitHub, a project-view is a way to visualize the issues in a project. A project can have 1 or more views, where each view has its own visualization-customizations and [preset filters](https://docs.github.com/en/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/filtering-projects). Fundamentally, GitHub supports 3 different view types:

1. [**Table**](https://docs.github.com/en/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/changing-the-layout-of-a-view#about-the-table-layout) - a spreadsheet comprised of issues.
2. [**Board**](https://docs.github.com/en/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/changing-the-layout-of-a-view#about-the-board-layout) - spreads issues across customizable columns.
3. [**Roadmap**](https://docs.github.com/en/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/changing-the-layout-of-a-view#about-the-roadmap-layout) - a high-level visualization of issues across a configurable timespan.

### Common Filters

There are a few filters common across our views. It's highly recommended you memorize them.

1. `is:open` - An issue that has not [been closed](https://docs.github.com/en/issues/tracking-your-work-with-issues/administering-issues/closing-an-issue).
2. `has:sub-issues-progress` - An issue that [has sub-issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/browsing-sub-issues#navigating-issue-hierarchy) (a.k.a. child-issues).
3. `has:parent-issue` - An issue that is a sub-issue (and therefore [has a parent](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/browsing-sub-issues#finding-a-sub-issues-parent-issue)).

### Our Custom Views

Below are our custom project-views, each with:

* a short description of the insight it gives us into our project;
* the preset filters (and what they do).

<figure><img src="/files/IUwrCSfwqWqZvABzJ6dH" alt=""><figcaption><p>You can tab between views</p></figcaption></figure>

#### [Task Board](https://github.com/orgs/ocadotechnology/projects/3/views/8)

All [tasks](#tasks), grouped by [Status](#status).

This helps us to explore all the [tasks](#tasks) in our project (also see [Open Task Table](#open-task-table)).

**Preset filters ("Filter to issues that..."):**

1. `-has:sub-issues-progress` - ...do NOT have sub-issues.

#### [Sprint Board](https://github.com/orgs/ocadotechnology/projects/3/views/15)

All open [tasks](#tasks) assigned to the current or a previous [Sprint](#sprint), grouped by [Status](#status) and by [Assignee](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/assigning-issues-and-pull-requests-to-other-github-users).

This helps to see how many open [tasks](#tasks) are remaining in the current sprint, including [tasks](#tasks) carried over from previous sprints.

**Preset filters ("Filter to issues that..."):**

1. `-has:sub-issues-progress` - ...do NOT have sub-issues...
2. `sprint:<=@current` - ...and are in the current or previous sprints...
3. `has:status` - ...and have a status (aren't in the [No Status](#no-status) column)...
4. `-status:Closed` - ...and are NOT in the [Closed](#closed) column (this hides the column).

#### [Open Task Table](https://github.com/orgs/ocadotechnology/projects/3/views/14)

All open [tasks](#tasks).

Similar to our [Task Board](#task-board), this helps us to explore all the open [tasks](#tasks) in our project but see them in a dense spreadsheet format that supports bulk-editing field values by multi-selecting cells.

**Preset filters ("Filter to issues that..."):**

1. `-has:sub-issues-progress` - ...do NOT have sub-issues...
2. `is:open` - ...and are open.

#### [Epic Roadmap](https://github.com/orgs/ocadotechnology/projects/3/views/1)

All open [top-level epics](#top-level-epics).

This helps us to estimate the timelines ([start](#est.-start) & [end](#est.-end)) of each [top-level epic](#top-level-epics) so that we can roughly plan the year ahead. Generally, the next quarter (3 months) should be understood to be well planned, with each proceeding quarter having rougher estimations.

> The only thing that is constant is change — **Heraclitus**

**Preset filters ("Filter to issues that..."):**

1. `has:sub-issues-progress` - ...have sub-issues...
2. `-has:parent-issue` - ...and do NOT have a parent-issue...
3. `is:open` - ...and are open.

## Roles & Responsibilities

Below are the roles we define when managing our project, each with their own responsibilities and assignee(s).

### \[Sprint] Planner 🧭

Prioritizes [tasks](#tasks) by assigning them to the current or upcoming sprints.

**Responsibilities:**

1. (Un)assigns [tasks](#tasks) to a sprint.
2. Chases CFL team members to curate [tasks](#tasks) which are assigned to next sprint.
3. Consults CFL team members for potential [blocking tasks](#blocking-tasks).

**Assignees:** CFL's team lead, [Sidi Jow](https://github.com/sjforever).

### \[House] Keeper :broom:

Curates [tasks](#tasks) to maintain a clean project with well defined requirements.&#x20;

**Responsibilities:**

1. Writes a full description.
2. Writes the required deliverables.
3. Sets the correct labels.
4. Sets the correct [Size](#size).
5. Sets the correct [Category](#category).
6. Sets the correct [relationships](#issue-relationships-and-types).
7. Checks with other CFL team members if there are any doubts on any details.
8. Closes tasks that are no longer relevant.

**Assignees:** [Everyone in CFL](https://github.com/orgs/ocadotechnology/teams/cfl?query=membership%3Achild-team).

### \[Trouble] Maker :bomb:

Creates new [tasks](#tasks) to track work that needs to be done at some point.

**Responsibilities:**

1. Searches existing [tasks](#tasks) to ensure no duplicate [tasks](#tasks) already exist.
2. Creates new [tasks](#tasks) with full descriptions and correct [field values](#custom-project-fields).

**Assignees:** [Everyone in CFL](https://github.com/orgs/ocadotechnology/teams/cfl?query=membership%3Achild-team).

### \[Project] Contributor :muscle:

Is assigned to [tasks](#tasks), delivers their requirements, and follows our [Definition of Done](#definition-of-done) \[to close [tasks](#tasks)].

**Responsibilities:**

1. Updates the [Status](#status) to reflect the current situation.
2. Regularly comments significant progress-updates.
3. Comments any discoveries which are perceived to be 'blockers'.
4. Comments any discoveries which are believed to change the required deliverables.
5. Attaches or links to the required deliverables in a comment.
6. Addresses all feedback (through multiple [review rounds](#id-5.-in-review) if necessary) until the reviewer accepts.
7. Avoids sharing [PII](https://www.ibm.com/think/topics/pii) of others and security vulnerabilities, which others could use to exploit.
8. Is kind, collaborative and patient with everyone.

**Assignees:** Anyone. <a href="/pages/doM9vPREazsmcYQfsjUx" class="button primary" data-icon="heart">Become a Contributor</a>

## Automated Workflows

To keep our project 'clean' we've created [@cfl-bot](https://github.com/cfl-bot) whose job it is to monitor to all issues and:

* nudge user(s) or team(s) to create clean issues by commenting on them with change requests;
* perform actions on others' behalf when [prompted](#prompts);
* enforce rules (unless [ignored](#bot-ignore-labels)).

### Prompts

[Contributors](#project-contributor) can instruct [@cfl-bot](https://github.com/cfl-bot) to perform actions on their behalf by commenting one of the following prompts:

{% hint style="info" %}
Usually [contributors](#project-contributor) will NOT have the permissions to perform these actions themselves.
{% endhint %}

#### "assign me"

**Description:** Assigns you to an issue.

**Use When:** You want to work on an issue.

#### "unassign me"

**Description:** Unassigns you from an issue.

**Use When:** You no longer want to work on an issue.

#### "ready for review"

**Description:** Sets the status of an issue to [Ready For Review](#id-4.-ready-for-review).

**Use When:** You've attached deliverables to an issue and you would like a CFL team member to review it.

#### "requires changes"

**Description:** Sets the status of an issue to [In Progress](#id-3.-in-progress).

**Use When:** You've realized that your deliverables are missing something.

#### "link pr \<number> \<repo?>" <a href="#link-pr" id="link-pr"></a>

**Description:** Links a pull request to an issue.

**Arguments:**

1. **\<number>** The number of the PR to link.
2. **\<repo?>** The repo the PR is in.[\*](#prompt-notes) Defaults to the issue's repo.

**Use When:** You want to associate your code changes with an issue.

**Examples:**

1. `link pr 1`
2. `link pr 1 codeforlife-portal`
3. `link pr 1 portal`

#### "unlink pr \<number> \<repo?>" <a href="#unlink-pr" id="unlink-pr"></a>

**Description:** Unlinks a pull request from an issue.

**Arguments:**

1. **\<number>** The number of the PR to unlink.
2. **\<repo?>** The repo the PR is in.[\*](#prompt-notes) Defaults to the issue's repo.

**Use When:** You want to disassociate your code changes with an issue.

**Examples:**

1. `unlink pr 1`&#x20;
2. `unlink pr 1 codeforlife-portal`&#x20;
3. `unlink pr 1 portal`&#x20;

#### Prompt Notes

\*Only [CFL repos](https://github.com/orgs/ocadotechnology/repositories?q=codeforlife-) may be specified. You can optionally omit the "codeforlife-" prefix.

### Bot-Ignore Labels

If a CFL team member wants an issue to be ignored by the bot, they can add the bot-ignore label.

* ":robot:" ( a.k.a. **:robot:** ) - ignores all rules.

{% hint style="warning" %}
Bot-ignore labels should be used sparingly! We should not lightly abandon the rules that help us keep order.
{% endhint %}


# Become a Contributor

Contribute to Code for Life

## Help Build Code for Life

As Code for Life is an [open-source](https://github.com/ocadotechnology/codeforlife-workspace) project, we welcome external contributors and all forms of contribution such as:

* code changes
* design
* student resources
* teacher resources
* strategic insights from qualified teachers
* process review
* cloud infrastructure setup
* running [coding clubs](https://code-for-life.gitbook.io/code-for-life-primary-club-resources/)

If you would like to contribute in one of the ways mentioned above or in a way not mentioned above, please reach out at <codeforlife@ocado.com> - all help is welcome! 😉

## Why Should I Contribute?

Some of the reasons we would like to highlight:

* Your contributions will be directly used by students and teachers worldwide, helping them to flourish in an increasingly digital world.
* You'll learn a variety of technologies and gain experience developing a production-ready system.
* You'll build your portfolio and industry-experience, which is highly valued by employers.
* You'll have the satisfaction of making the world a better place, one contribution at a time. 😊

Want more reasons? See [why you should contribute to open-source](https://opensource.guide/how-to-contribute/#why-contribute-to-open-source).

## Getting Started

Get ready to dig in! 💪 We're hoping that contributing to this project will be as rewarding to you as it is to us. 🚀

{% hint style="success" %}
We endorse and extend [Python's Community Code of Conduct](https://www.python.org/psf/codeofconduct/); please make sure you are friendly and welcoming.
{% endhint %}

### Create a GitHub Account

Every contributor will need a GitHub account, regardless of whether they wish to contribute code or other types of work to the project. This is because we use GitHub to manage our project's tasks. If you don't already have a personal GitHub account, [create one](https://github.com/signup).

### Notice of Intention

We recommend that you start your journey with us by reaching out to us at <codeforlife@ocado.com> and notify us of your intent to contribute. While it's not required to do this, we recommend starting a conversation with us early on so that we may learn more about your individual skill set and suggest tasks that you're suited to.

{% hint style="info" %}
Notifying us of your intent to contribute is not a commitment on your part. You are never obligated to start or complete any work for CFL.
{% endhint %}

### Sign our Agreement

Before you begin contributing, you must first sign our [contributor agreement](https://github.com/ocadotechnology/codeforlife-workspace/blob/main/CONTRIBUTING.md). This gives CFL permission to use your contributions in our app! 🚀 After reading the agreement, you must sign it by following the below steps. If you have any trouble, please reach out to <support@codeforlife.education>.

#### 1. Set up your Git identity.

{% hint style="info" %}
[See](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) Git's first-time setup docs.
{% endhint %}

```bash
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
```

Set `user.name` to be anything you like.

Set `user.email` to be an email address that you own. Note that:

* This email address will be forever publicly visible! If you wish to keep your personal email address private, then we recommend you create a new email address for the sole purpose of making contributions. If you have a GitHub account, you can [add the new email address](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-email-preferences/adding-an-email-address-to-your-github-account) to it.
* You cannot use a private/noreply email address. If you have a GitHub account, this is enabled by default and can be turned off at **Settings > Emails > Keep my email addresses private**.

#### 2. Fork our [code workspace](https://github.com/ocadotechnology/codeforlife-workspace).

{% hint style="info" %}
You only need to fork the **main** branch.
{% endhint %}

{% hint style="info" %}
[See](https://docs.github.com/en/get-started/quickstart/fork-a-repo) how to do this on GitHub.
{% endhint %}

#### 3. Sign your email address.

On the **main** branch of your forked **codeforlife-workspace** repo, write your email address on a new line at the *bottom* of **CONTRIBUTING.md**.

{% hint style="warning" %}
You must not make any other edits!
{% endhint %}

```markdown
<example@gmail.com>
```

#### 4. Commit your changes.

```bash
git commit -m "user.email"
```

Replace `user.email` with your email address.

#### 5. Push your changes.

```bash
git push
```

#### 6. Create a pull request.

Create a pull request from the **main** branch of your forked **codeforlife-workspace** repo to the **main** branch of [Ocado Technology's **codeforlife-workspace** repo](https://github.com/ocadotechnology/codeforlife-workspace).

{% hint style="info" %}
[See](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork) how to do this on GitHub.
{% endhint %}

#### 7. Verify your email address.

To affirm that you own the email address you provided, an email will be sent to the email address after your pull request has been reviewed and approved by a member of our team. The email will contain a link to the pull request that added the email address as a contributor. You must forward the email to <codeforlife@ocado.com> from the same email address and state:

{% code overflow="wrap" %}

```
I confirm that I created this pull request and I agree to being a contributor to the Code for Life project.
```

{% endcode %}

### Finding Tasks

All of our project's tasks are tracked using [GitHub Issues](https://github.com/features/issues) - we use the words "issue" and "task" interchangeably. Each code repository has an **Issues** tab where you can browse the various tasks we have for the repo. You can find our list of repos by looking at our [reading list](/repositories-and-packages).

<figure><img src="/files/nZGC2skU5Mno6CxX9rE2" alt=""><figcaption><p>What the <strong>Issues</strong> tab looks like in GitHub</p></figcaption></figure>

Although you're welcome to pick up any task, not all issues are suitable for contributors. This is because some tasks require specialised knowledge or familiarity with how our system works. To help contributors find tasks we believe to be suitable for them, we label some of our tasks with a **volunteers** tag.

<figure><img src="/files/Md4saYEVif3qsixAbMlL" alt=""><figcaption><p>Listing and filtering issues on GitHub </p></figcaption></figure>

You can search for these with the filters:

```
is:issue is:open label:"volunteers"
```

Furthermore, we label some tasks with **good first issue** that we believe to be easy enough for first time contributors:

```
is:issue is:open label:"volunteers" label:"good first issue"
```

### Contributing as a Developer

If you are contributing code changes, we recommend you spend a little time skimming through the docs of our different code repos (see our [reading list](/repositories-and-packages)). This will give you some insight into how our system is structured and, given that each task is associated to a repo, you'll have a high-level understanding of the area of the system that you'll be working on.

Once you have an overview of our system, [set up your development environment](/software-developer-guide/dev-environment-setup).&#x20;

#### General Skills

All dev contributors will need to have these skills to contribute code changes:

* A basic understanding of what [Git](https://git-scm.com/) does. You'll need to know what the following commands do:
  * `git clone`
  * `git pull`
  * `git commit`
  * `git push`
* A basic understanding of what [Docker](https://docs.docker.com/get-started/overview/) does.
* A basic understanding of what [VSCode](https://code.visualstudio.com/) does.

#### Back End Skills

It's recommended contributors wishing to contribute to our back end familiarise themselves with:

{% hint style="info" %}
You **don't** have to be familiar with all these technologies - as long as you are keen to learn.
{% endhint %}

* The basics of [Python](https://www.python.org/).
* The basics of [pip](https://pip.pypa.io/en/stable/) and [pipenv](https://pipenv.pypa.io/en/latest/).
* The basics of [Django](https://www.djangoproject.com/).
* The basics of [unittest](https://docs.python.org/3/library/unittest.html) and [pytest](https://docs.pytest.org/en/).

#### Front End Skills

It's recommended contributors wishing to contribute to our front end familiarise themselves with:

{% hint style="info" %}
You **don't** have to be familiar with all these technologies - as long as you are keen to learn.
{% endhint %}

* The basics of [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML).
* The basics of [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS).
* The basics of [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript) and [TypeScript](https://www.typescriptlang.org/).
* The basics of [npm](https://docs.npmjs.com/) and [Yarn](https://yarnpkg.com/).
* The basics of [React](https://react.dev/).
* The basics of [Cypress](https://www.cypress.io/).

## Working on Tasks

Below is everything you need to know about how to handle tasks as a contributor.

### Picking up a Task

Before you start working on a task, we recommend you reach out to us at <codeforlife@ocado.com> so that we may assign the tasks you're working on to your GitHub account.

{% hint style="info" %}
If you're a dev contributor, you'll first need to fork any repo you wish to develop for. You should have forked all of CFL's repos when you [set up your dev environment](/software-developer-guide/dev-environment-setup).
{% endhint %}

{% hint style="info" %}
If you've been assigned a task and we've seen no activity from you in the past 2 weeks, you'll be unassigned so that others may have a chance to pick up the task. You can always be re-assigned if you so wish.
{% endhint %}

### Support Requests

If you have questions or require guidance, we'll do our best to respond promptly and provide you with support.

Our preferred communication channel is GitHub - we ask you make comments directly on a task so that we may keep all conversations regarding a specific task in a central location. Otherwise, you may reach out to us at <codeforlife@ocado.com> or via the email address of any CFL team member you may have previously been in contact with.

### Review Requests & Change Requests

When you've completed your task, you must request a review from us to determine whether we can accept your contribution. The simplest way to do so is to comment on the task:

```
ready for review
```

{% hint style="info" %}
If you're a dev contributor, review requests will come in the form of [pull requests from your forked repo](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork).
{% endhint %}

If we discover issues in our review, we'll request changes. It's normal to have multiple rounds of review requests (by you) followed by change requests (by us) until the task is completed to our standards. Change requests will usually be commented directly on their respective GitHub task or pull request.

### Closing a Task

Once a task has been closed by us we'll go through some internal processes which will ultimately result in your contribution getting deployed in the next version of system.

It may take some time before your accepted contributions are live on our system as we batch changes and release them as new versions on our system.

{% hint style="info" %}
You can see when your contributions have been released by keeping an eye on our [release notes](/release-notes). However, we're aiming to improve our notifications so you're kept in the loop every step of the way.
{% endhint %}


# Industry Experience

Gaining Industry Experience through partnerships

## Gaining experience through working on our products

As Code for Life is an [open-source](https://github.com/ocadotechnology/codeforlife-workspace) project, we work with external contributors on all forms of contribution including design and development. This means that we can design short projects for students and partners in order to provide experience in working within software in the EdTech industry.

## What are the benefits of collaborating this way?

Some of the reasons we would like to highlight:

* Your students will learn a variety of technologies and gain experience developing a production-ready system.
* Your students will gain mentoring directly from the team, learn about software development in an Agile environment, and gain insights into working in a fast paced small software team.
* The contributions will be directly used by students and teachers worldwide, helping them to flourish in an increasingly digital world.
* Your students will build their portfolio and gain industry-experience, which is highly valued by employers.
* You and your students will have the satisfaction of making the world a better place, one contribution at a time. 😊

## How to get started and find out more

In order to design projects suitable for your students, please get in touch with us at <mark style="color:purple;"><codeforlife@ocado.com></mark> and title your email; *Industry Experience.*

Some previous partners have been **Imperial College London** and **CS in Schools** Cadet scheme.

Find out more about how we collaborate with our partners [here](https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FPavvCifcuUeZZZLkV01C%2FOpportunities%20with%20Code%20for%20Life.pdf?alt=media).

{% hint style="success" %}
We endorse and extend [Python's Community Code of Conduct](https://www.python.org/psf/codeofconduct/); please make sure you are friendly and welcoming.
{% endhint %}


# Wall of Fame

Our incredible internal and external contributors to our mission.

Thank you to everyone - we all made it happen. ❤️

## A

Abdelrahman AbouDeghedy, Adam Kirchberger, Adam Mandel, [Aedan Shields](https://www.linkedin.com/in/aedan-shields-738b3b304/), Alexandre Fernando, Ana Crisan, Anders Schuller, Andre Gomes, Andreia Silva Cabecinhas, Andrew King, Andrew Lucas, Andrew Males, Andrew Miller, Angela Brownsey, Anne Marie Neatham, Aparbek Smailov, Ashley Marshall, Assia Iossifova, Aviv Cohen.

## B

Barry Parker, Ben Cardy, Blazej Strozewski, Bree King.

## C

Cam Mac, Céline Boudier, Cherie Pun, Chi-En Wei, Chris Leach, Chris Mukherjee, Chris Pavli, Christopher Brett, Clifford Bailey, Clyde.

## D

Daniel Hourigan, Daniel Palma, Daniela Ortner, Darcie Gomer, Dave Owen, Dawid Chodura, Delivibot Dee, Devon Alexander, Dioni Zhong, Dhru Sachania, Duncan Russell.

## E

Ed March, Edd Armitage, Eloise Hopes, Enora Hauduc, [Eva Lawther](https://github.com/evalawther-ocado), [Eve Martin](https://www.linkedin.com/in/eve-m-245341157/).

## F

Felix Stephenson, Florian Aucomte.

## G

Gabby Barsoum, George Smith.

## H

Helen Mead.

## I

Isabel Richards, [Isabella Ta](https://www.linkedin.com/in/isabella-ta/).

## J

Jacq Train, James Dimmock, James Holland, James Smyth, Javi Carretero, Jazmin Hempenstall, Jennet Pitch, Joe Slade, Joseph Zammit, Josh Blake, Juan Lucas, Julie Yortson, Julieta Sanguedolce.

## K

Kamil Sosiński, Katarzyna Zych, Kenny MacMillan, Kristian Brugts.

## L

Laura Cumming, Leila Hajaj, Ligia Olmos, Liza Konstantinova, Lloyd Allen, Lucy House, Lucy Light, Lukasz Brzezowski, Luna Cao.

## M

Maciej Zywiol, Mahana Clutha, Marcin Zieba, Maria Skrzypek, Mariana Fonseca, Marius Goubert, Mateusz Gizycki, Matt Whelan, Matthew Daggitt, Matthew Dyachuk, Matthew Harman, Meera Tom, Menelik Collymore, Michael Storey, Miguel Trigueira, Mike Bryant, Mo-anna Tucker, Mykhaylo Marfeychuk.

## N

Nel Sui, Niall Egan, Niket Shah, [Noah Bakr](https://www.linkedin.com/in/noah-bakr/).

## O

Olaf Szmidt, Oliver Cartz, Oliver Jeeves.&#x20;

## P

Paris Goldman-Smith, Patricia Botta-Guasch, Paul Clarke, Paul Heideman, Paul Wright, Paulina Koch, Peter Hancock, Piotr ‘Kru’ Kaczmar, Piotr Repetowski, [Prisha Sharda](https://www.linkedin.com/in/prisha-sharda-24670a275/)

## Q

## R

Rachel Lord, Radhika Gudipati, Rafal Wawryk, Rain Ashford, Razvan Mahu, Rebecca D'Cruz, Ria Jha, Ricardo Mejias, Richard Hughes, Ridwanah, Rishika Varadarajan, Robert Brignull, Rosanna Danza, Roxanne Sammons, Ruby Arenson, Ruth Wall.

## S

Sahba Najafi, Salman Ashraf, Seb Palmer, Sharon Harrison, Shubham Jain, Sophie Whelan, [Stefan Kairinos](https://www.linkedin.com/in/stefan-kairinos), Steph Lovis, Stephen Kennedy, Suzanne Westlake.

## T

Thomas Cassany, Tricy Dino.

## U

## V

Varadh Kalidasan, Vikas Shah.

## W

Wael Al Jeshi, Will Peck, Will Vauclain.

## X

## Y

Yongji Zhou.

## Z

Zoe Broad.


# Repositories and Packages

Our Services

## Services

Below is the list of microservices we have within our system. Each service has its own documentation and code repository. Read more about how to use each service, their responsibilities and how they work under the hood.

### [Portal](https://code-for-life.gitbook.io/portal)

### [Rapid Router](https://code-for-life.gitbook.io/rapid-router)

### [Single Sign-On (SSO)](https://code-for-life.gitbook.io/single-sign-on/)

## Packages

Below is the list of code packages we install across multiple services. Each package has its own documentation and code repository. Read more about the code each package contains.

### [Python Package](https://code-for-life.gitbook.io/python-package)

### [JavaScript Package](https://code-for-life.gitbook.io/javascript-package)

## Other

Below are empty code repositories that were created to track different types of tasks.

### [Design](https://github.com/ocadotechnology/codeforlife-design)

### [Admin](https://github.com/ocadotechnology/codeforlife-admin)


# National Curriculum alignment

Introduction to coding (England)

The National curriculum for computing can be found [here](https://www.gov.uk/government/publications/national-curriculum-in-england-computing-programmes-of-study). These are the statutory programmes of study and attainment targets for computing at key stages 1 to 4.

{% tabs %}
{% tab title="Key Stage 1" %}
Rapid Router can help you to cover the following national curriculum points:

• Understand what **algorithms** are; how they are implemented as programs on digital devices; and that programs execute by following precise and unambiguous instructions&#x20;

• Create and debug simple **programs**&#x20;

• Use logical reasoning to **predict the behaviour** of simple programs&#x20;

• Recognise common uses of technology beyond school

We recommend that you start at Level 1 on Rapid Router.
{% endtab %}

{% tab title="Key stage 2" %}
Rapid Router can help you to cover the following national curriculum points:

* **Design, write and debug programs** that accomplish specific goals, including controlling or simulating physical systems; solve problems by decomposing them into smaller parts, use sequence, selection, and repetition in programs; work with variables and various forms of input and output&#x20;
* Use **logical reasoning (offline resources, all debugging tasks and levels 13 - 18)** to explain how some simple algorithms work and to detect and correct errors in algorithms and programs&#x20;
* use **sequence (levels 1 - 18), selection (levels 29 - 50), and repetition (19 onward),** in programs; work with variables and various forms of input and output

We recommend that you start at Level 1 on Rapid Router.
{% endtab %}

{% tab title="Key stage 3" %}
Rapid Router can help you to cover the following national curriculum points:

* design, use and evaluate computational abstractions that model the state and behaviour of real-world problems and physical systems
* design and develop modular programs that use **procedures or functions (levels 61 - 67)**

Rapid Router can be used to develop skills with sequence, selection and iteration, as well as debugging.&#x20;

Please see our Python Den resources for textual programming.&#x20;

We recommend that you start at around Level 13 - 18 on Rapid Router.
{% endtab %}

{% tab title="Key stage 4" %}
Rapid Router can help you to cover the following national curriculum points:

* Develop and apply their **analytic, problem-solving, design, and computational thinking skills**

Rapid Router can be used to develop skills with sequence, selection and iteration, as well as debugging and modular program development.&#x20;

We recommend that you start at around Level 13 - 18 on Rapid Router. Please see our Python Den resources for textual programming.&#x20;
{% endtab %}
{% endtabs %}


# National Curriculum alignment

Introduction to coding (Scotland)

The Curriculum for Excellence (CfE) initiative highlights [Technologies](https://education.gov.scot/curriculum-for-excellence/curriculum-areas/technologies/) as one of the curriculum areas considered to be particularly important. Within the Computing Science section:

{% tabs %}
{% tab title="Early" %}
Rapid Router can help you to cover the following national curriculum points:

* TCH 0-13a - Exploring Computational Thinking in everyday tasks and identifying patterns.
* TCH 0-14a - Understanding sequences of instructions.&#x20;

We recommend that you start at Level 1 on Rapid Router.
{% endtab %}

{% tab title="First" %}
Rapid Router can help you to cover the following national curriculum points:

* TCH 0-13a - Exploring and commenting on processes in the world around them, making use of computational thinking skills and organising information in a logical way
* TCH 0-14a - Understanding instructions in a visual programming language and predicting the outcome of a program using a visual language.&#x20;

We recommend that you start at Level 1 on Rapid Router.
{% endtab %}

{% tab title="Second" %}
Rapid Router can help you to cover the following national curriculum points:

* TCH 0-13a - Understanding how a process works and its outcome.
* TCH 0-14a - Explaining core programming language concepts.&#x20;

Rapid Router can be used to develop skills with sequence, selection and iteration, as well as debugging.&#x20;

Please see our Python Den resources for textual programming.&#x20;

We recommend that you start at around Level 13 - 18 on Rapid Router.
{% endtab %}

{% tab title="Third" %}
Rapid Router can help you to cover the following national curriculum points:

* TCH 0-13a - Describing processes and how they can used to solve problems. How information can be used in a real-world system.&#x20;

Rapid Router can be used to develop skills with sequence, selection and iteration, as well as debugging and modular program development.&#x20;

We recommend that you start at around Level 13 - 18 on Rapid Router. Please see our Python Den resources for textual programming and concepts for TCH 0-14a and TCH 3-15a.

Python Den can also be used to support [National Qualifications](https://www.sqa.org.uk/sqa/48477.html) in Computing Science.&#x20;
{% endtab %}

{% tab title="Fourth" %}

* TCH 0-13a - Describing processes used in real-world systems and comparing algorithms for efficiency.&#x20;

We recommend that you start at around Level 13 - 18 on Rapid Router. Please see our Python Den resources for textual programming and concepts for TCH 0-14a and TCH 3-15a.
{% endtab %}
{% endtabs %}


# Glossary

Everything explained

## algorithm

A precise step-by-step set of instructions to solve a problem or complete a specific task.

## avatar

A picture or cartoon, for example this could be a favourite character that you use to represent yourself online. It is sensible to protect your privacy by not using a recognisable photo of yourself.

## boolean

A data type with only two values, TRUE or FALSE.

## debugging

Identifying and correcting the errors in a computer program.

## decomposition

Decomposition is breaking a problem into smaller manageable chunks that can be solved individually. This might mean creating ‘sub-programs’ or procedures that contain the code for a particular part of the task.

## input

Data put into a computer system, for example through the keyboard, mouse, microphone, or other sensors connected to the computer.

## logical reasoning

A systematic approach to solving problems using a set of consistent rules that apply to the system. For example, when fixing a bug in their Rapid Router program, children might apply the rules they have learnt about the way repeat loops work in this app.

## output

The information produced by a computer system for the user, for example on a screen, printer, through speakers.

## sequence

A set of programming instructions carried out in a specific and consistent order every time.

## procedure or function

A self contained sub program, also called a **subroutine**, to which you give a unique name, that can be used or ‘called’ by the main program multiple times. Both a function and a procedure can accept inputs.

A function sends information back into the main program, whereas a procedure does not. A multiplication function might, for example, have two number inputs and return an answer to the main program.

## program

A set of instructions encoded in a programming language understood by the computer.

(A program is also an algorithm, but not all algorithms are programs e.g. a recipe in English is an algorithm but it is not a computer program).

## repetition

A feature of a programming language where sections of code are repeated. This can be a fixed number of times, or until a condition is met (Rapid Router example: repeat 5 times, repeat until at destination).

## selection

A feature of a programming language where a choice is made. The instructions followed depend on whether a particular condition is met (Rapid Router example: if traffic lights red, wait).

## subroutine

A general term, also called a subprogram, for a **function or procedure**.

## variable

A programming structure that contains data (often numbers or text) and can change or be changed. Variables are used to keep score in computer games, and in Rapid Router to store the colour of the traffic lights.

*Some definitions are adapted from* [*http://www.computingatschool.org.uk/data/uploads/CASPrimaryComputing.pdf*](http://www.computingatschool.org.uk/data/uploads/CASPrimaryComputing.pdf) *where you can find additional explanations of computing terms.*


# Publications

## Opportunities with Code for Life

<figure><img src="/files/MWXusmaKjqMuasIEKAvx" alt="" width="375"><figcaption></figcaption></figure>

{% file src="/files/Sax8ipADLT0DZS3RCJZH" %}

## Impact Reports

<figure><img src="/files/T0XxqSdwAa58XeWRMfVu" alt="" width="375"><figcaption><p>Impact Report 2023</p></figcaption></figure>

{% file src="/files/TdxCHSo7O8rGA5y0xZ6P" %}

<figure><img src="/files/1S5vu2H2XnJIzqTCYN9z" alt="" width="375"><figcaption><p>Impact Report 2024</p></figcaption></figure>

{% file src="/files/G5TdWtbX15mdIJbEqeUM" %}


# Newsletters

A library of previous newsletters bringing activities, news and computing history to your classrooms.


# Spring 2025

This newsletter, we have packed in resources for you to read, enjoy, and get involved with. We want to hear what you think is useful, and how we can make things easier to navigate. Alongside this, we celebrate Bett 2025, our Industry experience scheme and much more!

| <img src="/files/ignBsxawnVeBWDM16I20" alt="" data-size="original"> | <h4>Testing Python knowledge</h4><p>We have been working on <a href="https://code-for-life.gitbook.io/code-for-life-test-space/">some assessments</a> for Python Den and would like  would like to get your feedback on how useful they would be.</p><p><br></p><p>Please <a href="https://code-for-life.gitbook.io/code-for-life-test-space/">take a look here</a>.</p> |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

### Please provide feedback for our User Experience Cadet!

This month, we are working with some students from [CS in Schools](https://csinschools.io/), as part of our Industry experience scheme. We have been shaping this scheme over the last year and it is proving to be a successful way for students to gain experience and mentoring from our core team, whilst helping to contribute to the product itself.

One of our engineering students is working on a UX task, and would like to receive some feedback on her work so far. Please take a minute to feed back [here](https://usabi.li/do/3a27a806aaf2/d7f3).

| <img src="/files/kp7FN6sgcLdGE82hN1ec" alt="" data-size="original"> | "Hi, I’m Prisha, and I’m a second-year Computer Science student at RMIT. Through my work with Code For Life, I’ve been focusing on improving the user experience for educators by relocating a key feature on the website to make it more accessible. It’s been an incredible ongoing learning experience, especially with the guidance of my mentor, Laura, whose expertise and support have assisted me a lot. I’m looking forward to hearing your feedback!" |
| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Two other students from the scheme are also working on tasks. They have picked up development tasks and are being guided by Stefan, one of our Senior software engineers.

If you want to take a look behind the scenes, you can see the tickets on Github [here](https://github.com/ocadotechnology/rapid-router/issues/1740) and [here](https://github.com/ocadotechnology/rapid-router/issues/1627).

| <h4>Impact Report</h4><p>We have released our Impact Report and it is packed with lots of activities from the year. We are proud of our achievements. In 2023–2024, over 220,000 active users across 187 countries engaged with our interactive tools. You can have a read <a href="https://storage.googleapis.com/codeforlife-assets/impact_reports/impact_report_2024.pdf">here</a>.</p> | <img src="/files/nP4tPbZA9KbxnfkSvdBu" alt="" data-size="original"> |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |

| <img src="/files/s3e4HBLxZ1u1Tglia0Lu" alt="" data-size="original"> | <h4>Safer Internet Day</h4><p>On February 11th it is Safer Internet Day!</p><p>Technology is constantly changing and evolving. Especially now that AI is at the forefront of everyone's minds, a lot of new possibilities have been created for benevolent technologists and scammers alike. It is important to understand how these technologies work and how they can be used as well as abused, so you know how to detect and defend yourself from a scam.</p> |
| ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Safer Internet Day provides resources, quizzes and tips to help educate people on the online risks that exist today. Find their resources [here](https://saferinternet.org.uk/safer-internet-day/safer-internet-day-2025)!

Check out our own [Safety Online worksheet](https://code-for-life.gitbook.io/code-for-life-extras/safety-online-passwords-and-security) to learn about passwords and security.

### Events

| <img src="/files/7KLAZmi2tOeZMLhUCCIW" alt="" data-size="original"> | <h4>Bett Show 2025</h4><p>What a show! We had an amazing time at the Bett Show this year, probably our busiest yet! Educators from all over the world were excited to see how our games and progress tracking worked, along with the teacher dashboard and level control. Let us know if you went to Bett and why <a href="https://usabi.li/do/b4d0e2ee75a7/9eca">here</a>.</p>                                                                                                                                                                                                                                            |
| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <img src="/files/i6oixGkOR0WxRN1bNLhe" alt="" data-size="original"> | <h4>St Francis' STEAM week</h4><p>We had a lovely time at St Francis de Sales school in London, UK, talking to the pupils about the technology at Ocado, and linking coding to robotics. After presenting in assembly, we delivered simultaneous workshops with year 2 pupils.</p><p><br></p><p>The kids had a great time and came up with some brilliant ideas including cooking robots, tickling robots, and even robots that went to school instead of them!</p><p><br></p><p>For workshop enquiries, please contact <a href="mailto:codeforlife@ocado.com?subject=Workshops%20contact"><codeforlife@ocado.com></a></p> |

| [![](https://i.emlfiles4.com/cmpimg/sys/socnet/facebook-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggqrPCGjr-pQoYidfRAMPUB8SpNcp2WBaV2uVcSEV2N5thyKfP) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/linkedin-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg6sLDGnEoV1LWwjoLDDEnnU5nNuNAw9dbVPGKnYAsAFFy_DdO) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/x-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggq7PCGgXRMy9HAtDBpSo75iEvTYss2xkl-ij-bbCM_LiKSnUw) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/instagram-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg68LDGiNLJq1kKclDH4rzs-I4xlQjiNcpG-yYTHON98bvObVu) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/youtube-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg7MLDGpkPQT8s8L3HEGzS2YZDL9ra-f2DxLnSL4ORvi_NIInc) |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

<figure><img src="https://i.emlfiles4.com/cmpimg/7/1/6/2/2/2/files/944580_ocado_4tags_horizontal_ol01.png" alt=""><figcaption></figcaption></figure>


# Bett show 2025

Thanks for visiting us at the Bett Show this year

We wanted to check if you visited our website and made use of our FREE programming and technology resources. You haven’t yet? Don’t miss out, [get registered here](https://www.codeforlife.education/register_form).

If you are already using our fantastic resources, let us know by sending your [feedback](https://usabi.li/do/b8b6659f5e1b/1b9c).<br>

|                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                                                                                                                                                                                                                                                                                                                      |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <img src="/files/lOyoyTBXiMlQOV3aVjku" alt="" data-size="original">                                                                                                                                                                                                                                                                                                                                | <h4>Newsletters</h4><p>Our newsletters are packed with career stories, events, puzzles and more. You can see <a href="https://code-for-life.gitbook.io/newsletters/">previous newsletters here</a>.</p><p><br></p><p>You can unsubscribe at any time.</p>                                                                                                                                            |
| <h4>Impact Report</h4><p>We have released our Impact Report and it is packed with lots of activities from the year. We are proud of our achievements. In 2023–2024, over 220,000 active users across 187 countries engaged with our interactive tools. You can have a read <a href="https://storage.googleapis.com/codeforlife-assets/impact_reports/impact_report_2024.pdf">here</a>.</p>         | <img src="/files/WBVTPT10jX7vljOLTDHo" alt="" data-size="original">                                                                                                                                                                                                                                                                                                                                  |
| <img src="/files/GmMB2hCVsv98vJ3AmzOq" alt="" data-size="original">                                                                                                                                                                                                                                                                                                                                | <h4>Career highlights</h4><p>You may have picked up a career poster at Bett from us. If you found it useful, you can find more here and <a href="https://code-for-life.gitbook.io/careers-in-technology/">print them at school</a>. We also have videos and profiles to show your students.</p><p><br></p><p>We will be making primary versions soon too. Keep an eye out in our newsletters. 👀</p> |
| <h4>Work with us</h4><p>If you are looking for Industry experience, partnerships or more, take a look <a href="https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FPavvCifcuUeZZZLkV01C%2FOpportunities%20with%20Code%20for%20Life.pdf?alt=media">here</a> at all the other activities we do and how you can get involved.</p> | <img src="/files/9p4pHz9QdSLMjcdNJfSe" alt="" data-size="original">                                                                                                                                                                                                                                                                                                                                  |

| [![](https://i.emlfiles4.com/cmpimg/sys/socnet/facebook-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggqrPCGjr-pQoYidfRAMPUB8SpNcp2WBaV2uVcSEV2N5thyKfP) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/linkedin-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg6sLDGnEoV1LWwjoLDDEnnU5nNuNAw9dbVPGKnYAsAFFy_DdO) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/x-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggq7PCGgXRMy9HAtDBpSo75iEvTYss2xkl-ij-bbCM_LiKSnUw) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/instagram-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg68LDGiNLJq1kKclDH4rzs-I4xlQjiNcpG-yYTHON98bvObVu) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/youtube-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg7MLDGpkPQT8s8L3HEGzS2YZDL9ra-f2DxLnSL4ORvi_NIInc) |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

<figure><img src="https://i.emlfiles4.com/cmpimg/7/1/6/2/2/2/files/944580_ocado_4tags_horizontal_ol01.png" alt=""><figcaption></figcaption></figure>


# December 2024

Welcome to our December Newsletter

## Seasons greetings!

The snow is back in our games, just in time for the festive season! Santa and Rudolph are on hand to help with deliveries, so don’t miss out—get stuck in before the snow melts away for another year!&#x20;

Technology has completely transformed the way we celebrate festivals over the years. From digital vouchers to virtual promises in e-cards, the internet has made gifting easier and greener. Many digital gifting services now include eco-friendly touches, like planting trees or supporting carbon offset schemes with every purchase. So, while you’re spreading joy, you’re also helping to keep the planet merry and bright!&#x20;

### <mark style="color:red;">Create a more environmentally friendly challenge for your students using our electric van!</mark>

<figure><img src="/files/Slq3tcRfOkBaPRFTWyRP" alt=""><figcaption><p>Level creator in Rapid Router</p></figcaption></figure>

Have you tried out our solar panels and electric van in the level creator yet? It may not be much, but it is a step towards creating levels more aligned to helping our planet. Every bit we can do to help towards creating a cleaner climate counts.&#x20;

[Take a look and get creative](https://www.codeforlife.education/rapidrouter/level_editor/)!

{% hint style="info" %}

#### Did you know?

Judith Donath (MIT Media Lab) created the first E-card site, *The Electric Postcard*. The award-winning site eventually became open source.

[Source](https://www.nationaldayarchives.com/day/national-electronic-greetings-day)
{% endhint %}

### Planning for next term's activities?

Have you taken a look at [Python Den](https://youtu.be/pB9klqkY82I?si=SKTvhDDwl3eR-thf) yet? It's got some great challenges, and is supported by videos and plans should any support teacher have to take over a lesson last minute! [Get started here](https://www.codeforlife.education/pythonden/)!

<figure><img src="/files/2q4dsIRgbiZrXlpR0NdQ" alt=""><figcaption></figcaption></figure>

### Under the Spotlight

#### Our amazing volunteers at Ocado Group!

For the past 10 years, Code For Life has been supported, and was initially created by a community of volunteers from within Ocado Group. Now a small dedicated full-time team builds the free-to-use products, drives quality and ensures security of the platform, data and all its users. We are still reliant on our volunteers to contribute to new features, improvements, and help with our multiple outreach programmes.

This includes colleagues that are based all over the world in various departments. Recently, we teamed up with our office in Sofia to continue our 10 year coding and robotics workshop celebrations!&#x20;

### <mark style="color:red;">Our 10 year celebrations reach Sofia!!!</mark>

> <mark style="color:purple;">**"Joining Code for Life has been an incredibly rewarding experience. It’s inspiring to see students light up as they grasp new concepts and gain confidence in creating something with their own hands. The program’s focus on making technology accessible and engaging ensures that participants are not only learning valuable skills but also developing a love for problem-solving. Being part of this initiative has allowed me to contribute meaningfully to the next generation’s education."**</mark>

Today, Code for Life has grown into a vibrant coding platform supported by the expertise of Ocado Group’s talented teams. From regular security testing by Ocado’s specialists to ensuring data protection and compliance with the latest regulations, we take safety and privacy seriously. Our solutions benefit from industry-leading advice, ensuring scalability and reliability for classrooms everywhere.

Sustainability is at the heart of what we do, aligning with [Ocado Group’s commitment](https://www.ocadogroup.com/sustainability/sustainability) to responsible resourcing. We have access to a pool of over 2,000 technologists, including experts in robotics, AI, and ethics. With their input, we’re not just teaching coding—we’re connecting classrooms to the future of technology. Together, we’re making computing education secure, exciting, and ready to take on tomorrow’s challenges.

> <mark style="color:purple;">**"Helping young students learn about robotics and coding let me share my expertise and passion for technology. This was fulfilling as it hopefully helps inspire the next generation of engineers/STEM workers. Furthermore, teaching these concepts to young students helps develop soft skills such as communication, patience, and adaptability, which are valuable in my professional role."**</mark>

| [![](https://i.emlfiles4.com/cmpimg/sys/socnet/facebook-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggqrPCGjr-pQoYidfRAMPUB8SpNcp2WBaV2uVcSEV2N5thyKfP) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/linkedin-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg6sLDGnEoV1LWwjoLDDEnnU5nNuNAw9dbVPGKnYAsAFFy_DdO) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/x-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggq7PCGgXRMy9HAtDBpSo75iEvTYss2xkl-ij-bbCM_LiKSnUw) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/instagram-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg68LDGiNLJq1kKclDH4rzs-I4xlQjiNcpG-yYTHON98bvObVu) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/youtube-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg7MLDGpkPQT8s8L3HEGzS2YZDL9ra-f2DxLnSL4ORvi_NIInc) |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

<figure><img src="https://i.emlfiles4.com/cmpimg/7/1/6/2/2/2/files/944580_ocado_4tags_horizontal_ol01.png" alt=""><figcaption></figcaption></figure>


# Autumn 2024

Welcome back everyone!

We’re excited to welcome you back with some fantastic updates and new features. This term, we’ve introduced a beta release of our Python Den, some updates to Rapid Router, and some new features in the level editor. Our goal is to support you in creating an engaging and effective learning environment for your students. Stay tuned for upcoming events and online sessions to help you get the most out of these new features. Here’s to a successful school year ahead!

<figure><img src="/files/ubREeAyan6r84ey1sClE" alt=""><figcaption><p>Alicia Chong Rodriguez</p></figcaption></figure>

> #### <mark style="color:red;">"We can track heart rhythm, breathing, temperature, posture and movement, and by applying algorithms, we can use this data to decode symptoms, articulate arrhythmia triggers and generate personalised digital biomarkers."</mark>
>
> Alicia Chong Rodriguez, [A smart bra for better heart health](https://www.ted.com/talks/alicia_chong_rodriguez_a_smart_bra_for_better_heart_health?utm_campaign=tedspread\&utm_medium=referral\&utm_source=tedcomsharehttp://)
>
> Image: [LinkedIn](https://www.linkedin.com/in/achongr/)

{% hint style="info" %}

#### Did you know?

Bloomer Tech is named after Amelia Bloomer, an activist for women's rights who encouraged women to wear loose-fitting pants!
{% endhint %}

| <p><strong>Have you seen the cows?</strong></p><p></p><p>Keep a look out for the cows on some levels, they appear in the most inconvenient places!</p><p></p><p>We have also introduced pigeons to our city scenes! This is thanks to our work experience student that came to us at the beginning of the summer. Énora worked on several new elements for Rapid Router scenes. <a href="https://www.linkedin.com/posts/code-for-life-uk_volunteer-programming-techforgood-activity-7231585879033581571-iaJO?utm_source=share&#x26;utm_medium=member_desktop">Read More</a></p> | <img src="/files/tADxnC9N9ZMs2XPQ2Bcn" alt="" data-size="original"> |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |

### <mark style="color:red;">Translations of blocks</mark>

Our colleagues at Ocado have been helping us out with some translations for our customers in other parts of the world. You now have the ability to translate the blocks in Rapid Router into Catalan, Spanish, French and Hindi, with other translations coming soon. Get in touch and let us know what could help you out too.

| <img src="/files/xmHqYrWJfbxIXKiJzWoI" alt="" data-size="original"> | <img src="/files/Kg3Rp0S8VCAvZAwmLZ37" alt="" data-size="original"> |
| ------------------------------------------------------------------- | ------------------------------------------------------------------- |

### <mark style="color:red;">**Events and Workshops**</mark>

<mark style="color:red;">**Craig n' Dave conference**</mark>

Code for Life attended the first Craig n' Dave event up at Bramsgrove School and enjoyed a day of conversation and talks. It was great to meet everyone and we hope we gained a few more schools. [Read More](https://www.linkedin.com/posts/code-for-life-uk_coding-computing-edtech-activity-7219248039012499457-S56-?utm_source=share\&utm_medium=member_desktop)

| <img src="/files/caJg7COVnjFN9kblQQdT" alt="" data-size="original">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | <p><mark style="color:red;"><strong>CAS conference</strong></mark></p><p>We had a great time at the CAS conference in July where we had a stand, and delivered two workshops for primary and secondary teachers. Lots of great conversations and questions. <a href="https://www.linkedin.com/posts/code-for-life-uk_computing-stem-teachers-activity-7223552842458894336-NOmT?utm_source=share&#x26;utm_medium=member_desktop">Read More</a></p>                                                                                                                                                                            |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><mark style="color:red;"><strong>World Tour - UK Leg</strong></mark></p><p>We completed the UK leg of the world tour with a fantastic reception from the year 3's at Howe Dell primary school in Hatfield. They were amazed at all the technology and automation behind sorting and packing deliveries for their homes, and got stuck into design and coding exercises with the team. <a href="https://www.linkedin.com/posts/code-for-life-uk_teachers-techforgood-coding-activity-7219928966617313281-M1to?utm_source=share&#x26;utm_medium=member_desktop">Read More</a></p> | <img src="/files/R3qzJvkvDwUakxvGyp5e" alt="" data-size="original">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| <img src="/files/hmEwhukvrlFrKY9dz89o" alt="" data-size="original">                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | <p><mark style="color:red;"><strong>In2Science Contributor session</strong></mark></p><p>After selecting 13 students, we spent the afternoon helping everyone get set up and ready to contribute to our initiative as external contributors. Fuelled with pizza and enthusiasm, we managed to get most set up and have had contributions to our code that have made it into production already! Interested in becoming a contributor? <a href="https://www.linkedin.com/posts/code-for-life-uk_volunteer-careers-coding-activity-7219574143220936704-YFP0?utm_source=share&#x26;utm_medium=member_desktop">Read More</a></p> |

<mark style="color:red;">**Upcoming**</mark>

We have a few events to look forward to this term too. including an adult re-skilling session through Careers you Love. Keep a look out on social media for upcoming sessions.

## <mark style="color:red;">Under the Spotlight</mark>&#x20;

#### Salman Ashraf - Intern software engineer

<figure><img src="/files/16YM0PjpByEmLyjCnPeN" alt=""><figcaption><p>Salman Ashraf - Intern software engineer</p></figcaption></figure>

Salman, a computer science student from Manchester University, worked with us as an intern for 10 weeks this summer. Read about what he got up to in the text below, and what he thinks about learning new digital skills.

> #### <mark style="color:red;">"In just 5 weeks, I had the opportunity to dive deep into Python Django and to explore the vast capabilities of AWS and GCP. I've engaged with the senior developers, learned about the technologies at CFL and contributed to a meaningful project. "</mark>

I work as a Software Engineer Intern, where I help build computer programs to improve user experience. I got this role by studying hard in school, learning about computers and coding in my free time, and doing well in my classes at the University of Manchester. I enjoy my job because I get to solve puzzles every day by figuring out how to make our programs run faster and better.

Learning new digital skills is important because it allows us to create tools that help people in their daily lives. With better digital tools, we can make online shopping faster, help doctors keep track of patients, or even help scientists discover new medicines. By improving technology, we make life easier and solve big problems in our world. [Read More](https://www.linkedin.com/feed/update/urn:li:activity:7228996204175527936)

{% hint style="info" %}
Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.
{% endhint %}

| [![](https://i.emlfiles.com/cmpimg/sys/socnet/facebook-v2.png)](https://www.facebook.com/codeforlifeuk/) | [![](https://i.emlfiles.com/cmpimg/sys/socnet/linkedin-v2.png)](https://www.linkedin.com/company/code-for-life-uk/) | [![](https://i.emlfiles.com/cmpimg/sys/socnet/x-v2.png)](https://twitter.com/codeforlifeuk) | [![](https://i.emlfiles.com/cmpimg/sys/socnet/instagram-v2.png)](https://www.instagram.com/codeforlife_uk) | [![](https://i.emlfiles.com/cmpimg/sys/socnet/youtube-v2.png)](https://www.youtube.com/@CodeForLife-uk) |
| -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |

<figure><img src="/files/MPQ9DfCH3bgRwzrbpsxM" alt=""><figcaption></figcaption></figure>


# Summer 2024

Welcome to our summer newsletter! 🌞 In this edition of the Code for Life Newsletter we focus on User Experience (UX), a term coined by Don Norman in 1993.

<figure><img src="/files/sxaqPKp9dY9bjLUqqHzn" alt=""><figcaption><p>Don Norman</p></figcaption></figure>

<mark style="color:blue;">"Computer scientists have so far worked on developing powerful programming languages that make it possible to solve the technical problems of computation. Little effort has gone toward devising the languages of interaction."</mark> *Don Norman, "The Design of Everyday Things", 1988.*

Today, "user experience" (UX) is a widely recognised term, and companies across various industries are increasingly valuing the role of UX designers. Don Norman notes that the term UX has evolved beyond his initial vision. He intended it to encompass everything affecting a person’s experience with a product, even beyond direct interactions.

Now, UX covers more than just websites, apps, and smartphones. It includes emerging technologies like virtual reality, AI, augmented reality, inclusive design, voice technology, and wearables. For example, designing a self-driving car requires considering the entire user experience, from approaching the vehicle to ending the ride.

At Ocado Group, the importance of UX design is paramount. UX designers play a critical role in crafting seamless and enjoyable experiences for not only the customers, but also the Ocado workforce. They are essential in designing intuitive interfaces for the Ocado online grocery platform, efficient systems for the automated warehouses, and innovative solutions in robotics.&#x20;

{% hint style="info" %}

#### Did you know?

91% of unsatisfied customers don’t complain about their bad experience— they simply leave without giving feedback. [Source](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggirnDGgU_9CX5U90GMJYbagRA7Xu6ymmA9bC5tZ5gGE1hWMo3)
{% endhint %}

### <mark style="color:red;">New AI primary resources</mark>

| <p>Through our partnership with Barefoot Computing, we've crafted engaging lesson plans and videos tailored specifically for students aged 9-11. These activities are designed to spark curiosity and inspire the next generation of technologists.</p><p>And the best part? All of these resources are absolutely free! ✨ </p><p></p><p></p><p></p><p></p><p></p><p>Check out our <a href="https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg4K3DGo2oFdfQVbpcDdra2NkpXrx5MV9qM86uHgoQHDnwa-YI">teaser video</a></p><p><a href="https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggi67DGmcAA1lXD8E_ghjb8QDSL7Kunn0loXdhTRatexvwTUnd">Download the resources here</a></p> | <p></p><p><img src="/files/W70iHDJ4WnGZKVf0mvqf" alt="Barefoot Computing website" data-size="original"></p> |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |

|                                                                                   |                                                                                                                                                                                                                                                                                                    |
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p></p><p><img src="/files/Rdc0lIkYXkI3AKifRaDp" alt="" data-size="original"></p> | <h3><mark style="color:red;"><strong>New Python resources</strong></mark></h3><p>We have had a great response from our readers to give feedback on our new Python Hub. Thank you to everyone that is helping us to shape the space. Keep an eye out for updates and a release later this year!</p> |

### Rapid Router is becoming renewable!

Our under the spotlight section focusses on one of our volunteers, Ligia. She has been working on various tasks for us alongside her day job at Ocado, meaning that we are making progress in several areas. One of the tasks she has been looking at is working on some new graphics to have a more eco friendly Rapid Router skin, meaning students can [create their own levels](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggtMPDGrLU4sQ3ekfYbTkMrkEipil2nlLVpCPqiLLbSJrNkB_u) using these elements. We will be adding these shortly in our level editor. Let us know what you think when they arrive!

<table data-header-hidden><thead><tr><th width="171"></th><th width="323"></th><th></th></tr></thead><tbody><tr><td><p></p><p><img src="/files/ACcRCTUCMFYe0yWERNac" alt="" data-size="original"></p></td><td><p></p><p><img src="/files/BdXvI0i84eUXJwwJCGTm" alt="" data-size="original"></p></td><td><p></p><p><img src="/files/tJiJR5wCJNaHXWbN33G9" alt="" data-size="original"></p></td></tr></tbody></table>

### Under the Spotlight

Ligia Olmos Rossi - Senior UX Designer

I'm a Senior Product Designer at Ocado Technology. My job is to make the website where you can buy groceries online look awesome and easy to use. I've loved drawing and making things look cool since I was really young. I always wondered how the things we use every day are made and how they make us feel. So, I decided to learn how to make them better!

| <p></p><p><img src="/files/zEe8peWCP85W1XBnE1LI" alt="" data-size="original"></p> | <h4><mark style="color:red;">"I feel really lucky to be able to help make</mark> </h4><h4><mark style="color:red;">the world a better-looking and easier-to-use</mark> </h4><h4><mark style="color:red;">place for everyone."</mark></h4> |
| --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Making websites and apps is like a mix of being super creative, understanding how people think, and knowing how technology works. I kept learning and practising, and now I get to do it as a job! It's not just a job for me, though. Making things look great and work well is like my whole way of life! I feel really lucky to be able to help make the world a better-looking and easier-to-use place for everyone. It's pretty cool to think that something I design can help lots of people buy their groceries with just a few clicks!

| <h3>Upcoming events</h3><p></p><p>Come and visit our stall at these upcoming events. We will be available to walk through our products and will be running workshops for Primary and Secondary teachers.<br></p><p><a href="https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg9OnDGsEudtaLDMVm3IuSxkxXCChCC_gBPSqqDYktemTdqsvV">Craig 'n' Dave conference 2024</a>, Wednesday 3rd July at Bromsgrove School.</p><p></p><p><a href="https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg9enDGkakiHlzXVSBMz_M_S0d3uve7IM7hf02aB1abTldJshe">CAS conference 2024</a>, Saturday, 13 July at Ada, the National College for Digital Skills</p> | <p></p><p><img src="/files/DzOdlyLL1wpghWWLbOg1" alt="" data-size="original"></p> |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |

{% hint style="success" %}
Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.
{% endhint %}

| [![](https://i.emlfiles4.com/cmpimg/sys/socnet/facebook-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggqrPCGjr-pQoYidfRAMPUB8SpNcp2WBaV2uVcSEV2N5thyKfP) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/linkedin-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg6sLDGnEoV1LWwjoLDDEnnU5nNuNAw9dbVPGKnYAsAFFy_DdO) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/x-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggq7PCGgXRMy9HAtDBpSo75iEvTYss2xkl-ij-bbCM_LiKSnUw) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/instagram-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg68LDGiNLJq1kKclDH4rzs-I4xlQjiNcpG-yYTHON98bvObVu) | [![](https://i.emlfiles4.com/cmpimg/sys/socnet/youtube-v2.png)](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulgg7MLDGpkPQT8s8L3HEGzS2YZDL9ra-f2DxLnSL4ORvi_NIInc) |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

<figure><img src="https://i.emlfiles4.com/cmpimg/7/1/6/2/2/2/files/944580_ocado_4tags_horizontal_ol01.png" alt=""><figcaption></figcaption></figure>

[Contact us](mailto:codeforlife@ocado.com?subject=Contact%20us)

Ocado Innovation Limited is  registered in England under registered company number 08813912 with its registered office at Buildings One & Two Trident Place, Mosquito Way, Hatfield, Hertfordshire, United Kingdom, AL10 9UL

You can find out about our privacy policy [here](https://info.codeforlife.education/t/c/AQiZyw0Q-rdgGKjdulggrLPCGm8g5yHTY0SKlQzI-S5StnGtVDTyMBuQ0bpNc3mKZqvA)


# Spring 2024

Welcome to the Easter Code for Life Newsletter!

This month we are celebrating robots and how we make them move with instructions. We have included real-world applications to interactive coding projects and spotlighting student achievements in a competition. Join us in fostering a passion for STEM education and empowering young minds to shape the future through innovation and creativity. Happy coding!

> #### <mark style="color:red;">“AI is the most powerful tool ever invented by humanity.”</mark>
>
> Demis Hassabis, Co-founder of DeepMind

## **First Robot to Use Artificial Intelligence (1972)**

It was known as [Shakey](https://www.aventine.org/robotics/history-of-robotics#First_Robot%20to%20Use%20Artificial%20Intelligence) (shown in video below) because of the stuttering way it moved around, but what was most distinguishing about this robot, created by a group of engineers at the Stanford Research Institute, was that it included pioneering artificial intelligence. If you gave Shakey a goal — such as navigating its way across a room or pushing a box along the floor — it could accomplish it by observing the world around it, creating a plan, and executing. With sensors that included a TV camera, a range finder and touch-sensitive metal whiskers, Shakey would gather data that enabled it to build a model of its environment and then use a “planning” program to generate its next moves. This idea of a separate “planning” layer was such a crucial innovation that it is still central to many robotic systems today.  - Source: [Arventine.org](https://www.aventine.org/)

{% hint style="info" %}

#### Did you know?

Ocado's robotic arms make smart decisions on the fly, packing grocery items densely into bags without any prior knowledge of what the products are or what’s coming next.
{% endhint %}

## Can you complete a Code for Life brainteaser? They are quite tricky!

There are some levels in Rapid Router for those that need a bit more of a challenge.

You can find them in the red section on the levels page.

[Here's a link to one, see if you can do it!](https://www.codeforlife.education/rapidrouter/74/#)

<figure><img src="/files/iz17KEhYBjGy8gCBm4tA" alt=""><figcaption></figcaption></figure>

## An afternoon designing robots, and coding with Rapid Router!

<figure><img src="/files/P4ZLBXU5PIbVWgWke23G" alt=""><figcaption><p>Ocado Technology and Code for Life staff at The Grove Primary School</p></figcaption></figure>

Code for Life partnered with some talented colleagues at Ocado Technology to create an engaging robotics and coding workshop for primary school students. The event was a resounding success, captivating approximately 90 young minds over a fun-filled afternoon.

> **“The children were buzzing after the session and found it really exciting to be able to design a robot and to meet real life coding experts. It was great to see them applying their coding knowledge on the Rapid Router game.”**<br>
>
> Mr Emanuel, Deputy Headteacher.

Mr Emanuel from The Grove Junior School in Harpenden, arranged for the team to take over three classes, one after the other, initially showing a short presentation and then, encouraging the children to design a robot to solve a problem. If they managed to finish this task they then moved onto coding with Rapid Router, which we demonstrated on the screen beforehand. The feedback we received was fantastic and we all had a great time working with the children.

<div><figure><img src="/files/W9XApBGVnbIVMACdbcsq" alt=""><figcaption></figcaption></figure> <figure><img src="/files/RUUwt6A5kWZWsj46zNwh" alt=""><figcaption></figcaption></figure> <figure><img src="/files/E4F7v6IvXlPLu1yECoeH" alt=""><figcaption></figcaption></figure></div>

> [Get in touch](mailto:codeforlife@ocado.com) if you would like us to help run a robotics workshop at your school.

## Under the Spotlight

### Mark Richardson - CEO of [OIA](https://ocadointelligentautomation.com/)

I live in North London with my family and a labradoodle named Zuko. My first summer job was selling ice cream on a beach in Norfolk. I did it for six years in a row and loved it, despite working long hours as a 13-year-old. One summer, I worked on a local fairground which was seriously tough but a good reference point for hard days in the office.

<figure><img src="/files/0Lf1EMLnTFLskLIltm4w" alt=""><figcaption><p>Mark Richardson - CEO of OIA</p></figcaption></figure>

> #### <mark style="color:red;">"Early Ocado was like a rollercoaster whose bolts hadn’t been tightened. If you get the chance to work in a start-up you should do it. The task seemed enormous, but so was the drive and determination."</mark>

I studied Physics at UCL before joining the IT department at John Lewis Partnership. They trained me in software development, let me build a procurement team and improve their network infrastructure. I also created their first e-commerce website.

I then moved on to work for Ocado, where I ran the Technology team for ten years. Early Ocado was like a rollercoaster whose bolts hadn’t been tightened. If you get the chance to work in a start-up you should do it. The task seemed enormous, but so was the drive and determination. I have been responsible for Logistics, building new CFCs, creating our own ASRS, and installing it around the world.

Now we are all on another adventure with [OIA](http://https://ocadointelligentautomation.com/). I have always been better at starting than finishing, and it is my very good fortune to have spent most of my career in an organisation that starts so much!

{% hint style="success" %}
Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.
{% endhint %}

| [![](https://i.emlfiles.com/cmpimg/sys/socnet/facebook-v2.png)](https://www.facebook.com/codeforlifeuk/) | [![](https://i.emlfiles.com/cmpimg/sys/socnet/linkedin-v2.png)](https://www.linkedin.com/company/code-for-life-uk/) | [![](https://i.emlfiles.com/cmpimg/sys/socnet/x-v2.png)](https://twitter.com/codeforlifeuk) | [![](https://i.emlfiles.com/cmpimg/sys/socnet/instagram-v2.png)](https://www.instagram.com/codeforlife_uk) | [![](https://i.emlfiles.com/cmpimg/sys/socnet/youtube-v2.png)](https://www.youtube.com/@CodeForLife-uk) |
| -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |

<figure><img src="/files/tWecNKO3TLtjAld3FA0c" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
[Contact us](https://r1-app.dotdigital.com/resources/easyeditor/V2/anchor19)

Ocado Innovation Limited is registered in England under registered company number 08813912 with its registered office at Buildings One & Two Trident Place, Mosquito Way, Hatfield, Hertfordshire, United Kingdom, AL10 9UL

You can find out about our privacy notice [here](https://www.codeforlife.education/privacy-policy?campaignkw=Privacy%20policy)
{% endhint %}


# Winter 2024

Welcome to the Code for Life Newsletter

## A Decade of Empowering Young Minds with Coding Education!

We are thrilled to announce a momentous milestone in our journey - Code for Life is celebrating its 10th anniversary! 🎉&#x20;

What started as a small initiative has grown into a thriving community, and we couldn't have done it without the support and enthusiasm of educators like you who share our vision for equipping the next generation with essential coding skills. We've been on an incredible journey, developing innovative teaching resources that cater to learners at various stages, starting with Blockly and progressing to Python.

To celebrate a decade of empowering learners through coding, we have some exciting updates and celebrations in store this year. Stay tuned for new features, enhanced game experiences, and more engaging content to keep the coding journey fresh and inspiring!

Thank you for being an integral part of Code for Life's success story. Here's to another decade of fostering curiosity, creativity, and coding brilliance!

<figure><img src="/files/hYXhVkyJWd0LZmH6CYyr" alt=""><figcaption></figcaption></figure>

## **Impact Report**

As Code for Life turns 10 years old, we are thrilled to share the incredible achievements of our not-for-profit initiative in our first [Impact Report](https://storage.googleapis.com/codeforlife-assets/impact_reports/impact_report_2023.pdf).

Code For Life is consistently used in over 180 countries, achieving over 600,000 registrations worldwide.

## Exciting milestones for the year ahead!

<figure><img src="/files/R8PU4eVvdqzgBlEb06Y0" alt=""><figcaption><p> <strong>Python with Rapid Router and Raspberry Pi Code Editor</strong></p></figcaption></figure>

## **Python with Rapid Router and Raspberry Pi Code Editor**

We have some exciting releases planned for the year ahead, including our new Python sessions. This is a brand new resource hub that combines Rapid Router with the use of Raspberry Pi's code editor in order to build on the student's learning. If you want early access to the Beta version, [get in touch](mailto:codeforlife@ocado.com?subject=Beta%20access%20to%20Python%20hub).

<figure><img src="/files/evv0L2KzahPPTniCydT8" alt=""><figcaption><p><strong>AI with Barefoot Computing</strong></p></figcaption></figure>

## **AI with Barefoot Computing**

We are bringing Ocado's technology to the classroom through our AI Collaboration with [Barefoot Computing](https://www.barefootcomputing.org/). There will be lessons and videos. Keep an eye out for updates!

## Under the Spotlight - Darcie Gomer, Graduate User Researcher

<figure><img src="/files/nzxcszSnIEuexfFzZntp" alt=""><figcaption><p>Darcie Gomer</p></figcaption></figure>

Have you ever clicked on a button expecting it to do one thing but it does another? My role in UX (User Experience) is to capture instances like this, and feed them back to my team so they can make better choices in the design of websites. I do this by running interviews, sending out surveys, and testing prototypes directly with the people who will use the website. My job means I get to learn from new perspectives and ask lots of questions. I find it really exciting knowing that data I collect impacts product decisions and improves what we offer to customers.

> #### "Understanding your user is especially important in a technology company. It takes a lot of time and effort for software engineers to write code for a new feature, programme, or product. So, it's critical to make sure that what is developed is needed and understood by users."

I had a tough time choosing what I wanted to do at university; for my A levels I did Chemistry and Maths, Theatre Studies and English Literature! I then came across Anthropology - a social science where you can study people and their cultures. Anthropology combined my passion for learning about people and reading with my skills for research and analysis. When it came to my career I did not think I would be able to use my degree every day, but now I'm a User Experience Researcher!

{% hint style="success" %}
Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.
{% endhint %}

<figure><img src="/files/bk3NGAIBcLMVXcxdwugO" alt=""><figcaption></figcaption></figure>


# December 2023

Welcome to the Code for Life Newsletter

## Seasons greetings!

What a year it has been for Code for Life. Our small, dedicated team, housed amongst the roboticists in Ocado Technology, has remained resilient in a tough year. We have continued to push and drive our platform forward, building new features, new teaching resources, and new relationships with companies such as *Barclays*, *CS in Schools*, *BCS* and *Barefoot Computing*. We are excited to see what the new year brings, and are itching to show you our new features and lessons we are putting together for you.&#x20;

Our newsletter this quarter is celebrating this time of year and we have packed this stocking of an issue full of fun facts and puzzles to keep you and your students busy in the run up to Christmas.&#x20;

<figure><img src="/files/z3z1e0Te0COErDbifyZr" alt="https://pwilson1.typepad.com/.a/6a014e60e24e16970c01b7c93d8450970b-popup"><figcaption><p>Alan Turing (right) at the console of the Ferranti Mark I. Photo courtesy of the University of Manchester School of Computer Science</p></figcaption></figure>

#### <mark style="color:red;">"Listeners to BBC radio heard an utterly new sound in 1951 — a computer playing music"</mark>

[Jack Copeland and Jason Long, The British Library](https://blogs.bl.uk/sound-and-vision/2017/12/christmas-carols-from-turings-computer.html)

Among its Christmas fare the BBC broadcast two melodies that, although instantly recognisable, sounded like nothing else on earth. They were Jingle Bells and Good King Wenceslas, played by the mammoth Ferranti Mark I computer that stood in Alan Turing's Computing Machine Laboratory, in Manchester.

According to Ferranti’s marketing supremo, Vivian Bowden, it was "the most expensive and most elaborate method of playing a tune that has ever been devised". Bowden may have kicked himself for predicting, at this seminal moment, that computer-generated music had no future." [Read more.](https://blogs.bl.uk/sound-and-vision/2017/12/christmas-carols-from-turings-computer.html)

> #### Did you know?
>
> Now we hear computer generated music all the time, can your students identify any of their favourite Christmas songs that have been created with help from a computer?

| <h3>What's wrong with this solution?</h3><p>Uh oh! Phil has been scrambling up the solutions again. Not sure he will be getting a visit from Santa this year!</p><p></p><p>Can you help Santa get the blocks in the correct order so he can deliver to the houses on time? <a href="https://www.codeforlife.education/rapidrouter/54/">Try here.</a></p> | <p></p><p><img src="/files/4lisqfY643sw28pV7YyO" alt="" data-size="original"></p> |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |

## Have you used our new While Loop section yet?

| <p> </p><p><img src="/files/a0TO0vNAq9GcQX6sEE3b" alt="" data-size="original"></p> | Last newsletter we showed you that we released a new section based on While Loops. Have you ﻿had﻿ a try yet? [Have a look here](https://code-for-life.gitbook.io/introduction-to-python/G4tP1H8PLL6ZO1DfFLvB/?campaignkw=While%20Loop%20lessons) and let us know your feedback. |
| ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

## Under the Spotlight

### Claire Ainscough, Chief People Officer, Ocado Group

"My four years here have been a whirlwind - like all tech organisations, no day is ever the same. My role is responsible for Ocado’s employees- basically ensuring this is an amazing place to work regardless of your background.&#x20;

The best thing about my job is when I see people grow and develop - here you can do this through your role, through professional courses and by volunteering internally. One great example of this is through Code for Life which benefits the skills and wellbeing of our volunteers, and inspires people to a future career in tech. This combination of learning, wellbeing, diversity and inspiring young people is one of the best ways Ocado builds a stronger organisation for the future."

<figure><img src="/files/6zhvA8kMUQRT6HV68LNS" alt=""><figcaption><p>Claire Ainscough - Chief People Officer, Ocado Group</p></figcaption></figure>

> #### <mark style="color:red;">"The best thing about my job is when I see people grow and develop... One great example of this is through Code for Life which benefits the skills and wellbeing of our volunteers, and inspires people to a future career in tech."</mark>

"Prior to Ocado I held senior HR roles with Expedia (online travel) and Premier Farnell (B2B distributor) and before that I worked at a start-up - all were great places where I learned loads. I was lucky enough to live in Chicago for five years which was a fantastic work and life experience. Chicago definitely gave me the travel bug and I love to take trips for holidays or work."

### <mark style="color:red;">New Python lessons</mark>

We are very excited about this. We have been busy exploring the open source IDE from Raspberry Pi and we think it's great!

We have a set of lessons ready to test in your classrooms and homes. If you'd like early access, drop us a line and we can share a link with you.&#x20;

### <mark style="color:red;">Intro to Coding for Primary Schools</mark>

<figure><img src="/files/UPKytq29tnsxSh3SCFf2" alt=""><figcaption></figcaption></figure>

A while ago we mentioned we were partnering up with our Australian friends, *CS in Schools*. Well, we have a Beta set of lessons for you to test here in the UK too!

[The course is free](https://csinschools.io/courses/introduction-to-coding-for-primary-schools/), and CS in Schools also offers free teacher support and teacher Professional Development.

Here is what the CEO, Megan Woff says:

> "This is the perfect introduction to grade 5 or 6 primary school students to algorithms and block coding! The course contains a full classroom-in-a-box for any teacher to be able to introduce fun & effective coding skills over 6 lessons.
>
> The course includes full lesson slides, classroom based activities, worksheets, assignment, teacher notes & support and of course Rapid Router. The course is mapped to the Australian upper primary school curriculum (ages 8-12) and can be adapted for UK key stage 3."

{% hint style="info" %}
Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.
{% endhint %}

<figure><img src="/files/mMTc3Q6OSNqXrmApEI1U" alt=""><figcaption></figcaption></figure>


# Autumn 2023

Welcome to our Autumn newsletter

A celebrated female in technology to hit the headlines recently was Mira Murati, the CTO of OpenAI.&#x20;

| <p></p><p><img src="/files/JiFFOYOuOQCPUQy3AxU2" alt="Mira Murati" data-size="original"></p> | <mark style="color:red;">**"...If we think that the answer of the model is incorrect, we can say, “Are you sure? I think actually…” And then the model has an opportunity to go back and forth with you, similar to how we would converse with another human."**</mark> [Mira Murati, Time Magazine](https://time.com/6252404/mira-murati-chatgpt-openai-interview/?dm_t=0,0,0,0,0) |
| -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

Mira Murati is currently the chief technology officer of OpenAI, the artificial intelligence research company that develops ChatGPT. She rose to prominence after the release of ChatGPT where she was widely celebrated by women in tech.

Murati joined OpenAI in 2018, later becoming its chief technology officer, where she leads the company's work on ChatGPT, Dall-E, and Codex. Her responsibilities include oversight of the company's research, product and safety teams. She is an advocate for the regulation of AI. Source: [Wikipedia](https://en.wikipedia.org/wiki/Mira_Murati)

## Women at Ocado

We celebrate our female colleagues too here at Ocado Technology, and Carisa Lopez, one of our Business Support Specialists, has helped us highlight how diversity in technology is fundamental in producing high quality products and services:

> <mark style="color:blue;">**“Throughout history, women have made notable contributions across diverse fields, including computing, programming, engineering, and more. In the contemporary landscape, the role of women in technology holds unparalleled significance." ... "Women offer distinct viewpoints, ingenuity, and adeptness in problem solving, which fuel innovation and extend the boundaries of possibility." ..."Celebrating the achievements of women in technology, who serve as a continual source of inspiration, has been a truly enriching experience... ”**</mark> Carisa Lopez, Ocado

## New features coming soon <mark style="color:red;">🎉</mark>

| <p>We are looking for teaching and learning Volunteers to feedback on our new <a href="https://code-for-life.gitbook.io/while-loop-lessons-beta/?dm_t=0,0,0,0,0">While Loop material</a> to be released soon. We have two lesson plans that you can test for us here. The final sessions will be embedded in Rapid Router.</p><p>To get involved, however small, and try the resources before release, <a href="mailto:codeforlife@ocado.com">please get in touch</a>.</p> | <p></p><p><img src="/files/5SxxeDzM0jFeLl6sjp7F" alt="" data-size="original"></p> |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |

## We are teaming up with CS in Schools

| <p></p><p><img src="/files/1imccPWrIVfFpqr1NHLj" alt="" data-size="original"></p> | Earlier this year we got together with CS in Schools, a charity in Australia with a similar mission to us, to talk about how we can align Rapid Router to the Australian curriculum. We are excited to announce some new teaching material we will be testing this quarter in the UK and Australia. 🎉 |
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

## New Robotics worksheet 🤖

| <p>We have been busy creating new resources to introduce robots into the classroom. With help of the roboticists at Ocado Technology we are launching our <a href="https://r1.ddlnk.net/t/4RRT-UUHH-3HZXAE-SPRZG-1/c.aspx">new robotics worksheet</a>. Please let us know your thoughts <a href="mailto:codeforlife@ocado.com?subject=Robotics%20worksheet%20feedback">here</a>. We will be adding more resources to this section and would love to know what is useful to you in your classrooms!</p><p></p><p>Share your experiences with our resources on social media and tag us <a href="https://r1.ddlnk.net/t/4RRT-UUHH-3HZXAE-SPRZD-1/c.aspx">@codeforlifeuk</a></p> | <p></p><p><img src="/files/ou3ArsJmCi4Reln0phSi" alt="" data-size="original"></p> |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |

## Brainsteaser time!

| <p></p><p><img src="/files/QYUChscD86ZjEaaZ44Gm" alt="" data-size="original"></p> | <p>Kirsty has set a challenge for you on Rapid Router. It's not as easy as it seems. Can you get full points?</p><p></p><p><a href="https://r1.ddlnk.net/t/4RRT-UUHH-3HZXAE-T0U6I-1/c.aspx">Go to the challenge</a></p> |
| --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

## Under the Spotlight

Carisa Lopez - Business Support

|                                                                                                                                                |                                                                                   |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| <mark style="color:red;">**"I hope to continue to inspire and encourage women and allies to get involved in the technology industry."**</mark> | <p></p><p><img src="/files/8IYNsBDY16vcuuq7OlMf" alt="" data-size="original"></p> |

I am a Business Support Specialist in North America for Ocado. I work as a key player to support the operation of the site. As a woman without a technical background, I’ve had to learn and understand a basic level of technical operations by submerging myself in technology. I work on projects called BOT School, Peripheral school, and Safety Training. These activities are aimed at providing the necessary assistance to ensure smooth site operations and support for my team.

Gaining a foundational understanding of equipment, diverse software systems and achieving expertise in Google Suite has empowered me to constantly advocate for my team members. Furthermore, I can foster a sense of inclusion among my team onsite, which is essential for creating an environment conducive to attracting and retaining top talents.

What I enjoy most about my role is that it has pushed me to become innovative and think outside of the box to become a stronger professional, but the best part of my role is the ability to form a professional relationship with each of my team members onsite and getting to know them individually. I hope to continue to inspire and encourage women and allies to get involved in the technology industry.

{% hint style="info" %}
Help us get more girls into technology by sharing our FREE resources.
{% endhint %}

<figure><img src="/files/mMTc3Q6OSNqXrmApEI1U" alt=""><figcaption></figcaption></figure>


# Summer 2023

It's summer time!

No doubt, you will be looking forward to some sunshine and relaxing after school ends for the year. In this newsletter we look at the relationship between holidays and programming - the entire journey from picking your holiday to landing at your destination is filled with computers and coding!

The holiday journey starts with a booking website full of algorithms that suggest your perfect getaway, and compare flights and hotels with your search criteria. Once you are at the airport, all sorts of computing is completed to get you onto a plane, which in turn is guided by air traffic control to guide your plane through the airspace to your destination. Imagine all of the calculations!

For some advanced computing in flight calculations, we celebrate Melba Mouton and her work at NASA’s flight centre. Read more about her below.

### Melba Mouton (1929-1990)

| <p></p><p><img src="/files/nOCESx9JfKG2dl3wWjTG" alt="" data-size="original"></p> | <p>Mouton worked at NASA’s Goddard Space Flight Centre, coding computer programs to calculate the trajectories and locations of various aircraft.</p><p></p><p>She also led the group of "human computers," who tracked the Echo satellites. Mouton and her team's computations helped produce the orbital element timetables by which millions could view the satellite from Earth as it passed overhead.</p><p><br></p><p><a href="https://www.nasa.gov/image-feature/melba-roy-mouton-mathematician">Source</a></p> |
| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

### How have computers helped aviation?

Just as computers have affected virtually every aspect of modern life, from medicine to sports to education, they have also had a major impact on aviation. Computers are now used in all parts of aviation. They are used to design airplanes, to control them in flight, and to ensure that they reach their destinations safely and (more or less) on time.

The latest application of computers (to airplane technology) is for what is called "[the Airborne Internet](https://en.wikipedia.org/wiki/Airborne_Internet)." Airplanes will be connected by radio and satellite link to a global information system that will provide them with information on the weather and aircraft in their immediate vicinity, as well as their flight plan.

The ultimate application of computers may be to take over control of flying completely. Already planes can be flown over long distances, with multiple course changes, entirely by computer. They can also take off and land automatically (although current flight rules prohibit this). It is not a far step to completely automatic operation.

[Source](https://www.centennialofflight.net/essay/Evolution_of_Technology/Computers/Tech37.htm)

{% hint style="info" %}

#### Did you know?

[About 1/3rd of your taste buds can go numb during a flight. The reason is that the air up in the sky is so dry that it absorbs the moisture from your body. This is one of the prime reasons why airplane food tastes so bad.](https://youtu.be/EIKfHOk8rx0) [Cool Facts for Kids](https://www.coolkidfacts.com/airplane-facts-for-kids/)
{% endhint %}

### Are you stuck for where to go on holiday?

| <p></p><p><img src="/files/jJnR8DLK8EYYnUeHG6qv" alt="" data-size="original"></p> | <p>Maybe you can write a program to help…</p><p>Can you write a program using Python that asks what animal you’d like to see on your holidays and then outputs one of the counties where you can see that animal in the wild?</p><p>E.g.</p><p><a href="https://unsplash.com/photos/ZxNKxnR32Ng?utm_source=unsplash&#x26;utm_medium=referral&#x26;utm_content=creditShareLink">Lions</a>, Kenya</p><p><a href="https://unsplash.com/photos/YuQgNYku1M8?utm_source=unsplash&#x26;utm_medium=referral&#x26;utm_content=creditShareLink">Tigers</a>, India</p><p><a href="https://unsplash.com/photos/3v1GBL9pWE4?utm_source=unsplash&#x26;utm_medium=referral&#x26;utm_content=creditShareLink">Reindeer</a>, Sweden</p><p><a href="https://unsplash.com/photos/-W5lbMU5Dak?utm_source=unsplash&#x26;utm_medium=referral&#x26;utm_content=creditShareLink">Bears</a>, Canada</p> |
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

Solutions to the exercise are [here](broken://pages/DpbOnOqHGo0u5VBbNvt7).

### Under The Spotlight

#### Tom Regan

I’m a Software Engineer at Ocado, and I work on the systems that run our customer fulfilment centres.

Building software requires planning, organisation, and communication. Just like air traffic controllers managing multiple aircraft, software engineers juggle many complex tasks at once as we design, build, and debug systems.

|                                                                                                                                                                                                                                                                                              |                                                                                   |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| <h4><mark style="color:blue;">"At Ocado we face very busy traffic</mark> </h4><h4><mark style="color:blue;">management, based on air traffic control</mark> </h4><h4><mark style="color:blue;">and path planning in real-time."</mark></h4><p><br></p><p><br></p><p><br></p><p>Tom Regan</p> | <p></p><p><img src="/files/WUIQaYhOaBBaeBTCts4z" alt="" data-size="original"></p> |

At Ocado we face the very busy traffic management, based on air traffic control and path planning in real-time. Our robots travel at 15kph along tracks over 7 metres from the ground, and pass one another just 5 millimetres apart. Safety is our number one priority, and we work carefully to keep our complex network of moving machines running smoothly.

What I enjoy most is working as part of a team; it allows me to design things that are much bigger than I could build on my own, and see them come to life - together we can turn big ideas into working systems. It’s an incredibly rewarding feeling.

{% hint style="info" %}
Let us know what you think of our newsletter by getting in touch and sharing your thoughts and ideas.
{% endhint %}

<figure><img src="/files/mMTc3Q6OSNqXrmApEI1U" alt=""><figcaption></figcaption></figure>


# Spring 2023

Welcome to the Code for Life Easter newsletter.

This month we have a special AI focus, including our colleague's thoughts on ChatGPT. Have you experimented with it yet, are you worried about its capability, or are you celebrating the success of OpenAI?

## ChatGPT and the future of homework

<figure><img src="https://i.emlfiles4.com/cmpimg/7/1/6/2/2/2/files/1260012_screenshot20230309at18.19.21.png" alt=""><figcaption><p>ChatGPT example</p></figcaption></figure>

Ever since a company called OpenAI released a website called [ChatGPT](https://r1.ddlnk.net/t/4RRT-ST7L-32G5NS-Q4P53-1/c.aspx), there’s been debate on how it will affect how we use it for work, study, and even for coding.

Essentially, it’s a powerful AI model trained on millions of examples from around the internet, which can come up with new content on the basis of a user prompt (question). It can be used to answer questions, compose poems, draft essays and yes, write code. The range and quality of its output is pretty impressive. There’s [a handy introduction](https://r1.ddlnk.net/t/4RRT-ST7L-32G5NS-Q4P1K-1/c.aspx) to ChatGPT from the BBC.

But lots of teachers and parents are worried about students using it to churn out homework! One camp says this is fine - ChatGPT can be used as a shortcut to produce a solid first draft that a student needs to learn to refine and review. They compare its impact on writing to how using a calculator has made mathematics much easier and quicker.

Others are concerned about cheating and poor quality learning. They point to the fact that ChatGPT’s output isn’t always accurate, and that students won’t learn how to formulate their own, original work.

**What do you and your students think about using ChatGPT?**

{% hint style="info" %}

#### Did you know?

In the US, the New York City education department has even banned ChatGPT on school devices!
{% endhint %}

### **🐰 Easter Quiz 🐰**

The paragraphs below describe types of machine learning.

<table data-view="cards"><thead><tr><th></th><th></th><th></th></tr></thead><tbody><tr><td><strong>Supervised Learning</strong></td><td>Classifications are known in advance; the machine is trained on labelled known data.</td><td><mark style="color:blue;">Goal: predict the label for a new piece of data.</mark></td></tr><tr><td><strong>Unsupervised Learning</strong></td><td>The classifications are not known in advance.</td><td><mark style="color:blue;">Goal: Determine the pattern or groupings and identify which group a new piece of data belongs to.</mark></td></tr><tr><td><strong>Reinforcement Learning</strong></td><td>The model tries to maximise the reward and learns from experience.</td><td><mark style="color:blue;">Goal example: learn over time how to reduce the power consumption of industrial robots.</mark></td></tr></tbody></table>

**Question 1: Can you decide which type of machine learning might be suitable for these applications?**

1. Beat this human player at this game
2. Spam email detection
3. Image recognition
4. Recommendation engines

**Question 2: How is it possible for a machine trained with millions of correct examples to produce the wrong answer?**

<details>

<summary>Answers</summary>

Question 1:

1. Reinforcement learning
2. Supervised learning
3. Supervised learning
4. Unsupervised learning

Question 2:

* Incomplete training data
* Training data with bias, e.g. many more of one group than another
* Training data that doesn’t represent the real world

</details>

{% hint style="info" %}
**Try it yourself**

Dale Lane from IBM has created some free teaching resources with worksheets to allow you to try this for yourself. Have a look here: [https://machinelearningforkids.co.uk](https://r1.ddlnk.net/t/4RRT-ST7L-32G5NS-QESHL-1/c.aspx)
{% endhint %}

## Under the Spotlight

### Myrna Macgregor - Lead, Responsible AI & Robotics

Artificial intelligence, or AI, is becoming a key part of how Ocado works: from computer vision systems which allow robots to pick a wide variety of items, to recommendation engines which identify the most relevant products for each customer. It’s critical that we develop and deploy these technologies responsibly.

It’s really motivating to work on such a cutting edge issue. One of my key tasks has been to bring 40+ colleagues together to figure out what responsible AI means to our business - it’s been fascinating to hear their perspectives. And I’m really proud that we got sign-off to publish the commitments we came up with in Ocado’s 2022 Annual Report (see: Ethics of AI and Robotics).

<figure><img src="https://i.emlfiles4.com/cmpimg/7/1/6/2/2/2/files/1262630_myrna_spotlight_image.png" alt=""><figcaption><p>Myrna Macgregor</p></figcaption></figure>

> <mark style="color:blue;">**"My role is thinking through how Ocado can use AI and robotic AI technologies in a safe and trustworthy way."**</mark>

I’m not a technical specialist. My degree was in European Studies, French and German. Prior to joining Ocado, I worked for Foreign Office and the BBC. My career journey has been translating my experience in policy, strategy and human rights to a technology context. So I’m proof that all kinds of people can transition into a career in AI!

## Our UX volunteer&#x20;

### Marie Barsoum

<figure><img src="https://i.emlfiles4.com/cmpimg/7/1/6/2/2/2/files/1267042_marie.png" alt=""><figcaption><p>Marie Barsoum</p></figcaption></figure>

> <mark style="color:blue;">**"Volunteering for Code for Life allowed me to gain professional experience before graduating. The brief was exciting and helped me to explore a unique user journey from the gamer’s experience. .."**</mark>
>
> "...Liaising with Laura from the Code for Life team was very smooth and friendly. I can't wait for user testing to see how people react to proposed screens to allow me to improve and iterate my work"

We recently had the pleasure of working with Marie Barsoum who is currently studying UX at the University of Arts London. Marie contacted us in the hope she could volunteer to gain some industry experience and work on a live product. We were delighted to be able to get her onto one of our tasks and support her with the work. Now it's up to you, our teachers,  to take it to the next stage.

Marie has put some visuals together tackling a gap in our level creation zone. Please take a look at the visuals here and let us know your [feedback on the new feature](https://r1.ddlnk.net/t/4RRT-ST7L-32G5NS-QDK4V-1/c.aspx).

{% hint style="info" %}
Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.
{% endhint %}

<figure><img src="/files/784wADMJzplUIWL1RvXb" alt=""><figcaption></figcaption></figure>


# December 2022

Welcome to the Christmas newsletter - Seasons greetings!

It's that time of year again, where we dust off our winter coats and huddle down for some festive family time. This year we have introduced some new features, have you seen them? [Take a look](https://www.codeforlife.education/) and see what has changed. We have also turned the snow on again, so get coding!

🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄

### The Father Christmas worm (even hackers get into the holiday spirit!)

In December 1988, a worm named ‘The Father Christmas worm' was released into a NASA network. The aim of this worm was to send a Christmas greeting from "Father Christmas" from the affected system. The infection, originated in Switzerland, was thought to have spread to more than 6,000 computer nodes through the NASA network! 😱

When discovered, an email was sent out to warn centre managers that a worm had been released. One strategy to prevent infection was to create an empty "Hi.com" file which would stop the worm from being able to create a new version of the same file (this was its own strategy). This prevented mass infection and only 2% of infected devices launched the worm.

Although the Father Christmas worm caused little damage, it greatly increased the awareness of computer security protocol. This was proved in 1989, when a nearly identical worm was released into the Easynet intranet. The network manager was able to quickly prevent the spread of the worm because of the exposure of the Father Christmas worm from the previous month.

What a lot of worms! 🪱 You can read how to improve some of your own security measures on our [Code for Life security worksheet](https://code-for-life.gitbook.io/code-for-life-extras/) here. [Source](https://en.wikipedia.org/wiki/Father_Christmas_\(computer_worm\)).

{% hint style="info" %}

#### Did you know?

A computer worm duplicates itself to spread to uninfected computers. It often does this by exploiting parts of an operating system that are automatic and invisible to the user. [Source](https://www.techtarget.com/searchsecurity/definition/worm)
{% endhint %}

### Try your luck with a random snowy level!

Help Santa and Rudolph through a snowy level deliver to the presents to the houses.

<figure><img src="/files/VSki37jhvTeWDUhjcila" alt=""><figcaption></figcaption></figure>

### Logic Puzzle

Test your powers of logic with this puzzle. Read the clues very carefully and then try to work out which child received which present by a process of elimination. Draw a table to help you work it out. You can find more puzzles on our Code for Life [newsletter](https://code-for-life.gitbook.io/newsletters/) pages.

<div><figure><img src="/files/WehEXkl3SdajtABPMfca" alt=""><figcaption></figcaption></figure> <figure><img src="/files/lWF5G4eWAjK0ss7mUi9G" alt=""><figcaption></figcaption></figure> <figure><img src="/files/Ydjr35keFknpRFWUbPjS" alt=""><figcaption></figcaption></figure></div>

Oh no! Rudolph has eaten the labels from three children’s presents. Can you help Santa deliver the presents to the right children?&#x20;

* The children are aged 12, 14 and 15.
* Gilly isn’t the youngest and she doesn’t live in Greene Road
* The child who received the telescope lives on Birch Grove and is younger than William.
* Timothy didn’t receive a bicycle.
* The oldest child received a remote-controlled car but doesn’t live on Freeman Avenue.

<figure><img src="/files/9TfTAbx90rpzJgIodTDb" alt=""><figcaption></figcaption></figure>

### Help Santa find the present!

Santa has dropped some of his presents. Can you help him find his way? You can generate your own mazes [here](https://www.puzzlemaker.discoveryeducation.com/maze).

<figure><img src="/files/KuwulPXqZcVplfxLOrhF" alt=""><figcaption></figcaption></figure>

### Under the Spotlight

**Anna Len - Automation Development Tester**

<img src="/files/DOj7ySODNE9BCzYM1usw" alt="Portrait of Anna Len" data-size="original">

> #### <mark style="color:blue;">"Nowadays digital shopping is very popular and in the near future it could possibly dominate the market. I am just happy that I can be part of it."</mark>

Anna, an Automation Development Tester, joined the Ocado Technology team from one of Ocado's Customer Fulfilment Centres. "I've received an incredible opportunity to move to the Technology department. This was a great occasion for me to develop my passion as I am fascinated by the large amount of automation within the warehouse. I really enjoy what I am doing as I work with the robots. I get to test them every day to make sure they work perfectly when they are being used. Which helps me be able to learn something new everyday, meet new people from other parts of the world, and be a part of the great team which makes a difference in the technology and future."

{% hint style="info" %}
Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.
{% endhint %}

![](/files/784wADMJzplUIWL1RvXb)


# Autumn 2022

It's National Coding Week 🎉

[National Coding week](https://r1.ddlnk.net/t/4RRT-PYYE-5H8B9G-MYW16-1/c.aspx) was started in 2013 by Richard Rolfe, an inspiring former head teacher who wanted to help adults learn digital skills. This month, we celebrate his initiative with the hashtag #nationalcodingweek on our social channels. You will find our updates [highlight a job](https://r1-app.dotdigital.com/easyeditor/preview?id=1211702\&doctype=#Job-link) that is related to coding, and use Code For Life to introduce coding skills to drivers and warehouse operatives at Ocado Group.

<figure><img src="/files/8ohnEWVkFnIcOI6ctX8t" alt=""><figcaption><p>Richard Rolfe</p></figcaption></figure>

> #### "It struck me that whilst there was government investment in a new computer science curriculum for school children, there wasn’t enough being done to support adults."

“It struck me that whilst there was government investment in a new computer science curriculum for school children, there wasn’t enough being done to support adults… there wasn’t enough being done to support teacher training especially for non-specialists. Parents and governors needed training too… most people aren’t in education so I wondered what was being done to support and retrain those who had missed out on digital skills training or for older people who wanted to switch careers or become more cybersecure.” [codingweek.org](https://codingweek.org/richard-rolfe-founder-of-national-coding-week-tells-his-story/)

{% hint style="info" %}

### Did you know?

**Python** is used in the whole data pipeline of the [James Webb Space Telescope](https://talkpython.fm/episodes/show/357/python-and-the-james-webb-space-telescope). [Explore the universe with Webb](https://webbtelescope.org/news/news-releases).
{% endhint %}

### **Try it out/Can you solve this?**

Test your skills with one of our [Brain Teaser levels](https://www.codeforlife.education/rapidrouter/76/).

<figure><img src="/files/W33iOs04sxA7yr4F12td" alt=""><figcaption><p>Brain Teaser</p></figcaption></figure>

### <mark style="color:red;">Under the Spotlight</mark>

Richard Watkins - Data Scientist

<figure><img src="/files/yjzQ0QWDv87KfOG2byia" alt=""><figcaption><p>Richard Watkins</p></figcaption></figure>

Richard is a Data Scientist working in Supply Chain at Ocado Technology. His team design forecasting algorithms – helping retailers offer their customers good levels of product availability, while minimising waste. As customers can add items to their orders until just a few hours before delivery, and fresh items can have a very short shelf life, this is a huge challenge.

> #### "It's nice to be able to see your algorithms reducing food waste."

## **Help, it won't stop!**

Have a look at the code below. Why does it create an infinite loop?

```python
number = 1
while number < 10:
    print(number)
print("Finished!")
```

Answer: The loop is controlled by the value of *number* but *number* is never changed.

Therefore which is the correct solution from the examples below?

{% code title="a" %}

```python
number = 1
while number < 10:
    print(number)
    number + 1
print("Finished!")
```

{% endcode %}

{% code title="b" %}

```python
number = 1
while number < 10:
    print(number + 1)
print("Finished!")
```

{% endcode %}

{% code title="c" %}

```python
number = 1
while number < 10:
    print(number)
    number = number +1
print("Finished!")
```

{% endcode %}

{% code title="d" %}

```python
number = 1
while number < 10:
    print(number)
number = number +1
print("Finished!")
```

{% endcode %}

## **Celebrate National Coding week with Code for Life**

Code for Life has been delivering support to teachers, parents and students around the world since 2014. This month we are releasing our first coding club packs. We have two different packs; the first is based on [Primary learning](https://code-for-life.gitbook.io/code-club-resources/) and suitable for younger students, and our [alternative club pack](https://code-for-life.gitbook.io/code-club-resources-intermediate/) is ideal for introducing teenagers and adults to the principles of the Python language.

We want anyone to be able to set up a club and start delivering the courses. There are guides and resources for you to follow alongside a set of editable slides. [Let us know](mailto:codeforlife@ocado.com?subject=Contact%20us) how you get on with them and if you have any suggestions to improve them.

<figure><img src="/files/AXunAI8LSNB7XU7uKQxd" alt=""><figcaption><p><strong>Club certificate</strong></p></figcaption></figure>

## Solutions

#### Brain Teaser solution

<figure><img src="/files/18lpzDwjoqYR7f3TaRXN" alt=""><figcaption><p>Brain teaser solution</p></figcaption></figure>

#### Python solution:

a) No, number is not being increased. You must assign number + 1 back to number&#x20;

b) No, number is not being increased. You must assign number + 1 back to number. You can’t do this in a print statement&#x20;

c) **This is correct**. 1 is being added to number and that value is being stored back in number&#x20;

d) Here, the increment to number is not inside the loop. It must be indented to line up with the print()

![](/files/784wADMJzplUIWL1RvXb)


# Summer 2022

Code for Life Newsletter

## <mark style="color:red;">The history of personal computers</mark>

![A Kit-built Altair 8800 by Tim Colegrove](/files/myHcqFcIohMwjTrPREBi)

Personal computers are a relatively new invention, believe it or not! The very first one was the Altair 8800 which was released in 1975. These early personal computers weren’t very easy to use though and were only really used by electronic hobbyists. The Altair 8800 came as a build-it-yourself kit which involved soldering!

There was no keyboard, mouse or screen with the Altair 8800! You used switches to enter your program in binary and there were lights on the front for your output.

| ![](/files/ODi1BhsadaF5rrjEUnEi) | <h3>ZX Spectrum</h3><p></p><p>In 1982, the Sinclair ZX Spectrum was released. This was a huge step forward and was much more accessible to home users. Many adults today had ZX Spectrum as their first computer and have built their love of programming and computers since then.<br></p><p>This computer plugged into your TV. It had a tape drive for saving your programs, a little printer and you could even get a joystick for playing games.</p> |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

### Did you know?

The ZX Spectrum was programmed using BASIC. It was really easy to learn and I’m sure you can work out what this program does?

![](/files/d4APvGBQGjezliDDGiNS)

| Check out some of these games you could play on the website [torinak](http://torinak.com/qaop/games)! | ![](/files/f8yrdxgCAp02IAn2LmmF) |
| ----------------------------------------------------------------------------------------------------- | -------------------------------- |

### Can you rearrange these lines of Python code to count down?

The program should only output “Blast off!” once…

```python
count = count - 1 
print(count) 
print(“Blast off!”) 
while count >= 0: 
count = 1
```

[Solution here](broken://pages/f0MxtjQrmoXCT6n0TDzM)

### Under the spotlight

**Radhika Gudipati** - Research Coordinator (Robotics & AI)

My role as a Research Coordinator is to interact with various technology teams within Ocado, understand their current challenges (e.g., what is the best route for an Ocado van to deliver the shopping to a customer) and collaborate with the research teams at Universities to develop a solution.

My biggest challenge is to find a solution and at the same time not give away the secret sauce to the competitors. I enjoy working with roboticists at different organisations. My PhD in robotics and my passion in taking the research to solve real world challenges brought me into this role.

![Radhika Gudipati - Research Coordinator](/files/wBSjQtXb5Z0kYNN8ZP6X)

> #### <mark style="color:blue;">"My first exposure to a computer was in my Yr 8 where a class of 50 students had to share 10 computers in a small room (air conditioned lab was the highlight for the hot tropical weather)."</mark>

COBOL was the language we were taught in the classroom and we were asked to handwrite the code in our homework books. As I typed the code in, executed it and saw the special characters printed in shapes appearing on the screen - it made my day! 🙂

### Code for Life updates - your chance to have your say!

**Renaming v to my\_van**

![](/files/tVlWWlgIOO5Bu3gblmGd)

We have updated the variable in Rapid Router so that it makes more sense to the students. It should make your Python lessons easier to follow.&#x20;

**Bett Show 2022**

![Dioni Zhong and Laura Cumming (Code for Life Team)](/files/PetUfYhdaK6qbif83GrJ)

Did any of you come and meet us at the Bett show this year? If so, let us know what you think of our resources so far by feeding back to us through the link below.

**Gitbook Resources**

![Gitbook resources](/files/RGe7QYwFvTgGwOYQgWeN)

It has been some time now since we moved our resources to Gitbook in order to improve your experience.&#x20;

**Scoreboard and tracking progress**

![Flexible scoreboard viewing](/files/iNeyG3ozVs2X5EKZMplv)

You told us that you needed more and we have responded. The new scoreboard allows you to select and focus on particular areas of Rapid Router and highlights areas which may need improvement. We will be updating the scoreboard further still to give you more flexibility and feedback on how your students are doing.&#x20;

If you want to feedback on our resources or any of our updates, you can do so through this [short survey](https://usabi.li/do/7028bab8d112/c001).

![](/files/784wADMJzplUIWL1RvXb)


# Spring 2022

Code for Life Newsletter

![The Bett show 2022](/files/79FGGc9Ym6zBm0QlptG8)

## It's that time of year again!

Spring is in the air, the daffodils are flowering and... the [Bett show](https://uk.bettshow.com/visit?gclid=Cj0KCQiAmpyRBhC-ARIsABs2EAomXonRGJ-sVVCiJlcAE6hc4IfRUa5JPC5rcbmIQ9UbVgt80XZii_8aAndAEALw_wcB) is back!&#x20;

Code for Life is excited to announce we will be at the Bett show again this year. Come and have a chat about our products and meet the team at <mark style="color:purple;">**stand NH71**</mark> from <mark style="color:purple;">**March 23rd–25th**</mark>. We would love to say hello. To help celebrate tech in education, this newsletter is all about digital literacy.

![Nasa image of a connected world. Source: Unsplash](/files/4SQ7vUCxVU1FrsKrh75g)

Computer scientists **Vinton Cerf** and **Bob Kahn** are credited with inventing the Internet communication protocols that we use today and the system referred to as the Internet. Though other protocols were developed and used before Cerf and Kahn's TCP/IP, such as the file transfer protocol (FTP) and network control protocol (NCP), the Internet as we know it today is built on their basis of a “network of networks.” Source: *Source: <https://www.britannica.com>*

> ### <mark style="color:purple;">Did you know?</mark>
>
> <mark style="color:purple;">**75% of organisations around the world have experienced some kind of phishing attack and a cyberattack is attempted every 39 seconds! This is even more reason to be careful when you open your emails.**</mark> *source: graphic.ai*

### So how do we keep safe online?

#### <mark style="color:red;">What scams might we come across and how will we spot them?</mark>

We have introduced a new worksheet around online safety and hardware. [Take a look](broken://spaces/duiYnCr4VZqAFS44bumW/pages/5PZKPrmEYxToK2yFHMIF) and let us know what you think.&#x20;

### Debugging exercises

Can you debug these pieces of code below? Take a look and see if you can spot the mistakes we have made.

<mark style="color:purple;">**Exercise 1**</mark>

```python
# This program outputs if the student has passed
# They must have at least 50 marks to pass
# Nothing is output if they fail

mark = input("Enter your mark")
if mark > 50:
    print("Pass")
```

<mark style="color:purple;">**Exercise 2**</mark>

```python
# This program calculates a pass or fail where you must have 
# at least 50 marks to pass

mark = int(input("Enter your mark"))
if mark > 50:
    result = Pass
if mark <= 50:
    result = Fail
print("result")
```

<mark style="color:red;">**Solutions**</mark>

```python
mark = int(input("Enter your mark"))
if mark >= 50:
    print("Pass")
```

```python
mark = int(input("Enter your mark"))
if mark >= 50:
    result = "Pass"
else: 
    result = "Fail"
print(result)
```

### Under the Spotlight

Dioni Zhong

![Dioni Zhong - Senior Software Engineer, Code for Life](/files/YaheCq1VqQQV5wB0XiB8)

Dioni is a Senior Software Engineer in our very own Code for Life team! She has been helping us improve our products and keep everything running smoothly. Read more about what she gets up to every day below.

> #### <mark style="color:purple;">"I love problem solving and building things. I’m passionate about education. I feel a great sense of pride and joy knowing that I play a part in building something that helps students and teachers worldwide."</mark>

I work in Code for Life team at Ocado to develop the website and the Rapid Router and Kurono games. In a small team, we have to do a variety of things. Apart from coding, I also work with data, charts, and documentation. I love problem-solving and building things. I’m passionate about education. I feel a great sense of pride and joy knowing that I play a part in building something that helps students and teachers worldwide.

Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.

![](/files/784wADMJzplUIWL1RvXb)


# December 2021

Code for Life Newsletter

## <mark style="color:red;">Seasons greetings from us all at Code for Life</mark>

It's that time of year again when we switch on the snow in our Rapid Router game and ask Rudolph to help with our deliveries!

We thought we would celebrate something related to Christmas and what better way to do that than to learn about [Thomas Cane's light-up stocking invention](https://patents.google.com/patent/US5523741A/en)? Read about it below.

![](https://lh6.googleusercontent.com/h27EKVyyHnh9WL9jGZGMvGgwXB5Wlx7h3VrW_X7HOCEkhNtzy5vq6aZ_oqnwT6duuGpXrjPLjNNqc52v3tB1gZJ_W0vv0ZMP2kEh1VwoUEOs0wBPXFbOTMV-MfDVMA)

| <h3><mark style="color:red;"><strong>It is therefore an object of the present invention to provide a children's device capable of providing selective illumination to signal the arrival of Santa Claus.</strong></mark> </h3><p>Sourced from Google patents</p> | <p>Thomas' magical Christmas invention is a stocking with a light signalling the arrival of Santa Claus. The stocking features a light and power source, as well as a switch to connect the light to the power (and therefore light up). A chord or ribbon needs to be pulled for the light to light up. This, of course, is a job for Santa ;)</p><p> </p><p>So, anyone with a stocking invented by Thomas Cane will know if you’ve been good when you wake up on Christmas day and the stocking is lit and there are presents around your tree!</p> |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

{% hint style="info" %}

#### Want to make your own?

You could adapt this idea with your class to use the sound sensor in a micro:bit. Here is a [micro:bit project](https://microbit.org/projects/make-it-code-it/sound-meter/?campaignkw=micro%3Abit%20project) that creates a graph on the LED output to show the sound level. You could make a Christmas tune play if anyone pulls on your Santa detector!
{% endhint %}

![Level 59](/files/7UOs22rxJr9mhiIXCRjj)

### We have turned on the snow!

Check out Rapid Router - it's started to snow! Can you help Rudolph and Santa get those deliveries done in time this year?

Check out [level 59](https://www.codeforlife.education/rapidrouter/59/#?campaignkw=level%2059) and see for yourself.

### <mark style="color:blue;">Can you solve our festive puzzle?</mark>

![](/files/y3YJv7A44VcnzPIXceOm)

Here is a Nonogram. [Print off the grid here](broken://spaces/duiYnCr4VZqAFS44bumW). The rules are simple.

You have a grid of squares, which must be either filled in black or marked with X. Beside each row of the grid are listed the lengths of the runs of black squares together on that row. Above each column are listed the lengths of the runs of black squares in that column. Your aim is to find all black squares.

### <mark style="color:red;">Under the Spotlight</mark>

![Anthony Youngman](/files/X1dMHMrdrF50rhhRN7lu)

Anthony works as a roster analyst in the department responsible for Business Analysis. His role is extremely important in helping Ocado Group get groceries out to its customers. His job is to prepare the 13-week rosters in advance before they are sent out to drivers letting them know when they are working. Having been a driver last year, this year Anthony wanted to help by making such a busy period as easy as possible.

> <mark style="color:red;">**"I'm spending this Christmas trying to give the drivers the present of a roster that fits in with their lifestyle."**</mark>

Just like our Rapid Router challenges, it is all about efficiency and saving energy wherever possible at Ocado Group, so making sure the drivers know their roster ahead of time means that the full service can be much smoother.

### Can you get creative this Christmas?

Our Code for Life teaching consultant has been busy at her school this year, and when she showed us this, we had to put it in the newsletter to show you! If you look closely, you can spot all the different computer elements.

![Christmas Wreath made from computer parts](/files/xzr9R9Ih35V26qG9MLgf)

Why don't you have a go yourself?

Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas. Is there anything else you'd like us to include?

![](/files/784wADMJzplUIWL1RvXb)


# Newsletter challenges

### Ocado Robot Debugging Challenge!

Oh no! The program of an Ocado bot has a bug! This robot is supposed to collect the groceries, but it's not working correctly. Your mission is to debug the Python code and get the robot back on track.

The Grid:

Imagine the maze as a simple grid. Your robot can move in four directions: "up", "down", "left", and "right".

Here's the layout of your grid:

```
# # # # # #
# S - A - #
# - - - - #
# - B - - #
# - - - - #
# C - - E #
# # # # # #
```

*# represents a wall – the robot can't go there.*

*- represents an empty space the robot can move through.*

*S is the robot's starting position.*

*A is the avocado.*

*B is the banana.*

*C is the carrot.*

*E is the delivery exit.*

### The Challenge:

#### **The following Python code has some bugs. Your task is to:**

1. Identify the errors in the code.
2. Correct the errors so the robot can successfully collect the avocado ('A'), banana ('B'), and carrot ('C').
3. The robot should start at 'S' and end at 'E'

Here's the buggy Python code:

{% code overflow="wrap" %}

```python
def robot_path():
    # Initial robot position
    robot_row = 1
    robot_col = 1

    # Items collected
    collected_items = []

    print("Starting the Ocado Bot!")

    # Move to Avocado
    robot_col += 1
    print("Moved Right")
    robot_col += 1
    print(Moved Right)
    if robot_row == 1 and robot_col == 3:
        print("Yummy! Found an avocado!")
        collected_items.append("avocado")

    # Move to Banana
    robot_row += 1
    print("Moved Down")
    robot_col -= 1
    print("Moved Left")
    if robot_row == 3 and robot_col == 1:
        print "Yummy! Found a banana!"
        collected_items.append("banana"

    # Move to Carrot
    robot_row += 1
    print("Moved Down")
    robot_col -= 1
    print("Moved Left")
    if robot_row == 5 and robot_col == 1:
        print("Yummy! Found a carrot!")
        collected_items.append("carrot")

    # Move to Exit
    robot_row += 3
    print(“Moved Right 3 times”)
    if robot_row == 5 and robot_col == 4:
        print(“Yay! Found the delivery exit!”)

    if "Avocado" in collected_items and "banana" in collected_items and "carrot" in collected_items:
        print("Mission Complete! All groceries collected!")
    else:
        print("Oh no! The robot didn't collect all the items.")

# Run the function!
robotpath()


```

{% endcode %}

Debugging Tips:

* Read the code carefully, line by line.
* Think about the robot's starting position and the grid layout.
* Trace the robot's movements based on the code.
* Identify where the robot goes wrong.
* Correct the code to ensure the robot reaches each item.
* Test your corrected code to make sure it works!


# Ocado Robot Debugging Challenge!

### Ocado Robot Debugging Challenge!

Oh no! The program of an Ocado bot has a bug! This robot is supposed to collect the groceries, but it's not working correctly. Your mission is to debug the Python code and get the robot back on track.

The Grid:

Imagine the maze as a simple grid. Your robot can move in four directions: "up", "down", "left", and "right".

Here's the layout of your grid:

```
# # # # # #
# S - A - #
# - - - - #
# - B - - #
# - - - - #
# C - - E #
# # # # # #
```

*# represents a wall – the robot can't go there.*

*- represents an empty space the robot can move through.*

*S is the robot's starting position.*

*A is the avocado.*

*B is the banana.*

*C is the carrot.*

*E is the delivery exit.*

### The Challenge:

#### **The following Python code has some bugs. Your task is to:**

1. Identify the errors in the code.
2. Correct the errors so the robot can successfully collect the avocado ('A'), banana ('B'), and carrot ('C').
3. The robot should start at 'S' and end at 'E'

Here's the buggy Python code:

{% code overflow="wrap" %}

```python
def robot_path():
    # Initial robot position
    robot_row = 1
    robot_col = 1

    # Items collected
    collected_items = []

    print("Starting the Ocado Bot!")

    # Move to Avocado
    robot_col += 1
    print("Moved Right")
    robot_col += 1
    print(Moved Right)
    if robot_row == 1 and robot_col == 3:
        print("Yummy! Found an avocado!")
        collected_items.append("avocado")

    # Move to Banana
    robot_row += 1
    print("Moved Down")
    robot_col -= 1
    print("Moved Left")
    if robot_row == 3 and robot_col == 1:
        print "Yummy! Found a banana!"
        collected_items.append("banana"

    # Move to Carrot
    robot_row += 1
    print("Moved Down")
    robot_col -= 1
    print("Moved Left")
    if robot_row == 5 and robot_col == 1:
        print("Yummy! Found a carrot!")
        collected_items.append("carrot")

    # Move to Exit
    robot_row += 3
    print(“Moved Right 3 times”)
    if robot_row == 5 and robot_col == 4:
        print(“Yay! Found the delivery exit!”)

    if "Avocado" in collected_items and "banana" in collected_items and "carrot" in collected_items:
        print("Mission Complete! All groceries collected!")
    else:
        print("Oh no! The robot didn't collect all the items.")

# Run the function!
robotpath()


```

{% endcode %}

Debugging Tips:

* Read the code carefully, line by line.
* Think about the robot's starting position and the grid layout.
* Trace the robot's movements based on the code.
* Identify where the robot goes wrong.
* Correct the code to ensure the robot reaches each item.
* Test your corrected code to make sure it works!


# Books of Robots

These books are being created from drawings made in our robotics workshops. The children have come up with some fantastic ideas that we wanted everyone to see.

<figure><img src="/files/02PF74I6eqUOuKuIvWk3" alt=""><figcaption></figcaption></figure>

{% file src="/files/RgOzq2s68DLdElJsGOjt" %}


# How do Computers work?

Have you ever wondered how a computer actually works? Have you ever looked inside your computer and wondered what all those parts are? We hope this worksheet will help to answer those questions for you.

### **What is a computer?**

A computer is an electronic device that takes input from the outside world, processes it according to a set of instructions, stores some data and produces output. This is true if you are doing your homework: typing your answers (input), formatting and arranging it on a page (processing), storing it on your computer (storage) and showing it on the screen or printing it out (output). It’s also true if you are using your computer to play a game. You give input to the computer with your keyboard, mouse or controller, the computer responds to your input by moving your character around and checking if you have collided with something, for example. It stores your current position and score and the output is the graphics on the screen and sound.

![](https://lh6.googleusercontent.com/Gkq3cdE0_T1WaqHNwprOM74kFchYjgjJRhyD40LaOOoIjIx0E2g7fjpjSmQphwvbT1DqcOuiGkzPskRL8UwrG3UOjC6bR9qzNFVEAcA5MpZYfTGbE0jGnh4-rfYnSs1KmgwSt_rA)

### Input and Output devices&#x20;

<mark style="color:red;">An input device is one that allows you to send data to the computer. An output device is one that the computer sends data to. Can you categorise these devices into input or output devices?</mark>&#x20;

* Keyboard&#x20;
* Printer&#x20;
* Screen
* Mouse
* Microphone
* Speakers
* Scanner
* Projector
* Barcode reader

### Computers and Electricity

Computers use electric circuits and switches to represent all data and instructions. These switches allow electricity to be on or off in a circuit. We combine lots of circuits and switches to represent data and instructions.

![](/files/dw35E2v26eDLHhuyFniT)

Switches in this state could represent the number 174, the character **®** or this colour:

![](/files/D27haPRiivyXHck4YcHO)

<mark style="color:red;">**How is this possible and why would we do this?**</mark>&#x20;

Computers use electric wires and circuits to carry all information and the electricity in those wires is either on or off. With one wire, you can represent: yes or no; true or false; 1 or 0. We can create codes for colours, text characters and sound and represent them with numbers.&#x20;

We can then convert these numbers into something called binary. Binary is a counting system that uses two different characters: 0 and 1.

### Binary and decimal

**Decimal**

Think about the numbers you use every day. You are, of course, happy that with a number like 9999 those 9s have different values because they are in different places in the number. The one on the left is worth 9000 because it is in the 1000s column.

![Table showing Decimal numbering](/files/dcSQmaYTe47mgjIzzlrA)

This number system is called **decimal** or **base ten**. We have ten digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. The place values are multiplied by ten as you move from right to left.

**Binary**

Computers use binary to represent all data. **Binary** is also called **base 2**. This follows the same system but multiplies <mark style="color:blue;">**by 2 instead of 10**</mark>.  <mark style="color:red;">Can you guess how many digits there are in binary? What about the place values, can you fill them in?</mark>

![](/files/b0ISdtlCYiuZmvArM661)

If you have got this right, you will have represented the decimal number **15 in binary**. Can you see why?

{% hint style="info" %}

### <mark style="color:blue;">Answers</mark>

<mark style="color:blue;">**Input and output devices**</mark>

* <mark style="color:blue;">Keyboard - input device</mark>
* <mark style="color:blue;">Printer - output device</mark>
* <mark style="color:blue;">Screen - output device (unless it's a touch screen, then it's both input and output)</mark>
* <mark style="color:blue;">Mouse - input device</mark>
* <mark style="color:blue;">Microphone - input device</mark>
* <mark style="color:blue;">Speakers - output device</mark>
* <mark style="color:blue;">Scanner - input device</mark>
* <mark style="color:blue;">Projector - output device</mark>
* <mark style="color:blue;">Barcode reader - input device</mark>

<mark style="color:blue;">**Binary place values**</mark>

![](/files/ljqavIByvK8o3hLH78j6)
{% endhint %}

### **Exercises**

1. We often use binary numbers in groups of 8 bits called a byte. \ <mark style="color:red;">**Can you fill in the rest of these place values?**</mark>

![](/files/zWxj7Uq6vDCzyMNETpUf)

2\. <mark style="color:red;">Convert this</mark> <mark style="color:red;"></mark><mark style="color:red;">**binary**</mark> <mark style="color:red;"></mark><mark style="color:red;">number to</mark> <mark style="color:red;"></mark><mark style="color:red;">**decimal**</mark><mark style="color:red;">: 00101001</mark>

3\. <mark style="color:red;">Convert the</mark> <mark style="color:red;"></mark><mark style="color:red;">**binary**</mark> <mark style="color:red;"></mark><mark style="color:red;">number 00001001 to</mark> <mark style="color:red;"></mark><mark style="color:red;">**decimal**</mark>

4\. <mark style="color:red;">Convert the</mark> <mark style="color:red;"></mark><mark style="color:red;">**binary**</mark> <mark style="color:red;"></mark><mark style="color:red;">number 10001000 to</mark> <mark style="color:red;"></mark><mark style="color:red;">**decimal**</mark>

5\. <mark style="color:red;">Convert the</mark> <mark style="color:red;"></mark><mark style="color:red;">**decimal**</mark> <mark style="color:red;"></mark><mark style="color:red;">number 7 to</mark> <mark style="color:red;"></mark><mark style="color:red;">**binary**</mark>

6\. <mark style="color:red;">Convert the</mark> <mark style="color:red;"></mark><mark style="color:red;">**decimal**</mark> <mark style="color:red;"></mark><mark style="color:red;">number 100 to</mark> <mark style="color:red;"></mark><mark style="color:red;">**binary**</mark>

7\. <mark style="color:red;">How many different values can you store in</mark> <mark style="color:red;"></mark><mark style="color:red;">**two binary**</mark> <mark style="color:red;"></mark><mark style="color:red;">digits?</mark>&#x20;


# How Ocado uses AI

Share with your students

{% embed url="<https://youtu.be/hnDtW32Ctgk?si=0V4MQqhfJfoD-oXJ>" %}

Inside the Hive

{% embed url="<https://youtu.be/e31UqBT5bKE?si=8psPVrkkhIFqXkNN>" %}


# Safety online: Passwords and Security

> *<mark style="color:blue;">Have you ever wondered what your rock star name would be? If you became a really famous musician, you might want a really cool name. I can help you. You can go to my website and type in your full name, date of birth, the name of your first pet, your favourite colour and your postcode and I will suggest the best name ever!</mark>*

Are you happy to do that? We do hope not… What might we do with all that personal information about you? <mark style="color:red;">**Write down some ideas.**</mark>

\
\ <br>

So how do we keep safe online? What scams might we come across and how will we spot them?

The trick you might have fallen for is called **social engineering**. It is when criminals use psychological tricks to fool you into giving away personal data. It might include <mark style="color:blue;">free giveaways, quizzes or password generators</mark>.

**Shoulder surfing** is when someone watches you as you enter private information like a password or a pin.

**Phishing** is when you get fake emails that pretend to come from reputable companies or government organisations. Often they ask you to log in and then steal your login details.

So, what should you look out for if you get an unexpected email?&#x20;

* Unexpected email with a request for information&#x20;
* Message content contains spelling or grammatical errors&#x20;
* Suspicious hyperlinks in email&#x20;
* Text that is hyperlinked to a web address that contains spelling errors and/or lots of random numbers and letters&#x20;
* Text that is hyperlinked to a domain name that you don't recognise and/or isn't connected to the email sender. You can check this by hovering over the link with your mouse cursor.&#x20;
* Emails that don't address you by name or contain any personal information that you would expect the sender to know

For example, what do you notice that is suspicious about this email?

> *<mark style="color:purple;">Dear valued customer,</mark>*&#x20;
>
> *<mark style="color:purple;">We have noticed an unexpected login from your account and are worried that someone might be hoping to steel your informations. Please click this</mark>* [*<mark style="color:purple;">link</mark>*](http://www.we-steal-your-data.com) *<mark style="color:purple;">and log in STRAIGHTAWAY so that we can protect you safely.</mark>*
>
> &#x20;*<mark style="color:purple;">Yours faithfully,</mark>*&#x20;
>
> *<mark style="color:purple;">Customer Services</mark>*&#x20;
>
> *<mark style="color:purple;">ABC Bank Ltd.</mark>*

Did you notice that they didn’t use your name? Surely if you have an account with this bank, they know your name? Also, there are spelling and grammatical errors and they ask you to log in STRAIGHTAWAY. Doesn’t that link look odd? It doesn’t even belong to ABC Bank Ltd.

### Secure passwords

Most of us have lots of different online accounts and it is really tricky to keep track of all our passwords. Which of these things do you think you should or shouldn’t do to keep your details safe?

a) Use the same password for everything. It is much safer than writing lots of different passwords down

b) Replace letters with numbers, e.g **pa55w0rd**

c) Use your pet name or parts of your birthday, e.g. **Toby1990**

d) Use a long random password that only you will know and then use it for everything, e.g. **S(3kskjhG72639#13e4ks**

e) Just use the special secure password for important things like your bank

I hope you said, “None of those! They are all really bad!”

So, what can you do to help you remember all the passwords you need?

{% hint style="info" %} <mark style="color:blue;">**Top tips**</mark>

* You could use a secure password vault so you only need to remember one special password. You have to trust the company who make the password vault though!&#x20;
* You could use a phrase instead of a single word, e.g. **I\_l0v3\_beans\_and\_ch0colat3!**&#x20;
* Use parts of a phrase, e.g. **myM8BobIsAGr8Guy!** (my mate Bob is a great guy)&#x20;
* Join some unrelated words, e.g. **UnicornMango#815$Delphi**
  {% endhint %}

> #### Commonly used passwords
>
> On top of this, you can familiarise yourself with the most commonly used passwords so you make sure never to use those! They include things like **123456**, **password**, **qwerty**... and variants of those. You can find the list [here](https://nordpass.com/most-common-passwords-list/).

### What is brute-forcing?

The longer your password, the better. This is because of a technique hackers use called **brute-forcing**. This is when someone tries lots of random combinations to find a password. For example, assuming a password is 5 characters long and contains only lowercase letters, I could try inputting **aaaaa**, and then **aaaab**, and then **aaaac**... and so on until I get to **zzzzz**.

Manually, this would of course take an extremely long time, but hackers can use software to try many combinations in a short amount of time. Making your password at least 10 characters long, and including numbers and special characters increases the number of possible combinations, which means it'll be a lot harder for the program to go through all the combinations... without being detected by the website as a robot.

In fact, most websites now have a protection against automated brute-forcing by only allowing a certain amount of requests in a given amount of time. At the end of the day however, the main protection comes from the complexity of your password itself!


# The World of Robotics

How many kinds of robots do you know?

## Where does the word "robot" come from?

Did you know that the word "robot" was first used in a play in the 1920s? That is right! The word "robot" was introduced by the work of the Czech writer Karel Capek, entitled R. U. R. (Rossumovi Univerzalni Roboti), which means Universal Robots of Rossum, in English, written in 1920. The word comes from the Czech word Roboti, meaning "hard work". In the play, the robots are machines that look like humans, and invented by them.

<figure><img src="/files/a15LiwdezSzgzV27QB7S" alt="" width="188"><figcaption></figcaption></figure>

## After all, what is a robot?

A robot is a mechanism that is basically formed by joints and links. The joints have motors and they are programmable so they can move within its environment to perform the desired tasks.

<figure><img src="/files/ZxGtQciWnKl0VBaKiQwW" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Ja4A4OcfKvGEdwQ1SVoU" alt=""><figcaption><p>Representation of a robot with links and joints. It has motors on its joints, so it can move the links.</p></figcaption></figure>

### Exercise

1. <mark style="color:red;">How many joints does the following robot have?</mark>

<figure><img src="/files/0Df5JoIIMxLCwvOjdKFc" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/CBO9QjZP8dwUdAoelRwJ" alt=""><figcaption></figcaption></figure>

{% hint style="info" %} <mark style="color:blue;">**Answer**</mark>

<mark style="color:blue;">Two</mark>
{% endhint %}

## What types of robots are there?

### Manipulators

Manipulators, as the name suggests, are robots able to manipulate objects; they can move an object in the environment to another position. The most common examples are industrial robots, and they look like arms, as the examples below.

We can also attach a tool to the robotic arm to help with the manipulation. This tool will act like our hand, but not necessarily need to have the format of a hand, or have fingers.

<div><figure><img src="/files/lUgxR6wsqsmqpZ9QH3PW" alt=""><figcaption></figcaption></figure> <figure><img src="/files/p8keB023v7GCa0Fhtxu9" alt=""><figcaption></figcaption></figure></div>

### Bi-manual manipulators

Manipulator robots can have one arm or more. The ones that have two arms are called bi-manual manipulators. In this case, the world "bi" refers to "two".

<figure><img src="/files/ggcS9Yyos5KmWNOIGioK" alt=""><figcaption></figcaption></figure>

### Mobile robots

The mobile robots are able to move, some have wheels and some have legs.

In the examples below, on the left we have a robot with legs that moves like an insect. On the right, we have a robot with wheels, similar to the vacuum cleaner robots that you might have seen.

<div><figure><img src="/files/i7hcd7M1GxbPJ71JgyKm" alt=""><figcaption><p>Robot with legs</p></figcaption></figure> <figure><img src="/files/3rpyQeJMBz4Hme8CQOlw" alt=""><figcaption><p>Robot with wheels</p></figcaption></figure></div>

### Mobile manipulators

The mobile manipulators have the characteristics of a manipulator robot as well as the characteristics of a mobile robot. A robot with wheels **and** an arm, for instance, is a mobile manipulator.

<figure><img src="/files/3EYIPSstvlSh8UaH7tdN" alt=""><figcaption></figcaption></figure>

### UAVs

UAVs is an acronym for “unmanned aerial vehicles”, meaning they are robots that can fly with no pilot on board.

Have you ever seen people taking photos or filming with drones? Drones are examples of an UAV.

<figure><img src="/files/oXVabAxBndyghTbEyjgu" alt=""><figcaption></figcaption></figure>

### Humanoids

Humanoid robots are robots that look like a human. In general, we call humanoids the robots with two legs, two arms, a torso and a head. How cool are they?

<div><figure><img src="/files/qg1LcYEmT7hDwF1Wszh3" alt=""><figcaption></figcaption></figure> <figure><img src="/files/KrN1Cq5ZGEwy1ZuFqd3O" alt=""><figcaption></figcaption></figure></div>

### Exercise

1. <mark style="color:red;">What type of robot is the one below?</mark>

<figure><img src="/files/Jasqgc2OV09svzrkhgOx" alt=""><figcaption></figcaption></figure>

2. <mark style="color:red;">What type of robot is the one below?</mark>

<figure><img src="/files/cLq5JZ0SQHNSlvFsctL2" alt=""><figcaption></figcaption></figure>

{% hint style="info" %} <mark style="color:blue;">**Answers**</mark>

1. <mark style="color:blue;">Mobile robot</mark>
2. <mark style="color:blue;">Manipulator</mark>
   {% endhint %}

## What is a rigid body?

You can squish a sponge and change its shape, but you cannot do this with a chair made of wood, right? In this case, the chair is considered a 'rigid body', and the sponge is a 'deformable' object.&#x20;

<div><figure><img src="/files/IwEWk13rIKIwyC0Z9Y8N" alt="Photo of a chair by Kelly Miller on unsplash" width="375"><figcaption></figcaption></figure> <figure><img src="/files/LaJUY80cIReXd7VQ1Job" alt="Photo of sponge by Artem Makarov on Unsplash" width="375"><figcaption></figcaption></figure></div>

### So what? Why are rigid bodies relevant to robotics?

If you pick up a chair by its back and move it, the whole chair moves, not only its back. Why is that? This happens because the chair is a rigid body.&#x20;

Since rigid bodies are not 'deformable', when you move a part of this object, the whole object (body) moves in the same way. A robot with a rigid body is easier to program because we know the overall shape won't change, whereas if it was squidgy, it is much harder to program how to move it.

### Exercise

<mark style="color:red;">Can you tell what object is a rigid body from the list below?</mark>

1. <mark style="color:red;">A bottle made of glass.</mark>
2. <mark style="color:red;">A pen.</mark>
3. <mark style="color:red;">A bag of chips.</mark>
4. <mark style="color:red;">A table.</mark>
5. <mark style="color:red;">A marble (toy).</mark>
6. <mark style="color:red;">Play dough.</mark>

{% hint style="info" %} <mark style="color:blue;">**Tip**</mark>

<mark style="color:blue;">If you can apply a force, for instance, squish the object, and it does not change its form, it is a rigid body.</mark>
{% endhint %}

{% hint style="info" %} <mark style="color:blue;">**Answers**</mark>

1. <mark style="color:blue;">A bottle made of glass - rigid body.</mark>
2. <mark style="color:blue;">A pen - rigid body.</mark>
3. <mark style="color:blue;">A bag of chips - deformable body.</mark>
4. <mark style="color:blue;">A table - rigid body.</mark>
5. <mark style="color:blue;">A marble (toy) - rigid body.</mark>
6. <mark style="color:blue;">Play dough. - deformable body.</mark>
   {% endhint %}

## References:

* (2004)  Human-Robot Interaction. In W. S. Bainbridge (Ed.), Berkshire Encyclopedia of Human-computer Interaction. Berkshire Publishing Group.
* ISO 8373:2012 (en) Robots and robotic devices - Vocabulary. Available from <https://www.iso.org/obp/ui/#iso:std:iso:8373:ed-2:v1:en>. Accessed on 8th September 2020.
* descomplicandoarobotica. Available from <https://www.instagram.com/descomplicandoarobotica/>. Accessed on 15 August 2023.
* The robot images are from the CoppeliaSim simulator. Available from <https://www.coppeliarobotics.com/>. Accessed on 21 August 2023.&#x20;


# Careers in technology

This is where we store information on all sorts of jobs we do in technology here at Ocado Group and Code for Life. You can find poster versions of these in this section too.

<figure><img src="/files/aDaWdxgkNKrfDeWlVnBh" alt=""><figcaption><p>Ligia Olmos Rossi - Senior UX Designer</p></figcaption></figure>

I'm a Senior Product Designer at Ocado Technology. My job is to make the website where you can buy groceries online look awesome and easy to use. I've loved drawing and making things look cool since I was really young. I always wondered how the things we use every day are made and how they make us feel. So, I decided to learn how to make them better!

> <mark style="color:purple;">"I feel really lucky to be able to help make the world a better-looking and easier-to-use place for everyone."</mark>

Making websites and apps is like a mix of being super creative, understanding how people think, and knowing how technology works. I kept learning and practising, and now I get to do it as a job! It's not just a job for me, though. Making things look great and work well is like my whole way of life! I feel really lucky to be able to help make the world a better-looking and easier-to-use place for everyone. It's pretty cool to think that something I design can help lots of people buy their groceries with just a few clicks!

<figure><img src="/files/3IA4QOtgI6kVF1CbHGND" alt=""><figcaption><p>Mark Richardson - CEO of OIA</p></figcaption></figure>

I live in North London with my family and a labradoodle named Zuko. My first summer job was selling ice cream on a beach in Norfolk. I did it for six years in a row and loved it, despite working long hours as a 13-year-old. One summer, I worked on a local fairground which was seriously tough but a good reference point for hard days in the office.

> #### <mark style="color:purple;">"Early Ocado was like a rollercoaster whose bolts hadn’t been tightened. If you get the chance to work in a start-up you should do it. The task seemed enormous, but so was the drive and determination."</mark>

I studied Physics at UCL before joining the IT department at John Lewis Partnership. They trained me in software development, let me build a procurement team and improve their network infrastructure. I also created their first e-commerce website.

I then moved on to work for Ocado, where I ran the Technology team for ten years. Early Ocado was like a rollercoaster whose bolts hadn’t been tightened. If you get the chance to work in a start-up you should do it. The task seemed enormous, but so was the drive and determination. I have been responsible for Logistics, building new CFCs, creating our own ASRS, and installing it around the world.

Now we are all on another adventure with [OIA](http://https://ocadointelligentautomation.com/). I have always been better at starting than finishing, and it is my very good fortune to have spent most of my career in an organisation that starts so much!

<figure><img src="/files/9VwJrJVnAPmElJDDaNdZ" alt=""><figcaption><p>Darcie Gomer - Graduate User Researcher</p></figcaption></figure>

Have you ever clicked on a button expecting it to do one thing but it does another? My role in UX (User Experience) is to capture instances like this, and feed them back to my team so they can make better choices in the design of websites. I do this by running interviews, sending out surveys, and testing prototypes directly with the people who will use the website. My job means I get to learn from new perspectives and ask lots of questions. I find it really exciting knowing that data I collect impacts product decisions and improves what we offer to customers.

> #### <mark style="color:green;">"Understanding your user is especially important in a technology company. It takes a lot of time and effort for software engineers to write code for a new feature, programme, or product. So, it's critical to make sure that what is developed is needed and understood by users."</mark>

I had a tough time choosing what I wanted to do at university; for my A levels I did Chemistry and Maths, Theatre Studies and English Literature! I then came across Anthropology - a social science where you can study people and their cultures. Anthropology combined my passion for learning about people and reading with my skills for research and analysis. When it came to my career I did not think I would be able to use my degree every day, but now I'm a User Experience Researcher!

<figure><img src="/files/nxkHb6WdI8GcNZwslm4D" alt=""><figcaption><p>Claire Ainscough, Chief People Officer, Ocado Group</p></figcaption></figure>

"My four years here have been a whirlwind - like all tech organisations, no day is ever the same. My role is responsible for Ocado’s employees- basically ensuring this is an amazing place to work regardless of your background.&#x20;

The best thing about my job is when I see people grow and develop - here you can do this through your role, through professional courses and by volunteering internally. One great example of this is through Code for Life which benefits the skills and wellbeing of our volunteers, and inspires people to a future career in tech. This combination of learning, wellbeing, diversity and inspiring young people is one of the best ways Ocado builds a stronger organisation for the future."

> #### <mark style="color:red;">"The best thing about my job is when I see people grow and develop... One great example of this is through Code for Life which benefits the skills and wellbeing of our volunteers, and inspires people to a future career in tech."</mark>

"Prior to Ocado I held senior HR roles with Expedia (online travel) and Premier Farnell (B2B distributor) and before that I worked at a start-up - all were great places where I learned loads. I was lucky enough to live in Chicago for five years which was a fantastic work and life experience. Chicago definitely gave me the travel bug and I love to take trips for holidays or work."

<figure><img src="/files/dRqWL1Wwj3BXzAMjs8Kb" alt=""><figcaption><p>Carisa Lopez - Business Support</p></figcaption></figure>

I am a Business Support Specialist in North America for Ocado. I work as a key player to support the operation of the site. As a woman without a technical background, I’ve had to learn and understand a basic level of technical operations by submerging myself in technology. I work on projects called BOT School, Peripheral school, and Safety Training. These activities are aimed at providing the necessary assistance to ensure smooth site operations and support for my team.

> <mark style="color:orange;">**"I hope to continue to inspire and encourage women and allies to get involved in the technology industry."**</mark>

Gaining a foundational understanding of equipment, diverse software systems and achieving expertise in Google Suite has empowered me to constantly advocate for my team members. Furthermore, I can foster a sense of inclusion among my team onsite, which is essential for creating an environment conducive to attracting and retaining top talents.

What I enjoy most about my role is that it has pushed me to become innovative and think outside of the box to become a stronger professional, but the best part of my role is the ability to form a professional relationship with each of my team members onsite and getting to know them individually. I hope to continue to inspire and encourage women and allies to get involved in the technology industry.

<figure><img src="/files/BZSmMgvgcwtBwJaqvhFe" alt=""><figcaption><p>Tom Regan</p></figcaption></figure>

I’m a Software Engineer at Ocado, and I work on the systems that run our customer fulfilment centres.

Building software requires planning, organisation, and communication. Just like air traffic controllers managing multiple aircraft, software engineers juggle many complex tasks at once as we design, build, and debug systems.

At Ocado we face the very busy traffic management, based on air traffic control and path planning in real-time. Our robots travel at 15kph along tracks over 7 metres from the ground, and pass one another just 5 millimetres apart. Safety is our number one priority, and we work carefully to keep our complex network of moving machines running smoothly.

> #### <mark style="color:blue;">"At Ocado we face very busy traffic management, based on air traffic control and path planning in real-time."</mark>

What I enjoy most is working as part of a team; it allows me to design things that are much bigger than I could build on my own, and see them come to life - together we can turn big ideas into working systems. It’s an incredibly rewarding feeling.

<figure><img src="https://i.emlfiles4.com/cmpimg/7/1/6/2/2/2/files/1262630_myrna_spotlight_image.png" alt=""><figcaption><p>Myrna Macgregor</p></figcaption></figure>

### Myrna Macgregor - Lead, Responsible AI & Robotics

Artificial intelligence, or AI, is becoming a key part of how Ocado works: from computer vision systems which allow robots to pick a wide variety of items, to recommendation engines which identify the most relevant products for each customer. It’s critical that we develop and deploy these technologies responsibly.

It’s really motivating to work on such a cutting edge issue. One of my key tasks has been to bring 40+ colleagues together to figure out what responsible AI means to our business - it’s been fascinating to hear their perspectives. And I’m really proud that we got sign-off to publish the commitments we came up with in Ocado’s 2022 Annual Report (see: Ethics of AI and Robotics).

> <mark style="color:yellow;">**"My role is thinking through how Ocado can use AI and robotic AI technologies in a safe and trustworthy way."**</mark>

I’m not a technical specialist. My degree was in European Studies, French and German. Prior to joining Ocado, I worked for Foreign Office and the BBC. My career journey has been translating my experience in policy, strategy and human rights to a technology context. So I’m proof that all kinds of people can transition into a career in AI!

<figure><img src="/files/i9HLRkPo7h8oH3YqbBto" alt=""><figcaption><p>Anna Len</p></figcaption></figure>

**Anna Len - Automation Development Tester**

> #### <mark style="color:blue;">"Nowadays digital shopping is very popular and in the near future it could possibly dominate the market. I am just happy that I can be part of it."</mark>

Anna, an Automation Development Tester, joined the Ocado Technology team from one of Ocado's Customer Fulfilment Centres. "I've received an incredible opportunity to move to the Technology department. This was a great occasion for me to develop my passion as I am fascinated by the large amount of automation within the warehouse. I really enjoy what I am doing as I work with the robots. I get to test them every day to make sure they work perfectly when they are being used. Which helps me be able to learn something new everyday, meet new people from other parts of the world, and be a part of the great team which makes a difference in the technology and future."

<figure><img src="/files/wFe0oOpt9mrqwUicpQLi" alt=""><figcaption><p>Richard Watkins</p></figcaption></figure>

**Richard Watkins - Data Scientist**

Richard is a Data Scientist working in Supply Chain at Ocado Technology. His team design forecasting algorithms – helping retailers offer their customers good levels of product availability, while minimising waste. As customers can add items to their orders until just a few hours before delivery, and fresh items can have a very short shelf life, this is a huge challenge.

> #### <mark style="color:red;">"It's nice to be able to see your algorithms reducing food waste."</mark>

<figure><img src="/files/zyiNInG59zTZGMsPBc6f" alt=""><figcaption><p>Radhika Gudipati</p></figcaption></figure>

**Radhika Gudipati** - Research Coordinator (Robotics & AI)

My role as a Research Coordinator is to interact with various technology teams within Ocado, understand their current challenges (e.g., what is the best route for an Ocado van to deliver the shopping to a customer) and collaborate with the research teams at Universities to develop a solution.

My biggest challenge is to find a solution and at the same time not give away the secret sauce to the competitors. I enjoy working with roboticists at different organisations. My PhD in robotics and my passion in taking the research to solve real world challenges brought me into this role.

> #### <mark style="color:blue;">"My first exposure to a computer was in my Yr 8 where a class of 50 students had to share 10 computers in a small room (air conditioned lab was the highlight for the hot tropical weather)."</mark>

COBOL was the language we were taught in the classroom and we were asked to handwrite the code in our homework books. As I typed the code in, executed it and saw the special characters printed in shapes appearing on the screen - it made my day! 🙂

<figure><img src="/files/45DAcLuwr2MDYAsJBhs1" alt=""><figcaption><p>Dioni Zhong</p></figcaption></figure>

**Dioni Zhong** - Senior software Engineer

Dioni is a Senior Software Engineer in our very own Code for Life team! She has been helping us improve our products and keep everything running smoothly. Read more about what she gets up to every day below.

> #### <mark style="color:purple;">"I love problem solving and building things. I’m passionate about education. I feel a great sense of pride and joy knowing that I play a part in building something that helps students and teachers worldwide."</mark>

I work in Code for Life team at Ocado to develop the website and the Rapid Router and Kurono games. In a small team, we have to do a variety of things. Apart from coding, I also work with data, charts, and documentation. I love problem-solving and building things. I’m passionate about education. I feel a great sense of pride and joy knowing that I play a part in building something that helps students and teachers worldwide.

Let us know what you think of our newsletter by [getting in touch](mailto:codeforlife@ocado.com?subject=Newsletter%20feedback) and sharing your thoughts and ideas.

<figure><img src="/files/vnFcC7weIbZ3xF4GfTQF" alt=""><figcaption><p>Antony Youngman</p></figcaption></figure>

Anthony works as a roster analyst in the department responsible for Business Analysis. His role is extremely important in helping Ocado Group get groceries out to its customers. His job is to prepare the 13-week rosters in advance before they are sent out to drivers letting them know when they are working. Having been a driver last year, this year Anthony wanted to help by making such a busy period as easy as possible.

> <mark style="color:blue;">**"I'm spending this Christmas trying to give the drivers the present of a roster that fits in with their lifestyle."**</mark>

Just like our Rapid Router challenges, it is all about efficiency and saving energy wherever possible at Ocado Group, so making sure the drivers know their roster ahead of time means that the full service can be much smoother.


# Careers posters

Download and print posters for your classrooms to inspire your students. Help them to learn about all of the different careers available to them in technology.

Download and print posters for your classrooms to inspire your students. Help them to learn about all of the different careers available to them in technology.

<figure><img src="/files/xm1AqKpTbgsuF01hm8MC" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/etBRLgXQ4w59jn1pT2mp" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/54vzaN8FsB5g25QqdbAl" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/5npXA1Gk1DCUd3KAUt91" alt=""><figcaption></figcaption></figure>

{% file src="/files/N0l4jemOe2Eb0yGrzUr4" %}

{% file src="/files/nZajs4gJhb3AXWMD6Jgl" %}

{% file src="/files/1QtDDE9qrSDR1MTJgwjn" %}

{% file src="/files/SVUrWUhdREUxDU7RvxE1" %}


# Career based videos

The Code for Life Team Lead asked other women at OcadoTechnology to help inspire the students at St Albans Girls School. It was a fantastic experience.

{% embed url="<https://youtu.be/YBGyu160-f4>" %}
Annual Inspiring Women Event 2013 at STAGS
{% endembed %}

The Code for Life Team Lead, alongside other colleagues at OcadoTechnology delivered a talk to In2Science alumni on applying for jobs, interviews and writing CVs! Check out the video below.

{% embed url="<https://youtu.be/tljaitweas4?si=ykN65zOCU5eP5BK5>" %}

{% embed url="<https://youtu.be/CZ9YLrFNqcw>" %}


# Blockly to Python Guide

Blockly to Python guide for Rapid Router and Python Den

## Van starting block

![](/files/JYVNlmngqC55QqsTSrAA)

```python
from van import Van
my_van = Van()
```

The starting code has been created ‘behind the scenes‘ in Python and has to be imported.

Those two lines are therefore automatically added to your new program in Rapid Router. When you open the Python pane, you should see this code. These two lines are required before all other commands.

After this code, the van object, which is the object controlling van movement on the map, is indicated by the variable `my_van`.

You could change the name of this object to whatever you like, but be consistent and use the same name with the commands afterwards.

## Move forwards, turn left, turn right

![](/files/g7uJ4uzuhzxOtkXqtMv5)

```python
my_van.move_forwards()
my_van.turn_left()
my_van.turn_right()
```

`move_forwards`, `turn_left` and `turn_right` are, in fact, procedures. Once called, they cause the van to move. This is why when we want the van to move forwards, we call its `move_forwards` procedure by putting () after its name (e.g. `my_van.move_forwards()`)

Note the underscore (“\_”) is an essential part of the name.

## Repeat n times

![](/files/9R2UkBViLo81wjaiIQaG)

```python
for number in range(n):
```

This code will repeat all commands indented underneath it `n` times, where `n` is a whole number such as 3. It works with any name inserted where the word number is shown in the example. (The built-in range function just tells the loop how many times to repeat.)

```python
for count in range(3):
    my_van.move_forwards()
```

The example on the left would repeat `my_van.move_forwards()` 3 times. You can use the count variable inside the body of the loop if you want the van’s behaviour to differ depending on how many times the for loop was executed. On the first time through the loop, its value will be 0, incremented by one each time around the loop.

You must use a colon `:` at the end of the `for` line because this indicates that a sequence of instructions should follow (we call them the body of the loop). These instructions must all be indented by the same amount (ideally by 4 spaces).

## Wait

![](/files/N0dRJM5gFOS255xSMdGO)

```python
my_van.wait()
```

A procedure which when executed or ‘called’, causes the van to wait.

## If, else if and else

![](/files/kXwlmHuYuHZ30vYwx70i)

```python
if my_van.is_road_forward():
    my_van.move_forwards()
elif my_van.is_road_left():
    my_van.turn_left()
else:
    my_van.turn_right()
```

The indentation of the instructions inside a block must match. Ideally, they would be indented 4 spaces more than the previous statement.

`if`, `elif` and `else` statements must all be indented to the same level as each other, and all require a colon `:` at the end of their statement.

{% hint style="info" %}
`elif` is short for `else if`
{% endhint %}

![](/files/7rXh1jrrDTAP4twxyq6w)

```python
if my_van.at_traffic_light_red():
    my_van.wait()
```

The example to the left will cause the van to wait if it is currently at a red traffic light.

## Conditions

![](/files/llwEfjxzOjw0pLCmSJpU)

```python
my_van.is_road_forward()
my_van.is_road_left()
my_van.is_road_right()
my_van.at_traffic_light_red()
my_van.at_traffic_light_green()
```

These conditions can be added after an `if`, `elif` or `else` statement.

Each of the conditions are functions that check the state the van is in (i.e. what kind of road is ahead or what colour the traffic light is) and returns `True` or `False`.

{% hint style="info" %}
If a variable can only be True or False, it is called a “Boolean”.
{% endhint %}

## Repeat until at destination

![](/files/R7jcbS8nDQsogS6Zksun)

```python
while not my_van.at_destination():
    my_van.move_forwards()
```

The `while` not statement repeats until the condition is `True`.

Remember the colon denotes a set of instructions to be followed if the `while` condition is met (we call it the body of the loop).

## Repeat while traffic light is red

![](/files/t1DkDpREI49QynOc5TZz)

```python
while my_van.at_traffic_light_red():
    my_van.wait()
```

These instructions must be consistently indented, ideally by 4 spaces.

This example will cause the van to wait until the traffic lights are no longer red.

## Procedures

![](/files/9423mSPLkBdOJu072Qd3)

```python
def procedurename():
```

To create a procedure, you use the `def` keyword. The procedure needs a meaningful name where `procedurename` is placed in the example. You must have a pair of brackets () and a colon `:` after it.&#x20;

```python
def proc1():
    my_van.turn_left()
    my_van.turn_right()
    
proc1()
```

All subsequent statements that are to be part of the procedure must be indented to the same level as each other (ideally 4 spaces).

The procedure is then executed (or called), by typing the name of the procedure followed by a pair of brackets ().

In this example, the proc1 procedure will move the van left and then right when called. In reality, it is better to choose a more meaningful name for your procedure.

```python
def forward_left(n):
    for count in range(n):
        my_van.move_forwards()
        my_van.turn_left()
        
forward_left(4)
```

What happens inside the procedure can be changed each time by passing in arguments. Arguments available to the procedure are defined in between the two brackets, such as the argument n in this example. This value is then used to change how many times the loop is executed.


# Python Commands

Useful Python commands to use in the later levels of Rapid Router

Run the following commands on the van object v, e.g. `my_van.move_forwards()`

## **Movement**

```python
my_van.move_forwards()
my_van.turn_left()
my_van.turn_right()
my_van.turn_around()
my_van.wait()
```

## **Position**

```python
my_van.at_dead_end()
my_van.at_destination()
my_van.at_red_traffic_light()
my_van.at_green_traffic_light()
my_van.at_traffic_light(c)
# where c is 'RED' or 'GREEN'
```

```python
my_van.is_road_forward()
my_van.is_road_left()
my_van.is_road_right()
my_van.is_road(d)
# where d is 'FORWARD', 'LEFT', or 'RIGHT'
```

## **Animals**

```python
my_van.is_animal_crossing()
my_van.sound_horn()
```


# Level Maps 1‒50

Road maps for levels

![](/files/FctMrIM8UwAPWsWvHvXS)

![](/files/QTcuGdXqHdzjZhBapRIS)

![](/files/afea35TgC8lxiahLuVAE)

![](/files/HV4JoF0rhxzs6gqXV7e2)

![](/files/246F3XYxtdQfUtwDo7gS)

![](/files/uhhqURo7DpnwUejFfmWe)

![](/files/CAU0Pf3r1KzhOrB4huQN)

![](/files/kYQC5qfMjqBjObHsgBSe)

![](/files/MQEBi4x3ql3To1pbH6a1)

![](/files/UPtgg1Gcz8pJWekX1WFr)

![](/files/fNI4CZZHEhuenIG8wSBP)

![](/files/ZjD3LtfOhU7Jk4dn8uOj)

![](/files/7NzXJquOtX1iyzaCesj0)

![](/files/s7Bu4sOF9oEZhLKgUfSn)

![](/files/4dQKUP3x6wBVEB5zQMi6)

![](/files/FqFvxS2Ouu3hZ9zSsK1o)

![](/files/KZ64pAPgShnLA0OUFHLj)

![](/files/LwGpxQ29sV7hPJ2hujqc)

![](/files/hjDmtL2ayLbiHngh9y6W)

![](/files/QpatDRbRry3ANQuokqcI)

![](/files/REZw4nLlWXWtjmjIGk2v)

![](/files/49BTTtxRDLCmB30R3tjP)

![](/files/93d0cnwvxtEqNzuvdGqj)

![](/files/EJirHiIsnPgOjN0WtsNH)

![](/files/WVqFdOQ1nfpAiIZHZBv3)

![](/files/OAkLQUvEi8iefMAkg8ty)

![](/files/ctNylYhQpXcowPxLv2VO)

![](/files/ESkudmAK6tMb19tPeILd)

![](/files/OL34XozuT2mQtD8djwqa)

![](/files/8rjtCuJCePYu2eY1WnjW)

![](/files/0ENIjEtOZ3MtYiAd3bVE)

![](/files/ZrAsZXCiHnPQzFYaux4p)

![](/files/kGhNGQdQ0j1d09qRt8E2)

![](/files/4fJYEfqEyaRq1Uhl6Aej)

![](/files/FLSckHp5936CdvTG64B9)

![](/files/AIAD3LdVdJ84dwcZ6LpR)

![](/files/qsEkpBzTFC69yP2PfuLN)

![](/files/Jp54feHu1dr9Stfr3FNh)

![](/files/SgBDF5DxWia7VTMtXLfy)

![](/files/pkduG9fE40p1nl7L1gsr)

![](/files/2KgzWMYBFCnJ7eb31hOQ)

![](/files/qARP2fYIm5drTlMTPFyy)

![](/files/C3Z0BgQ7PEGnou97423Z)

![](/files/3C6oArUeKPKyWLV8I8OL)

![](/files/fOOP7JlpPaB4gmTtlCzV)

![](/files/XEi5UCzLiL1RKaZoA86d)

![](/files/joACo2LQodEtd4743Z8r)

![](/files/umBVMWLaHEuiRxanC5ac)

![](/files/6dV04emi1rhRddbhpWiZ)

![](/files/lor9hLErHV7ywzEDW26d)

![](/files/gEwbQcVLRynvg2dsdw8E)


# Level maps 51–67

Road maps for levels

<figure><img src="/files/euTZT0tKucHwbVtuwehM" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/IccOoySutZZWjB2ifrzr" alt=""><figcaption></figcaption></figure>


# Dev Environment Setup

Set up your dev environment with dev containers for VS Code.

Code for Life (CFL) has set up their development environment within [dev containers for VS Code](https://code.visualstudio.com/docs/devcontainers/containers). In short, dev containers are containerised virtual machines that come preinstalled with all the software and tools necessary for you to develop.

{% hint style="info" %}
A git submodule is synonymous with a git repository; a submodule is a repo that's nested within the workspace.
{% endhint %}

VS Code's dev containers allow us to setup your dev environment for you so you don't have to worry about doing it yourself. Furthermore, anytime we make a change to our dev environment, we will git-push the latest dev container to the workspace repo. Then, you can just simply git-pull the latest dev container and rebuild it.

Follow the below steps to setup the CFL workspace in a dev container.

***

## 1. Create a GitHub account

If you don't already have a GitHub account, [sign up for GitHub](https://github.com/signup).

***

## 2. Install and set up Git

Git is required to sync your local code changes with our online Git repos.

Follow Git's [installation instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and set up your Git user.

{% hint style="success" %}
We recommend you use the same username and email you used to create your GitHub account.
{% endhint %}

```bash
git config --global user.name "John Doe"
```

```bash
git config --global user.email "john.doe@example.com"
```

{% hint style="info" %}
For further guidance and how to set up Git, follow Git's [first-time setup instructions](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup).
{% endhint %}

***

## 3. Install Docker Engine

Docker Engine is required to build and run dev containers.

Note that Docker Desktop is an app built around Docker Engine that provides a user interface and additional tools. You only need Docker Engine.

{% hint style="danger" %}
If you're using an Ocado-issued laptop, **DO NOT install Docker Desktop** - it's licensed software requiring a paid subscription.
{% endhint %}

Follow the steps to install Docker Engine depending on your computer's operating system.

### Windows

{% hint style="success" %}
For an easier setup experience, we recommend you create a Linux environment using [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/about#what-is-wsl-2) and [install the Ubuntu distro](https://documentation.ubuntu.com/wsl/stable/howto/install-ubuntu-wsl2/#install-ubuntu-wsl). You can then follow the simpler [Linux steps](#linux) instead.
{% endhint %}

[Follow the steps](https://docs.docker.com/engine/install/binaries/#install-server-and-client-binaries-on-windows) to download and install Docker Engine's server and client binaries.

### macOS

We recommend running the following commands. Alternatively, you can install [Docker Engine's client binaries](https://docs.docker.com/engine/install/binaries/#install-client-binaries-on-macos).

Install Docker Engine and Colima.

```bash
brew install docker colima
```

Start Colima and use it as Docker's context.

```bash
colima start && docker context use colima
```

Test Docker is working.

```bash
sudo docker run hello-world
```

### Linux

Check the [supported platforms](https://docs.docker.com/engine/install/#supported-platforms) to find your Linux distro. If you're using Ubuntu, follow [these steps](https://docs.docker.com/engine/install/ubuntu/).&#x20;

***

## 4. Install the Docker Compose plugin

The Docker Compose plugin is required as [our dev container runs multiple containers for different tools](https://github.com/ocadotechnology/codeforlife-workspace/blob/main/.devcontainer/docker-compose.yml).

Follow the steps to install the plugin depending on your computer's operating system.

### Windows

{% hint style="danger" %}
There's no way to install the plugin unless you install Docker Desktop. If you're using an Ocado-issued laptop, **DO NOT install Docker Desktop** - it's licensed software requiring a paid subscription.
{% endhint %}

{% hint style="success" %}
We recommend you create a Linux environment using [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/about#what-is-wsl-2) and [install the Ubuntu distro](https://documentation.ubuntu.com/wsl/stable/howto/install-ubuntu-wsl2/#install-ubuntu-wsl). You can then follow the [Linux steps](#linux) instead.
{% endhint %}

### macOS

We recommend installing the plugin [via Homebrew](https://formulae.brew.sh/formula/docker-compose).

```bash
brew install docker-compose
```

Alternatively, you can [install the plugin manually](https://docs.docker.com/compose/install/linux/#install-the-plugin-manually).

### Linux

[Follow these steps](https://docs.docker.com/compose/install/linux/#install-using-the-repository) to install the plugin using the repository. Alternatively, you can [install it manually](https://docs.docker.com/compose/install/linux/#install-the-plugin-manually).

***

## 5. Install VS Code

Our dev containers are specifically defined to work within the VS Code IDE.

[Install VS Code](https://code.visualstudio.com/).

***

## 6. Install the Dev Containers extension in VS Code

Open the Extensions tab (Ctrl+Shift+X) in VS Code.

Search for the **"Dev Containers"** extension and install it.

<figure><img src="/files/XCIRDz8h18Z8upHfcgoE" alt=""><figcaption></figcaption></figure>

***

## 7. Fork and clone the CFL workspace

You'll need to clone our [workspace](https://github.com/ocadotechnology/codeforlife-workspace) in a folder of your choosing on your local machine. How you do so will depend on whether you're an external or internal contributor

### External Contributor

{% hint style="success" %}
This option is for you if you're NOT a CFL team member.
{% endhint %}

Fork ([see how](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo#forking-a-repository)) our [workspace](https://github.com/ocadotechnology/codeforlife-workspace) on GitHub (only the **main** branch) into your personal GitHub account and then clone your fork:

```bash
# Replace {username} with your GitHub username!
git clone https://github.com/{username}/codeforlife-workspace.git
```

### Internal Contributor

{% hint style="danger" %}
This option is for you ONLY if you're a CFL team member.
{% endhint %}

Clone the workspace and recursively clone each repo/submodule within the workspace:

```bash
git clone --recurse-submodules https://github.com/ocadotechnology/codeforlife-workspace.git
```

***

## 8. Change line endings (Windows only)

If you're using Windows as your OS, then you'll need to change the line endings in your cloned workspace before opening the dev container.

{% hint style="info" %}
[Inside the dev container the OS is Ubuntu](https://github.com/ocadotechnology/codeforlife-workspace/blob/main/.devcontainer/Dockerfile#L2) and Unix-like OS's (like Linux and macOS) use different *end of line* (EOL) [control characters](https://en.wikipedia.org/wiki/Control_character) to Windows. Linux distributions (like Ubuntu) use *line feed* (LF), which is control character "\n", while Windows uses *carriage return and line feed* (CRLF), which is control characters "\r\n". [See EOL table](https://en.wikipedia.org/wiki/Newline#Representation).
{% endhint %}

Open a Git Bash terminal in the directory of your cloned workspace.

<figure><img src="/files/1zxjrfaXdlBBxracPxjo" alt=""><figcaption><p>example terminal that's open in the "codeforlife-workspace" directory</p></figcaption></figure>

Configure the workspace to use LF as the EOL control character.

```bash
git config core.eol lf
```

Remove all the files tracked by Git in the workspace.

```bash
git rm -rf --cached .
```

Re-download the files. They should now have LF endings.

```bash
git reset --hard HEAD
```

To confirm that the files have LF endings, open any file in the workspace in VS Code and look at the bottom right (in the toolbar). You should see "LF" (not "CRLF").

<figure><img src="/files/do3jPalCYQoKL65VTS6Q" alt=""><figcaption></figcaption></figure>

***

## 9. Open the CFL workspace in a Dev Container

In VS Code, open the command palette (Ctrl+Shift+P or go to `View > Command Palette...`).

Search for the command: **">Dev Containers: Open Workspace in Container..."** and select it.

<figure><img src="/files/L0D25ihLiaE1u5AlEd0V" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Make sure Docker Engine is running before working with dev containers.
{% endhint %}

Select the **codeforlife.code-workspace** file in your local **codeforlife-workspace** folder.

```
path/to/codeforlife-workspace/codeforlife.code-workspace
```

VS Code will now begin building your dev container. If you wish to see the output of the build as it is happening, click the following prompt in the bottom-right:

<figure><img src="/files/qi0py3dzgyfPgM4xS6FX" alt=""><figcaption></figcaption></figure>

At some point, VS Code will reload the window so that it may re-open the code-workspace within the dev container.&#x20;

{% hint style="info" %}
The first time the container is built takes some time, as it needs to download its OS and the various software, tools and extensions required for development. The duration of the build will also depend on your internet speed and processing power.

First-time builds have been known to take around 10-15 minutes.

Luckily, this is a one-off; the build is cached and rebuilds will be significantly faster!
{% endhint %}

### Known issues

#### Fails to pull [docker/dockerfile](https://hub.docker.com/r/docker/dockerfile)

If the build fails with an error message similar to:

<pre><code><strong>=> ERROR resolve image config for docker.io/docker/dockerfile:1.4        31.5s
</strong><strong>=> [auth] docker/dockerfile:pull token for registry-1.docker.io           0.0s
</strong><strong>------
</strong><strong>> resolve image config for docker.io/docker/dockerfile:1.4:
</strong><strong>------
</strong></code></pre>

Run this command *before* opening/building the dev container.

<pre class="language-bash"><code class="lang-bash"><strong>docker pull docker.io/docker/dockerfile:1.4
</strong></code></pre>

#### Images or dependencies fail to install

If you get build errors stating that some images or dependencies failed to install, it could be due to any VPN / DDoS mitigation software you might have running on your machine or network. Try disabling those temporarily to see if it helps.

***

## 10. Set up your CFL workspace

{% hint style="success" %}
If you cloned the workspace as an [internal contributor](#internal-contributor), you should skip this step by entering "n" (no) when the setup script asks if you would like to run the optional steps:

<img src="/files/6j2GziAy7JSdLxSX2O64" alt="" data-size="line">
{% endhint %}

While the workspace is open in VS Code you'll notice there are a few empty folders. These are the repos contained within the workspace, each of which will also need to be forked and cloned ([like how you forked and cloned the workspace](#id-5.-fork-and-clone-the-cfl-workspace)).

To help you quickly fork and clone the many repos contained within our workspace, we've created a script that runs automatically when you start the workspace's dev container. You'll be prompted to sign into GitHub in VS Code's terminal window.

<figure><img src="/files/M7oQXaKbIBWvJaXiFq8B" alt=""><figcaption><p>Use the arrows on your keyboard and Enter to select an option</p></figcaption></figure>

Follow the on-screen instructions in the terminal. Once you've successfully authenticated with GitHub, each repo within the workspace should be forked and cloned; the once empty folders should now be populated.

<figure><img src="/files/HaR4EqYvudz1MMzoKEOe" alt=""><figcaption></figcaption></figure>

***

## 11. Enable source control

{% hint style="info" %}
You many not need to do this step. If VS Code has disabled source control for the CFL repos you wish to develop for, you'll need to trust the repos within VS Code to enable source-control features like:

* checking out branches
* pulling, committing and pushing code changes.
  {% endhint %}

With the workspace folder open in VS Code, open the Source Control tab (Ctrl+Shift+G).

Click "**Manage Unsafe Repositories**". Then, select the one or more CFL repos shown in the drop-down.

<figure><img src="/files/G3k3Y7N4yOo06vRC5rdQ" alt=""><figcaption></figcaption></figure>

***

## 12. Set up the repo's virtual environment

{% hint style="info" %}
This step is only needed if you are working on either the `rapid-router` or `codeforlife-portal` repo.
{% endhint %}

In a new terminal in VS Code, run the following command:

```bash
pipenv install --dev
```

This will install all the dependencies the repo requires for the code to run. Then, activate the virtual environment by running:

```bash
pipenv shell
```

Finally, to start working on the project locally, run:

```bash
./run
```

This script will:

* run the project's database migrations,
* collect the static files,
* and start a Django server.

Once the script has finished running, you'll be able to run and view the project locally in your browser by going to `localhost:8000`.

{% hint style="info" %}
Any backend changes you make to the code should automatically reload the Django server (a.k.a. hot reloading). HTML changes will also be visible instantly.

However, any JS or CSS changes will require you to manually close the server using `Ctrl/Cmd + C` and relaunch the `run` script so that the static files are re-collected.
{% endhint %}

Enjoy working on the project!

***

## 13. Exiting the Dev Container

There are a few different ways you can stop running your VS Code window in a dev container and run it on your local machine instead.

* Close the VS Code window and open a new window.
* Open a local folder in the existing VS Code window (\[Ctrl+K Ctrl+O] or go to `File > Open Folder...`).
* Reopen the current folder locally by either:
  1. Opening the command palette (Ctrl+Shift+P or go to `View > Command Palette...`) and typing **">Dev Containers: Reopen Folder Locally"**.
  2. Clicking the Dev Container toolbox in the bottom-left of your VS Code window and selecting `Reopen Folder Locally`.
* Close the connection to the dev container by either:
  1. Opening the command palette (Ctrl+Shift+P or go to `View > Command Palette...`) and typing **">Remote: Close Remote Connection"**.
  2. Clicking the Dev Container toolbox in the bottom-left of your VS Code window and selecting `Close Remote Connection`.

<div data-full-width="true"><figure><img src="/files/YGlIOiQxyxHK9WseIqkr" alt=""><figcaption><p>Dev Container: toolbox</p></figcaption></figure></div>


# Code Promotion Strategy

How we promote code from development to production

<mark style="color:red;">Documentation coming soon</mark>


# Back End

How our back end is developed, tested and run

<mark style="color:red;">Documentation coming soon</mark>


# Overview

About our back ends

## Technology Stack

We have built our back ends primarily using [Python](https://www.python.org/), [Django](https://www.djangoproject.com/), and [Django Rest Framework](https://www.django-rest-framework.org/).

{% hint style="info" %}
We recommend getting familiar with the basics of each technology before contributing to one of our back ends.
{% endhint %}

## Code Repositories

Each service has a back end code repository in the [Ocado Technology](https://github.com/ocadotechnology) GitHub organisation which follows the naming convention:

```
codeforlife-{service}-backend
```

[View](https://github.com/orgs/ocadotechnology/repositories?q=codeforlife-+-backend) our back end repos on GitHub.

### Template

To speed up the process of creating a new back end repo, we created the template repo [codeforlife-template-backend](https://github.com/ocadotechnology/codeforlife-template-backend) which can be used to scaffold a new service's back end repo. Read [here](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) on how to create a repo from a template.

{% hint style="success" %}
After creating a repo from the template, run a case-insensitive search across all files for **replace-me**. Replace these strings with the appropriate value; this will most likely be the service's name.
{% endhint %}

## CI/CD Pipelines

In order to avoid repeating the same pipelines in every back end service, we centrally define the pipelines in our [workspace repo](https://github.com/ocadotechnology/codeforlife-workspace/tree/main/.github/workflows), and reference them in each back end service. In GitHub's terminology, these are referred to as [reusable workflows](https://docs.github.com/en/actions/sharing-automations/reusing-workflows).

There are 2 main pipelines in each back end service.

### main.yaml

The main pipeline for each back end service which simply reuses the [backend](https://github.com/ocadotechnology/codeforlife-workspace/blob/main/.github/workflows/backend.yaml) pipeline located in the workspace. This pipeline is responsible for testing and deploying a back end service.

You can see an example of this pipeline in the [back end template repo](https://github.com/ocadotechnology/codeforlife-template-backend/blob/development/.github/workflows/main.yaml).

### contributing.yaml

This pipeline is responsible for managing the process of contributing to our code base, such as checking our contributors have signed our contributor agreement, auto-assigning/-unassigning contributors to issues, and more.

You can see an example of this pipeline in the [back end template repo.](https://github.com/ocadotechnology/codeforlife-template-backend/blob/development/.github/workflows/contributing.yaml)

## Python Package

To avoid repeating code across 2 or more back ends, we have created the repo [codeforlife-package-python](https://github.com/ocadotechnology/codeforlife-package-python) which automatically tests and releases new version of the package using [semantic versioning](https://semver.org/). These versioned packages can then be installed into our Python virtual-environments (.venv).

Learn more about our Python package [here](https://code-for-life.gitbook.io/python-package).&#x20;


# Coding Patterns

Coding patterns we follow on our back end

## The 3 Layers

Each backend consists of 3 layers that build on top of each other. Starting from the bottom layer, the layers are:

1. [Models](#models): Defines the data tables (a.k.a. models) and columns (a.k.a. fields).
2. [Serializers](#serializers): Handles converting data to objects and vice versa.
3. [Views](#views): Defines our API endpoints.

Because \[data] models are our bottom layer, it can be said that our backend is model-centric. This means (almost) all our serializers and views and are model-serializers and model-views.

## Models

Below are the conventions we follow when modelling our data.

First, understand how to [define a Django model](https://docs.djangoproject.com/en/3.2/topics/db/models/).

### File Structure

#### TL;DR

* [x] &#x20;One file per model in the `models` directory.
* [x] &#x20;Each model-file follows the naming convention `{model}.py`.
* [x] &#x20;Each model is imported from its file in `models/__init__.py`.
* [x] &#x20;One test-file per model in the `models` directory.
* [x] &#x20;Each model-test-file follows the naming convention `{model}_test.py`.
* [x] &#x20;Each model-test-case follows the naming convention `Test{model}`.
* [x] &#x20;Each model-test-case inherits `ModelTestCase`.
* [x] &#x20;Each model-test-case sets their type parameter to the model being tested.

***

For each model, create a file named after the model in the directory `models`.

{% code title="models/person.py" %}

```python
class Person(WarehouseModel): ...
```

{% endcode %}

{% code title="models/car.py" %}

```python
class Car(WarehouseModel): ...
```

{% endcode %}

All models should be imported into `models/__init__.py` to support importing multiple models from `models`.

{% code title="models/**init**.py" %}

```python
from .car import Car
from .person import Person
```

{% endcode %}

```python
# some other py file can now import one or more models at a time.
from path.to.models import Car, Person
```

Any custom logic defined in a model-file should be tested in the directory `models`, where each model has its own test-file following the naming convention `{model}_test.py`. Model-tests should inherit `ModelTestCase` and set their type parameter to be the model they are testing. The name of the model-test-case should follow the convention `Test{model}`.

{% code title="models/person\_test.py" %}

```python
from codeforlife.tests import ModelTestCase

from ...models import Person

class TestPerson(ModelTestCase[Person]): ...
```

{% endcode %}

{% code title="models/car\_test.py" %}

```python
from codeforlife.tests import ModelTestCase

from ...models import Car

class TestCar(ModelTestCase[Car]): ...
```

{% endcode %}

### Warehousing Data

#### TL;DR

* [x] &#x20;Inherit `WarehouseModel` if storing the model's historical data will provide meaningful insights.
* [x] &#x20;Inherit `models.Model` if storing the model's historical data will NOT provide meaningful insights.

***

Determine whether the data stored in a model needs to be warehoused. Data should be warehoused if it can contribute to analyzing users' behavior. By default, new models should be warehoused as it's a rare occurrence that meaningful insights cannot be gained from analyzing its data.

Defining a model as a warehouse-model allows us to sync data from our database to our data warehouse before it's deleted from our database. See our [data deletion strategy](https://code-for-life.gitbook.io/code-for-life-dev/data/storage#data-deletion-strategy).

Defining a warehouse-model:

```python
from codeforlife.models import WarehouseModel

class Example(WarehouseModel): ...
```

Defining a non-warehouse-model:

```python
from django.db import models

class Example(models.Model): ...
```

### Defining Fields

#### TL;DR

* [x] &#x20;Always set `verbose_name`.
* [x] &#x20;Always set `help_text`.

***

When defining fields of any type, always set the verbose name and help text. These arguments aid future developers and super-users on the Django admin to understand the purpose of these fields.

```python
from django.utils.translation import gettext_lazy as _

class CompanyMember(WarehouseModel):
  is_exec = models.BooleanField(
    verbose_name=_("is executive"),
    default=False,
    help_text=_(
      "Whether or not this company member is an executive member."
      " Executive members have elevated permissions to perform sensitive actions."
    ),
  )
```

### Defining Foreign Keys

#### TL;DR

* [x] &#x20;Create type hints for backward relationships, such as `cars: QuerySet["Car"]`.
* [x] &#x20;Import type hints for backward relationships inside of `if t.TYPE_CHECKING`.
* [x] &#x20;Set `related_name` of the relationship to be the plural of the model's name.

***

When defining a foreign key between 2 models, a few steps need to be taken to inform our static type checker of backward relationships between objects.

Say we have the following models:

{% code title="models/person.py" %}

```python
class Person(WarehouseModel):
  pass
```

{% endcode %}

{% code title="models/car.py" %}

```python
from .person import Person

class Car(WarehouseModel):
  owner = models.ForeignKey(Person, on_delete=models.CASCADE)
```

{% endcode %}

From this we understand that an instance of `Car` has the attribute `owner` of type `Person`. [Django will create an attribute](https://docs.djangoproject.com/en/3.2/topics/db/queries/#following-relationships-backward) for "backward relationships" on each related object with the naming convention `{model}_set` at **runtime**. Therefore, `Person` has the attribute `car_set` which is a set of type `Car`.

The problem is static type checkers do not know attributes for backward relationships are going to being auto-generated. Therefore, we need to add type hints.

{% code title="models/person.py" %}

```python
import typing as t

from django.db.models.query import QuerySet

if t.TYPE_CHECKING:
  from .car import Car

class Person(WarehouseModel):
  cars: QuerySet["Car"] 
```

{% endcode %}

{% code title="models/car.py" %}

```python
from .person import Person

class Car(WarehouseModel):
  owner = models.ForeignKey(
    Person,
    on_delete=models.CASCADE,
    related_name="cars",
  )
```

{% endcode %}

We import the model we are type hinting inside of `if t.TYPE_CHECKING` to avoid circular-imports. We also define the name of the backward relationships to be the plural of the model's name to improve readability.

### Defining Meta Classes

Models' meta class should inherit `TypedModelMeta` to support type hinted Meta classes.

```python
from django_stubs_ext.db.models import TypedModelMeta

class Person(WarehouseModel):
  class Meta(TypedModelMeta): ...
```

### Defining Managers

#### TL;DR

If you're defining a model with a custom manager:

* [x] &#x20;Define object manager as `Manager` within the model.
* [x] &#x20;If the model inherits `WarehouseModel`, its manager should inherit `WarehouseModel.Manager` and set the type variable to a string with the model's name.
* [x] &#x20;Write `objects: Manager = Manager()` below a custom manager.

If you're defining an abstract model with a custom manager:

* [x] &#x20;Create a type variable lazily bound to the abstract model with naming convention `Any{model}`.
* [x] &#x20;Add generic type parameter of type any model that inherits the abstract model on the manager.
* [x] &#x20;Write `objects: Manager[t.Self] = Manager()` below a custom manager.

***

A model's manager should be defined within the model's class as `Manager`. If the model inherits `WarehouseModel`, the manager should inherit `WarehouseModel.Manager`, providing a string of the model's name as the type parameter to inform the manager of the type of model it will be managing. Below the manager's definition, create a class-level attribute on the model called `objects` which has its type set to `Manager` and its value set to an instance of the `Manager` class.

```python
class Person(WarehouseModel):
  class Manager(WarehouseModel.Manager["Person"]): ...

  objects: Manager = Manager()
```

{% hint style="info" %}
Django requires the `User` model's manager to be defined globally (not locally nested within the `User` class). This is an exception and is required by Django so that it may auto-discover the location of the user-manager.
{% endhint %}

If you need to create an abstract model with a custom manager, add a generic type parameter to the manager which is bound to the manager's model. A type variable will need to be defined before the abstract model, following the naming convention `Any{model}`. However, to bind the type variable to the model before the model is defined, use a lazy binding by referencing the model's name as a string. Below the abstract model's manager, set the type of `objects` to be `Manager[t.Self]` so that the manager is managing the type of the inherited model (not the abstract model).

```python
import typing as t

AnyPerson = t.TypeVar("AnyPerson", bound="AbstractPerson")

class AbstractPerson(WarehouseModel):
  class Meta(TypedModelMeta):
    abstract = True

  class Manager(WarehouseModel.Manager[AnyPerson], t.Generic[AnyPerson]): ...

  objects: Manager[t.Self] = Manager() 

class Musician(AbstractPerson):
  class Manager(AbstractPerson.Manager["Musician"]): ...

  objects: Manager = Manager()
```

### Defining Constraints

#### TL;DR

* [x] &#x20;Use constraint naming convention `{field}__{condition}`.
* [x] &#x20;Use unit-test naming convention `test_constraint__{constraint_name}`.
* [x] &#x20;Use CFL's assertion helper `assert_check_constraint`.

***

When defining constraints, the naming convention is `{field}__{condition}`.

```python
class Person(WarehouseModel):
  years_old = models.IntegerField()

  class Meta(TypedModelMeta):
    constraints = [
      models.CheckConstraint(
        check=models.Q(years_old__gte=18),
        name="years_old__gte__18"
      )
    ]
```

Test your custom constraint in `models/{model}_test.py`. Your test name should follow the naming convention `test_constraint__{constraint_name}`. The unit test should leverage CFL's assertion helper `assert_check_constraint`, which will check the constraint is enforced under the expected conditions.

```python
class TestPerson(ModelTestCase[Person]):
  def test_constraint__years_old__gte__18(self):
    with self.assert_check_constraint("years_old__gte__18"):
      Person.objects.create(years_old=17)
```

### Define Verbose Names

When defining a model, set its verbose names in its meta attributes.

```python
from django.utils.translation import gettext_lazy as _

class Person(WarehouseModel):
  class Meta(TypedModelMeta):
    verbose_name = _("person")
    verbose_name_plural = _("persons")
```

### QuerySets as Properties

#### TL;DR

* [x] &#x20;Convert common query-sets filtered by model instance's attributes to properties.
* [x] &#x20;Import models inside the property to avoid circular-imports.

***

If there are query-sets that are filtered by a model instance's attributes, create properties on the model's class that return the query-sets. This achieves a shorthand that makes the code base less repetitive and more readable. It's only worth doing this if the query-set is used in 2 or more locations in the code base.

```python
class Person(WarehouseModel):
  favorite_music_genre = models.TextField()
  
  @property
  def recommended_songs(self):
    """Songs recommended for this person based on their favorite music genre."""
    # pylint: disable-next=import-outside-toplevel
    from .song import Song

    return Song.objects.filter(genre=self.favorite_music_genre)
```

We import `Song` outside the top level to avoid circular-imports.

### Defining Settings

If a model has business logic that impacts its functionality based on custom conditions, add class-level settings on the model in all caps to configure the conditions.

For example, if the `Person` model has a property which checks if the person is too young:

```python
class Person(WarehouseModel):
  MIN_YEARS_OLD = 16

  years_old = models.IntegerField()

  @property
  def is_too_young(self):
    return self.years_old < self.MIN_YEARS_OLD 
```

This will also help to make tests more robust as values can be dynamically calculated.

```python
class TestPerson(ModelTestCase[Person]):
  def test_is_too_young(self):
    assert Person(years_old=Person.MIN_YEARS_OLD - 1).is_too_young
```

## Serializers

Below are the conventions we follow when serializing our data.

First, understand how to [serialize a Django model](https://www.django-rest-framework.org/api-guide/serializers/#modelserializer).

### Model Serializers

For each model, we create a file with the naming convention `{model}.py` in the directory `serializers`. Within a model's serializer-file, we create one or more serializers. It's advised to create one serializer per [model-view-set](https://github.com/ocadotechnology/codeforlife-workspace/blob/main/docs/service/backend/VIEWS.md#model-view-sets) action. Each model-serializer should inherit CFL's `ModelSerializer` by default and set the type parameter to the model being serialized.

{% code title="serializers/person.py" %}

```python
from codeforlife.serializers import ModelSerializer

from ..models import Person

class CreatePersonSerializer(ModelSerializer[Person]):
  class Meta:
    model = Person

class UpdatePersonSerializer(ModelSerializer[Person]):
  class Meta:
    model = Person
```

{% endcode %}

To avoid repetitively setting the model being serialized to `Person`, a base serializer may be created with the naming convention `Base{model}Serializer`.

{% code title="serializers/person.py" %}

```python
from codeforlife.serializers import ModelSerializer

from ..models import Person

class BasePersonSerializer(ModelSerializer[Person]):
  class Meta:
    model = Person

class CreatePersonSerializer(BasePersonSerializer): ...

class UpdatePersonSerializer(BasePersonSerializer): ...
```

{% endcode %}

All serializers should be imported into `serializers/__init__.py` to support importing multiple serializers from `serializers`.

{% code title="serializers/**init**.py" %}

```python
from .person import CreatePersonSerializer, UpdatePersonSerializer
```

{% endcode %}

Any custom logic defined in a model-serializer-file should be tested in the directory `serializers`, where each model has its own serializer-test-file following the naming convention `{model}_test.py`. Model-serializer-test-cases should inherit CFL's `ModelSerializerTestCase`, set the type parameter to be the model being serialized and set `model_serializer_class` to the model-serializer being tested. The name of the model-serializer-test-case should follow the convention `Test{model}Serializer`.

{% code title="serializers/person\_test.py" %}

```python
from codeforlife.tests import ModelSerializerTestCase

from ...models import Person
from ...serializers.person import PersonSerializer

class TestPersonSerializer(ModelSerializerTestCase[Person]):
  model_serializer_class = PersonSerializer
```

{% endcode %}

### Model List Serializers

When defining model-list-serializers, follow the naming convention `{model}ListSerializer`. Model-list-serializers should inherit CFL's `ModelListSerializer` by default to support bulk-creating and bulk-updating model instances.

```python
from codeforlife.serializers import ModelListSerializer

from ..models import Person

class PersonListSerializer(ModelListSerializer[Person]): ...
```

When overriding `validate(self, attrs)`, *always* call `super().validate(attrs)` first before implementing any additional validations. This is necessary to ensure the data is valid before bulk-creating or bulk-updating.

```python
class PersonListSerializer(ModelListSerializer[Person]):
  def validate(self, attrs):
    super().validate(attrs)
```

When overriding `update(self, instance, validated_data)`, both `instance` and `validated_data` are of equal length and sorted in the correct order. Therefore, to get the data per model, use `zip` on `instance` and `validated_data`.

```python
class PersonListSerializer(ModelListSerializer[Person]):
  def update(self, instance, validated_data):
    for person, data in zip(instance, validated_data): ...
```

### Validation Errors

When defining validation errors, always set the `code` of the validation error so that it may be asserted in a test. Error codes **must** always be unique per validation function so that they may be individually asserted in tests.

```python
class PersonSerializer(ModelSerializer[Person]):
  years_old = serializers.IntegerField()
  country = serializers.CharField()

  def validate_years_old(self, value: int):
    if value < 18:
      raise serializers.ValidationError(
        "You are too young.",
        code="too_young",
      )
  
  def validate(self, attrs):
    if attrs["country"] == "GB" and attrs["years_old"] < 16:
      raise serializers.ValidationError(
        "A person in GB must be at least 16 years old.",
        code="gb_too_young",
      )
```

When testing validation errors, the `error_code` that is expected to be raised must be provided. When testing the validations of a field, the test must follow the naming convention `test_validate_{field}__{validation_error_code}` and use CFL's `assert_validate_field` helper. When testing general validations, the test must follow the naming convention `test_validate__{validation_error_code}` and use CFL's `assert_validate` helper.

```python
class TestPersonSerializer(ModelSerializerTestCase[Person]):
  model_serializer_class = PersonSerializer

  def test_validate_years_old__too_young(self):
    """A person must be at least 18."""
    self.assert_validate_field(
      name="years_old",
      value=17,
      error_code="too_young",
    )
  
  def test_validate__gb_too_young(self):
    """A person in GB must be at least 16."""
    self.assert_validate(
      attrs={"country": "GB", "years_old": 16},
      error_code="gb_too_young",
    )
```

### Testing create() and update()

If `create(self, validated_data)` was overridden in a model-serializer, a test named `test_create` will need to be created and use CFL's `assert_create` helper. Likewise, if `update(self, instance, validated_data)` was overridden in a model-serializer, a test named `test_update` will need to be created and use CFL's `assert_update` helper.

```python
class PersonSerializer(ModelSerializer[Person]):
  years_old = serializers.IntegerField()

  def create(self, validated_data):
    return Person.objects.create(**validated_data, created_at=timezone.now())
  
  def update(self, instance, validated_data):
    instance.years_old = validated_data["years_old"]
    instance.last_updated_at = timezone.now()
    instance.save(update_fields=["years_old", "last_updated_at"])
    
    return instance
```

```python
class TestPersonSerializer(ModelSerializerTestCase[Person]):
  model_serializer_class = PersonSerializer

  def test_create(self):
    """A person is successfully created."""
    self.assert_create(validated_data={"years_old": 18})
  
  def test_update(self):
    """A person is successfully updated."""
    self.assert_update(
      instance=Person.objects.get(pk=1),
      validated_data={"country": "GB", "years_old": 15},
    )
```

If `create(self, validated_data)` was overridden in a model-list-serializer, a test named `test_create_many` will need to be created and use CFL's `assert_create_many` helper. Likewise, if `update(self, instance, validated_data)` was overridden in a model-list-serializer, a test named `test_update_many` will need to be created and use CFL's `assert_update_many` helper.

```python
class PersonListSerializer(ModelListSerializer[Person]):
  def create(self, validated_data):
    return Person.objects.bulk_create([
      Person(**person_fields, created_at=timezone.now())
      for person_fields in validated_data
    ])
  
  def update(self, instance, validated_data):
    for person, data in zip(instance, validated_data):
      person.years_old = validated_data["years_old"]
      person.last_updated_at = timezone.now()
      person.save(update_fields=["years_old", "last_updated_at"])
      
    return instance

class PersonSerializer(ModelSerializer[Person]):
  years_old = serializers.IntegerField()

  class Meta:
    model = Person
    list_serializer_class = PersonListSerializer
```

```python
class TestPersonSerializer(ModelSerializerTestCase[Person]):
  model_serializer_class = PersonSerializer

  def test_create_many(self):
    """Many people are successfully created at once."""
    self.assert_create_many(
      validated_data=[{"years_old": 18}, {"years_old": 25}]
    )
  
  def test_update_many(self):
    """Many people are successfully updated at once."""
    self.assert_update_many(
      instance=[Person.objects.get(pk=1), Person.objects.get(pk=2)],
      validated_data=[{"years_old": 67}, {"years_old": 49}],
    )
```

### Testing to\_representation()

If `to_representation(self, instance)` was overridden in a model-serializer, a test named `test_to_representation` will need to be created and use CFL's `assert_to_representation` helper.

```python
class TestPersonSerializer(ModelSerializerTestCase[Person]):
  model_serializer_class = PersonSerializer

  def test_to_representation(self):
    """A data-field designating if a person is too young is included."""
    person = Person.objects.filter(age=17).first()
    assert person is not None

    self.assert_to_representation(
      instance=person,
      new_data={"is_too_young": True},
    )
```

```python
class PersonSerializer(ModelSerializer[Person]):
  def to_representation(self, instance):
    representation = super().to_representation()
    representation["is_too_young"] = instance.years_old < 18

    return representation
```

## Views

Below are the conventions we follow when viewing our data.

First, understand how to [view a Django model](https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset).

### Model View Sets

For each model, we create a file with the naming convention `{model}.py` in the directory `views`. Within a model's view-file, we create one view-set following the naming convention `{model}ViewSet`. Each model-view-set should inherit CFL's `ModelViewSet` by default and set the type parameter to the model being viewed.

{% code title="views/person.py" %}

```python
from codeforlife.views import ModelViewSet

from ..models import Person

class PersonViewSet(ModelViewSet[Person]): ...
```

{% endcode %}

All views should be imported into `views/__init__.py` to support importing multiple views from `views`.

{% code title="views/**init**.py" %}

```python
from .person import PersonViewSet
```

{% endcode %}

Any custom logic defined in a model-view-file should be tested in the directory `views`, where each model has its own view-test-file following the naming convention `{model}_test.py`. Model-view-set-test-cases should inherit CFL's `ModelViewSetTestCase`, set the type parameter to be the model being viewed, set `model_view_set_class` to the model-view-set being tested and set `basename` to the basename used to register the model-view-set in the urls. The name of the model-view-set-test-case should follow the convention `Test{model}ViewSet`.

{% code title="views/person\_test.py" %}

```python
from codeforlife.tests import ModelViewSetTestCase

from ...models import Person
from ...views import PersonViewSet

class TestPersonViewSet(ModelViewSetTestCase[Person]):
  model_view_set_class = PersonViewSet
  basename = "person"
```

{% endcode %}

### Register URLs

Each model-view-set needs to be registered in `urls.py` using DRF's `DefaultRouter`. Each registration needs to set `prefix` to be the plural name of the model with kebab-casing, `viewset` to be the model-view-set being registered and `basename` to be the singular of the singular name of the model with kebab-casing.

{% code title="urls.py" %}

```python
from rest_framework.routers import DefaultRouter

from .views import PersonViewSet

router = DefaultRouter()
router.register(
    prefix="persons",
    viewset=PersonViewSet,
    basename="person",
)

urlpatterns = router.urls
```

{% endcode %}

If a model has a foreign key to another model, it's also acceptable to set `prefix` to be a sub-path of the related model, where each model's name is plural with kebab casing.

```python
from .views import PartyInvitationViewSet, VipPartyInvitationViewSet

router.register(
    prefix="parties/invitations",
    viewset=PartyInvitationViewSet,
    basename="party-invitation",
)
# in practice, `is_vip` would likely be a field of `PartyInvitationViewSet` but
# this example is purely to demonstrate the naming convention of `prefix`.
router.register(
    prefix="parties/vip-invitations",
    viewset=VipPartyInvitationViewSet,
    basename="vip-party-invitation",
)
```

### Permissions

Permissions must at the very least be set per action in `get_permissions`, but further conditions can be specified. All permission must be imported from CFL's package to support unit testing.

```python
from codeforlife.permissions import AllowNone
from codeforlife.user.permissions import IsTeacher

class SchoolViewSet(ModelViewSet[School]):
  def get_permissions(self):
    if self.action == "list":
      return [AllowNone()]
    if self.action == "destroy":
      return [IsTeacher(is_admin=True)]
    
    return [IsTeacher(in_school=True)]
```

If `get_permissions` is overridden, a test will need to be created for each action the model-view-set provides where each test follows the naming convention `test_get_permissions__{action}`. Each test should use CFL's `assert_get_permissions` helper.

```python
from codeforlife.permissions import AllowNone
from codeforlife.user.permissions import IsTeacher

class TestSchoolViewSet(ModelViewSetTestCase[School]):
  def test_get_permissions__list(self):
    """No one is allowed to list schools."""
    self.assert_get_permissions(
      permissions=[AllowNone()],
      action="list",
    )

  def test_get_permissions__destroy(self):
    """Only admin teachers can destroy schools."""
    self.assert_get_permissions(
      permissions=[IsTeacher(is_admin=True)],
      action="destroy",
    )

  def test_get_permissions__retrieve(self):
    """Only school teachers can retrieve schools."""
    self.assert_get_permissions(
      permissions=[IsTeacher(in_school=True)],
      action="retrieve",
    )
  
  ...
```

#### Limiting Default Actions

If any of a model's [default actions](https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions) should not be allowed, they can be disallowed in one of 2 ways.

The first is by excluding an action's HTTP method from `http_method_names`. The is the preferred way if no action with that HTTP method should be allowed.

The second is to not permit some or all users to trigger the action. The is the preferred way if only some actions for a HTTP should be allowed.

```python
class PersonViewSet(ModelViewSet[Person]):
  http_method_names = ["get"]

  def get_permissions(self):
    if self.action == "list":
      return [AllowNone()]
    
    return [IsAuthenticated()]
```

In the above example, actions that do not use HTTP GET are not allowed (e.g. The destroy action which uses HTTP DELETE is not allowed). Furthermore, of the 2 actions which use HTTP GET: list and retrieve, list is not allowed and only authenticated users are allowed to retrieve.

### Custom Actions

If a custom action needs to be created for a model-view-set, use CFL's `action` decorator. A custom action should set `detail` and `methods`.

```python
from codeforlife.views import ModelViewSet, action

class PersonViewSet(ModelViewSet[Person]):
  @action(detail=True, methods=["post"])
  def send_reset_password_email(self, pk: str): ...
```

### Testing Actions

Each action provided by a model-view-set should have one test case that calls the action as it is intended to be called. Normally, unit tests can be said to test the "unhappy scenarios" - where we are asserting that the bad scenarios we are expecting to encounter are handled as expected. However, we will also test the "happy scenario" of each action to assert that the action does indeed work.

CFL has provided client-helpers to call and assert each of the default actions. Each action-test should follow the naming convention `test_{action}`.

```python
class TestPersonViewSet(ModelViewSetTestCase[Person]):
  def test_create(self):
    """Successfully creates a person."""
    self.client.create(
      data={
        "first_name": "John",
        "last_name": "Doe",
        "email": "john.doe@codeforlife.education",
      },
    )
```

### Custom Update or Bulk-Update Actions

If a custom update or bulk-update action needs to be created for a model-view-set, use CFL's `ModelViewSet.update_action` or `ModelViewSet.bulk_update_action` helpers and pass the name of the action as the first argument. As these actions require a serializer to be provided, you'll also need to override `get_serializer_class`.

**NOTE:** Update actions use HTTP PUT and so it needs to be added to `http_method_names`.

```python
class PersonViewSet(ModelViewSet[Person]):
  http_method_names = ["put"]

  def get_serializer_class(self):
    if action == "reset_password":
      return ResetPersonPasswordSerializer
    if action == "block_login":
      return BlockPersonLoginSerializer
    
    return PersonSerializer

  reset_password = ModelViewSet.update_action("reset_password")
  block_login = ModelViewSet.bulk_update_action("block_login")
```

To test the "[happy scenarios](#testing-actions)" of each update action, use CFL's client helpers `update` or `bulk_update`.

```python
class TestPersonViewSet(ModelViewSetTestCase[Person]):
  def test_reset_password(self):
    """Successfully resets a person's password."""
    self.client.update(
      model=person,
      data={"password": "example password"},
      action="reset_password",
    )

  def test_block_login(self):
    """Successfully block the specified persons from logging in."""
    self.client.bulk_update(
      models=[person1, person2],
      data=[{}, {}],  # no additional data required
      action="block_login",
    )
```

### Testing get\_queryset()

If you are overriding a model-view-set's `get_queryset` callback, a test will need to be created for each action at the very least where each test follows naming convention `test_get_queryset__{action}`. Each test will need to use CFL's `assert_get_queryset` helper. Additional test dimensions can be specified if other factors affect a queryset.

```python
class CarViewSet(ModelViewSet[Car]):
  def get_queryset(self):
    queryset = Car.objects.filter(is_insured=True)
    if action == "drive":
      return queryset.filter(owner=self.request.user)
    if action == "list":
      return queryset | queryset.filter(is_insured=False)

    return queryset
```

In the above example, the default queryset is all insured cars. For the drive action, only insured owners can drive their cars. For the list action, insured or uninsured cars can be listed.

```python
class TestCarViewSet(ModelViewSetTestCase[Car]):
  def test_get_queryset__drive(self):
    """Only cars owned by the requesting user can be driven."""
    self.assert_get_queryset(
      values=Car.objects.filter(is_insured=True, owner=user),
      action="drive",
      request=self.client.request_factory.post(user=user),
    )

  def test_get_queryset__list(self):
    """All cars can be listed."""
    self.assert_get_queryset(
      values=Car.objects.all(),
      action="list",
    )
  
  def test_get_queryset__partial_update(self):
    """Only insured cars can be partially updated."""
    self.assert_get_queryset(
      values=Car.objects.filter(is_insured=True),
      action="partial_update",
    )

  ...
```

### Testing get\_serializer\_class()

If you are overriding a model-view-set's `get_serializer_class` callback, a test will need to be created for each action at the very least where each test follows naming convention `test_get_serializer_class__{action}`. Each test will need to use CFL's `assert_get_serializer_class` helper.

```python
from ..serializers.person import (
  CreatePersonSerializer,
  ListPersonSerializer,
  PersonSerializer
)

class PersonViewSet(ModelViewSet[Person]):
  def get_serializer_class(self):
    if self.action == "create":
      return CreatePersonSerializer
    if self.action == "list":
      return ListPersonSerializer

    return PersonSerializer
```

```python
from ...serializers.person import (
  CreatePersonSerializer,
  ListPersonSerializer,
  PersonSerializer
)

class TestPersonViewSet(ModelViewSetTestCase[Person]):
  def test_get_serializer_class__create(self):
    """Creating a person has a dedicated serializer."""
    self.assert_get_serializer_class(
      serializer_class=CreatePersonSerializer,
      action="create",
    )

  def test_get_serializer_class__list(self):
    """Listing persons has a dedicated serializer."""
    self.assert_get_serializer_class(
      serializer_class=ListPersonSerializer,
      action="list",
    )

  def test_get_serializer_class__partial_update(self):
    """Partially updating a person uses the general serializer."""
    self.assert_get_serializer_class(
      serializer_class=PersonSerializer,
      action="partial_update",
    )

  ...
```

### Testing get\_serializer\_context()

If you are overriding a model-view-set's `get_serializer_context` callback, only the actions that have additional context will need to have a test created. The test should follow the naming convention `test_get_serializer_context__{action}`. Each test will need to use CFL's `assert_get_serializer_context` helper.

```python
class PersonViewSet(ModelViewSet[Person]):
  def get_serializer_context(self):
    context = super().get_serializer_context()
    if self.action == "create":
      context["favorite_color"] = "red" 
    
    return context
```

```python
class TestPersonViewSet(ModelViewSetTestCase[Person]):
  def test_get_serializer_context__create(self):
    """Includes the person's favorite color."""
    self.assert_get_serializer_context(
      serializer_context={"favorite_color": "red"},
      action="create",
    )
```


# Testing Strategy

How we test our back end

When a PR is submitted, a series of tests will be run with Github actions. It is fine to just submit your PR and let the tests run on Github. However, if the tests fail, you may need to run the tests locally to investigate what's going on, then either fix the tests, or fix your code.

## Running Python Tests Locally

To run Python tests, simply run at the top folder of the repository:

```
pytest -n auto
```

The `pytest` command will run both the tests written with [pytest](https://docs.pytest.org/) and those with the built-in python [unittest](https://docs.python.org/3/library/unittest.html).

{% hint style="info" %}
We are aiming to migrate all **unittest** to **pytest.** Meanwhile you will see a combination of these. If you write new tests, please use **pytest**.
{% endhint %}

For Rapid Router and Portal, `pytest` also runs [Selenium tests](/software-developer-guide/front-end/testing-strategy). Check the section below for what you need to install to run it.

The Python tests in Portal also include some snapshot tests. Running `pytest` will also automatically run the snapshot tests. When needed, the snapshot tests can be updated by running `pytest --snapshot-update`.


# Front End

How our front end is developed, tested and run

<mark style="color:red;">Documentation coming soon</mark>


# Overview

About our front ends

## Technology Stack

We have built our front ends primarily using [Node.js](https://nodejs.org/en), [React](https://react.dev/), and [Redux Toolkit](https://redux-toolkit.js.org/).

{% hint style="info" %}
We recommend getting familiar with the basics of each technology before contributing to one of our front ends.
{% endhint %}

## Code Repositories

Each service has a front end code repository in the [Ocado Technology](https://github.com/ocadotechnology) GitHub organisation which follows the naming convention:

```
codeforlife-{service}-frontend
```

[View](https://github.com/orgs/ocadotechnology/repositories?q=codeforlife-+-frontend) our front end repos on GitHub.

### Template

To speed up the process of creating a new front end repo, we created the template repo [codeforlife-template-frontend](https://github.com/ocadotechnology/codeforlife-template-frontend) which can be used to scaffold a new service's front end repo. Read [here](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) on how to create a repo from a template.

{% hint style="success" %}
After creating a repo from the template, run a case-insensitive search across all files for **replace-me**. Replace these strings with the appropriate value; this will most likely be the service's name.
{% endhint %}

## CI/CD Pipelines

In order to avoid repeating the same pipelines in every front end service, we centrally define the pipelines in our [workspace repo](https://github.com/ocadotechnology/codeforlife-workspace/tree/main/.github/workflows), and reference them in each front end service. In GitHub's terminology, these are referred to as [reusable workflows](https://docs.github.com/en/actions/sharing-automations/reusing-workflows).

There are 2 main pipelines in each front end service.

### main.yaml

The main pipeline for each front end service which simply reuses the [frontend](https://github.com/ocadotechnology/codeforlife-workspace/blob/main/.github/workflows/frontend.yaml) pipeline located in the workspace. This pipeline is responsible for testing and deploying a front end service.

You can see an example of this pipeline in the [front end template repo](https://github.com/ocadotechnology/codeforlife-template-frontend/blob/development/.github/workflows/main.yaml).

### contributing.yaml

This pipeline is responsible for managing the process of contributing to our code base, such as checking our contributors have signed our contributor agreement, auto-assigning/-unassigning contributors to issues, and more.

You can see an example of this pipeline in the [front end template repo](https://github.com/ocadotechnology/codeforlife-template-frontend/blob/development/.github/workflows/contributing.yaml).

## JavaScript Package

To avoid repeating code across 2 or more front ends, we have created the repo [codeforlife-package-javascript](https://github.com/ocadotechnology/codeforlife-package-javascript) which automatically tests and releases new version of the package using [semantic versioning](https://semver.org/). These versioned packages can then be installed into our JavaScript environment (node\_modules).

Learn more about our JavaScript package [here](https://code-for-life.gitbook.io/javascript-package).&#x20;


# Coding Patterns

Coding patterns we follow on our front end

## API

We're using [Redux Toolkit Query](https://redux-toolkit.js.org/rtk-query/overview) (RTK Query) to define our API endpoints and cache the response data.

### Defining Models

For each model defined on the back end, create a file named after the model in the directory `api`. At the top of the file, define the model on a global level and export it. Use the `Model` type constructor.

{% code title="api/person.ts" %}

```typescript
import { type Model } from "codeforlife/utils/api"

export type Person = Model<
    number, // the type of the "id" field
    {
        first_name: string
        last_name: string
        age: number
    }
>
```

{% endcode %}

In addition, the name of each model will need to be registered as a tag in `tagTypes`, at `api/index.ts`.

{% code title="api/index.ts" %}

```typescript
const api = createApi({
    tagTypes: ["Person"],
})
```

{% endcode %}

### Picking Model Fields

If you'd like to define an object containing a subset of a model's fields, you can use `Pick`.

```typescript
const person: Pick<Person, "id" | "age"> = { id: 1, age: 29 }
```

### Defining Results & Args

When defining the result (i.e. response body) and arg (i.e. request body) for an endpoint, you must define their types as a pair on a global level below the model's type and export them. The result's type should come first, immediately followed by the arg's type. The result & arg types should follow the naming convention `{endpoint_name}Result` and `{endpoint_name}Arg`. Each result & arg pair should be separated with one newline.

{% code title="api/person.ts" %}

```typescript
export type Person = Model<...>

// For endpoint "updatePersonName"
export type UpdatePersonNameResult = { id: number }
export type UpdatePersonNameArg = {
    id: number
    first_name: string
    last_name: string
}

// For endpoint "updatePersonAge"
export type UpdatePersonAgeResult = { id: number }
export type UpdatePersonAgeArg = {
    id: number
    age: number
}
```

{% endcode %}

If the fields of the result or arg are fields of the model, use the `Result` and `Arg` type constructors. These function similarly to [`Pick`](#picking-model-fields).

```typescript
import { type Arg, type Result } from "codeforlife/utils/api"

export type UpdatePersonNameResult = Result<Person>
export type UpdatePersonNameArg = Arg<
  Person, // model
  never, // required fields.
  "first_name" | "last_name" // optional fields
> & Pick<Person, "id"> // "id" cannot be a required or optional field
```

If the result and arg are for a [default action on the model-view-set](https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions), use the default type helper for the specific action. These function similarly to [`Pick`](#picking-model-fields).

```typescript
import { type UpdateArg, type UpdateResult } from "codeforlife/utils/api"

export type UpdatePersonResult = UpdateResult<Person>
export type UpdatePersonArg = UpdateArg<
  Person, // model
  never, // required fields
  "first_name" | "last_name" | "age" // optional fields
> // "id" is picked by default
```

If no data is included in the result or arg, set either to `null`.&#x20;

```typescript
export type DeletePersonResult = null
export type DeletePersonArg = Person["id"]
```

### Defining URLs

<mark style="color:red;">Documentation coming soon</mark>

### Defining Endpoints

Endpoints should be defined below the result & arg pairs. Endpoints should be injected into the base API, imported from `api/index.ts`.  The subset of API endpoints should follow the naming convention `{model_name}Api` and be exported as default. In addition, each hook auto-generated from the endpoints should be unpacked and exported as a constant below the default export.

{% code title="api/person.ts" %}

```typescript
import api from "."

export type Person = Model<...>

export type UpdatePersonResult = UpdateResult<Person>
export type UpdatePersonArg = UpdateArg<Person, ...>

const personApi = api.injectEndpoints({
    endpoints: build => ({
        updatePerson: build.mutation<UpdatePersonResult, UpdatePersonArg>({
            query: ({ id, ...body }) => ({
                url: `persons/${id}/`,
                method: "PATCH",
                body,
            })
        })
    })
})

export default personApi
export const { useUpdatePersonMutation } = personApi
```

{% endcode %}

### Defining a Retrieve Endpoint

When defining a retrieve endpoint, it's recommended to use the `RetrieveResult` and `RetrieveArg` type constructors. The endpoint should follow the naming convention `retrieve{model_name}`, be defined as a `query`, use the method `"GET"`, and name the query's arg as `id`. To build the URL, the `buildUrl` utility should be called, providing the model's detail URL and id as a URL parameter. The tag should be provided by calling the `tagData` utility and providing the model's name as an argument.

```typescript
import {
    type RetrieveArg,
    type RetrieveResult,
    buildUrl,
    tagData,
} from "codeforlife/utils/api"

export type RetrievePersonResult = RetrieveResult<Person, ...>
export type RetrievePersonArg = RetrieveArg<Person>

const personApi = api.injectEndpoints({
    endpoints: build => ({
        retrievePerson: build.query<RetrievePersonResult, RetrievePersonArg>({
            query: id => ({
                url: buildUrl(personUrls.detail, { url: { id } }),
                method: "GET",
            }),
            providesTags: tagData("Person")
        })
    })
})
```

### Defining a List Endpoint

When defining a list endpoint, it's recommended to use the `ListResult` and `ListArg` type constructors. The endpoint should follow the naming convention `list{model_name_plural}`, be defined as a `query`, use the method `"GET"`, and name the query's arg as `search`. To build the URL, the `buildUrl` utility should be called, providing the model's list URL and the search parameters. The tags should be provided by calling the `tagData` utility and providing the model's name as an argument and setting `includeListTag` to true.

```typescript
import {
    type ListArg,
    type ListResult,
    buildUrl,
    tagData,
} from "codeforlife/utils/api"

export type ListPersonsResult = ListResult<Person, ...>
export type ListPersonsArg = ListArg<...>

const personApi = api.injectEndpoints({
    endpoints: build => ({
        listPersons: build.query<ListPersonsResult, ListPersonsArg>({
            query: search => ({
                url: buildUrl(personUrls.list, { search }),
                method: "GET",
            }),
            providesTags: tagData("Person", { includeListTag: true })
        })
    })
})
```

### Defining a Create Endpoint

When defining a create endpoint, it's recommended to use the `CreateResult` and `CreateArg` type constructors. The endpoint should follow the naming convention `create{model_name}`, be defined as a `mutation`, use the method `"POST"`, and name the query's arg as `body`. The URL should be set as the model's list URL. The tags should be invalidated by calling the `tagData` utility and providing the model's name as an argument and setting `includeListTag` to true.

```typescript
import {
    type CreateArg,
    type CreateResult,
    tagData,
} from "codeforlife/utils/api"

export type CreatePersonResult = CreateResult<Person, ...>
export type CreatePersonArg = CreateArg<Person, ...>

const personApi = api.injectEndpoints({
    endpoints: build => ({
        createPerson: build.mutation<CreatePersonResult, CreatePersonArg>({
            query: body => ({
                url: personUrls.list,
                method: "POST",
                body,
            }),
            invalidatesTags: tagData("Person", { includeListTag: true })
        })
    })
})
```

### Defining a Update Endpoint

When defining a update endpoint, it's recommended to use the `UpdateResult` and `UpdateArg` type constructors. The endpoint should follow the naming convention `update{model_name}`, be defined as a `mutation`, use the method `"PATCH"`, and unpack the query's arg as `({ id, ...body })`. To build the URL, the `buildUrl` utility should be called, providing the model's detail URL and id as a URL parameter. The tags should be invalidated by calling the `tagData` utility and providing the model's name as an argument and setting `includeListTag` to true.

```typescript
import {
    type UpdateArg,
    type UpdateResult,
    buildUrl,
    tagData,
} from "codeforlife/utils/api"

export type UpdatePersonResult = UpdateResult<Person, ...>
export type UpdatePersonArg = UpdateArg<Person, ...>

const personApi = api.injectEndpoints({
    endpoints: build => ({
        updatePerson: build.mutation<UpdatePersonResult, UpdatePersonArg>({
            query: ({ id, ...body }) => ({
                url: buildUrl(personUrls.detail, { url: { id } }),
                method: "PATCH",
                body,
            }),
            invalidatesTags: tagData("Person", { includeListTag: true })
        })
    })
})
```

### Defining a Destroy Endpoint

When defining a destroy endpoint, it's recommended to use the `DestoryResult` and `DestroyArg` type constructors. The endpoint should follow the naming convention `destroy{model_name}`, be defined as a `mutation`, use the method `"DELETE"`, and name the query's arg as `id`. To build the URL, the `buildUrl` utility should be called, providing the model's detail URL and id as a URL parameter. The tags should be invalidated by calling the `tagData` utility and providing the model's name as an argument and setting `includeListTag` to true.

```typescript
import {
    type DestroyArg,
    type DestroyResult,
    buildUrl,
    tagData,
} from "codeforlife/utils/api"

export type DestroyPersonResult = DestroyResult
export type DestroyPersonArg = DestroyArg<Person>

const personApi = api.injectEndpoints({
    endpoints: build => ({
        destroyPerson: build.mutation<DestroyPersonResult, DestroyPersonArg>({
            query: id => ({
                url: buildUrl(personUrls.detail, { url: { id } }),
                method: "DELETE",
            }),
            invalidatesTags: tagData("Person", { includeListTag: true })
        })
    })
})
```

## Forms

<mark style="color:red;">Documentation coming soon</mark>

### Defining Fields

<mark style="color:red;">Documentation coming soon</mark>

### Submitting a Form

<mark style="color:red;">Documentation coming soon</mark>

## Schemas

<mark style="color:red;">Documentation coming soon</mark>

### Defining a Schema

<mark style="color:red;">Documentation coming soon</mark>

## Components

<mark style="color:red;">Documentation coming soon</mark>

### Defining a Component

<mark style="color:red;">Documentation coming soon</mark>

### Reusing Components

<mark style="color:red;">Documentation coming soon</mark>

## Pages

<mark style="color:red;">Documentation coming soon</mark>

### Defining Routes

<mark style="color:red;">Documentation coming soon</mark>

### Navigating to Routes

<mark style="color:red;">Documentation coming soon</mark>

### Link Components

<mark style="color:red;">Documentation coming soon</mark>

## Theme

<mark style="color:red;">Documentation coming soon</mark>

### Extending the Theme

<mark style="color:red;">Documentation coming soon</mark>

## Environment Variables

<mark style="color:red;">Documentation coming soon</mark>

### Setting Env. Variables

<mark style="color:red;">Documentation coming soon</mark>

### Importing Env. Variables

<mark style="color:red;">Documentation coming soon</mark>


# Testing Strategy

How we test our front end

When a PR is submitted, a series of tests will be run with Github actions. It is fine to just submit your PR and let the tests run on Github. However, if the tests fail, you may need to run the tests locally to investigate what's going on, then either fix the tests, or fix your code.

## Running Cypress tests locally

[Cypress](https://www.cypress.io/) is a frontend test framework that is used on part of Portal.

To run Cypress tests locally, you need two shell windows.

**Shell #1**

The following will run the portal/game on local server.

```
./run
```

**Shell #2**&#x20;

This will run the Cypress tests in the terminal.

```
yarn run cypress run
```

If you want to view the tests as they run using Cypress' test runner window, you can run:

```
yarn run cypress open
```

## Running Selenium tests locally

Selenium is a frontend test framework that is **used in Rapid Router and in Portal**. We aim to gradually migrate Selenium tests to Cypress.

**To run Selenium tests you need to install chromedriver**. Please check here on [how to install](https://chromedriver.chromium.org/getting-started) for your OS.

Similar with Cypress, it will launch a browser windows and you should be able to see a series of frontend actions.


