# notes

path: Operating_system_API.md
sortable_path: Operating_system_API.md
title: Operating system API
checksum: 7aeb44d375bb920e23b475fc0948194c841f603bdf7371ea17aa577bcf8e1d13
created: 2025-10-01 13:31:00.377559743+00:00
modified: 2025-08-13 15:57:13.957588918+00:00
metadata: {"created":"Wednesday, July 17, 2024","tags":["operating-systems"]}
lead:
  A user can interact with the operating system either via the GUI or the
  [shell](Intro_to_the_Unix_shell.md). (Both ultimately access the OS via the
  shell since the UI is an abstraction layer of the shell.)

body:
  A user can interact with the operating system either via the GUI or the
  [shell](Intro_to_the_Unix_shell.md). (Both ultimately access the OS via the
  shell since the UI is an abstraction layer of the shell.)

  When _programs_ interact with the operating system they use the **operating
  system's API** directly. The GUI and shell also invoke the OS API but the access
  is mediated.

  Every OS has an API. This specification details how a program should interact
  with the OS, exposing functions, properties and data types.

  Whether using the GUI or a terminal emulator, the shell translates the user's
  commands into API calls. The API the invokes internal operating system code to
  perform the action.

  ![OS API diagram](../img/OS-api.svg)

  ## Example: opening a file

  A user can use a file explorer and the mouse to open a file. Or they can open
  the file by invoking it from the terminal.

  A running application doesn't have to do this. If it's remit includes opening
  files, it can do so by calling the OS API.

  On a Unix-like system the applicaton would use the `open` API function to open
  the file:

  ```
  open("foo.txt", 0_WRONLY|0_CREAT)
  ```

  This command makes the action write-only and creates the file because it does
  not yet exist. When the user opens a file in their File Explorer, the
  application translates their graphical actions into this API call.

  ## Different OSs have different APIs

  Unix-like and Linux operating systems use variations on the **Portable Operating
  System Interface** (POSIX) standard. This defines the OS API and also the rules
  for the shell's behaviour and its included utilities.

  Variations on this include _Cocoa_, macOS's API and Android's _Android Platform_
  API.

  Windows has its own API called _The Windows API_. The original version was
  16-bit called _Win16_, then when it moved to 32-bits it became _Win32_. When it
  moved to an x86 [instruction_set_architecture](Instruction_set_architectures.md)
  it became _Win64_. Starting with Windows 10, it introduced the _Universal
  Windows Platform_ which aims to make app development consistent accross
  different devices that run Windows.

raw_content:
  ---
  tags: [operating-systems]
  created: Wednesday, July 17, 2024
  ---

  # Operating system API

  A user can interact with the operating system either via the GUI or the
  [shell](Intro_to_the_Unix_shell.md). (Both ultimately access the OS via the
  shell since the UI is an abstraction layer of the shell.)

  When _programs_ interact with the operating system they use the **operating
  system's API** directly. The GUI and shell also invoke the OS API but the access
  is mediated.

  Every OS has an API. This specification details how a program should interact
  with the OS, exposing functions, properties and data types.

  Whether using the GUI or a terminal emulator, the shell translates the user's
  commands into API calls. The API the invokes internal operating system code to
  perform the action.

  ![OS API diagram](../img/OS-api.svg)

  ## Example: opening a file

  A user can use a file explorer and the mouse to open a file. Or they can open
  the file by invoking it from the terminal.

  A running application doesn't have to do this. If it's remit includes opening
  files, it can do so by calling the OS API.

  On a Unix-like system the applicaton would use the `open` API function to open
  the file:

  ```
  open("foo.txt", 0_WRONLY|0_CREAT)
  ```

  This command makes the action write-only and creates the file because it does
  not yet exist. When the user opens a file in their File Explorer, the
  application translates their graphical actions into this API call.

  ## Different OSs have different APIs

  Unix-like and Linux operating systems use variations on the **Portable Operating
  System Interface** (POSIX) standard. This defines the OS API and also the rules
  for the shell's behaviour and its included utilities.

  Variations on this include _Cocoa_, macOS's API and Android's _Android Platform_
  API.

  Windows has its own API called _The Windows API_. The original version was
  16-bit called _Win16_, then when it moved to 32-bits it became _Win32_. When it
  moved to an x86 [instruction_set_architecture](Instruction_set_architectures.md)
  it became _Win64_. Starting with Windows 10, it introduced the _Universal
  Windows Platform_ which aims to make app development consistent accross
  different devices that run Windows.


path: Order_of_operations.md
sortable_path: Order_of_operations.md
title: Order of operations
checksum: fc78c76d7c349997d2bcbd5869fe79de661b6b4d428894d5b5f8dbd5272e9dfa
created: 2025-10-01 13:31:00.391878087+00:00
modified: 2025-08-13 15:57:14.001974757+00:00
metadata: {"tags":["prealgebra"]}
lead:
  1. Evaluate expressions in **parentheses**
  1. Evaluate **exponents**
  1. Evaluate **multiplications and divisions** from left to right in the order
     that they appear
  1. Evaluate **additions and subtractions** from left to right in the order that
     they appear.

body:
  1. Evaluate expressions in **parentheses**
  1. Evaluate **exponents**
  1. Evaluate **multiplications and divisions** from left to right in the order
     that they appear
  1. Evaluate **additions and subtractions** from left to right in the order that
     they appear.

  In the absence of grouping symbols, addition holds no precedence over
  subtraction and vice versa.

  ```
  15 - 8 + 4 = 7 + 4
  					= 11
  ```

  ```
  15 - 8 + 4 = 15 - 12
  					 = 3
  ```

raw_content:
  ---
  tags:
    - prealgebra
  ---

  # Order of operations

  1. Evaluate expressions in **parentheses**
  1. Evaluate **exponents**
  1. Evaluate **multiplications and divisions** from left to right in the order
     that they appear
  1. Evaluate **additions and subtractions** from left to right in the order that
     they appear.

  In the absence of grouping symbols, addition holds no precedence over
  subtraction and vice versa.

  ```
  15 - 8 + 4 = 7 + 4
  					= 11
  ```

  ```
  15 - 8 + 4 = 15 - 12
  					 = 3
  ```


path: Package_management_in_NodeJS.md
sortable_path: Package_management_in_NodeJS.md
title: Package management
lead: ## List installed packages
checksum: a4752920727fecb5b8ce97d7572b92652a86d679349fb8b71c6d9695790bc888
created: 2025-10-01 13:31:00.397267312+00:00
modified: 2025-08-13 15:57:13.750550372+00:00
metadata: {"tags":["node-js"]}
body:
  ## List installed packages

  ```bash
  npm list
  ```

  This will return a recursive tree that lists dependencies, dependences of
  dependencies, ... and so on. To limit the depth you can add the `--depth=` flag.
  For example to see only your installed packages and their versions use
  `npm list --depth=0`.

  ## View `package.json` data for an installed package

  We could go to the NPM registry and view details or we can quickly view the
  `package.json` for the dependency with the command `npm view [package_name]`

  We can pinpoint specific dependencies in the `package.json`, e.g.
  `npm view [package_name] dependencies `

  ## View outdated modules

  See whether your dependency version is out of date use `npm outdated`. This
  gives us a table, for example:

  ![Pasted image 20220411082627.png](Pasted_image_20220411082627.png)

  - _Latest_ tells us the latest release available from the developers
  - _Wanted_ tells us the version that our `package.json` rules target. To take
    the first dependency as an example. We must have set our SemVer syntax to
    `^0.4.x` since it is telling us that there is a minor release that is more
    recent than the one we have installed but is not advising that we update to
    the latest major release.
  - _Current_ tells us which version we currently have installed regardless of the
    version that our `package.json` is targeting or the most recent version
    available.

  ## Updating

  `npm update` only updates from _current_ to _wanted_. In other words it only
  updates in accordance with your caret and tilde rules applied to
  [semantic versioning](Semantic_versioning.md).

raw_content:
  ---
  tags:
    - node-js
  ---

  # Package management

  ## List installed packages

  ```bash
  npm list
  ```

  This will return a recursive tree that lists dependencies, dependences of
  dependencies, ... and so on. To limit the depth you can add the `--depth=` flag.
  For example to see only your installed packages and their versions use
  `npm list --depth=0`.

  ## View `package.json` data for an installed package

  We could go to the NPM registry and view details or we can quickly view the
  `package.json` for the dependency with the command `npm view [package_name]`

  We can pinpoint specific dependencies in the `package.json`, e.g.
  `npm view [package_name] dependencies `

  ## View outdated modules

  See whether your dependency version is out of date use `npm outdated`. This
  gives us a table, for example:

  ![Pasted image 20220411082627.png](Pasted_image_20220411082627.png)

  - _Latest_ tells us the latest release available from the developers
  - _Wanted_ tells us the version that our `package.json` rules target. To take
    the first dependency as an example. We must have set our SemVer syntax to
    `^0.4.x` since it is telling us that there is a minor release that is more
    recent than the one we have installed but is not advising that we update to
    the latest major release.
  - _Current_ tells us which version we currently have installed regardless of the
    version that our `package.json` is targeting or the most recent version
    available.

  ## Updating

  `npm update` only updates from _current_ to _wanted_. In other words it only
  updates in accordance with your caret and tilde rules applied to
  [semantic versioning](Semantic_versioning.md).


path: Pacman.md
sortable_path: Pacman.md
title: Pacman
lead: ## List all installed packages
checksum: 738de908496dfb512f61ea4a98d91d2c16be995c84218c17a528376a4ccbb587
created: 2025-10-01 13:31:00.415306519+00:00
modified: 2025-08-13 15:57:14.088389788+00:00
metadata: {"tags":["Linux","procedural","arch-linux"]}
body:
  ## List all installed packages

  ```
  pacman -Qe
  ```

  ## List all packages installed for current user

  ```
  pacman -Qqe
  ```

  ## Uninstall, and list dependencies for package to be uninstalled

  ```
  pacman -Rcns
  ```

raw_content:
  ---
  tags:
    - Linux
    - procedural
    - arch-linux
  ---

  # Pacman

  ## List all installed packages

  ```
  pacman -Qe
  ```

  ## List all packages installed for current user

  ```
  pacman -Qqe
  ```

  ## Uninstall, and list dependencies for package to be uninstalled

  ```
  pacman -Rcns
  ```


path: Passing_arguments_and_options_to_Bash_scripts.md
sortable_path: Passing_arguments_and_options_to_Bash_scripts.md
title: Passing arguments and options to Bash scripts
lead: ## Relation between commands and programs
checksum: c9040e163dcc20cf93166987910dfe06ee8c1f57e1e9cf47ae5dd4bcdcf3d29d
created: 2025-10-01 13:31:00.422036348+00:00
modified: 2025-08-13 15:57:14.022905373+00:00
metadata: {"tags":["shell"]}
body:
  ## Relation between commands and programs

  Whenever we issue a command in bash we are running an executable program that
  the command token references. This is why when we create our own bash scripts we
  must run `chmod` to make them executable. When we issue a command like
  `./do_something.sh` we are running an executable program.

  When we run a program like `cd` or `npm` we don’t have to type `./cd.sh` or
  `./npm.sh`. This is because a reference to the program file is already in our
  [`$PATH`](The_PATH.md).

  In the case of `cd`, this is an in-built program and as such it will be sourced
  from a binary and we have a reference to the binary in path. In the case of
  `npm`, this is not an in-built program however in order to run it we must
  already have it in our `PATH`.

  ## Passing arguments

  A script is really just a function that runs when you source it. As such there
  needs to be a way for you to pass data to the function so that it can actually
  act like a function and take arguments. When we use for example `cd ./Desktop`
  we are passing a directory name as an argument to the `cd` program. We can do
  the same thing with our custom bash scripts.

  To pass an argument we simply add the values after the script in the command.
  For example:

  ```bash
  ./arguments.sh Thomas 33
  ```

  We can use built-in variables to return information about the invocation of this
  script:

  ```bash
  #!/bin/bash

  echo "File is called $0"
  echo "The arguments provided are $@"
  echo "The first argument is $1"
  echo "The second argument is $2"
  echo "Your name is $1 and you are $2 years old"
  echo "There were $# arguments"
  ```

  This outputs:

  ```
  File is called ./arguments.sh
  The arguments provided are Thomas 33
  The first argument is Thomas
  The second argument is 33
  Your name is Thomas and you are 33 years old
  There were 2 arguments.
  ```

  Key points:

  - `$0` designates the script or function that is being executed
  - `$@` designates a list of all the arguments that are passed to the script
  - `$1...` designates each individual argument
  - `$#` gives us a count of the number of arguments

  ## Passing options

  Options differ from arguments in that they are prepended with `-` and they can
  be passed in any order. We use the `getops` program to parse the options that
  the user inputs with their command.

  We can demonstrate this with a script that takes in a username and password as
  options.

  We can handle an option-based input like:

  ```
  some-program -u thomas -p password123
  ```

  With the following construct:

  ```bash
  while getopts u:p: option; do
    case $option in
      u) user=$OPTARG;;
      p) pass=$OPTARG;;
    esac
  done

  echo "user: $user / pass: $pass"
  ```

  Which returns:

  ```
  user: thomas / pass: password123
  ```

  Here we set up a `while` loop against the `getopts` command to parse the options
  in the stdin and store each one in a `option`. We run each `option` through a
  case statement and individuate each one, storing them in dedicated local
  variables via the global `$OPTARG` variable

  ### The role of the colons

  Using a colon after each option means that the script will expect the given
  option to have a value. If we put a colon _before_ each of the options we expect
  this will allow us to view any option the user provides in our option handler.
  This is useful when you are working with very many options, as with a
  command-line program.

  This version demonstrates a more exhaustive use case:

  ```bash
  while getopts :u:p: option; do
    case $option in
      u) user=$OPTARG;;
      p) pass=$OPTARG;;
      a) echo "got the 'a' flag";;
      b) echo "got the 'b' flag";;
      ?) echo "Don't know what $OPTARG is!"
    esac
  done

  ```

raw_content:
  ---
  tags:
    - shell
  ---

  # Passing arguments and options to Bash scripts

  ## Relation between commands and programs

  Whenever we issue a command in bash we are running an executable program that
  the command token references. This is why when we create our own bash scripts we
  must run `chmod` to make them executable. When we issue a command like
  `./do_something.sh` we are running an executable program.

  When we run a program like `cd` or `npm` we don’t have to type `./cd.sh` or
  `./npm.sh`. This is because a reference to the program file is already in our
  [`$PATH`](The_PATH.md).

  In the case of `cd`, this is an in-built program and as such it will be sourced
  from a binary and we have a reference to the binary in path. In the case of
  `npm`, this is not an in-built program however in order to run it we must
  already have it in our `PATH`.

  ## Passing arguments

  A script is really just a function that runs when you source it. As such there
  needs to be a way for you to pass data to the function so that it can actually
  act like a function and take arguments. When we use for example `cd ./Desktop`
  we are passing a directory name as an argument to the `cd` program. We can do
  the same thing with our custom bash scripts.

  To pass an argument we simply add the values after the script in the command.
  For example:

  ```bash
  ./arguments.sh Thomas 33
  ```

  We can use built-in variables to return information about the invocation of this
  script:

  ```bash
  #!/bin/bash

  echo "File is called $0"
  echo "The arguments provided are $@"
  echo "The first argument is $1"
  echo "The second argument is $2"
  echo "Your name is $1 and you are $2 years old"
  echo "There were $# arguments"
  ```

  This outputs:

  ```
  File is called ./arguments.sh
  The arguments provided are Thomas 33
  The first argument is Thomas
  The second argument is 33
  Your name is Thomas and you are 33 years old
  There were 2 arguments.
  ```

  Key points:

  - `$0` designates the script or function that is being executed
  - `$@` designates a list of all the arguments that are passed to the script
  - `$1...` designates each individual argument
  - `$#` gives us a count of the number of arguments

  ## Passing options

  Options differ from arguments in that they are prepended with `-` and they can
  be passed in any order. We use the `getops` program to parse the options that
  the user inputs with their command.

  We can demonstrate this with a script that takes in a username and password as
  options.

  We can handle an option-based input like:

  ```
  some-program -u thomas -p password123
  ```

  With the following construct:

  ```bash
  while getopts u:p: option; do
    case $option in
      u) user=$OPTARG;;
      p) pass=$OPTARG;;
    esac
  done

  echo "user: $user / pass: $pass"
  ```

  Which returns:

  ```
  user: thomas / pass: password123
  ```

  Here we set up a `while` loop against the `getopts` command to parse the options
  in the stdin and store each one in a `option`. We run each `option` through a
  case statement and individuate each one, storing them in dedicated local
  variables via the global `$OPTARG` variable

  ### The role of the colons

  Using a colon after each option means that the script will expect the given
  option to have a value. If we put a colon _before_ each of the options we expect
  this will allow us to view any option the user provides in our option handler.
  This is useful when you are working with very many options, as with a
  command-line program.

  This version demonstrates a more exhaustive use case:

  ```bash
  while getopts :u:p: option; do
    case $option in
      u) user=$OPTARG;;
      p) pass=$OPTARG;;
      a) echo "got the 'a' flag";;
      b) echo "got the 'b' flag";;
      ?) echo "Don't know what $OPTARG is!"
    esac
  done

  ```


path: Passing_arguments_to_Python_scripts.md
sortable_path: Passing_arguments_to_Python_scripts.md
title: Passing arguments to Python scripts
lead:
  `sys.argv` is a list that contains the command-line arguments passed to a Python
  scripts.

checksum: 8b5c6497c1b17aaf8a5ad1d2d7f86edf63f3825229136af7133af23238556c9a
created: 2025-10-01 13:31:00.432089347+00:00
modified: 2025-08-13 15:57:13.743713941+00:00
metadata: {"created":"Wednesday, June 19, 2024","id":"44li","tags":["python"]}
body:
  `sys.argv` is a list that contains the command-line arguments passed to a Python
  scripts.

  - `sys.argv[0]` = the name of script
  - `sys.argv[1]` = the first argument
  - `sys.argv[2]` = the second argument, and so on

  Example invocation:

  ```sh
  python3 ./my_script.py argument_one argument_two

  ```

  ```python
  import sys

  print(sys.argv[0])
  print(sys.arg)
  print(sys.argv[1])

  # my_script.py
  # ['my_script.py', 'argyment_one', 'argument_two']
  # argument_one

  ```

raw_content:
  ---
  id: 44li
  tags: [python]
  created: Wednesday, June 19, 2024
  ---

  # Passing arguments to Python scripts

  `sys.argv` is a list that contains the command-line arguments passed to a Python
  scripts.

  - `sys.argv[0]` = the name of script
  - `sys.argv[1]` = the first argument
  - `sys.argv[2]` = the second argument, and so on

  Example invocation:

  ```sh
  python3 ./my_script.py argument_one argument_two

  ```

  ```python
  import sys

  print(sys.argv[0])
  print(sys.arg)
  print(sys.argv[1])

  # my_script.py
  # ['my_script.py', 'argyment_one', 'argument_two']
  # argument_one

  ```


path: Peer_to_peer_network.md
sortable_path: Peer_to_peer_network.md
title: Peer to peer network
lead:
  A decentralised network model where each participant (peer) acts as both a
  client and a server.

checksum: bb1364bf5d9ed4a089d9697585e4832a7907e2142a23af856133de69e365e9e9
created: 2025-10-01 13:31:00.435662897+00:00
modified: 2025-08-13 15:57:13.837438827+00:00
metadata: {"created":"Friday, August 09, 2024","tags":["networks"]}
body:
  A decentralised network model where each participant (peer) acts as both a
  client and a server.

  Resources are shared directly between peers rather than being coordinated via a
  server.

  Under a server architecture, multiple requests are made from different hosts for
  resources. The server manages this load and is in control of what is being
  shared, to whom, and when. With P2P there is no central authority equivalent to
  this. Each peer both shares and consumes resources and in this sense is both a
  client and a server.

  A practical example of this is [torrenting](Torrenting.md) - an applicaton of
  P2P technology to file sharing.

  ## Benefits

  - Decentralisation, no central authority, also means no single point of failure.
  - Scalable: the network capacity grows with the number of users (contrast
    servers)
  - Efficiency: idle resources of peers are put to use
  - Improved performance for popular content

  ## Drawbacks

  - Security: potential for malicious peers and content
  - Inconsistent availability of resources

raw_content:
  ---
  tags: [networks]
  created: Friday, August 09, 2024
  ---

  # Peer to peer network

  A decentralised network model where each participant (peer) acts as both a
  client and a server.

  Resources are shared directly between peers rather than being coordinated via a
  server.

  Under a server architecture, multiple requests are made from different hosts for
  resources. The server manages this load and is in control of what is being
  shared, to whom, and when. With P2P there is no central authority equivalent to
  this. Each peer both shares and consumes resources and in this sense is both a
  client and a server.

  A practical example of this is [torrenting](Torrenting.md) - an applicaton of
  P2P technology to file sharing.

  ## Benefits

  - Decentralisation, no central authority, also means no single point of failure.
  - Scalable: the network capacity grows with the number of users (contrast
    servers)
  - Efficiency: idle resources of peers are put to use
  - Improved performance for popular content

  ## Drawbacks

  - Security: potential for malicious peers and content
  - Inconsistent availability of resources


path: Ping.md
sortable_path: Ping.md
title: Ping
checksum: 93c2e66315606664cbc568d8ba2309d8a5c0826627747e27188931b6314703bd
created: 2025-10-01 13:31:00.4472605+00:00
modified: 2025-08-13 15:57:14.014964724+00:00
metadata: {"created":"Monday, January 13, 2025","tags":["networks","procedural"]}
lead:
  `ping` is perhaps the most basic network debugging tool. It sends
  [ICMP](./ICMP_Protocol.md) echo request packets to a recipient host.

body:
  `ping` is perhaps the most basic network debugging tool. It sends
  [ICMP](./ICMP_Protocol.md) echo request packets to a recipient host.

  If the recipient receives the packet and is configured to reply, it sends an
  ICMP echo response packet in return.

  For example:

  ```
  $ ping google.com
  PING google.com (142.250.200.14) 56(84) bytes of data.
  64 bytes from lhr48s29-in-f14.1e100.net (142.250.200.14): icmp_seq=1 ttl=116 time=19.1 ms
  64 bytes from lhr48s29-in-f14.1e100.net (142.250.200.14): icmp_seq=2 ttl=116 time=19.2 ms
  64 bytes from lhr48s29-in-f14.1e100.net (142.250.200.14): icmp_seq=3 ttl=116 time=19.1 ms
  64 bytes from lhr48s29-in-f14.1e100.net (142.250.200.14): icmp_seq=4 ttl=116 time=21.1 ms
  ```

  The first indicates the IP address of the host you are pinging (once per second,
  by default). The subsequent lines are the response packets, echoed back from
  this host.

  The `icmp_seq` is the number of the request in the sequence. If there was to be
  a gap in the sequence, this would be the clearest indication of a connection
  problem.The packets should not arrive out of order since there is only one
  packet being sent per second.

  `time` is the round-trip time - from the sending of the packet to its return to
  the sender.

  If the packet cannot reach the destination host, the final router to see the
  packet retunes a "host unreachable" packet to `ping`.

raw_content:
  ---
  tags: [networks, procedural]
  created: Monday, January 13, 2025
  ---

  # Ping

  `ping` is perhaps the most basic network debugging tool. It sends
  [ICMP](./ICMP_Protocol.md) echo request packets to a recipient host.

  If the recipient receives the packet and is configured to reply, it sends an
  ICMP echo response packet in return.

  For example:

  ```
  $ ping google.com
  PING google.com (142.250.200.14) 56(84) bytes of data.
  64 bytes from lhr48s29-in-f14.1e100.net (142.250.200.14): icmp_seq=1 ttl=116 time=19.1 ms
  64 bytes from lhr48s29-in-f14.1e100.net (142.250.200.14): icmp_seq=2 ttl=116 time=19.2 ms
  64 bytes from lhr48s29-in-f14.1e100.net (142.250.200.14): icmp_seq=3 ttl=116 time=19.1 ms
  64 bytes from lhr48s29-in-f14.1e100.net (142.250.200.14): icmp_seq=4 ttl=116 time=21.1 ms
  ```

  The first indicates the IP address of the host you are pinging (once per second,
  by default). The subsequent lines are the response packets, echoed back from
  this host.

  The `icmp_seq` is the number of the request in the sequence. If there was to be
  a gap in the sequence, this would be the clearest indication of a connection
  problem.The packets should not arrive out of order since there is only one
  packet being sent per second.

  `time` is the round-trip time - from the sending of the packet to its return to
  the sender.

  If the packet cannot reach the destination host, the final router to see the
  packet retunes a "host unreachable" packet to `ping`.


path: Political_accomodation_inveigelment_surveillance_capitalism.md
sortable_path: Political_accomodation_inveigelment_surveillance_capitalism.md
title: fbbfbc32-political-accommodation-inveigelment-surveillance-capitalism
checksum: 68352d1a57dcb358ab8a805550c10d8022f50445c03e634f6c38c7cc423fcff6
created: 2025-10-01 13:31:00.45674319+00:00
modified: 2025-08-13 15:57:14.062988122+00:00
metadata: {"created":"Sunday, December 01, 2024","tags":["ecopolsoc","internet","surveillance-capitalism"]}
lead:
  The reason why surveillance capitalism was able to take root when it did was not
  merely down to technological forces. Google, as the originator of the form, was
  able to exploit the political currents of the time to further innoculate itself
  against scrutiny and oversight.

body:
  The reason why surveillance capitalism was able to take root when it did was not
  merely down to technological forces. Google, as the originator of the form, was
  able to exploit the political currents of the time to further innoculate itself
  against scrutiny and oversight.

  The discovery of behavioural surplus coincided with September 11 and the
  subsequent "global war on terror". The quest for domestic "security" led to the
  sweeping erosion of previous generations' privacy rights.

  Prior to 911, the FCC had been arranging a series of legal challenges to Google
  on the question of privacy. This went out the window in the post-911 era where
  Google's unique ability to track and surveil online behaviour became a coveted
  commodity for the intelligence apparatus. Google began working closely with both
  the CIA and the NSA, with the CIA establishing an office and forward base in
  Silicon Valley.

  There was an deep interdependency between the Pentagon, intelligence agencies
  and Google:

  _The US intelligence community's incubation of Google from inception occurred
  through a combination of direct sponsorship and informal networks of financial
  influence, themselves closely aligned with Pentagon interests._

  _The Age of Surveillance Capitalism_ (2019): 118

  Another key aspect was cosying up to politicians during the electoral cycle.
  Most notably during Obama's elections:

  _Google demonstrated that the same predictive knowledge derived from behavioural
  surplus that had made the surveillance capitalists wealthy could also help
  candidates win elections_

  _Ibid_: 122

  Eric Schmidt took an active role in making Google's dataset and technologies
  available to the Obama campaign in both of his elections in order to target
  voters more accurately. He then was swiftly appointed to advisory roles within
  the administration throughout both terms.

raw_content:
  ---
  tags: [ecopolsoc, internet, surveillance-capitalism]
  created: Sunday, December 01, 2024
  ---

  # fbbfbc32-political-accommodation-inveigelment-surveillance-capitalism

  The reason why surveillance capitalism was able to take root when it did was not
  merely down to technological forces. Google, as the originator of the form, was
  able to exploit the political currents of the time to further innoculate itself
  against scrutiny and oversight.

  The discovery of behavioural surplus coincided with September 11 and the
  subsequent "global war on terror". The quest for domestic "security" led to the
  sweeping erosion of previous generations' privacy rights.

  Prior to 911, the FCC had been arranging a series of legal challenges to Google
  on the question of privacy. This went out the window in the post-911 era where
  Google's unique ability to track and surveil online behaviour became a coveted
  commodity for the intelligence apparatus. Google began working closely with both
  the CIA and the NSA, with the CIA establishing an office and forward base in
  Silicon Valley.

  There was an deep interdependency between the Pentagon, intelligence agencies
  and Google:

  _The US intelligence community's incubation of Google from inception occurred
  through a combination of direct sponsorship and informal networks of financial
  influence, themselves closely aligned with Pentagon interests._

  _The Age of Surveillance Capitalism_ (2019): 118

  Another key aspect was cosying up to politicians during the electoral cycle.
  Most notably during Obama's elections:

  _Google demonstrated that the same predictive knowledge derived from behavioural
  surplus that had made the surveillance capitalists wealthy could also help
  candidates win elections_

  _Ibid_: 122

  Eric Schmidt took an active role in making Google's dataset and technologies
  available to the Obama campaign in both of his elections in order to target
  voters more accurately. He then was swiftly appointed to advisory roles within
  the administration throughout both terms.


path: Ports_in_NodeJS.md
sortable_path: Ports_in_NodeJS.md
title: Ports
checksum: c9975673e974869e0d02f1f89f50d66c63960e6cdd9b0af1d6d5912241e71bb3
created: 2025-10-01 13:31:00.460627122+00:00
modified: 2025-08-13 15:57:13.982111593+00:00
metadata: {"tags":["node-js"]}
lead:
  When working in development we are able to specify the specific port from which
  we want top serve our application. In production, we do not always have this
  control: the port will most likely be set by the provider of the server
  environment.

body:
  When working in development we are able to specify the specific port from which
  we want top serve our application. In production, we do not always have this
  control: the port will most likely be set by the provider of the server
  environment.

  While we may not know the specific port, whatever it is, it will be accessible
  via the `PORT` environment variable. So we can use this when writing our
  [event listeners](Events%20module.md#event-emitters):

  ```js
  const port = process.env.PORT || 3000;
  ```

  This way, if a port is set by the provider it will use it. If not, it will fall
  back to 3000.

raw_content:
  ---
  tags:
    - node-js
  ---

  # Ports

  When working in development we are able to specify the specific port from which
  we want top serve our application. In production, we do not always have this
  control: the port will most likely be set by the provider of the server
  environment.

  While we may not know the specific port, whatever it is, it will be accessible
  via the `PORT` environment variable. So we can use this when writing our
  [event listeners](Events%20module.md#event-emitters):

  ```js
  const port = process.env.PORT || 3000;
  ```

  This way, if a port is set by the provider it will use it. If not, it will fall
  back to 3000.


path: Practical_walkthrough_Lambda_creation_within_AWS.md
sortable_path: Practical_walkthrough_Lambda_creation_within_AWS.md
title: Practical walkthrough of creating a Lambda function via the AWS Management Console
lead: ## Basic set-up
checksum: 8aaa595a4ee06aa4eaf98a9d65d0034ff5b0f795fe36d42fe503ee3453f7c696
created: 2025-10-01 13:31:00.477598241+00:00
modified: 2025-08-13 15:57:13.847356955+00:00
metadata: {"tags":["AWS","aws-lambda","node-js"]}
body:
  ## Basic set-up

  First we name the function and accept the defaults:

  ![](/img/lambda_func_one.png)

  This presents us with the function dashboard - a graphical representation of the
  Lambda showing [triggers]() as an input and destination as an output:

  ![](/img/lambda-func-two.png)

  Beneath this we have a code editor with the handler function with a basic
  boilerplate:

  ![](/img/lambda-func-three.png)

  ## Adding a trigger

  Next we need to add a [trigger](Lambda_triggers.md) that
  execute the handler.

  We will do this using [AWS API Gateway](AWS_API_Gateway.md). We
  select "Add trigger" from the dashboard view and input basic settings:

  ![](/img/api-gateway-trigger.png)

  Now we see this step displayed in the dashboard:

  ![](/img/lambda-overview.png)

  With the endpoint and other settings displayed:

  ![](/img/trigger-info.png)

  If we go to the endpoint URL
  (`https://4kjqwbvd7g.execute-api.us-east-1.amazonaws.com/default/myFirstFunction`),
  we will see the output: `Hello from Lambda`.

  ## Handling parameters

  We can make the example more realistic by expanding the handler to accept query
  parameters. We do this by accessing the value `queryStringParameters` on the
  `event` object:

  ```js
  exports.handler = async (event) => {
    const name = event.queryStringParameters && event.queryStringParameters.name;

    let message = "Hello Lambda";

    if (name !== null) {
      message = `Hello ${name}`;
    }

    const response {
      statusCode: 200,
      body: JSON.stringify(message)

    }
  };
  ```

  If we now access
  `https://4kjqwbvd7g.execute-api.us-east-1.amazonaws.com/default/myFirstFunction?name=Thomas`

  We get `Hello Thomas` as output.

  For a more advanced API with multiple endpoints and parameters, it's easiest to
  use Postman:

  ![](/img/postman-lambda.png)

raw_content:
  ---
  tags: [AWS, aws-lambda, node-js]
  ---

  # Practical walkthrough of creating a Lambda function via the AWS Management Console

  ## Basic set-up

  First we name the function and accept the defaults:

  ![](/img/lambda_func_one.png)

  This presents us with the function dashboard - a graphical representation of the
  Lambda showing [triggers]() as an input and destination as an output:

  ![](/img/lambda-func-two.png)

  Beneath this we have a code editor with the handler function with a basic
  boilerplate:

  ![](/img/lambda-func-three.png)

  ## Adding a trigger

  Next we need to add a [trigger](Lambda_triggers.md) that
  execute the handler.

  We will do this using [AWS API Gateway](AWS_API_Gateway.md). We
  select "Add trigger" from the dashboard view and input basic settings:

  ![](/img/api-gateway-trigger.png)

  Now we see this step displayed in the dashboard:

  ![](/img/lambda-overview.png)

  With the endpoint and other settings displayed:

  ![](/img/trigger-info.png)

  If we go to the endpoint URL
  (`https://4kjqwbvd7g.execute-api.us-east-1.amazonaws.com/default/myFirstFunction`),
  we will see the output: `Hello from Lambda`.

  ## Handling parameters

  We can make the example more realistic by expanding the handler to accept query
  parameters. We do this by accessing the value `queryStringParameters` on the
  `event` object:

  ```js
  exports.handler = async (event) => {
    const name = event.queryStringParameters && event.queryStringParameters.name;

    let message = "Hello Lambda";

    if (name !== null) {
      message = `Hello ${name}`;
    }

    const response {
      statusCode: 200,
      body: JSON.stringify(message)

    }
  };
  ```

  If we now access
  `https://4kjqwbvd7g.execute-api.us-east-1.amazonaws.com/default/myFirstFunction?name=Thomas`

  We get `Hello Thomas` as output.

  For a more advanced API with multiple endpoints and parameters, it's easiest to
  use Postman:

  ![](/img/postman-lambda.png)


path: Precursors_to_search_engines.md
sortable_path: Precursors_to_search_engines.md
title: ecec56e6_precursors_to_search_engines
checksum: f160dea20cd9f987f808c75db9e5931b5357007d35513bd3a30476ea42945ed3
created: 2025-10-01 13:31:00.492705424+00:00
modified: 2025-08-13 15:57:13.839702305+00:00
metadata: {"created":"Monday, November 04, 2024","tags":["world-wide-web","computer-history"]}
lead:
  Before search engines as searchable indices of all content on the web, the
  custom was for ISPs, browsers and websites (e.g. Yahoo!) to provide directories
  of links to other sites. They functioned as sort of global web-portals.

body:
  Before search engines as searchable indices of all content on the web, the
  custom was for ISPs, browsers and websites (e.g. Yahoo!) to provide directories
  of links to other sites. They functioned as sort of global web-portals.

  ![Yahoo's original homepage](../img/yahoo-original-homepage.png)

  _The Yahoo! homepage from 1999._

  ![AltaVista homepage](../img/alta-vista.png)

  _The AltaVista homepage from 1999. It has a primitive search engine but also
  directories of sites._

raw_content:
  ---
  tags: [world-wide-web, computer-history]
  created: Monday, November 04, 2024
  ---

  # ecec56e6_precursors_to_search_engines

  Before search engines as searchable indices of all content on the web, the
  custom was for ISPs, browsers and websites (e.g. Yahoo!) to provide directories
  of links to other sites. They functioned as sort of global web-portals.

  ![Yahoo's original homepage](../img/yahoo-original-homepage.png)

  _The Yahoo! homepage from 1999._

  ![AltaVista homepage](../img/alta-vista.png)

  _The AltaVista homepage from 1999. It has a primitive search engine but also
  directories of sites._


path: Prefixes_for_units_of_electrical_measurement.md
sortable_path: Prefixes_for_units_of_electrical_measurement.md
title: Prefixes for unit of electrical measurement
checksum: 8862db3b8a39d32e027c6882099e701167c87d7d3d07d136fba4c0ad18720de3
created: 2025-10-01 13:31:00.497041322+00:00
modified: 2025-08-13 15:57:14.072870323+00:00
metadata: {"tags":["physics","electricity","exponents"]}
lead:
  In electronics we are often dealing with units that are very large or very
  small, thus we rely on [exponents](Exponents.md) for formal
  expression.

body:
  In electronics we are often dealing with units that are very large or very
  small, thus we rely on [exponents](Exponents.md) for formal
  expression.

  | Prefix | Symbol | Expression as exponent | Expression as decimal value | English word |
  | ------ | ------ | ---------------------- | --------------------------- | ------------ |
  | Terra- | T      | $10^{12}$              | 1,000,000,000,000           | trillion     |
  | Giga-  | G      | $10^9$                 | 1,000,000,000               | billion      |
  | Mega-  | M      | $10^6$                 | 1,000,000                   | million      |
  | Kilo-  | k      | $10^3$                 | 1,000                       | thousand     |
  | Centi- | c      | $10^{-2}$              | 0.01                        | hundredth    |
  | Milli- | m      | $10^{-3}$              | 0.001                       | thousandth   |
  | Micro- | $\mu$  | $10^{-6}$              | 0.0000001                   | millionth    |
  | Nano-  | n      | $10^{-9}$              | 0.0000000001                | billionth    |
  | Pico-  | p      | $10^{-12}$             | 0.0000000000001             | trillionth   |

  For example, with Amps we tend not to use 1 whole amp as this is far too large
  for most electronics. More common is the milliampere (mA) and the microampere
  ($\mu$A).

  A mA is equal to one thousandth of an ampere: 0.001 A. It takes 1000
  milliamperes to equal one ampere.

  A $\mu$A is equal to one millionth of an ampere: 0.0000001 A. It takes one
  million micoramperes to equal one ampere.

raw_content:
  ---
  tags: [physics, electricity, exponents]
  ---

  # Prefixes for unit of electrical measurement

  In electronics we are often dealing with units that are very large or very
  small, thus we rely on [exponents](Exponents.md) for formal
  expression.

  | Prefix | Symbol | Expression as exponent | Expression as decimal value | English word |
  | ------ | ------ | ---------------------- | --------------------------- | ------------ |
  | Terra- | T      | $10^{12}$              | 1,000,000,000,000           | trillion     |
  | Giga-  | G      | $10^9$                 | 1,000,000,000               | billion      |
  | Mega-  | M      | $10^6$                 | 1,000,000                   | million      |
  | Kilo-  | k      | $10^3$                 | 1,000                       | thousand     |
  | Centi- | c      | $10^{-2}$              | 0.01                        | hundredth    |
  | Milli- | m      | $10^{-3}$              | 0.001                       | thousandth   |
  | Micro- | $\mu$  | $10^{-6}$              | 0.0000001                   | millionth    |
  | Nano-  | n      | $10^{-9}$              | 0.0000000001                | billionth    |
  | Pico-  | p      | $10^{-12}$             | 0.0000000000001             | trillionth   |

  For example, with Amps we tend not to use 1 whole amp as this is far too large
  for most electronics. More common is the milliampere (mA) and the microampere
  ($\mu$A).

  A mA is equal to one thousandth of an ampere: 0.001 A. It takes 1000
  milliamperes to equal one ampere.

  A $\mu$A is equal to one millionth of an ampere: 0.0000001 A. It takes one
  million micoramperes to equal one ampere.


path: Prime_factorization.md
sortable_path: Prime_factorization.md
title: Prime factorisation
checksum: a0d7c79fc40d3516ced0e25bf401f8a8f8a001882682cd2b1101108d62b8400a
created: 2025-10-01 13:31:00.50443561+00:00
modified: 2025-08-13 15:57:13.913463664+00:00
metadata: {"tags":["prealgebra","number-theory"]}
lead:
  Prime factorisation is the activity of expressing a composite number as the
  unique product of [prime numbers](Primes%20and%20composites.md). There are two
  main approaches to this:

body:
  Prime factorisation is the activity of expressing a composite number as the
  unique product of [prime numbers](Primes%20and%20composites.md). There are two
  main approaches to this:

  - - factor\* trees
  - repeated division by two

  > **Factor trees:** we take a number $n$ and break it down into two factors of
  > $n$. We then repeat this process with the resulting factors working
  > recursively until the numbers we are left with are primes.

  ![Untitled Diagram-Page-1.drawio.png](Untitled%20Diagram-Page-1.drawio.png) _The
  prime factors of 27 are 2, 3, 3_

  it doesn't matter which products we choose as the interim factors, we should
  always reach the same outcome:
  ![Untitled Diagram-Page-3.drawio 1.png](Untitled%20Diagram-Page-3.drawio%201.png)

  ![Untitled Diagram-Page-2.drawio.png](Untitled%20Diagram-Page-2.drawio.png)

raw_content:
  ---
  tags:
    - prealgebra
    - number-theory
  ---

  # Prime factorisation

  Prime factorisation is the activity of expressing a composite number as the
  unique product of [prime numbers](Primes%20and%20composites.md). There are two
  main approaches to this:

  - - factor\* trees
  - repeated division by two

  > **Factor trees:** we take a number $n$ and break it down into two factors of
  > $n$. We then repeat this process with the resulting factors working
  > recursively until the numbers we are left with are primes.

  ![Untitled Diagram-Page-1.drawio.png](Untitled%20Diagram-Page-1.drawio.png) _The
  prime factors of 27 are 2, 3, 3_

  it doesn't matter which products we choose as the interim factors, we should
  always reach the same outcome:
  ![Untitled Diagram-Page-3.drawio 1.png](Untitled%20Diagram-Page-3.drawio%201.png)

  ![Untitled Diagram-Page-2.drawio.png](Untitled%20Diagram-Page-2.drawio.png)


path: Primes_and_composites.md
sortable_path: Primes_and_composites.md
title: Prime and composite numbers
lead: Definition of a **prime number**:
checksum: dc753e7134e87d8c8702af7524489904121b6b8ef4884389166e2c482a0088df
created: 2025-10-01 13:31:00.517727425+00:00
modified: 2025-08-13 15:57:14.081439738+00:00
metadata: {"tags":["prealgebra","number-theory"]}
body:
  Definition of a **prime number**:

  > For any whole number $n$ where $n \neq 1$, $n$ is prime if and only if its
  > sole [factors](Factors%20and%20divisors.md) are $1$ and $n$

  Definition of a **composite number**:

  > For any whole number $n$, $n$ is composite just if $n$ is not prime

raw_content:
  ---
  tags:
    - prealgebra
    - number-theory
  ---

  # Prime and composite numbers

  Definition of a **prime number**:

  > For any whole number $n$ where $n \neq 1$, $n$ is prime if and only if its
  > sole [factors](Factors%20and%20divisors.md) are $1$ and $n$

  Definition of a **composite number**:

  > For any whole number $n$, $n$ is composite just if $n$ is not prime


path: Primitive_types.md
sortable_path: Primitive_types.md
title: Primitive types
checksum: 7e5afd3f7ab27ed61d7a12981598ff65f25a1a0bb6df6d01636b5b2332f9d00d
created: 2025-10-01 13:31:00.530747556+00:00
modified: 2025-08-13 15:57:14.066921968+00:00
metadata: {"tags":["typescript","data-types"]}
lead:
  The most basic type level is the one already present in JavaScript itself: the
  primitive data types: `boolean`, `string` and `number` . These are the types
  that would be returned from a `typeof` expression in ordinary JavaScript

body:
  The most basic type level is the one already present in JavaScript itself: the
  primitive data types: `boolean`, `string` and `number` . These are the types
  that would be returned from a `typeof` expression in ordinary JavaScript

  ## Type inference

  You can explicitly declare these data types yourself when you create a variable
  with `var`, `const`, or `let` if you like, but it is generally unnecessary since
  Typescript is intelligent enough to perform **type inference** and will know
  from what you write which type you mean.

  ```ts
  const age: number = 32;
  const name: string = "Thomas";
  const one: boolean = true;
  const zero: boolean = false;
  ```

  ## Arrays

  With arrays that you directly define the type will also be inferred but it can
  be helpful to explicitly declare them. If you declare an empty array, it is
  necessary to assign empty brackets.

  ```ts
  const store: number[] = [1, 2, 3]; // Populated array
  const store: string[] = []; // Empty array
  ```

  ## Object

  `Object` is a valid type declaration in TS but it is not particularly helpful
  since it becomes similar to using [any](Any.md) given that most primitive
  types in JavaScripts prototypically inherit from an Object.

  Generally, when you use objects in TypeScript you type them as
  [custom types](Custom_types_in_TypeScript.md).

  ## Array of (untyped) objects

  If we just know that it is going to be an array of objects we can use:

  ```ts
  const arrOfObj = {}[]
  ```

  If we wish to define a particular shape but without defining a type:

  ```ts
  const arrOfObj = { name: string, age: number }[]
  ```

  But better for reusability to do:

  ```ts
  type ArrayOfObj = {
    name: string,
    age: number
  }

  const arrOfObj: ArrayOfObj[] = [{}, ...]

  ```

raw_content:
  ---
  tags:
    - typescript
    - data-types
  ---

  # Primitive types

  The most basic type level is the one already present in JavaScript itself: the
  primitive data types: `boolean`, `string` and `number` . These are the types
  that would be returned from a `typeof` expression in ordinary JavaScript

  ## Type inference

  You can explicitly declare these data types yourself when you create a variable
  with `var`, `const`, or `let` if you like, but it is generally unnecessary since
  Typescript is intelligent enough to perform **type inference** and will know
  from what you write which type you mean.

  ```ts
  const age: number = 32;
  const name: string = "Thomas";
  const one: boolean = true;
  const zero: boolean = false;
  ```

  ## Arrays

  With arrays that you directly define the type will also be inferred but it can
  be helpful to explicitly declare them. If you declare an empty array, it is
  necessary to assign empty brackets.

  ```ts
  const store: number[] = [1, 2, 3]; // Populated array
  const store: string[] = []; // Empty array
  ```

  ## Object

  `Object` is a valid type declaration in TS but it is not particularly helpful
  since it becomes similar to using [any](Any.md) given that most primitive
  types in JavaScripts prototypically inherit from an Object.

  Generally, when you use objects in TypeScript you type them as
  [custom types](Custom_types_in_TypeScript.md).

  ## Array of (untyped) objects

  If we just know that it is going to be an array of objects we can use:

  ```ts
  const arrOfObj = {}[]
  ```

  If we wish to define a particular shape but without defining a type:

  ```ts
  const arrOfObj = { name: string, age: number }[]
  ```

  But better for reusability to do:

  ```ts
  type ArrayOfObj = {
    name: string,
    age: number
  }

  const arrOfObj: ArrayOfObj[] = [{}, ...]

  ```


path: Printing_values_in_C.md
sortable_path: Printing_values_in_C.md
title: Printing values in C
lead: ## To print a literal
checksum: ced1e80a73091c1f9c47ba46f368bc9999b9f74e507d4bc904524c2f85b2c28c
created: 2025-10-01 13:31:00.546806651+00:00
modified: 2025-08-13 15:57:14.080294459+00:00
metadata: {"created":"Thursday, February 29, 2024 | 17:33","id":"3hcv0amc","tags":["C"]}
body:
  ## To print a literal

  ```c
  printf("hello world")
  ```

  ## To print a variable

  ```c
  int age = 25
  print("%d", age)

  ```

  The `%d` is an example of a [format specifier](./zk/format-specifiers-in-c.md).
  It is the decimal integer format specifier.

raw_content:
  ---
  id: 3hcv0amc
  tags:
    - C
  created: Thursday, February 29, 2024 | 17:33
  ---

  # Printing values in C

  ## To print a literal

  ```c
  printf("hello world")
  ```

  ## To print a variable

  ```c
  int age = 25
  print("%d", age)

  ```

  The `%d` is an example of a [format specifier](./zk/format-specifiers-in-c.md).
  It is the decimal integer format specifier.


path: Process_module_in_NodeJS.md
sortable_path: Process_module_in_NodeJS.md
title: The process module in Node.js
checksum: c0471abbd224662b086b5b3f40c8d67e46decb2adefb72bb979d0b92686a0b94
created: 2025-10-01 13:31:00.560752871+00:00
modified: 2025-08-13 15:57:13.792707386+00:00
metadata: {"tags":["node-js"]}
lead:
  `process` is a core module and a global object accessible from anywhere in a
  Node.js application. It contains functionality that allows us to interact with
  information about the current process instance of Node.

body:
  `process` is a core module and a global object accessible from anywhere in a
  Node.js application. It contains functionality that allows us to interact with
  information about the current process instance of Node.

  For example, we can use it to get environment information, read environment
  variables, parse arguments that are passed to the run command, communicate with
  the terminal and exit the current process.

  ## Managing runtime environments

  See
  [Managing Environments](Managing_environments_in_NodeJS.md).

  ## Accessing arguments: `process.argv`

  We can use `process.argv` to return an array containing the command-line
  arguments passed when a Node process is launched. This could be a whole-app
  entrypoint (i.e. `index.js`) or a single file we are running.

  For instance if we run the following file:

  ```js
  // process-demo.js
  console.log(3 + 3);
  console.log(process.argv);
  ```

  We get:

  ```bash
  6
  [
    '/Users/thomasbishop/.nvm/versions/node/v16.10.0/bin/node',
    '/Users/thomasbishop/prepos/testNode.js'
  ]
  ```

  The first item is the last executed process. The second is the array of
  arguments.

  In the array, the first value is a reference to the Node runtime binary. The
  second is the file that was passed to Node.

  If we passed in a parameter we would get that too:

  ```
  node process-demo.js --fakeFlag
  ```

  Gives us:

  ```bash
  [
    "/Users/thomasbishop/.nvm/versions/node/v16.10.0/bin/node",
    "/Users/thomasbishop/prepos/testNode.js",
    "--fake-flag",
  ]
  ```

  When writing Node CLI applications we can write functions that parse standard
  input. For example:

  ```js
  function parseStandardInput(flag) {
    let indexAfterFlag = process.argv.indexOf(flag);
    console.log(process.argv[indexAfterFlag]);
  }
  ```

  Say we ran a program that took in a username:

  ```bash
  node userName.js --user Thomas
  ```

  Then `parseStandardInput("--user")` would give us `"thomas"`

  ## Standard input and output

  Below is the most basic use case: writing to the output.

  ```js
  // alpha.js
  process.stdout.write("Hello from file \n");
  ```

  ```
  node alpha.js
  Hello from file
  ```

  Typically we want to write and read data that the user provides. To do this we
  need to wait on that event. So we use Node's asynchonous
  [event listeners](events.md). We wait
  on the `data` event:

  ```js
  process.stdin.on("data", (data) => {
    process.stdout.write(data.toString().trim());
  });

  process.stdout.write("\n What is your name? \n");
  process.stdout.write(` \n > `);
  ```

  This waits for whatever input is given and then echoes it.

  Currently there is no way to end this process; it will just keep echoing the
  input.

  So we add an exit clause:

  ```js
  process.stdin.on("data", (data) => {
    process.stdout.write(data.toString().trim());
    process.exit();
  });
  ```

  We can also execute functionality on the exit event:

  ```js
  process.on("exit", () => {
    // Do something
  });
  ```

  > Timings can also obviously be managed via the `setTimeout` and `setInterval`
  > methods.

  ### Additional useful methods

  ```js
  process.stdout.clearLine();
  process.stdout.cursorTo([int]);
  ```

  ### `readline`

  The core `readline` module simplifies the handling of standard input and output
  by providing a wrapper. It reads the input stream line by line. Basic usage:

  ```js
  var readline = require("readline");

  var rl = readline.createInterface(process.stdin, process.stdout);

  rl.question("What is your age? ", (age) => {
    console.log("Your age is: " + age);
  });
  ```

  Usage scenarios at: https://www.geeksforgeeks.org/node-js-readline-module/

raw_content:
  ---
  tags:
    - node-js
  ---

  # The `process` module in Node.js

  `process` is a core module and a global object accessible from anywhere in a
  Node.js application. It contains functionality that allows us to interact with
  information about the current process instance of Node.

  For example, we can use it to get environment information, read environment
  variables, parse arguments that are passed to the run command, communicate with
  the terminal and exit the current process.

  ## Managing runtime environments

  See
  [Managing Environments](Managing_environments_in_NodeJS.md).

  ## Accessing arguments: `process.argv`

  We can use `process.argv` to return an array containing the command-line
  arguments passed when a Node process is launched. This could be a whole-app
  entrypoint (i.e. `index.js`) or a single file we are running.

  For instance if we run the following file:

  ```js
  // process-demo.js
  console.log(3 + 3);
  console.log(process.argv);
  ```

  We get:

  ```bash
  6
  [
    '/Users/thomasbishop/.nvm/versions/node/v16.10.0/bin/node',
    '/Users/thomasbishop/prepos/testNode.js'
  ]
  ```

  The first item is the last executed process. The second is the array of
  arguments.

  In the array, the first value is a reference to the Node runtime binary. The
  second is the file that was passed to Node.

  If we passed in a parameter we would get that too:

  ```
  node process-demo.js --fakeFlag
  ```

  Gives us:

  ```bash
  [
    "/Users/thomasbishop/.nvm/versions/node/v16.10.0/bin/node",
    "/Users/thomasbishop/prepos/testNode.js",
    "--fake-flag",
  ]
  ```

  When writing Node CLI applications we can write functions that parse standard
  input. For example:

  ```js
  function parseStandardInput(flag) {
    let indexAfterFlag = process.argv.indexOf(flag);
    console.log(process.argv[indexAfterFlag]);
  }
  ```

  Say we ran a program that took in a username:

  ```bash
  node userName.js --user Thomas
  ```

  Then `parseStandardInput("--user")` would give us `"thomas"`

  ## Standard input and output

  Below is the most basic use case: writing to the output.

  ```js
  // alpha.js
  process.stdout.write("Hello from file \n");
  ```

  ```
  node alpha.js
  Hello from file
  ```

  Typically we want to write and read data that the user provides. To do this we
  need to wait on that event. So we use Node's asynchonous
  [event listeners](events.md). We wait
  on the `data` event:

  ```js
  process.stdin.on("data", (data) => {
    process.stdout.write(data.toString().trim());
  });

  process.stdout.write("\n What is your name? \n");
  process.stdout.write(` \n > `);
  ```

  This waits for whatever input is given and then echoes it.

  Currently there is no way to end this process; it will just keep echoing the
  input.

  So we add an exit clause:

  ```js
  process.stdin.on("data", (data) => {
    process.stdout.write(data.toString().trim());
    process.exit();
  });
  ```

  We can also execute functionality on the exit event:

  ```js
  process.on("exit", () => {
    // Do something
  });
  ```

  > Timings can also obviously be managed via the `setTimeout` and `setInterval`
  > methods.

  ### Additional useful methods

  ```js
  process.stdout.clearLine();
  process.stdout.cursorTo([int]);
  ```

  ### `readline`

  The core `readline` module simplifies the handling of standard input and output
  by providing a wrapper. It reads the input stream line by line. Basic usage:

  ```js
  var readline = require("readline");

  var rl = readline.createInterface(process.stdin, process.stdout);

  rl.question("What is your age? ", (age) => {
    console.log("Your age is: " + age);
  });
  ```

  Usage scenarios at: https://www.geeksforgeeks.org/node-js-readline-module/


path: Processes.md
sortable_path: Processes.md
title: Processes
checksum: 2b331b124e4ae2014628e74cbe62db17966948066c36c6a255fecd473f58e76b
created: 2025-10-01 13:31:00.576883185+00:00
modified: 2025-08-13 15:57:13.928629632+00:00
metadata: {"created":"Friday, June 21, 2024","id":"t70u","tags":["operating-systems"]}
lead:
  Programs are sequences of machine instructions stored in a file. However they do
  not work by themselves. Something needs to load the file's intructions into
  memory, direct the CPU to run the program and manage it during runtime. The OS
  does this via processes.

body:
  Programs are sequences of machine instructions stored in a file. However they do
  not work by themselves. Something needs to load the file's intructions into
  memory, direct the CPU to run the program and manage it during runtime. The OS
  does this via processes.

  A process **is a running instance of a given program**. It can be thought of as
  a container in which a program runs. This container includes:

  - a copy of the program code loaded into memory
  - a memory address
  - other information about the state of the process

  Other than the `init` process started by the kernel (PID1) (see
  ![systemd](systemd.md)), every process has a parent process that started it.
  This parent-child relationship creates a tree of processes.

  It is possible that a parent process will terminate before one of its child
  processes. In this instance the child becomes an orphan. When this occurs in
  #Linux, the orphan process is adopted by `init`.

  Below, I have used the `pstree` utility to list all the running processes on my
  machine hierarchically.

  ![diagram of `pstree` output](../img/ps-tree.png)

  Children are represented vertically and horizontally.

  ```
  ├─terminator─┬─zsh───tmux: client
  │            ├─zsh───pstree
  │            └─6*[{terminator}]

  ```

  For instance here, `terminator` is a child of `init`, as are `zsh` and `tmux`
  but they are also children of `terminator`.`pstree` is a child of `zsh` and
  therefore also a child (grandchild) of `terminator`.

  Each process has a unique identifier called a _process identifier_, a
  _processID_ or just _PID_.

  ## Related notes

  ![systemd](./systemd.md)

  ![ps](./ps.md)

  ![Monitoring processes and resources](Monitoring_processes_and_resources.md)

raw_content:
  ---
  id: t70u
  tags: [operating-systems]
  created: Friday, June 21, 2024
  ---

  # Processes

  Programs are sequences of machine instructions stored in a file. However they do
  not work by themselves. Something needs to load the file's intructions into
  memory, direct the CPU to run the program and manage it during runtime. The OS
  does this via processes.

  A process **is a running instance of a given program**. It can be thought of as
  a container in which a program runs. This container includes:

  - a copy of the program code loaded into memory
  - a memory address
  - other information about the state of the process

  Other than the `init` process started by the kernel (PID1) (see
  ![systemd](systemd.md)), every process has a parent process that started it.
  This parent-child relationship creates a tree of processes.

  It is possible that a parent process will terminate before one of its child
  processes. In this instance the child becomes an orphan. When this occurs in
  #Linux, the orphan process is adopted by `init`.

  Below, I have used the `pstree` utility to list all the running processes on my
  machine hierarchically.

  ![diagram of `pstree` output](../img/ps-tree.png)

  Children are represented vertically and horizontally.

  ```
  ├─terminator─┬─zsh───tmux: client
  │            ├─zsh───pstree
  │            └─6*[{terminator}]

  ```

  For instance here, `terminator` is a child of `init`, as are `zsh` and `tmux`
  but they are also children of `terminator`.`pstree` is a child of `zsh` and
  therefore also a child (grandchild) of `terminator`.

  Each process has a unique identifier called a _process identifier_, a
  _processID_ or just _PID_.

  ## Related notes

  ![systemd](./systemd.md)

  ![ps](./ps.md)

  ![Monitoring processes and resources](Monitoring_processes_and_resources.md)


path: Prop_types_in_React.md
sortable_path: Prop_types_in_React.md
title: Prop types
checksum: 727c77a483cc8cd4beceb26f9145e1f40aef386f77b3ac6c2f4b43d874e30039
created: 2025-10-01 13:31:00.583566606+00:00
modified: 2025-08-13 15:57:13.86533129+00:00
metadata: {"tags":["javascript","react","data-types"]}
lead:
  **The `prop-types` package allows us to introduce type-checking during the
  development runtime of a React application. With larger applications or those
  with complex data flows, this can help reduce errors and bugs during
  development. This is a bit like using TypeScript but on a more minimal level.**

body:
  **The `prop-types` package allows us to introduce type-checking during the
  development runtime of a React application. With larger applications or those
  with complex data flows, this can help reduce errors and bugs during
  development. This is a bit like using TypeScript but on a more minimal level.**

  ## Install

  ```
  npm install prop-types
  ```

  ## Usage

  ```jsx
  import PropTypes from "prop-types";
  ```

  ## Examples

  Say we have a component with the following props:

  ```jsx
  function Page(props) {
    const classes = useStyles();
    return (
      <React.Fragment>
        <Typography className={classes.heading} variant="h1">
          {props.h1}
        </Typography>
        {props.h2 !== "" && <Typography variant="h2">{props.h2}</Typography>}
        {props.paras.map((paragraph, index) => (
          <Typography
            className={classes.paragraph}
            key={index}
            variant="body1"
            gutterBottom
          >
            {paragraph}
          </Typography>
        ))}
        {props.children}
        <Button
          className={classes.button}
          variant="contained"
          color="primary"
          disableElevation
          component={Link}
          to={props.buttonLink}
        >
          {props.buttonText}
        </Button>
      </React.Fragment>
    );
  }
  ```

  Before the final `export default` statement, we would add a PropTypes object
  that specifies the data or reference type that is required by each prop cited in
  the component:

  ```jsx
  Page.propTypes = {
    h1: PropTypes.string.isRequired, // should be string data type, must be present
    h2: PropTypes.string, // as above but optional
    paras: PropTypes.array, // should be array reference type
    buttonLink: PropTypes.string,
    buttonText: PropTypes.string,
    children: PropTypes.node, // can be anything (element, type, JSX) that is rendered to the screen
  };
  ```

  If one of these type checks failed you get a very semantic Warning in the
  console specifying which prop is not consistent with your prop type declaration.

  ## Additional checks

  Above are the most frequent and basic checks, but there are many other
  conditions you can check for:

  ```jsx
  // The full list of types
  [propName]: PropTypes.array,
  [propName]: PropTypes.bool,
  [propName]: PropTypes.func,
  [propName]: PropTypes.number,
  [propName]: PropTypes.object,
  [propName]: PropTypes.string,
  [propName]: PropTypes.symbol,

  // Anything that can be rendered: numbers, strings, elements or an arrayor fragment) containing these types.
  [propName]: PropTypes.node,

  // A function

  [propName]: PropTypes.func

  // An object that could be one of many types
  [objectProp]: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number,
    ]),

  // An array of a certain type
  [arrayProp]: PropTypes.arrayOf(PropTypes.number),

  // An object with property values of a certain type
  [objectProp]: PropTypes.objectOf(PropTypes.number),
  ```

raw_content:
  ---
  tags:
    - javascript
    - react
    - data-types
  ---

  # Prop types

  **The `prop-types` package allows us to introduce type-checking during the
  development runtime of a React application. With larger applications or those
  with complex data flows, this can help reduce errors and bugs during
  development. This is a bit like using TypeScript but on a more minimal level.**

  ## Install

  ```
  npm install prop-types
  ```

  ## Usage

  ```jsx
  import PropTypes from "prop-types";
  ```

  ## Examples

  Say we have a component with the following props:

  ```jsx
  function Page(props) {
    const classes = useStyles();
    return (
      <React.Fragment>
        <Typography className={classes.heading} variant="h1">
          {props.h1}
        </Typography>
        {props.h2 !== "" && <Typography variant="h2">{props.h2}</Typography>}
        {props.paras.map((paragraph, index) => (
          <Typography
            className={classes.paragraph}
            key={index}
            variant="body1"
            gutterBottom
          >
            {paragraph}
          </Typography>
        ))}
        {props.children}
        <Button
          className={classes.button}
          variant="contained"
          color="primary"
          disableElevation
          component={Link}
          to={props.buttonLink}
        >
          {props.buttonText}
        </Button>
      </React.Fragment>
    );
  }
  ```

  Before the final `export default` statement, we would add a PropTypes object
  that specifies the data or reference type that is required by each prop cited in
  the component:

  ```jsx
  Page.propTypes = {
    h1: PropTypes.string.isRequired, // should be string data type, must be present
    h2: PropTypes.string, // as above but optional
    paras: PropTypes.array, // should be array reference type
    buttonLink: PropTypes.string,
    buttonText: PropTypes.string,
    children: PropTypes.node, // can be anything (element, type, JSX) that is rendered to the screen
  };
  ```

  If one of these type checks failed you get a very semantic Warning in the
  console specifying which prop is not consistent with your prop type declaration.

  ## Additional checks

  Above are the most frequent and basic checks, but there are many other
  conditions you can check for:

  ```jsx
  // The full list of types
  [propName]: PropTypes.array,
  [propName]: PropTypes.bool,
  [propName]: PropTypes.func,
  [propName]: PropTypes.number,
  [propName]: PropTypes.object,
  [propName]: PropTypes.string,
  [propName]: PropTypes.symbol,

  // Anything that can be rendered: numbers, strings, elements or an arrayor fragment) containing these types.
  [propName]: PropTypes.node,

  // A function

  [propName]: PropTypes.func

  // An object that could be one of many types
  [objectProp]: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number,
    ]),

  // An array of a certain type
  [arrayProp]: PropTypes.arrayOf(PropTypes.number),

  // An object with property values of a certain type
  [objectProp]: PropTypes.objectOf(PropTypes.number),
  ```


path: Proper_shebang_syntax.md
sortable_path: Proper_shebang_syntax.md
title: Proper shebang syntax
checksum: edcb7998f0254eab27ba5419de171e27c3a25fc8f6863e4021a0bbb4a4fbbece
created: 2025-10-01 13:31:00.588766491+00:00
modified: 2025-08-13 15:57:13.748925088+00:00
metadata: {"tags":["shell"]}
lead:
  This is a more portable way of writing the shebang because the location of Bash
  on different systems can vary.

body:
  This is a more portable way of writing the shebang because the location of Bash
  on different systems can vary.

  ```bash
  #!/usr/bin/env Bash
  ```

  Rather than:

  ```bash
  #!/bin/bash
  ```

raw_content:
  ---
  tags:
    - shell
  ---

  # Proper shebang syntax

  This is a more portable way of writing the shebang because the location of Bash
  on different systems can vary.

  ```bash
  #!/usr/bin/env Bash
  ```

  Rather than:

  ```bash
  #!/bin/bash
  ```


path: Props_in_React.md
sortable_path: Props_in_React.md
title: Props
lead: ## Types or interfaces?
checksum: 5932443b8d7abf3608aa338b3410754fc1976a0a2fc49a45a3a865dba90389b0
created: 2025-10-01 13:31:00.593931663+00:00
modified: 2025-08-13 15:57:13.986714037+00:00
metadata: {"tags":["typescript","react"]}
body:
  ## Types or interfaces?

  They are mostly interchangeable but there are some specific differences

  ### Interfaces

  - Classes and other interfaces can extend an interface but not a type

    ```ts
    interface Animal {
      name: string;
    }

    interface Bear extends Animal {
      honey: boolean;
    }
    ```

  - You can add properties to an interface without generating a double declaration
    error:

    ```ts
    interface Window {
        }

    interface Window {
      ts: TypeScriptAPI;
    }
    ```

  ### Types

  You can create unions with types but not interfaces.

  > The consensus seems to be that interfaces should be used over types unless
  > there are ocassions when you do not want a type to be extendable /
  > redeclarable. Or when you want to use unions.

  ## How we type props

  The custom is to type props as an interface. This way we can easily type
  function prop types.

  ```tsx
  interface IProps {
    people: {
      name: string;
      age: number;
      note?: string;
    }[];
  }

  const List: React.FC<IProps> = ({people}: IProps) => {
      return()
  }

  // Note we say that the props into the func component are of type IProps
  // And we destructure the people key

  ```

  Then in the parent:

  ```tsx

  const [people, setPeople] = useState<IState['people']>({});

  <List props={people}>

  ```

  ## Common types for props

  ### Object with any number of properties

  ```tsx
  interface IProps {
    obj: {};
  }
  ```

  ### Array of objects

  ```tsx
  interface IProps {
    val1: string;
    val2: boolean;
  }
  [];
  ```

  ### Functions

  ```tsx

  // Function that doesn't receive or return anything
  interface IProps {
      onClick: () => void;
  }[]

  // Function with named parameter
  interface IProps {
      onClick: (id: number) => void;
  }[]

  // Function that takes an event
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
  ```

  ### Other React components

  ```js
  interface IProps {
    children: React.ReactNode;
  }

  interface IProps {
    children: JSX.Element;
  }
  ```

  `React.ReactNode` covers everything that React can render. This should be
  definitely used when the prop is a child component, otherwise `JSX.element` is
  ok.

  <p style="color: red;">Should I use type or interface? What is consensus?</p>

raw_content:
  ---
  tags:
    - typescript
    - react
  ---

  # Props

  ## Types or interfaces?

  They are mostly interchangeable but there are some specific differences

  ### Interfaces

  - Classes and other interfaces can extend an interface but not a type

    ```ts
    interface Animal {
      name: string;
    }

    interface Bear extends Animal {
      honey: boolean;
    }
    ```

  - You can add properties to an interface without generating a double declaration
    error:

    ```ts
    interface Window {
        }

    interface Window {
      ts: TypeScriptAPI;
    }
    ```

  ### Types

  You can create unions with types but not interfaces.

  > The consensus seems to be that interfaces should be used over types unless
  > there are ocassions when you do not want a type to be extendable /
  > redeclarable. Or when you want to use unions.

  ## How we type props

  The custom is to type props as an interface. This way we can easily type
  function prop types.

  ```tsx
  interface IProps {
    people: {
      name: string;
      age: number;
      note?: string;
    }[];
  }

  const List: React.FC<IProps> = ({people}: IProps) => {
      return()
  }

  // Note we say that the props into the func component are of type IProps
  // And we destructure the people key

  ```

  Then in the parent:

  ```tsx

  const [people, setPeople] = useState<IState['people']>({});

  <List props={people}>

  ```

  ## Common types for props

  ### Object with any number of properties

  ```tsx
  interface IProps {
    obj: {};
  }
  ```

  ### Array of objects

  ```tsx
  interface IProps {
    val1: string;
    val2: boolean;
  }
  [];
  ```

  ### Functions

  ```tsx

  // Function that doesn't receive or return anything
  interface IProps {
      onClick: () => void;
  }[]

  // Function with named parameter
  interface IProps {
      onClick: (id: number) => void;
  }[]

  // Function that takes an event
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
  ```

  ### Other React components

  ```js
  interface IProps {
    children: React.ReactNode;
  }

  interface IProps {
    children: JSX.Element;
  }
  ```

  `React.ReactNode` covers everything that React can render. This should be
  definitely used when the prop is a child component, otherwise `JSX.element` is
  ok.

  <p style="color: red;">Should I use type or interface? What is consensus?</p>


path: Prototypical_inheritance.md
sortable_path: Prototypical_inheritance.md
title: Prototypical inheritance
lead: ## Object oriented basis of JavaScript and nomenclature
checksum: b332dfadb655c7db9d31679a6ca1dc695fef44a404f9abc92e05b34c43b517a7
created: 2025-10-01 13:31:00.600260997+00:00
modified: 2025-08-13 15:57:14.041081061+00:00
metadata: {"tags":["javascript","OOP"]}
body:
  ## Object oriented basis of JavaScript and nomenclature

  As we know, everything in JS that isn't a primitive (i.e. a primitive data type:
  string, number, boolean, null) is an object. Where an object is a data structure
  that consists in key:value pairs.

  The key is always a string and the value can be: a primitive value, a method
  (function within an object), an array, another object etc.

  > In other object-oriented languages like C# and Java, **functions are called
  > methods** however in JS the term **method** is reserved for function that
  > exists as a property of an objects that contains it.

  ### Lack of classes in JS

  In contrast to more advanced object-oriented languages that are compiled (Java,
  C#), classes do not really exist in JavaScript. This is due to the
  prototype-based nature of JS (as we will see) however class-like functionality
  can be achieved through the use of functions.

  Remember in JS that functions can be simple code blocks that execute when called
  (which is what we mean most of the time by 'function') **or they can be
  constructor functions which create generic object types from which specific
  token instances can be generated as objects.**

  It is through these 'generic object types' that something akin to a class can be
  created in JavaScript. (These are sometimes called function-objects )

  The following is a good account of the differences between prototypal and
  class-based languages:

  > JavaScript is a prototype-based language, **meaning object properties and
  > methods can be shared through generalized objects that have the ability to be
  > cloned and extended**. This is known as **prototypical inheritance** and
  > differs from **class inheritance**. Among popular object-oriented programming
  > languages, JavaScript is relatively unique, as other prominent languages such
  > as PHP, Python, and Java are class-based languages, which instead **define
  > classes as blueprints for objects**.

  ### Example of a constructor function

  In order to understand prototypes in a moment, it will be helpful to have an
  example of a constructor function that can be used to generate object instances:

  ```jsx
  /* Create constructor function: */
  function Band(mainAlbum, subgenre) {
    // use Pascal for constructor function names
    this.mainAlbum = mainAlbum;
    this.subgenre = subgenre;
  }

  /* Then to create an object instance: */

  var slayer = new Band("Reign in Blood", "thrash metal");
  ```

  ## Prototypes

  Now that we know class-type functionality enters JS via constructor functions
  and we have an example, we can look at prototypes.

  > Prototypes are a special type of object that exist as a property within
  > function-objects.

  Whenever we create an instance-object from constructor function using `new`, the
  object is given a property with the key `_proto_` . It's value is the
  `[[prototype]]` property of the function that created, i.e the class of which
  the object is an instance:

  ```jsx
  {
    _proto_: prototype;
  }
  ```

  Note that we use the syntax `[[prototype]]` to indicate that **whilst the value
  exists, it is not accessible via JavaScript code**, in the manner of a normal
  object-literal or function-object, because it is the lower-level foundation of
  first-order JS code.

  So how would this work for the `slayer` object we created above?

  ```jsx
  Slayer._proto_ === Band.prototype;
  ```

  The thing is, you do not tend to see this prototype functionality and it is not
  possible to refer to it as a key:value directly. This is because it is something
  under-the-hood - it is a process that makes the object-oriented aspects of JS
  possible but it is not apparent on the first-order level of everyday coding.

  The prototype is like a hidden hook that facilitates the generation of objects
  from class-like constructor functions. With our new awareness of it, we are in a
  position _to understand how JavaScript works in foundational terms._

  ## Every non-primitive data type in JS possesses the `Object` prototype

  The title above indicates how and why JavaScript establishes its object-oriented
  data structure.

  When we create an object literal (i.e an every day object not a class-like
  function), under-the-hood JS is making a `new Object()` call in much the same
  way as we are calling the function-object `Band` when we declare
  `var slayer = new Band(...)` .

  All instance-objects in JavaScript (which, remember is the set of everything
  that is not a primitive) **inherit from the `Object` keyword**. And, to do this,
  prototypes are necessary. Now we see how integral prototypes are to JavaScript.

  ### Examples

  Here we create an object-literal and uncover how it has it's basis in the
  overall `Object` constructor.

  ```jsx
  var slayerMembers = {
    bassist: "Tom Araya",
    guitarist: "Kerry King",
    guitarist: "Jeff Hanneman",
    drummer: "Dave Lombardo",
  };

  //  slayerMembers._proto_ === Object.prototype
  ```

  Here we create an instance-object off of our `Band` constructor function and
  trace it back to `Object`

  ```jsx
  var deicide = new Band("Legion", "death metal");

  /* deicide object relies on Band prototype:
  		
  		deicide._proto_=== Band.prototype

  Band prototype in turn relies in turn on Object prototype: 

   Band.prototype._proto_=== Object.prototype

  */
  ```

  As the above examples show, ultimately all objects in JavaScript (whether
  variables, arrays, methods, or functions) eventually lead back to
  `Object.prototype` .

  ### How the browser uses prototypes when interpreting code

  When the browser interprets your code attempting to access a property or method
  of an object it runs through the following process:

  1. Search on the object itself. If fails →
  2. Search the object's prototype. If fails →
  3. Search the prototype of the linked object. If fails→
  4. Keep going until `Object.prototype` is reached

  Clearly with each step we are going to a lower level of abstraction, drawing the
  curtain back more and more until we got the point where JavaScript effectively
  stops because any lower would take you into its lower-level parent language
  (C/C++ depending on how the specific browser executes ECMAScript)

  Note (3) is basically the prototype of the component itself. So if you started
  at (1) with a custom array. At (3) the browser would be querying
  `Array.prototype` i.e the basic foundational array object.

  This explains why the full-name of certain methods on the global objects,
  includes reference to 'prototype', for instance:

  - `toFixed` → `Number.prototype.toFixed()`
  - `.trim` → `String.prototype.trim()`.

  ### Using the function-object of `Object` to create an object literal

  As a side-effect of uncovering the prototypical basis of `Object()` we can use
  it to create an object literal in another way.

  Standardly to create a new, empty object literal we would use:

  ```jsx
  var slayerMembers = {...}
  ```

  But now we could just as easily direct the code to `Object()` prototype and
  achieve the same outcome:

  ```jsx
  let slayerMembers = new Object();
  ```

  ### Finding the `[[Prototype]]` of a JS object with `getPrototypeOf()`

  We can find out the `[[prototype]]` of a given object in JavaScript with a
  special method applied to the object in question. The method we use is one of
  the inherent methods that belong to the `Object()` constructor function:
  `getPrototypeOf()` .

  Here is an example:

  ```jsx
  console.log(Object.getPrototypeOf(slayer));

  /*

  Returns: 

  Object {constructor: , __defineGetter__: ,
   __defineSetter__: , hasOwnProperty: , __lookupGetter__: , …}

  */
  ```

  We could also use the following approach to get the same output however this is
  not recommended for production:

  ```jsx
  console.log(slayer.__prototype__);
  ```

  The output we get when querying the prototype is the same in each instance.

  ## But why bother using prototypes in your code?

  It is informative to learn how prototypes are behind the object behaviour we
  observe at a high level in JavaScript and to know that there is a common,
  lower-level root but when would you actually need to use prototype methods?

  The reason is mainly to do with performance and optimisation

  > When we create a `deicide` and `slayer` object using the constructor function
  > `Band()` JS creates two _copies_ of the constructor function, one for each
  > generated object. This means there are two instances of `mainAlbum` for each
  > object even though each do exactly the same thing. This wastes memory and
  > performance time every time the script runs.

  As a prototype object is an object, we can attach properties and methods to the
  prototype object. Thus, enabling all the objects created using the constructor
  function to share those properties and methods. However, the beauty is that the
  method is applied to the prototype, so it is only stored in the memory once, but
  every instance of the object has access to it.

  ```jsx
  /* So say I wanted to add an age property to the Band()constructor that all objects of this type have access to. I could do this without wasting memory and without the need to change the original constructor function by referring to the prototype: */

  Band.prototype.age = null;

  Slayer.age = 25;
  ```

  ## Further steps

  We are going to stop here for the time being since the primary aim of uncovering
  prototypes and understanding how they underly all objects and object methods in
  JS has been achieved.

  However it is important to note that there is more that you can do with
  prototypes. The main additional thing is using the prototypical basis of
  constructor functions (i.e pseudo-classes) to add and remove key value pairs in
  the resulting objects. This is useful when you want to create behaviour that is
  much more like classes in compiled OOP languages.

raw_content:
  ---
  tags: [javascript, OOP]
  ---

  # Prototypical inheritance

  ## Object oriented basis of JavaScript and nomenclature

  As we know, everything in JS that isn't a primitive (i.e. a primitive data type:
  string, number, boolean, null) is an object. Where an object is a data structure
  that consists in key:value pairs.

  The key is always a string and the value can be: a primitive value, a method
  (function within an object), an array, another object etc.

  > In other object-oriented languages like C# and Java, **functions are called
  > methods** however in JS the term **method** is reserved for function that
  > exists as a property of an objects that contains it.

  ### Lack of classes in JS

  In contrast to more advanced object-oriented languages that are compiled (Java,
  C#), classes do not really exist in JavaScript. This is due to the
  prototype-based nature of JS (as we will see) however class-like functionality
  can be achieved through the use of functions.

  Remember in JS that functions can be simple code blocks that execute when called
  (which is what we mean most of the time by 'function') **or they can be
  constructor functions which create generic object types from which specific
  token instances can be generated as objects.**

  It is through these 'generic object types' that something akin to a class can be
  created in JavaScript. (These are sometimes called function-objects )

  The following is a good account of the differences between prototypal and
  class-based languages:

  > JavaScript is a prototype-based language, **meaning object properties and
  > methods can be shared through generalized objects that have the ability to be
  > cloned and extended**. This is known as **prototypical inheritance** and
  > differs from **class inheritance**. Among popular object-oriented programming
  > languages, JavaScript is relatively unique, as other prominent languages such
  > as PHP, Python, and Java are class-based languages, which instead **define
  > classes as blueprints for objects**.

  ### Example of a constructor function

  In order to understand prototypes in a moment, it will be helpful to have an
  example of a constructor function that can be used to generate object instances:

  ```jsx
  /* Create constructor function: */
  function Band(mainAlbum, subgenre) {
    // use Pascal for constructor function names
    this.mainAlbum = mainAlbum;
    this.subgenre = subgenre;
  }

  /* Then to create an object instance: */

  var slayer = new Band("Reign in Blood", "thrash metal");
  ```

  ## Prototypes

  Now that we know class-type functionality enters JS via constructor functions
  and we have an example, we can look at prototypes.

  > Prototypes are a special type of object that exist as a property within
  > function-objects.

  Whenever we create an instance-object from constructor function using `new`, the
  object is given a property with the key `_proto_` . It's value is the
  `[[prototype]]` property of the function that created, i.e the class of which
  the object is an instance:

  ```jsx
  {
    _proto_: prototype;
  }
  ```

  Note that we use the syntax `[[prototype]]` to indicate that **whilst the value
  exists, it is not accessible via JavaScript code**, in the manner of a normal
  object-literal or function-object, because it is the lower-level foundation of
  first-order JS code.

  So how would this work for the `slayer` object we created above?

  ```jsx
  Slayer._proto_ === Band.prototype;
  ```

  The thing is, you do not tend to see this prototype functionality and it is not
  possible to refer to it as a key:value directly. This is because it is something
  under-the-hood - it is a process that makes the object-oriented aspects of JS
  possible but it is not apparent on the first-order level of everyday coding.

  The prototype is like a hidden hook that facilitates the generation of objects
  from class-like constructor functions. With our new awareness of it, we are in a
  position _to understand how JavaScript works in foundational terms._

  ## Every non-primitive data type in JS possesses the `Object` prototype

  The title above indicates how and why JavaScript establishes its object-oriented
  data structure.

  When we create an object literal (i.e an every day object not a class-like
  function), under-the-hood JS is making a `new Object()` call in much the same
  way as we are calling the function-object `Band` when we declare
  `var slayer = new Band(...)` .

  All instance-objects in JavaScript (which, remember is the set of everything
  that is not a primitive) **inherit from the `Object` keyword**. And, to do this,
  prototypes are necessary. Now we see how integral prototypes are to JavaScript.

  ### Examples

  Here we create an object-literal and uncover how it has it's basis in the
  overall `Object` constructor.

  ```jsx
  var slayerMembers = {
    bassist: "Tom Araya",
    guitarist: "Kerry King",
    guitarist: "Jeff Hanneman",
    drummer: "Dave Lombardo",
  };

  //  slayerMembers._proto_ === Object.prototype
  ```

  Here we create an instance-object off of our `Band` constructor function and
  trace it back to `Object`

  ```jsx
  var deicide = new Band("Legion", "death metal");

  /* deicide object relies on Band prototype:
  		
  		deicide._proto_=== Band.prototype

  Band prototype in turn relies in turn on Object prototype: 

   Band.prototype._proto_=== Object.prototype

  */
  ```

  As the above examples show, ultimately all objects in JavaScript (whether
  variables, arrays, methods, or functions) eventually lead back to
  `Object.prototype` .

  ### How the browser uses prototypes when interpreting code

  When the browser interprets your code attempting to access a property or method
  of an object it runs through the following process:

  1. Search on the object itself. If fails →
  2. Search the object's prototype. If fails →
  3. Search the prototype of the linked object. If fails→
  4. Keep going until `Object.prototype` is reached

  Clearly with each step we are going to a lower level of abstraction, drawing the
  curtain back more and more until we got the point where JavaScript effectively
  stops because any lower would take you into its lower-level parent language
  (C/C++ depending on how the specific browser executes ECMAScript)

  Note (3) is basically the prototype of the component itself. So if you started
  at (1) with a custom array. At (3) the browser would be querying
  `Array.prototype` i.e the basic foundational array object.

  This explains why the full-name of certain methods on the global objects,
  includes reference to 'prototype', for instance:

  - `toFixed` → `Number.prototype.toFixed()`
  - `.trim` → `String.prototype.trim()`.

  ### Using the function-object of `Object` to create an object literal

  As a side-effect of uncovering the prototypical basis of `Object()` we can use
  it to create an object literal in another way.

  Standardly to create a new, empty object literal we would use:

  ```jsx
  var slayerMembers = {...}
  ```

  But now we could just as easily direct the code to `Object()` prototype and
  achieve the same outcome:

  ```jsx
  let slayerMembers = new Object();
  ```

  ### Finding the `[[Prototype]]` of a JS object with `getPrototypeOf()`

  We can find out the `[[prototype]]` of a given object in JavaScript with a
  special method applied to the object in question. The method we use is one of
  the inherent methods that belong to the `Object()` constructor function:
  `getPrototypeOf()` .

  Here is an example:

  ```jsx
  console.log(Object.getPrototypeOf(slayer));

  /*

  Returns: 

  Object {constructor: , __defineGetter__: ,
   __defineSetter__: , hasOwnProperty: , __lookupGetter__: , …}

  */
  ```

  We could also use the following approach to get the same output however this is
  not recommended for production:

  ```jsx
  console.log(slayer.__prototype__);
  ```

  The output we get when querying the prototype is the same in each instance.

  ## But why bother using prototypes in your code?

  It is informative to learn how prototypes are behind the object behaviour we
  observe at a high level in JavaScript and to know that there is a common,
  lower-level root but when would you actually need to use prototype methods?

  The reason is mainly to do with performance and optimisation

  > When we create a `deicide` and `slayer` object using the constructor function
  > `Band()` JS creates two _copies_ of the constructor function, one for each
  > generated object. This means there are two instances of `mainAlbum` for each
  > object even though each do exactly the same thing. This wastes memory and
  > performance time every time the script runs.

  As a prototype object is an object, we can attach properties and methods to the
  prototype object. Thus, enabling all the objects created using the constructor
  function to share those properties and methods. However, the beauty is that the
  method is applied to the prototype, so it is only stored in the memory once, but
  every instance of the object has access to it.

  ```jsx
  /* So say I wanted to add an age property to the Band()constructor that all objects of this type have access to. I could do this without wasting memory and without the need to change the original constructor function by referring to the prototype: */

  Band.prototype.age = null;

  Slayer.age = 25;
  ```

  ## Further steps

  We are going to stop here for the time being since the primary aim of uncovering
  prototypes and understanding how they underly all objects and object methods in
  JS has been achieved.

  However it is important to note that there is more that you can do with
  prototypes. The main additional thing is using the prototypical basis of
  constructor functions (i.e pseudo-classes) to add and remove key value pairs in
  the resulting objects. This is useful when you want to create behaviour that is
  much more like classes in compiled OOP languages.


path: Proxies.md
sortable_path: Proxies.md
title: Proxies
checksum: c9e57817c83a63911f8dbce2a5d9d6b49013996b0a74b9880930cae767f789a7
created: 2025-10-01 13:31:00.60611277+00:00
modified: 2025-08-13 15:57:13.745946105+00:00
metadata: {"created":"Monday, February 03, 2025","tags":["networks","proxies"]}
lead:
  A standard proxy stands as a blocking layer between a client and a server. A
  client makes a request to a server but before it reaches it, it is intercepted
  by a proxy that reviews the request and decides whether to pass on to the
  requested location.

body:
  A standard proxy stands as a blocking layer between a client and a server. A
  client makes a request to a server but before it reaches it, it is intercepted
  by a proxy that reviews the request and decides whether to pass on to the
  requested location.

  As such, from the server's point of view, the request comes from the proxy not
  the client.

  An example application would be organisations who want to monitor or filter
  their employees web activities.

  A **reverse proxy** has the opposite orientation. It acts as buffer between a
  server and a client, filtering the requests that are sent to a server.

  This can also be for reasons of security, but most typically a reverse-proxy is
  used to manage requests to different services that a server is running.

  If a client requests `service-a.some-server/slug` the request is sent to the
  proxy operating at the root level, it siphons the request to its intended
  sub-service (`service-a`) and the port this service is running on.

  So, from the point of view of Service A, the request doesn't come from the
  external client but from the reverse proxy.

  In addition to directing traffic, reverse proxies can also implement load
  balancing: running procedures that ensure traffic is met at times of high
  capacity, ensuring that the server's resources are not exhausted.

raw_content:
  ---
  tags: [networks, proxies]
  created: Monday, February 03, 2025
  ---

  # Proxies

  A standard proxy stands as a blocking layer between a client and a server. A
  client makes a request to a server but before it reaches it, it is intercepted
  by a proxy that reviews the request and decides whether to pass on to the
  requested location.

  As such, from the server's point of view, the request comes from the proxy not
  the client.

  An example application would be organisations who want to monitor or filter
  their employees web activities.

  A **reverse proxy** has the opposite orientation. It acts as buffer between a
  server and a client, filtering the requests that are sent to a server.

  This can also be for reasons of security, but most typically a reverse-proxy is
  used to manage requests to different services that a server is running.

  If a client requests `service-a.some-server/slug` the request is sent to the
  proxy operating at the root level, it siphons the request to its intended
  sub-service (`service-a`) and the port this service is running on.

  So, from the point of view of Service A, the request doesn't come from the
  external client but from the reverse proxy.

  In addition to directing traffic, reverse proxies can also implement load
  balancing: running procedures that ensure traffic is met at times of high
  capacity, ensuring that the server's resources are not exhausted.


path: Public_key_cryptography.md
sortable_path: Public_key_cryptography.md
title: bbdcb54f_public_key_cryptography
checksum: c03f7d29fb3b86739ddab99d4d1e7c9f10bab31461cc9b6c3fe2f90f27c281fb
created: 2025-10-01 13:31:00.615608567+00:00
modified: 2025-08-13 15:57:13.740401446+00:00
metadata: {"created":"Friday, December 20, 2024","tags":["encryption","cryptography"]}
lead:
  _A_ wants to send a message to _B_. A wants to ensure that only _B_ can read the
  message and that it is not intercepted or altered during transmission to _B_.

body:
  _A_ wants to send a message to _B_. A wants to ensure that only _B_ can read the
  message and that it is not intercepted or altered during transmission to _B_.

  Think of _B_ as being in possession of a letterbox. The letterbox contains
  messages that only he can read. Anyone can put letters in it for _B_ to read but
  _B_ alone can read them.

  This is achieved by encyrpting the messages with two keys: a public key and a
  private key. The public key can be shared with others and anyone in possession
  of the public key can encrypt a message for _B_. Once encrypted, only _B_ can
  decrypt it using his private key. Once receiving the message, B uses his private
  secret key - that he doesn't share with anyone else - to decrypt. This is the
  equivalent to opening up the letterbox and taking out the letters.

  Another useful analogy is to think of invisible ink. Anyone can write a letter
  using the invisible ink but only the recipient has the liquid that can render it
  visible again. Anyone intercepting the message (without the liquid) will see
  nothing, equivalent to the encrypted data.

  This is asymmetric encryption because the two communicating parties do not have
  equal access to the messages exchanged. _A_ can only send messages - he can't
  decrypt them, only _B_ can. So _A_ is unequal relative to _B_. With symmetric
  encryption _A_ and _B_ would both share a single private key which they would
  each use to encrypt and decrypt their messages.

raw_content:
  ---
  tags: [encryption, cryptography]
  created: Friday, December 20, 2024
  ---

  # bbdcb54f_public_key_cryptography

  _A_ wants to send a message to _B_. A wants to ensure that only _B_ can read the
  message and that it is not intercepted or altered during transmission to _B_.

  Think of _B_ as being in possession of a letterbox. The letterbox contains
  messages that only he can read. Anyone can put letters in it for _B_ to read but
  _B_ alone can read them.

  This is achieved by encyrpting the messages with two keys: a public key and a
  private key. The public key can be shared with others and anyone in possession
  of the public key can encrypt a message for _B_. Once encrypted, only _B_ can
  decrypt it using his private key. Once receiving the message, B uses his private
  secret key - that he doesn't share with anyone else - to decrypt. This is the
  equivalent to opening up the letterbox and taking out the letters.

  Another useful analogy is to think of invisible ink. Anyone can write a letter
  using the invisible ink but only the recipient has the liquid that can render it
  visible again. Anyone intercepting the message (without the liquid) will see
  nothing, equivalent to the encrypted data.

  This is asymmetric encryption because the two communicating parties do not have
  equal access to the messages exchanged. _A_ can only send messages - he can't
  decrypt them, only _B_ can. So _A_ is unequal relative to _B_. With symmetric
  encryption _A_ and _B_ would both share a single private key which they would
  each use to encrypt and decrypt their messages.


path: Push_buttons.md
sortable_path: Push_buttons.md
title: Push buttons
checksum: 04e804313c68988cb974b6293dd1807087288f983f73cecf701708e088b5522b
created: 2025-10-01 13:31:00.623517654+00:00
modified: 2025-08-13 15:57:13.822972918+00:00
metadata: {"created":"Tuesday, June 25, 2024","id":"nsrv","tags":["electronics"]}
lead:
  Push buttons are push-to-make switches. This means that they are **on when they
  pressed and off when they are not pressed**. A classic example would be the
  switches on a keyboard.

body:
  Push buttons are push-to-make switches. This means that they are **on when they
  pressed and off when they are not pressed**. A classic example would be the
  switches on a keyboard.

  Push buttons have four legs that are connected in signal-in and signal-out
  pairs.

  To create a breakable circuit we would connect a signal-in cable to the top left
  at row 23 and a signal-out cable to the bottom-right at row 25.

  ![Push button legs diagram](../img/push-button-legs.png)

  _The correct use of a push button where the button breaks the circuit_

  ![](../img/correct_push_button.jpg)

  To override the switch functionality and just have the button work as a
  connector we would connect the signal-in to the row 23 input and the row 23
  output.

  _The push button being used as simple connector which does not break the
  circuit:_

  ![](../img/incorrect_push_button.jpg)

  ## Related notes

  https://projects.raspberrypi.org/en/projects/button-switch-scratch-pi/1

raw_content:
  ---
  id: nsrv
  tags: [electronics]
  created: Tuesday, June 25, 2024
  ---

  # Push buttons

  Push buttons are push-to-make switches. This means that they are **on when they
  pressed and off when they are not pressed**. A classic example would be the
  switches on a keyboard.

  Push buttons have four legs that are connected in signal-in and signal-out
  pairs.

  To create a breakable circuit we would connect a signal-in cable to the top left
  at row 23 and a signal-out cable to the bottom-right at row 25.

  ![Push button legs diagram](../img/push-button-legs.png)

  _The correct use of a push button where the button breaks the circuit_

  ![](../img/correct_push_button.jpg)

  To override the switch functionality and just have the button work as a
  connector we would connect the signal-in to the row 23 input and the row 23
  output.

  _The push button being used as simple connector which does not break the
  circuit:_

  ![](../img/incorrect_push_button.jpg)

  ## Related notes

  https://projects.raspberrypi.org/en/projects/button-switch-scratch-pi/1


path: Python_application_structure.md
sortable_path: Python_application_structure.md
title: Python application structure
lead: ## Directory layout
checksum: 49847157a3a69633258b7d00d93230bf9d910ce35d8d9c93ba462884d16c2071
created: 2025-10-01 13:31:00.629541358+00:00
modified: 2025-08-13 15:57:13.854385364+00:00
metadata: {"created":"Tuesday, August 27, 2024","tags":["python"]}
body:
  ## Directory layout

  ```
  src/
      cli.py OR app.py
      constants.py
      __init__.py
  tests/
  requirements.txt
  setup.py
  ```

  ## `requirements.txt`

  Dependencies used within the venv for the project, e.g:

  ```
  google-auth==1.35.0
  google-auth-httplib2==0.1.0
  google-auth-oauthlib==0.4.6
  google-api-python-client==2.26.1
  gspread==3.7.0
  requests==2.25.1
  oauth2client==4.1.3
  ```

  ## `setup.py`

  The declaration file for the application, equivalent to `package.json`, e.g:

  ```py
  from setuptools import setup, find_packages

  setup(
      name="eolas-db",
      version="0.1",
      packages=find_packages(where="src"),
      package_dir={"": "src"},
      install_requires=[
          # List your project dependencies here
      ],
      entry_points={
          "console_scripts": [
              "eolas-db=cli:main",
          ],
      },
  )
  ```

  The `entry_points` key is important. This is the first execution point of the
  application. Typically you would name your entry-point script as `app.py` or
  `cli.py` and then specify its `main` function.

  E.g. in `cli.py`:

  ```py
  def main():
      print('run the application')

  if __name__ == "__main__":
      main()

  ```

  ## `__init__.py`

  See
  [[Python_modules_and_imports#distinguishing-_modules_-from-_packages_]]|Python
  modules]]

raw_content:
  ---
  tags: [python]
  created: Tuesday, August 27, 2024
  ---

  # Python application structure

  ## Directory layout

  ```
  src/
      cli.py OR app.py
      constants.py
      __init__.py
  tests/
  requirements.txt
  setup.py
  ```

  ## `requirements.txt`

  Dependencies used within the venv for the project, e.g:

  ```
  google-auth==1.35.0
  google-auth-httplib2==0.1.0
  google-auth-oauthlib==0.4.6
  google-api-python-client==2.26.1
  gspread==3.7.0
  requests==2.25.1
  oauth2client==4.1.3
  ```

  ## `setup.py`

  The declaration file for the application, equivalent to `package.json`, e.g:

  ```py
  from setuptools import setup, find_packages

  setup(
      name="eolas-db",
      version="0.1",
      packages=find_packages(where="src"),
      package_dir={"": "src"},
      install_requires=[
          # List your project dependencies here
      ],
      entry_points={
          "console_scripts": [
              "eolas-db=cli:main",
          ],
      },
  )
  ```

  The `entry_points` key is important. This is the first execution point of the
  application. Typically you would name your entry-point script as `app.py` or
  `cli.py` and then specify its `main` function.

  E.g. in `cli.py`:

  ```py
  def main():
      print('run the application')

  if __name__ == "__main__":
      main()

  ```

  ## `__init__.py`

  See
  [[Python_modules_and_imports#distinguishing-_modules_-from-_packages_]]|Python
  modules]]


path: Python_data_types.md
sortable_path: Python_data_types.md
title: Python data-types
checksum: 87a8e9b94c5a6050161b68234964ee99022aef37f835f759d55a650977ba7b2f
created: 2025-10-01 13:31:00.652307775+00:00
modified: 2025-08-13 15:57:13.982666576+00:00
metadata: {"tags":["python","data-types"]}
lead:
  - Python is dynamically typed rather than untyped. It updates the types on the
    fly as you are writing your code.
  - Type-hints in the editor like `-> str` mean "at the moment it is a string". It
    doesn't mean you can't redefine the value as something else.
  - Each data type in Python inherits off of a built-in class, similar to
    prototypes in JS

body:
  - Python is dynamically typed rather than untyped. It updates the types on the
    fly as you are writing your code.
  - Type-hints in the editor like `-> str` mean "at the moment it is a string". It
    doesn't mean you can't redefine the value as something else.
  - Each data type in Python inherits off of a built-in class, similar to
    prototypes in JS

  The core data-types are as follows:

  - [str](Strings_in_Python.md)
  - bool
  - float
  - double

  We can identify types using the built-in `type()` function:

  ```python
  # Integer number
  my_variable = 422
  print(my_variable)
  print(type(my_variable))
  # <class 'int'>

  # String type
  my_variable = 'Natalia'
  print(my_variable)
  print(type(my_variable))
  # <class 'str'>

  # Boolean type
  my_variable = True
  print(my_variable)
  print(type(my_variable))
  # <class 'bool'>
  ```

  ## Converting data-types

  For every data-type there is a corresponding converter method, e.g:

  ```python
  a_string = '32'
  print(f'a_string {a_string} is {type(a_string)}')
  an_int = int(a_string)

  print(f'an_int {a_string} is {type(an_int)}')
  a_float = float(a_string)

  print(f'a_float {a_string} is {type(a_float)}')
  another_string = str(42)

  print(f'another_string {a_string} is {type(another_string)}')
  ```

raw_content:
  ---
  tags: [python, data-types]
  ---

  # Python data-types

  - Python is dynamically typed rather than untyped. It updates the types on the
    fly as you are writing your code.
  - Type-hints in the editor like `-> str` mean "at the moment it is a string". It
    doesn't mean you can't redefine the value as something else.
  - Each data type in Python inherits off of a built-in class, similar to
    prototypes in JS

  The core data-types are as follows:

  - [str](Strings_in_Python.md)
  - bool
  - float
  - double

  We can identify types using the built-in `type()` function:

  ```python
  # Integer number
  my_variable = 422
  print(my_variable)
  print(type(my_variable))
  # <class 'int'>

  # String type
  my_variable = 'Natalia'
  print(my_variable)
  print(type(my_variable))
  # <class 'str'>

  # Boolean type
  my_variable = True
  print(my_variable)
  print(type(my_variable))
  # <class 'bool'>
  ```

  ## Converting data-types

  For every data-type there is a corresponding converter method, e.g:

  ```python
  a_string = '32'
  print(f'a_string {a_string} is {type(a_string)}')
  an_int = int(a_string)

  print(f'an_int {a_string} is {type(an_int)}')
  a_float = float(a_string)

  print(f'a_float {a_string} is {type(a_float)}')
  another_string = str(42)

  print(f'another_string {a_string} is {type(another_string)}')
  ```


path: Python_execution.md
sortable_path: Python_execution.md
title: Python execution
lead: For immediately executable scripts, we have to have a Python shebang at the top:
checksum: 30db233c5b46a73df2c5ab204f80b8f28ab8e94586db8ea06e7bcbe8cb0c090c
created: 2025-10-01 13:31:00.66598719+00:00
modified: 2025-08-13 15:57:14.067491705+00:00
metadata: {"tags":["python","data-types"]}
body:
  For immediately executable scripts, we have to have a Python shebang at the top:

  ```
  #! /usr/local/bin/python3
  ```

  With programs we can just run the `main` file with `python main.py`.

raw_content:
  ---
  tags: [python, data-types]
  ---

  # Python execution

  For immediately executable scripts, we have to have a Python shebang at the top:

  ```
  #! /usr/local/bin/python3
  ```

  With programs we can just run the `main` file with `python main.py`.


path: Python_interpreter.md
sortable_path: Python_interpreter.md
title: Python interpreter
lead: ## What is an implementation of a programming language?
checksum: 76b7b7c27f575074f2e906518a4155469c62525b955059dce6f9d22f5e9046eb
created: 2025-10-01 13:31:00.671466504+00:00
modified: 2025-08-13 15:57:13.815019389+00:00
metadata: {"tags":["python"]}
body:
  ## What is an implementation of a programming language?

  An implementation of Python:

  > means a program or environment which provides support for the execution of
  > programs written in the Python language

  As Python is interpreted, any implementation will perforce involve an
  interpreting language.

  There are three main implementations:

  - CPython
    - The default implementation, written in C
  - Jython
    - Python implemented by Java and running on the JVM
  - PyPy
    - A subset of Python which is faster due to machine code compilation

  ## CPython

  In the standard implementation, the language which interprets Python code is C.

  When Python runs in this implementation, code written in C converts it to
  bytecode (so-called because each instruction is
  [8-bits long](Binary_units_of_measurement.md)). This is a
  lower-level transliteration of Python is not meant to be understood by the CPU
  (since it is not binary) but rather to be run in the Python virtual machine
  which is equipped to understand bytecode. The Python Virtual Machine is
  therefore also known as "bytecode interpreter" or the CPython VM. The VM then
  converts bytecode into machine-executable code.

  The fact that Python does not compile to binary means that it can run on a
  greater variety of hardwares however it is slower than a language that compiles
  to machine code. PyPy is a solution for this because it is both interpreted and
  compiled to optimised machine code at run time.

  Where CPython is the interpreter, Python extensions can be written in C.

  ## PyPy

  PyPy is an alternative implementation to CPython. The main difference is that it
  uses a JIT-compiler and doesn't convert Python to the intermediary byte code. It
  is also written in Python itself, specifically RPython ('restricted Python').
  This is capable of converting Python directly to machine code without the
  CPython virtual machine.

  ## Jython

  Jython is an implementation of Python written in Java. Like CPython it converts
  Python to bytecode but this runs on the JVM. As it is written in Java, a Jython
  program can import and use any Java class.

  Where Jython is the interpreter, Python extension can be written in Java.

raw_content:
  ---
  tags: [python]
  ---

  # Python interpreter

  ## What is an implementation of a programming language?

  An implementation of Python:

  > means a program or environment which provides support for the execution of
  > programs written in the Python language

  As Python is interpreted, any implementation will perforce involve an
  interpreting language.

  There are three main implementations:

  - CPython
    - The default implementation, written in C
  - Jython
    - Python implemented by Java and running on the JVM
  - PyPy
    - A subset of Python which is faster due to machine code compilation

  ## CPython

  In the standard implementation, the language which interprets Python code is C.

  When Python runs in this implementation, code written in C converts it to
  bytecode (so-called because each instruction is
  [8-bits long](Binary_units_of_measurement.md)). This is a
  lower-level transliteration of Python is not meant to be understood by the CPU
  (since it is not binary) but rather to be run in the Python virtual machine
  which is equipped to understand bytecode. The Python Virtual Machine is
  therefore also known as "bytecode interpreter" or the CPython VM. The VM then
  converts bytecode into machine-executable code.

  The fact that Python does not compile to binary means that it can run on a
  greater variety of hardwares however it is slower than a language that compiles
  to machine code. PyPy is a solution for this because it is both interpreted and
  compiled to optimised machine code at run time.

  Where CPython is the interpreter, Python extensions can be written in C.

  ## PyPy

  PyPy is an alternative implementation to CPython. The main difference is that it
  uses a JIT-compiler and doesn't convert Python to the intermediary byte code. It
  is also written in Python itself, specifically RPython ('restricted Python').
  This is capable of converting Python directly to machine code without the
  CPython virtual machine.

  ## Jython

  Jython is an implementation of Python written in Java. Like CPython it converts
  Python to bytecode but this runs on the JVM. As it is written in Java, a Jython
  program can import and use any Java class.

  Where Jython is the interpreter, Python extension can be written in Java.


path: Python_modules_and_imports.md
sortable_path: Python_modules_and_imports.md
title: Python modules
lead: ## Distinguishing _modules_ from _packages_
checksum: c8d45e1dabc5ec3c2d533fd819b72a8b38b47d7f12b3614dc0e4c5e3835581d2
created: 2025-10-01 13:31:00.682412722+00:00
modified: 2025-08-13 15:57:13.791612165+00:00
metadata: {"tags":["python","OOP"]}
body:
  ## Distinguishing _modules_ from _packages_

  Modules and packages in Python are very similar to modules in Node.js: a
  combination of several pieces of functionality (often written in a mix of
  different syntactic styles) bundled together to be used as a unit.

  - A **module** is basically just a script - a single Python file that you can
    import using the `import` statement
  - A **package** is a _collection of modules_

  A package is a whole directory which has an `__init__.py` at its root which
  designates it as a package (this can be empty, but it is necessary to have this
  file for the interpreter to understand that the directory is a package).

  ## Creating modules

  ### Naming modules

  The name of a module is the name of its file, e.g. `utils.py` defines the module
  `utils`. When we import a module we do not need to specify the extension.

  ### Example module

  Here is an example of a module.

  ```py
  """utils module"""

  print('Hello I am the utils module')


  def printer(some_object):
      print('printer')
      print(some_object)
      print('done')


  class Shape:

      def __init__(self, id):
          self.id = id

      def __str__(self):
          return 'Shape - ' + self.id


  default_shape = Shape('square')


  def _special_function():
      print('Special function')

  ```

  ## Importing modules

  > Whether we are importing our own local module, a third-party module or a
  > built-in module native to Python, the syntax is the same.

  - If the module is in the same directory as the file you wish to import it into,
    you can just directly import with:
    ```py
    import utils
    utils.specialFunction
    shape = utils.Shape('circle')
    ```
  - If the module you want to import is in a subdirectory, you will need to make
    that subdirectory a package in order to be able to import from it. This means
    adding an `__init__.py`. Then you can use the following import syntax:
    ```py
    from subdir import utils
    ...
    ```

  ### Different import syntax

  - If you don't want to have to prepend the imported module's name when using it
    (e.g. `utils.specialFunction`). You can import like so:

    ```py
    from utils import *
    specialFunction()
    ```

  - By default an import makes everything in the module available, however you can
    choose to import only a subset. E.g.:
    ```py
    from utils import Shape
    #  or with an alias:
    from utils import Shape as lorem
    ```

  ## `__main__`

  The `__main__` attribute is important in Python.

  ### Usage in scripts/modules

  When you run a script (module) Python assigns the string `__main__` to the
  `__name__` attribute to the script that is being executed.

  If you run the script as an import into another script, the `__name__` attribute
  of the imported module is set to the module name, not `__main__`. This is why,
  when we import we say `import [module_name]` and not `import __main__`.

  When used with a module, `__main__` indicates code that should be run straight
  away when the given script file is run. You won't always want to execute
  everything in the module file on execution so you can put this stuff outside of
  `__main__`

  Typically you will only want immediate execution to happen when **the module is
  the entrypoint** to the program.

  We indicate this with `__main__` as follows:

  ```py
  if __name__ == "__main__":
      print("This runs only if the module is the main module")
  ```

  ### Usage in packages

  The only real difference with packages is that you can also define a
  `__main__.py` file in the root of the package directory.

  This functions in the same manner as `__main__` in an individual module however
  this time it is not the entry point for a single script but the entrypoint of
  the package as a whole.

  > When the package is run directly as a script, the code in `__main__.py` is
  > executed, just like it would be if it were a standalone script. This allows a
  > package to be run as a script, as well as letting it contain modules that can
  > be imported separately.

  You can of course still have individual entrypoints for the modules that
  comprise the package.

  ### Running the package as a package

  If you want to run the whole package at once, rather than individually importing
  the modules that belong to it. You can run the following from the command-line:

  ```
  python -m package_name
  ```

  With this, Python will try to locate the `__main__.py` file and execute it as
  though it were a standalone script.

  ### Using a `main()` function

  To ensure that certain code runs on initialisation we can define a special
  `main` function or class method that runs when the module or package is
  loaded.We would put the main set-up logic in `main` and coordinate the execution
  of the module or package through it.

  ```py
  def main():
      printer(default_shape)
      shape = Shape("circle")
      printer(shape)

  if __name__ == "__main__":
      main()
  ```

  ### Example

  ```py
  '''palindrome module'''

  def is_palindrome(inp):
      inp_list = list(inp)
      inp_list_len = len(inp_list)
      for i in range(inp_list_len):
          if inp_list[i] != inp_list[inp_list_len - 1 - i]:
              return False
      return True


  def main():
      palindrome_one = "soros"
      palindrome_two = "torot"
      not_palindrome = "chair"

      print(is_palindrome(palindrome_one))
      print(is_palindrome(palindrome_two))
      print(is_palindrome(not_palindrome))


  if __name__ == '__main__':
      main()
  ```

raw_content:
  ---
  tags: [python, OOP]
  ---

  # Python modules

  ## Distinguishing _modules_ from _packages_

  Modules and packages in Python are very similar to modules in Node.js: a
  combination of several pieces of functionality (often written in a mix of
  different syntactic styles) bundled together to be used as a unit.

  - A **module** is basically just a script - a single Python file that you can
    import using the `import` statement
  - A **package** is a _collection of modules_

  A package is a whole directory which has an `__init__.py` at its root which
  designates it as a package (this can be empty, but it is necessary to have this
  file for the interpreter to understand that the directory is a package).

  ## Creating modules

  ### Naming modules

  The name of a module is the name of its file, e.g. `utils.py` defines the module
  `utils`. When we import a module we do not need to specify the extension.

  ### Example module

  Here is an example of a module.

  ```py
  """utils module"""

  print('Hello I am the utils module')


  def printer(some_object):
      print('printer')
      print(some_object)
      print('done')


  class Shape:

      def __init__(self, id):
          self.id = id

      def __str__(self):
          return 'Shape - ' + self.id


  default_shape = Shape('square')


  def _special_function():
      print('Special function')

  ```

  ## Importing modules

  > Whether we are importing our own local module, a third-party module or a
  > built-in module native to Python, the syntax is the same.

  - If the module is in the same directory as the file you wish to import it into,
    you can just directly import with:
    ```py
    import utils
    utils.specialFunction
    shape = utils.Shape('circle')
    ```
  - If the module you want to import is in a subdirectory, you will need to make
    that subdirectory a package in order to be able to import from it. This means
    adding an `__init__.py`. Then you can use the following import syntax:
    ```py
    from subdir import utils
    ...
    ```

  ### Different import syntax

  - If you don't want to have to prepend the imported module's name when using it
    (e.g. `utils.specialFunction`). You can import like so:

    ```py
    from utils import *
    specialFunction()
    ```

  - By default an import makes everything in the module available, however you can
    choose to import only a subset. E.g.:
    ```py
    from utils import Shape
    #  or with an alias:
    from utils import Shape as lorem
    ```

  ## `__main__`

  The `__main__` attribute is important in Python.

  ### Usage in scripts/modules

  When you run a script (module) Python assigns the string `__main__` to the
  `__name__` attribute to the script that is being executed.

  If you run the script as an import into another script, the `__name__` attribute
  of the imported module is set to the module name, not `__main__`. This is why,
  when we import we say `import [module_name]` and not `import __main__`.

  When used with a module, `__main__` indicates code that should be run straight
  away when the given script file is run. You won't always want to execute
  everything in the module file on execution so you can put this stuff outside of
  `__main__`

  Typically you will only want immediate execution to happen when **the module is
  the entrypoint** to the program.

  We indicate this with `__main__` as follows:

  ```py
  if __name__ == "__main__":
      print("This runs only if the module is the main module")
  ```

  ### Usage in packages

  The only real difference with packages is that you can also define a
  `__main__.py` file in the root of the package directory.

  This functions in the same manner as `__main__` in an individual module however
  this time it is not the entry point for a single script but the entrypoint of
  the package as a whole.

  > When the package is run directly as a script, the code in `__main__.py` is
  > executed, just like it would be if it were a standalone script. This allows a
  > package to be run as a script, as well as letting it contain modules that can
  > be imported separately.

  You can of course still have individual entrypoints for the modules that
  comprise the package.

  ### Running the package as a package

  If you want to run the whole package at once, rather than individually importing
  the modules that belong to it. You can run the following from the command-line:

  ```
  python -m package_name
  ```

  With this, Python will try to locate the `__main__.py` file and execute it as
  though it were a standalone script.

  ### Using a `main()` function

  To ensure that certain code runs on initialisation we can define a special
  `main` function or class method that runs when the module or package is
  loaded.We would put the main set-up logic in `main` and coordinate the execution
  of the module or package through it.

  ```py
  def main():
      printer(default_shape)
      shape = Shape("circle")
      printer(shape)

  if __name__ == "__main__":
      main()
  ```

  ### Example

  ```py
  '''palindrome module'''

  def is_palindrome(inp):
      inp_list = list(inp)
      inp_list_len = len(inp_list)
      for i in range(inp_list_len):
          if inp_list[i] != inp_list[inp_list_len - 1 - i]:
              return False
      return True


  def main():
      palindrome_one = "soros"
      palindrome_two = "torot"
      not_palindrome = "chair"

      print(is_palindrome(palindrome_one))
      print(is_palindrome(palindrome_two))
      print(is_palindrome(not_palindrome))


  if __name__ == '__main__':
      main()
  ```


path: Python_package_management.md
sortable_path: Python_package_management.md
title: Package management
checksum: c2bb4284c280771e4178377e2944b67dcb6349f760178ef81060f6bbd62e3534
created: 2025-10-01 13:31:00.687650398+00:00
modified: 2025-08-13 15:57:13.770918821+00:00
metadata: {"tags":["python","data-types"]}
lead:
  - You can use `conda` (the package manager that comes with `anaconda`). This
    makes it easier to work with conflicting package libraries (a bit like a
    package lock).

body:
  - You can use `conda` (the package manager that comes with `anaconda`). This
    makes it easier to work with conflicting package libraries (a bit like a
    package lock).

  - The alternative is the native `pip` but you have to create virtual
    environments (`venv`) to manage packages at different versions.

  ## venv

  To make use of virtual environments in `pip` you have to create the virtual
  environment before installing anything:

  ```
  python3 -m venv venv
  ```

  This will create a `venv` directory in your project that will manage the
  handling of modules.

  > This is especially important in ArchLinux since without a virtual environment
  > it will ask you to install packages with `pacman` which is annoying for local
  > packages.

  You then activate the environment with:

  ```
  source venv3/bin/activate
  ```

  Now you can install packages:

  ```
  pip [library_name]
  ```

  ### Using venv after a system upgrade

  If you update your system's version of Python, this can cause `venv` to stop
  working. Resolve as follows:

  ```
  deactivate  # leave venv env if in it
  rm -rf venv  # remove venv
  python -m venv venv # reinstall venv
  source venv/bin/activate
  python -m ensurepip --upgrade # explicitly install pip
  pip install - e.
  ```

  ## requirements.txt

  The `requirements.txt` file is similar to the `package.json` in Node projects.

  Each line of the `requirements.txt`` file specifies a package that your project
  depends on and, optionally, the desired version of that package. When you share
  your project with others or move it between different environments (e.g., from
  development to production), this file makes it easy to set up your environment
  with the right dependencies.

  ### Example

  ```
  Flask==1.1.2
  requests>=2.24.0
  numpy~=1.19.2
  pandas
  ```

  ### Generate requirements file

  ```
  pip freeze > requirements.txt

  ```

  ## Pypy

  - pypi.org is package registry like NPM

raw_content:
  ---
  tags: [python, data-types]
  ---

  # Package management

  - You can use `conda` (the package manager that comes with `anaconda`). This
    makes it easier to work with conflicting package libraries (a bit like a
    package lock).

  - The alternative is the native `pip` but you have to create virtual
    environments (`venv`) to manage packages at different versions.

  ## venv

  To make use of virtual environments in `pip` you have to create the virtual
  environment before installing anything:

  ```
  python3 -m venv venv
  ```

  This will create a `venv` directory in your project that will manage the
  handling of modules.

  > This is especially important in ArchLinux since without a virtual environment
  > it will ask you to install packages with `pacman` which is annoying for local
  > packages.

  You then activate the environment with:

  ```
  source venv3/bin/activate
  ```

  Now you can install packages:

  ```
  pip [library_name]
  ```

  ### Using venv after a system upgrade

  If you update your system's version of Python, this can cause `venv` to stop
  working. Resolve as follows:

  ```
  deactivate  # leave venv env if in it
  rm -rf venv  # remove venv
  python -m venv venv # reinstall venv
  source venv/bin/activate
  python -m ensurepip --upgrade # explicitly install pip
  pip install - e.
  ```

  ## requirements.txt

  The `requirements.txt` file is similar to the `package.json` in Node projects.

  Each line of the `requirements.txt`` file specifies a package that your project
  depends on and, optionally, the desired version of that package. When you share
  your project with others or move it between different environments (e.g., from
  development to production), this file makes it easy to set up your environment
  with the right dependencies.

  ### Example

  ```
  Flask==1.1.2
  requests>=2.24.0
  numpy~=1.19.2
  pandas
  ```

  ### Generate requirements file

  ```
  pip freeze > requirements.txt

  ```

  ## Pypy

  - pypi.org is package registry like NPM


path: Querying_a_Mongo_collection.md
sortable_path: Querying_a_Mongo_collection.md
title: Query a Mongo collection with Mongoose
lead: We now have the following entries in our `courses` collection:
checksum: f4ac5106a9a718493ccba4d322bf1aff6ee105a11d648db5e50ffee8b902e7d7
created: 2025-10-01 13:31:00.692497421+00:00
modified: 2025-08-13 15:57:13.956475232+00:00
metadata: {"tags":["mongo-db","node-js","mongoose","databases"]}
body:
  We now have the following entries in our `courses` collection:

  ```js
  {
    name: 'Python Course',
    author: 'Terry Ogleton',
    tags: [ 'python', 'backend' ],
    isPublished: true,
    _id: new ObjectId("62f4e2527ac4aa2c30d41d23"),
    date: 2022-08-11T11:04:50.750Z,
    __v: 0
  }

  {
    name: 'Javascript Course',
    author: 'Tosh Gnomay',
    tags: [ 'js', 'frontend' ],
    isPublished: true,
    _id: new ObjectId("62f4e2527ac4aa2c30d41d24"),
    date: 2022-08-11T11:04:50.750Z,
    __v: 0
  }

  ```

  Now we will query the collection. This capability is provided via the Mongoose
  schema class we used to create the `Course`
  [model](Create_collections_and_documents_with_Mongoose.md#models).
  We have the following methods available to use from the schema:

  - `find`
  - `findById`
  - `findByIdAndRemove`
  - `findByIdAndUpdate`
  - `findOne`
  - `findOneAndUpdate`
  - `findOneAndRemove`
  - ...

  The various `find` methods return a value that is promisified.

  ## Return values with `find`

  ```js
  async function getCourses() {
    const courses = await Course.find();
    console.log(courses);
  }
  ```

  ## Filter values returned

  This will return all the published courses where Tosh Gnomay is the author:

  ```js
  async function getCourses() {
    const courses = await Course.find({
      author: "Tosh Gnomay",
      isPublished: true,
    });
    console.log(courses);
  }
  ```

  This time we will filter by the same author but we will add additional
  parameters to distinguish:

  - only the first ten entries (using `.limit(10)`)
  - sort ascending by name (using `.sort({name: 1}))` , to descend we would use
    `-1`)
  - only return the properties `name` and `tags` for the item in the collection
    (using `.select({name: 1, tags: 1})`)

  ```js
  async function getCourses() {
    const courses = await Course.find({
      author: "Tosh Gnomay",
      isPublished: true,
    })
      .limit(10)
      .sort({ name: 1 })
      .select({ name: 1, tags: 1 });
    console.log(courses);
  }
  ```

  This returns:

  ```js
  [
    {
      _id: new ObjectId("62f4f07a875cff48827b8731"),
      name: "Java Course",
      tags: ["java", "backend"],
    },
    {
      _id: new ObjectId("62f4e2527ac4aa2c30d41d24"),
      name: "Javascript Course",
      tags: ["js", "frontend"],
    },
  ];
  ```

  > Note that the UUID is always returned, whether we specify it or not.

  ## Querying with operators

  So far when filtering we have been doing so with reference to properties that
  exist on the document's model (`author`, `isPublished` etc) and we have applied
  tranformations on the data returned (sorting, limiting the number or matches
  etc.). However we can also apply **operators** within our queries. Operators
  allow us to perform computations on the data, for example: for a given numerical
  property on an object, return the objects for which this value is within a
  certain range.

  When we apply operators we use the `$` symbol before the operator and pass the
  operator function as an object.

  The schema:

  ```
  Model.find( { property: { $operator: conditions } } )
  ```

  ### Comparison operators

  The following comparison operators are available in MongoDB:

  | Operator | Function                  |
  | -------- | ------------------------- |
  | `eq`     | Equal to                  |
  | `ne`     | Not equal to              |
  | `gt`     | Greater than              |
  | `gte`    | Greater than or less than |
  | `lt`     | Less than                 |
  | `lte`    | Less than or equal to     |
  | `in`     | In                        |
  | `nin`    | Not in                    |

  We can employ these comparators within a `.find` filter. For example let's
  imagine that our `courses` instances have a property of `price`.

  To filter course prices that are greater than or equal to 10 and less than or
  equal to 29:

  ```js
  Course.find({ price: { $gte: 10, $lte: 20 } });
  ```

  To filter course prices that are either 10, 15 or 20:

  ```js
  Course.find({ price: { $in: [10, 15, 20] } });
  ```

  ### Logical operators

  When we apply logical operators, we do not apply the query within the main
  `find` method. We use a dedicated method that corresponds to the logical
  predicate.

  For example to query by logical
  [OR](Truth-functional_connectives.md#disjunction):

  ```js
  async function getCourses() {
    const courses = await Course.find().or([
      { author: "Tosh Gnomay" },
      { isPublished: true },
    ]);
    console.log(courses);
  }
  ```

  We write each disjunct as an object representing the conditions we are filtering
  for within an array that is passed to the `.or()` method.

  The same syntax applies for conjunction.

  ### Regular expressions

  When filtering by strings we can use Regex for greater power.

  Previously we filtered by the author name:

  ```js
  .find({author: "Tosh Gnomay"})
  ```

  To demonstrate regex we could filter by names beginning with `T`:

  ```js
  .find({author: /^T*/})
  ```

  ```js
  async function getCourses() {
    const courses = await Course.find()
      .or([{ author: "Tosh Gnomay" }, { isPublished: true }])
      .count();
    console.log(courses);
  }
  ```

  This will return a number.

  ### Pagination

  We previously used the `limit()` method to control how many matches we return
  from a query. We can extend this functionality by creating pagination. This
  allows us to meter the return values into set chunks. This is used frequently
  when interacting with a database through a mediating RESTful API. For example to
  return values from endpoints such as:

  ```
  /api/courses?pageNumber=2&pageSize=10
  ```

  To do this you pass two values as query parameters

  ```js
  const pageNumber = 2;
  const pageSize = 10;

  async function getCourses() {
    const courses = await Course.find()
      .skip(pageNumber - 1 * pageSize)
      .limit(pageSize);
    console.log(courses);
  }
  ```

raw_content:
  ---
  tags:
    - mongo-db
    - node-js
    - mongoose
    - databases
  ---

  # Query a Mongo collection with Mongoose

  We now have the following entries in our `courses` collection:

  ```js
  {
    name: 'Python Course',
    author: 'Terry Ogleton',
    tags: [ 'python', 'backend' ],
    isPublished: true,
    _id: new ObjectId("62f4e2527ac4aa2c30d41d23"),
    date: 2022-08-11T11:04:50.750Z,
    __v: 0
  }

  {
    name: 'Javascript Course',
    author: 'Tosh Gnomay',
    tags: [ 'js', 'frontend' ],
    isPublished: true,
    _id: new ObjectId("62f4e2527ac4aa2c30d41d24"),
    date: 2022-08-11T11:04:50.750Z,
    __v: 0
  }

  ```

  Now we will query the collection. This capability is provided via the Mongoose
  schema class we used to create the `Course`
  [model](Create_collections_and_documents_with_Mongoose.md#models).
  We have the following methods available to use from the schema:

  - `find`
  - `findById`
  - `findByIdAndRemove`
  - `findByIdAndUpdate`
  - `findOne`
  - `findOneAndUpdate`
  - `findOneAndRemove`
  - ...

  The various `find` methods return a value that is promisified.

  ## Return values with `find`

  ```js
  async function getCourses() {
    const courses = await Course.find();
    console.log(courses);
  }
  ```

  ## Filter values returned

  This will return all the published courses where Tosh Gnomay is the author:

  ```js
  async function getCourses() {
    const courses = await Course.find({
      author: "Tosh Gnomay",
      isPublished: true,
    });
    console.log(courses);
  }
  ```

  This time we will filter by the same author but we will add additional
  parameters to distinguish:

  - only the first ten entries (using `.limit(10)`)
  - sort ascending by name (using `.sort({name: 1}))` , to descend we would use
    `-1`)
  - only return the properties `name` and `tags` for the item in the collection
    (using `.select({name: 1, tags: 1})`)

  ```js
  async function getCourses() {
    const courses = await Course.find({
      author: "Tosh Gnomay",
      isPublished: true,
    })
      .limit(10)
      .sort({ name: 1 })
      .select({ name: 1, tags: 1 });
    console.log(courses);
  }
  ```

  This returns:

  ```js
  [
    {
      _id: new ObjectId("62f4f07a875cff48827b8731"),
      name: "Java Course",
      tags: ["java", "backend"],
    },
    {
      _id: new ObjectId("62f4e2527ac4aa2c30d41d24"),
      name: "Javascript Course",
      tags: ["js", "frontend"],
    },
  ];
  ```

  > Note that the UUID is always returned, whether we specify it or not.

  ## Querying with operators

  So far when filtering we have been doing so with reference to properties that
  exist on the document's model (`author`, `isPublished` etc) and we have applied
  tranformations on the data returned (sorting, limiting the number or matches
  etc.). However we can also apply **operators** within our queries. Operators
  allow us to perform computations on the data, for example: for a given numerical
  property on an object, return the objects for which this value is within a
  certain range.

  When we apply operators we use the `$` symbol before the operator and pass the
  operator function as an object.

  The schema:

  ```
  Model.find( { property: { $operator: conditions } } )
  ```

  ### Comparison operators

  The following comparison operators are available in MongoDB:

  | Operator | Function                  |
  | -------- | ------------------------- |
  | `eq`     | Equal to                  |
  | `ne`     | Not equal to              |
  | `gt`     | Greater than              |
  | `gte`    | Greater than or less than |
  | `lt`     | Less than                 |
  | `lte`    | Less than or equal to     |
  | `in`     | In                        |
  | `nin`    | Not in                    |

  We can employ these comparators within a `.find` filter. For example let's
  imagine that our `courses` instances have a property of `price`.

  To filter course prices that are greater than or equal to 10 and less than or
  equal to 29:

  ```js
  Course.find({ price: { $gte: 10, $lte: 20 } });
  ```

  To filter course prices that are either 10, 15 or 20:

  ```js
  Course.find({ price: { $in: [10, 15, 20] } });
  ```

  ### Logical operators

  When we apply logical operators, we do not apply the query within the main
  `find` method. We use a dedicated method that corresponds to the logical
  predicate.

  For example to query by logical
  [OR](Truth-functional_connectives.md#disjunction):

  ```js
  async function getCourses() {
    const courses = await Course.find().or([
      { author: "Tosh Gnomay" },
      { isPublished: true },
    ]);
    console.log(courses);
  }
  ```

  We write each disjunct as an object representing the conditions we are filtering
  for within an array that is passed to the `.or()` method.

  The same syntax applies for conjunction.

  ### Regular expressions

  When filtering by strings we can use Regex for greater power.

  Previously we filtered by the author name:

  ```js
  .find({author: "Tosh Gnomay"})
  ```

  To demonstrate regex we could filter by names beginning with `T`:

  ```js
  .find({author: /^T*/})
  ```

  ```js
  async function getCourses() {
    const courses = await Course.find()
      .or([{ author: "Tosh Gnomay" }, { isPublished: true }])
      .count();
    console.log(courses);
  }
  ```

  This will return a number.

  ### Pagination

  We previously used the `limit()` method to control how many matches we return
  from a query. We can extend this functionality by creating pagination. This
  allows us to meter the return values into set chunks. This is used frequently
  when interacting with a database through a mediating RESTful API. For example to
  return values from endpoints such as:

  ```
  /api/courses?pageNumber=2&pageSize=10
  ```

  To do this you pass two values as query parameters

  ```js
  const pageNumber = 2;
  const pageSize = 10;

  async function getCourses() {
    const courses = await Course.find()
      .skip(pageNumber - 1 * pageSize)
      .limit(pageSize);
    console.log(courses);
  }
  ```


path: Queue.md
sortable_path: Queue.md
title: Queues
lead: _Visualization of the queue data structure_
checksum: 07770787a6624e0fccf35e0a770a641009f179bfe320a3ef9237fe7dcdc9210f
created: 2025-10-01 13:31:00.721140417+00:00
modified: 2025-08-13 15:57:13.768552705+00:00
metadata: {"tags":["data-structures"]}
body:
  _Visualization of the queue data structure_

  ![queue.svg](queue.svg)

  ## A queue is a sequential data structure and most similar to a stack

  A queue is basically a stack inverted and can be visualised as a line of people
  waiting to be served. The person that is first into the queue is served first.
  The people who join the queue behind this person will be served after them.

  As a result it can be summarised as **'first in, first out'** or FIFO.

  Just like a stack it is a sequential data structure without random access. You
  cannot access all the elements at one instant, you can only access the oldest
  element. If you wish to access the newest element, you have to move through all
  the others that are ahead of it first, at which point it becomes the oldest.

  It differs from a stack in that a stack only has one point of transaction: the
  front or 'top' of the stack. With a stack you add and remove from the top or
  front. With a queue, you have two points of transaction: the front of the queue
  for removing elements and the back of the queue for adding elements.

  We can however add a 'peek' method to see which is the next element in line to
  come out.

  As we are removing the first element added, we use an `array shift` method to
  remove items from the front of the array.

  Removing an element from the queue is called **dequeuing**. Adding an element to
  the queue is called **enqueuing**. In terms of the tail/head nomenclature, the
  end of the queue where elements are enqueued is the **tail** and front of the
  queue, where elements are removed is the **head**.

  ```js
  class Queue {
    items = []; // array to store the elements comprising the queue
    enqueue = (element) => this.items.push(element); // add element to back
    dequeue = () => this.items.shift(); // remove element from the front

    // Optional helper methods:
    isEmpty = () => this.items.length === 0; // return true if the queue is empty
    clear = () => (this.items.length = 0); // empty the queue
    size = () => this.items.length; // count elements in queue
    peek = () => (!this.isEmpty() ? this.items[0] : undefined); // check which element is next in line
  }
  ```

  ## Use cases

  - A queue sequences data in the order that it was first received. Thus it is
    most beneficial in scenarios where receipt time is a factor. For example,
    imagine a service whereby tickets go on sale at a certain time for a limited
    period. You may want to prioritise those who sent their payment earliest over
    those who arrived later.
  - Serving requests on a single shared resource like a printer or CPU task
    scheduling.

raw_content:
  ---
  tags:
    - data-structures
  ---

  # Queues

  _Visualization of the queue data structure_

  ![queue.svg](queue.svg)

  ## A queue is a sequential data structure and most similar to a stack

  A queue is basically a stack inverted and can be visualised as a line of people
  waiting to be served. The person that is first into the queue is served first.
  The people who join the queue behind this person will be served after them.

  As a result it can be summarised as **'first in, first out'** or FIFO.

  Just like a stack it is a sequential data structure without random access. You
  cannot access all the elements at one instant, you can only access the oldest
  element. If you wish to access the newest element, you have to move through all
  the others that are ahead of it first, at which point it becomes the oldest.

  It differs from a stack in that a stack only has one point of transaction: the
  front or 'top' of the stack. With a stack you add and remove from the top or
  front. With a queue, you have two points of transaction: the front of the queue
  for removing elements and the back of the queue for adding elements.

  We can however add a 'peek' method to see which is the next element in line to
  come out.

  As we are removing the first element added, we use an `array shift` method to
  remove items from the front of the array.

  Removing an element from the queue is called **dequeuing**. Adding an element to
  the queue is called **enqueuing**. In terms of the tail/head nomenclature, the
  end of the queue where elements are enqueued is the **tail** and front of the
  queue, where elements are removed is the **head**.

  ```js
  class Queue {
    items = []; // array to store the elements comprising the queue
    enqueue = (element) => this.items.push(element); // add element to back
    dequeue = () => this.items.shift(); // remove element from the front

    // Optional helper methods:
    isEmpty = () => this.items.length === 0; // return true if the queue is empty
    clear = () => (this.items.length = 0); // empty the queue
    size = () => this.items.length; // count elements in queue
    peek = () => (!this.isEmpty() ? this.items[0] : undefined); // check which element is next in line
  }
  ```

  ## Use cases

  - A queue sequences data in the order that it was first received. Thus it is
    most beneficial in scenarios where receipt time is a factor. For example,
    imagine a service whereby tickets go on sale at a certain time for a limited
    period. You may want to prioritise those who sent their payment earliest over
    those who arrived later.
  - Serving requests on a single shared resource like a printer or CPU task
    scheduling.


path: Quote_marks_in_Bash.md
sortable_path: Quote_marks_in_Bash.md
title: Quote marks in Bash
lead: ## Single-quotes (aka _strong_ quotes)
checksum: 9a8b2de955dcbf7f9a4a1cd5944dfd9aaf4e40a8d3eb764f5759eae1c1f39d51
created: 2025-10-01 13:31:00.727554545+00:00
modified: 2025-08-13 15:57:13.858166037+00:00
metadata: {"tags":["shell"]}
body:
  ## Single-quotes (aka _strong_ quotes)

  Bash will interpret everything in the string as a literal:

  ```bash
  echo 'The directory is $(pwd)'
  # The directory is $(pwd)
  ```

  ## Double-quotes

  Bash will interpret strings as strings but will interpret expansions and
  substitutions as executable processes:

  ```bash
  $pointlessVar='directory'

  echo "The ${pointlessVar}"

  # The directory is /home/thomas
  ```

  It is therefore generally best to use double quotes whenever we wish to return
  mixed values.

raw_content:
  ---
  tags:
    - shell
  ---

  # Quote marks in Bash

  ## Single-quotes (aka _strong_ quotes)

  Bash will interpret everything in the string as a literal:

  ```bash
  echo 'The directory is $(pwd)'
  # The directory is $(pwd)
  ```

  ## Double-quotes

  Bash will interpret strings as strings but will interpret expansions and
  substitutions as executable processes:

  ```bash
  $pointlessVar='directory'

  echo "The ${pointlessVar}"

  # The directory is /home/thomas
  ```

  It is therefore generally best to use double quotes whenever we wish to return
  mixed values.


path: RESTful_APIs.md
sortable_path: RESTful_APIs.md
title: RESTful APIs
lead: ## Definition of an API
checksum: facc11be40d1315db02b61b5b886a72db631eb09de9e4aa7aeeb283823c7b63a
created: 2025-10-01 13:31:00.732980249+00:00
modified: 2025-08-13 15:57:13.799485257+00:00
metadata: {"tags":["APIs","REST"]}
body:
  ## Definition of an API

  An application programming interface (API) is a set of definitions and protocols
  for building and integrating application software. It can be thought of as a
  contract between an information provider and an informational consumer. The API
  is a mediator between the clients and the resources they wish to acquire from a
  server or database.

  ## REST

  REST stands for **Representational State Transfer**. It is a set of
  _architectural constraints_ on the structure of an API rather than a fixed
  protocol. It is a particular way of implementing client-server interaction over
  HTTP.

  When a request is made from a client to resources via RESTful API, the API
  transfers a representation of of the state of the resource to the requester or
  endpoint. The information is delivered via HTTP. The format can be of several
  types (HTML, XML, plaintext, Python, PHP etc) but is generally JSON because of
  its broad compatibility with multiple programming languages.

  ### Key constraints

  In order to qualify as RESTful, an API must meet the following constraints:

  1. **Uniform interface**: Possess a client-server architecture with request
     manage through HTTP
  1. **Client-server decoupling** : The client and server applications must be
     completely independent of one another. The _only_ information the client
     should know about the server is the URI it uses to request the resource, it
     can't interact with the server in any other way. Likewise, the server
     shouldn't modify the client application in any way (contrast for example SSR)
     other than passing the requested data via HTTP.
  1. **Statelessness** Server applications should not be able to store any data
     related to a client request. The request alone should contain all the
     information necessary for processing it, without recourse to any specifics of
     the client application. For example, a specification of POST with a certain
     JSON body and header authentication will be all that is provided to the
     server.
  1. **Cacheability** Where possible, resources should be cacheable on the client
     or server side. Server responses must contain information about whether
     caching is allowed for the delivered resource (you see this in the headers in
     the DevTools console). The goal here is to improve performance on the client
     side whilst increasing scaleability on the server side.
  1. **Layered system architecture** It may be the case that the data flow between
     the client and the server is not direct. For instance the request may be
     funneled through middleware or another program before it is received by the
     server. Similarly there may be several steps before the client receives the
     requested data. Whilst one should not assume a direct correspondence, REST
     APIs need to be designed so that neither the client nor the server can tell
     whether it communicates with the end application or an intermediary.

  ## Example

  A basic example of a REST API would be a series of methods corresponding to the
  main [HTTP request types](HTTP_request_types.md).

  | HTTP request type | URI                 | Action                      | Body ?                   |
  | ----------------- | ------------------- | --------------------------- | ------------------------ |
  | GET               | /api/customers      | Retrieve customers as array | No                       |
  | GET               | /api/customers/guid | Get a specific customer     | No, data comes from GUID |
  | PUT               | /api/customers/guid | Update an existing customer | Yes                      |
  | DELETE            | /api/customers/1    | Delete a customer           | No, data comes from GUID |
  | POST              | /api/customers      | Create a new customer       | Yes                      |

  // Add: PATCH and explain differenct from PUT

raw_content:
  ---
  tags: [APIs, REST]
  ---

  # RESTful APIs

  ## Definition of an API

  An application programming interface (API) is a set of definitions and protocols
  for building and integrating application software. It can be thought of as a
  contract between an information provider and an informational consumer. The API
  is a mediator between the clients and the resources they wish to acquire from a
  server or database.

  ## REST

  REST stands for **Representational State Transfer**. It is a set of
  _architectural constraints_ on the structure of an API rather than a fixed
  protocol. It is a particular way of implementing client-server interaction over
  HTTP.

  When a request is made from a client to resources via RESTful API, the API
  transfers a representation of of the state of the resource to the requester or
  endpoint. The information is delivered via HTTP. The format can be of several
  types (HTML, XML, plaintext, Python, PHP etc) but is generally JSON because of
  its broad compatibility with multiple programming languages.

  ### Key constraints

  In order to qualify as RESTful, an API must meet the following constraints:

  1. **Uniform interface**: Possess a client-server architecture with request
     manage through HTTP
  1. **Client-server decoupling** : The client and server applications must be
     completely independent of one another. The _only_ information the client
     should know about the server is the URI it uses to request the resource, it
     can't interact with the server in any other way. Likewise, the server
     shouldn't modify the client application in any way (contrast for example SSR)
     other than passing the requested data via HTTP.
  1. **Statelessness** Server applications should not be able to store any data
     related to a client request. The request alone should contain all the
     information necessary for processing it, without recourse to any specifics of
     the client application. For example, a specification of POST with a certain
     JSON body and header authentication will be all that is provided to the
     server.
  1. **Cacheability** Where possible, resources should be cacheable on the client
     or server side. Server responses must contain information about whether
     caching is allowed for the delivered resource (you see this in the headers in
     the DevTools console). The goal here is to improve performance on the client
     side whilst increasing scaleability on the server side.
  1. **Layered system architecture** It may be the case that the data flow between
     the client and the server is not direct. For instance the request may be
     funneled through middleware or another program before it is received by the
     server. Similarly there may be several steps before the client receives the
     requested data. Whilst one should not assume a direct correspondence, REST
     APIs need to be designed so that neither the client nor the server can tell
     whether it communicates with the end application or an intermediary.

  ## Example

  A basic example of a REST API would be a series of methods corresponding to the
  main [HTTP request types](HTTP_request_types.md).

  | HTTP request type | URI                 | Action                      | Body ?                   |
  | ----------------- | ------------------- | --------------------------- | ------------------------ |
  | GET               | /api/customers      | Retrieve customers as array | No                       |
  | GET               | /api/customers/guid | Get a specific customer     | No, data comes from GUID |
  | PUT               | /api/customers/guid | Update an existing customer | Yes                      |
  | DELETE            | /api/customers/1    | Delete a customer           | No, data comes from GUID |
  | POST              | /api/customers      | Create a new customer       | Yes                      |

  // Add: PATCH and explain differenct from PUT


path: ROM_versus_disk_loading.md
sortable_path: ROM_versus_disk_loading.md
title: ROM versus disk loading
checksum: f12aa9254eb7ecf2c9c48b2957218ddc91aa497e6babda04ce7811a64e14c47c
created: 2025-10-01 13:31:00.743545109+00:00
modified: 2025-08-13 15:57:14.036860908+00:00
metadata: {"created":"Monday, June 24, 2024","id":"rmvm","tags":["computer-architecture","memory"]}
lead:
  I will explore the concept via the practical examples of cartridge-based and
  disk-based video games console.

body:
  I will explore the concept via the practical examples of cartridge-based and
  disk-based video games console.

  When you insert a disk into an Xbox, the game data is typically read from the
  disk and transferred into the console's memory by the OS. If the game is
  installed to the hard drive, this initially involves transferring substantial
  amounts of data to speed up future access. When you insert a cartridge into a
  console like the SNES, the data is not transferred in the same way. Instead, the
  cartridge contains a ROM chip that, when inserted, integrates directly with the
  motherboard. From the operating system’s point of view, this ROM chip behaves as
  an extension of the system’s memory architecture.

  The primary advantage of a ROM-based game is significantly reduced latency. The
  game data can be accessed as rapidly as any other data moving along the buses of
  the motherboard. With a disk, the data must first be read into a buffer and then
  transferred to a memory address where it can be accessed by the CPU.

  With a ROM, while the console CPU still uses its own RAM to run the game
  (similar to disk-based systems), the game data on the ROM can be loaded into
  this RAM more quickly because it is directly attached to the motherboard. This
  makes the ROM cartridge effectively a fast, directly connected storage device.

  However, despite its speed, the limitation of a ROM cartridge is its storage
  capacity—it can hold only as much data as the chip can accommodate. In contrast,
  a disk can store much more data. This larger storage capacity allows not just
  for bigger and more complex games but also for the possibility of expanding the
  game through additional data downloaded to the console's hard drive. Such
  expansions or patches represent additional data from the console’s storage that,
  combined with the original disk data, are synthesized in memory at runtime for
  enhanced or updated gameplay experiences.

  (Note however that modern cartridge-based consoles like the Nintendo Switch can
  also combine ROM-data with expanded data from the console HDD, sourced from the
  internet.)

  Both disks and ROMs are forms of static storage in the context of a game
  console. While disks can technically be overwritten with new data, in practice,
  manufacturers implement various locks and protections to prevent this. Any
  changes or additions to the game, such as patches or expansions, are not written
  back to the original disk. Instead, these updates are stored on the console's
  hard drive.

  Therefore, if you download an expansion for a game on your Xbox, the original
  disk remains unchanged as when you first purchased it. Consequently, if you were
  to take that disk and load it on another Xbox, it would not include any of the
  expansions or updates. The game would function in its original form, as the
  additional content and updates reside solely on the hard drive of the first
  console where they were downloaded.

  ## Related notes

raw_content:
  ---
  id: rmvm
  tags: [computer-architecture, memory]
  created: Monday, June 24, 2024
  ---

  # ROM versus disk loading

  I will explore the concept via the practical examples of cartridge-based and
  disk-based video games console.

  When you insert a disk into an Xbox, the game data is typically read from the
  disk and transferred into the console's memory by the OS. If the game is
  installed to the hard drive, this initially involves transferring substantial
  amounts of data to speed up future access. When you insert a cartridge into a
  console like the SNES, the data is not transferred in the same way. Instead, the
  cartridge contains a ROM chip that, when inserted, integrates directly with the
  motherboard. From the operating system’s point of view, this ROM chip behaves as
  an extension of the system’s memory architecture.

  The primary advantage of a ROM-based game is significantly reduced latency. The
  game data can be accessed as rapidly as any other data moving along the buses of
  the motherboard. With a disk, the data must first be read into a buffer and then
  transferred to a memory address where it can be accessed by the CPU.

  With a ROM, while the console CPU still uses its own RAM to run the game
  (similar to disk-based systems), the game data on the ROM can be loaded into
  this RAM more quickly because it is directly attached to the motherboard. This
  makes the ROM cartridge effectively a fast, directly connected storage device.

  However, despite its speed, the limitation of a ROM cartridge is its storage
  capacity—it can hold only as much data as the chip can accommodate. In contrast,
  a disk can store much more data. This larger storage capacity allows not just
  for bigger and more complex games but also for the possibility of expanding the
  game through additional data downloaded to the console's hard drive. Such
  expansions or patches represent additional data from the console’s storage that,
  combined with the original disk data, are synthesized in memory at runtime for
  enhanced or updated gameplay experiences.

  (Note however that modern cartridge-based consoles like the Nintendo Switch can
  also combine ROM-data with expanded data from the console HDD, sourced from the
  internet.)

  Both disks and ROMs are forms of static storage in the context of a game
  console. While disks can technically be overwritten with new data, in practice,
  manufacturers implement various locks and protections to prevent this. Any
  changes or additions to the game, such as patches or expansions, are not written
  back to the original disk. Instead, these updates are stored on the console's
  hard drive.

  Therefore, if you download an expansion for a game on your Xbox, the original
  disk remains unchanged as when you first purchased it. Consequently, if you were
  to take that disk and load it on another Xbox, it would not include any of the
  expansions or updates. The game would function in its original form, as the
  additional content and updates reside solely on the hard drive of the first
  console where they were downloaded.

  ## Related notes


path: Radio basics.md
sortable_path: Radio basics.md
title: Radio basics
lead:
  Radio is the technology of communication or exchanging information using radio
  waves.

checksum: 62ca4eb82590c6f77d213a17a30778b83bb7f42d13c3976bb0fab23cddfba3e4
created: 2025-10-01 13:31:00.748527222+00:00
modified: 2025-07-07 15:47:40.751706342+00:00
metadata: {"created":"Sunday, July 06, 2025","tags":["radio"]}
body:
  Radio is the technology of communication or exchanging information using radio
  waves.

  Radio waves are electromagnetic waves that transmit at a certain frequency of
  the [electromagnetic spectrum](./Electromagnetism.md): between 3Hz and 300GHz.

  ![](../img/em-spectrum-radio.jpg)

  This makes them the lowest in frequency and the longest in wavelength.

  Radiowaves are generated by an electronic device called a **transmitter**, which
  is connected to an **antenna** which radiates the waves out into space.

  These waves can be detected by another antenna connected to a radio
  **receiver**.

  Information is transmitted by adding information to the raw electromagnetic
  wave. The wave by itself doesn not contain any information.

  The wave form used is a sine wave that fluctuates smoothly and consistently.

  There are two main methods of adding information to the waveform: AM and FM.

  AM stands for **amplitude modulation**. Here, the amplitude of the wave is
  altered. The amplitude is the distance from peak to peak. For example, the sine
  wave produced by a person's voice is overlaid onto the transmitter's sine wave
  to vary its amplitude.

  FM stands for **frequency modulation**. Here, the frequency of the wave is
  altered. The frequency is the number of oscillations over a given time period
  which we measure in Hertz.

raw_content:
  ---
  tags: [radio]
  created: Sunday, July 06, 2025
  ---

  # Radio basics

  Radio is the technology of communication or exchanging information using radio
  waves.

  Radio waves are electromagnetic waves that transmit at a certain frequency of
  the [electromagnetic spectrum](./Electromagnetism.md): between 3Hz and 300GHz.

  ![](../img/em-spectrum-radio.jpg)

  This makes them the lowest in frequency and the longest in wavelength.

  Radiowaves are generated by an electronic device called a **transmitter**, which
  is connected to an **antenna** which radiates the waves out into space.

  These waves can be detected by another antenna connected to a radio
  **receiver**.

  Information is transmitted by adding information to the raw electromagnetic
  wave. The wave by itself doesn not contain any information.

  The wave form used is a sine wave that fluctuates smoothly and consistently.

  There are two main methods of adding information to the waveform: AM and FM.

  AM stands for **amplitude modulation**. Here, the amplitude of the wave is
  altered. The amplitude is the distance from peak to peak. For example, the sine
  wave produced by a person's voice is overlaid onto the transmitter's sine wave
  to vary its amplitude.

  FM stands for **frequency modulation**. Here, the frequency of the wave is
  altered. The frequency is the number of oscillations over a given time period
  which we measure in Hertz.


path: React_Components.md
sortable_path: React_Components.md
title: Components
checksum: 04a9cd1e4e18d7f291d2c48096e3d854b6072eb7a441f18682e47a0046861369
created: 2025-10-01 13:31:00.758825534+00:00
modified: 2025-08-13 15:57:13.946066572+00:00
metadata: {"tags":["typescript","react"]}
lead:
  We write functional components in the manner of a normal
  [function](Functions.md) that take
  a props argument and return a JSX element.

body:
  We write functional components in the manner of a normal
  [function](Functions.md) that take
  a props argument and return a JSX element.

  ```jsx
  interface IProps = {
    message: string;
  };
  const App = ({message}: IProps): JSX.Element => <div>{message}</div>;
  ```

  ## `React.FunctionComponent` / `React.FC`

  It used to be the case that you would type a function component like so:

  ```jsx
  const App: React.FunctionComponent<{ message: string }> = ({ message }) => (
    <div>{message}</div>
  );
  ```

  This is now discouraged as it means the component can always accept children,
  even when you do not want this to be the case. There are several other minor
  drawerbacks but it's generally best to leave out the declaration.

raw_content:
  ---
  tags:
    - typescript
    - react
  ---

  # Components

  We write functional components in the manner of a normal
  [function](Functions.md) that take
  a props argument and return a JSX element.

  ```jsx
  interface IProps = {
    message: string;
  };
  const App = ({message}: IProps): JSX.Element => <div>{message}</div>;
  ```

  ## `React.FunctionComponent` / `React.FC`

  It used to be the case that you would type a function component like so:

  ```jsx
  const App: React.FunctionComponent<{ message: string }> = ({ message }) => (
    <div>{message}</div>
  );
  ```

  This is now discouraged as it means the component can always accept children,
  even when you do not want this to be the case. There are several other minor
  drawerbacks but it's generally best to leave out the declaration.


path: React_application_structure.md
sortable_path: React_application_structure.md
title: React application structure
checksum: f15ba5994809bb2ef31999f98ec2752f4b0a5e62f14fd2ae8222d460951746fb
created: 2025-10-01 13:31:00.76787057+00:00
modified: 2025-08-13 15:57:13.833831766+00:00
metadata: {"tags":["javascript","react"]}
lead:
  When you use `create-react-app` it creates a default directory structure that is
  a sensible one to follow:

body:
  When you use `create-react-app` it creates a default directory structure that is
  a sensible one to follow:

  ```
  build/
  public/
  	index.html
  src/
  	index.js
  	App.js
  ```

  ## `public/`

  - `public` constains the `index.html` file via which React connects to the
    traditional DCOM. Within `index.html` you have `<div id="root">...</div>` as
    the entry point where your application is injected into the standard DOM.

  - Everything in this folder is as per standard web development practice.

  - You shouldn't include React code here but you can paste necessary links and
    metadata to the `head` of `index.html`

  ## `src/`

  - It automatically contains `index.js` . This imports `React` and `ReactDOM` and
    contains the `ReactDOM.render()` method:
    ```js
    ReactDOM.render(
      <App />
    document.getElementById('root')
    );
    ```
  - The `App` component is your parent component and the container for your app.
    It is where you will import your sub-components.
  - If you are using React Router `App` becomes the index for the different page
    components. See [Routing](Routing.md) for more detail.

  ## `build`

  `build` houses the compiled version of your application, ready to be deployed to
  a server. All contents are minified, compressed and optimised using Webpack.

  Once you have executed `npm run build` you can test the output by using `serve`
  via the console:

  ```bash
  serve -s build
  ```

  `build` will comprise a minified version of `index.html` and a `static/`
  directory which holds your compiled CSS and JS that `index.html` links to, as
  per a standard static website.

raw_content:
  ---
  tags:
    - javascript
    - react
  ---

  # React application structure

  When you use `create-react-app` it creates a default directory structure that is
  a sensible one to follow:

  ```
  build/
  public/
  	index.html
  src/
  	index.js
  	App.js
  ```

  ## `public/`

  - `public` constains the `index.html` file via which React connects to the
    traditional DCOM. Within `index.html` you have `<div id="root">...</div>` as
    the entry point where your application is injected into the standard DOM.

  - Everything in this folder is as per standard web development practice.

  - You shouldn't include React code here but you can paste necessary links and
    metadata to the `head` of `index.html`

  ## `src/`

  - It automatically contains `index.js` . This imports `React` and `ReactDOM` and
    contains the `ReactDOM.render()` method:
    ```js
    ReactDOM.render(
      <App />
    document.getElementById('root')
    );
    ```
  - The `App` component is your parent component and the container for your app.
    It is where you will import your sub-components.
  - If you are using React Router `App` becomes the index for the different page
    components. See [Routing](Routing.md) for more detail.

  ## `build`

  `build` houses the compiled version of your application, ready to be deployed to
  a server. All contents are minified, compressed and optimised using Webpack.

  Once you have executed `npm run build` you can test the output by using `serve`
  via the console:

  ```bash
  serve -s build
  ```

  `build` will comprise a minified version of `index.html` and a `static/`
  directory which holds your compiled CSS and JS that `index.html` links to, as
  per a standard static website.


path: React_errors.md
sortable_path: React_errors.md
title: Errors
lead: ## State update on unmounted component
checksum: cfd6611ef29f02dc1c797220a7aa7235d5101356ad8dbe51db45b22375dd90c2
created: 2025-10-01 13:31:00.779022421+00:00
modified: 2025-08-13 15:57:14.0053088+00:00
metadata: {"tags":["javascript","react"]}
body:
  ## State update on unmounted component

  > Can't perform a React state update on an unmounted component. This is a no-op,
  > but it indicates a memory leak in your application. To fix, cancel all
  > subscriptions and asynchronous tasks in a useEffect cleanup function.

  This typically happens when you have an API request running in the background.
  Once the data is returned, React tries to update the state but the component is
  unmounted.

  As the warning suggests, this can be resolved using the cleanup parameter within
  [React_useEffect](React_useEffect.md#cleanup-functions).

raw_content:
  ---
  tags:
    - javascript
    - react
  ---

  # Errors

  ## State update on unmounted component

  > Can't perform a React state update on an unmounted component. This is a no-op,
  > but it indicates a memory leak in your application. To fix, cancel all
  > subscriptions and asynchronous tasks in a useEffect cleanup function.

  This typically happens when you have an API request running in the background.
  Once the data is returned, React tries to update the state but the component is
  unmounted.

  As the warning suggests, this can be resolved using the cleanup parameter within
  [React_useEffect](React_useEffect.md#cleanup-functions).


path: React_useContext.md
sortable_path: React_useContext.md
title: useContext
checksum: 18e785c75ecf5aa0804e9a60c86298bcdcf08758a91c45326c6ae1dc5ccf90ba
created: 2025-10-01 13:31:00.793609748+00:00
modified: 2025-08-13 15:57:13.881895417+00:00
metadata: {"tags":["javascript","react"]}
lead:
  We use React's Context API to enable us to easily share stateful data between
  all levels of an application without having to use repetitious 'prop-drilling'
  at a component level.

body:
  We use React's Context API to enable us to easily share stateful data between
  all levels of an application without having to use repetitious 'prop-drilling'
  at a component level.

  This works best with data that is global by definition, such as theme parameters
  or access authorisation. Context should not be used when standard and proximate
  compositional methods and prop-passing are sufficient.

  ## Providers and consumers

  The Context API preceded the introduction of hooks in React 16.8 and it still
  underpins context management in hooks, although the syntax is simplified.

  The process is as follows:

  - Initiate a context
  - Create a parent `Provider` component that owns the data that will be passed
    down
  - Create child `Consumer` components that receive the data of the parent.

  We will demonstrate using a set of styles as the context that we want to pass
  around our app.

  ```jsx
  const style = {
    border: "2px solid dodgerblue",
    background: "lightblue",
    color: "dodgerblue",
  };
  ```

  Le's initiate a context:

  ```jsx
  const StyleContext = React.createContext();
  ```

  Now that we have our data and have initialized a context, we can apply it to our
  app components:

  ```jsx
  <StyleContext.Provider value={style}>...</StyleContext.Provider>
  ```

  This is the parent element of the context environment. This stores the
  contextual data as a prop. Next we need to make a component that acts as the
  consumer of this data. Let's create this component and call it `Child` for
  simplicity:

  ```jsx
  const Child = () => {
    return (
      <StyleContext.Consumer>
        {(value) => (
          <div style={value}>
            <p>
              I'm a <b>child</b>. I <b>consume</b> of the data my parent provides.
            </p>
          </div>
        )}
      </StyleContext.Consumer>
    );
  };
  ```

  The contents of this component are wrapped in tags that reference the specific
  context (`StyleContext`) and the role that the component plays: `Consumer`.

  We are taking the `value` prop owned by `StyleContext.Provider` and passing it
  to the wrapping component of `Child` as a `style` tag. This means that `Child`
  will display these styles.

  The final step is just to insert our `<Child />` components beneath the parent
  component, e.g.:

  ```jsx
  <StyleContext.Provider value={style}>
    <Child />
    <Child />
  </StyleContext.Provider>
  ```

  ## `useContext` hook

  The hook removes the need to explicitly declare `Provider` and `Consumer`
  components; their role becomes more implicit.

  To demonstrate let's use a different example. We are going to have a single
  integer as the data context, `42`.

  First invoke and intialize the Context API, just as before:

  ```jsx
  const NumberContext = React.createContext(42);
  ```

  Next, we just need to create our provider component. We don't have to worry
  about a consumer since this is handled implicitly by the invocation of the hook

  ```jsx
  const Context = () => {
    const data = useContext(NumberContext);
    return <Typography>{data}</Typography>;
  };
  ```

  Then, in our code we just insert the `Context` component:

  ```jsx
  <Context>...</Context>
  ```

  ## Updating context state

  In the examples above we have only been consuming state that is owned by the
  provider however in most scenarios you will also want to update the state from a
  consumer. This is best achieved by combining `useContext` with a reducer and is
  detailed in [Application state management](Application_state_management_with_React_hooks.md).

raw_content:
  ---
  tags:
    - javascript
    - react
  ---

  # `useContext`

  We use React's Context API to enable us to easily share stateful data between
  all levels of an application without having to use repetitious 'prop-drilling'
  at a component level.

  This works best with data that is global by definition, such as theme parameters
  or access authorisation. Context should not be used when standard and proximate
  compositional methods and prop-passing are sufficient.

  ## Providers and consumers

  The Context API preceded the introduction of hooks in React 16.8 and it still
  underpins context management in hooks, although the syntax is simplified.

  The process is as follows:

  - Initiate a context
  - Create a parent `Provider` component that owns the data that will be passed
    down
  - Create child `Consumer` components that receive the data of the parent.

  We will demonstrate using a set of styles as the context that we want to pass
  around our app.

  ```jsx
  const style = {
    border: "2px solid dodgerblue",
    background: "lightblue",
    color: "dodgerblue",
  };
  ```

  Le's initiate a context:

  ```jsx
  const StyleContext = React.createContext();
  ```

  Now that we have our data and have initialized a context, we can apply it to our
  app components:

  ```jsx
  <StyleContext.Provider value={style}>...</StyleContext.Provider>
  ```

  This is the parent element of the context environment. This stores the
  contextual data as a prop. Next we need to make a component that acts as the
  consumer of this data. Let's create this component and call it `Child` for
  simplicity:

  ```jsx
  const Child = () => {
    return (
      <StyleContext.Consumer>
        {(value) => (
          <div style={value}>
            <p>
              I'm a <b>child</b>. I <b>consume</b> of the data my parent provides.
            </p>
          </div>
        )}
      </StyleContext.Consumer>
    );
  };
  ```

  The contents of this component are wrapped in tags that reference the specific
  context (`StyleContext`) and the role that the component plays: `Consumer`.

  We are taking the `value` prop owned by `StyleContext.Provider` and passing it
  to the wrapping component of `Child` as a `style` tag. This means that `Child`
  will display these styles.

  The final step is just to insert our `<Child />` components beneath the parent
  component, e.g.:

  ```jsx
  <StyleContext.Provider value={style}>
    <Child />
    <Child />
  </StyleContext.Provider>
  ```

  ## `useContext` hook

  The hook removes the need to explicitly declare `Provider` and `Consumer`
  components; their role becomes more implicit.

  To demonstrate let's use a different example. We are going to have a single
  integer as the data context, `42`.

  First invoke and intialize the Context API, just as before:

  ```jsx
  const NumberContext = React.createContext(42);
  ```

  Next, we just need to create our provider component. We don't have to worry
  about a consumer since this is handled implicitly by the invocation of the hook

  ```jsx
  const Context = () => {
    const data = useContext(NumberContext);
    return <Typography>{data}</Typography>;
  };
  ```

  Then, in our code we just insert the `Context` component:

  ```jsx
  <Context>...</Context>
  ```

  ## Updating context state

  In the examples above we have only been consuming state that is owned by the
  provider however in most scenarios you will also want to update the state from a
  consumer. This is best achieved by combining `useContext` with a reducer and is
  detailed in [Application state management](Application_state_management_with_React_hooks.md).


path: React_useEffect.md
sortable_path: React_useEffect.md
title: useEffect
checksum: 51bb0ac90d0fe8ea36cf7558d565e1952a742fea7607da793b900f2635046711
created: 2025-10-01 13:31:00.806901382+00:00
modified: 2025-08-13 15:57:13.922925142+00:00
metadata: {"tags":["javascript","react"]}
lead:
  `useEffect` should be used for any background process that does not arise as a
  result of a user interaction or standard state change. The canonical example
  would be dispatching a request to an API to retrieve data to display in a
  component's initial render.

body:
  `useEffect` should be used for any background process that does not arise as a
  result of a user interaction or standard state change. The canonical example
  would be dispatching a request to an API to retrieve data to display in a
  component's initial render.

  `useEffect` enshrines but also simplifies the
  [lifecyle methods](Lifecycle_methods.md) that are used with
  class-based React components.

  ## Demonstration

  ```jsx
  const [workflowTitle, setWorkflowTitle] = useState("");
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const fetchWorkflowTitle = () => {
      axios
        .post(`${process.env.REACT_APP_ENDPOINT}/load-workflows`, {
          workflow_id: project_id,
          user_id: isAuth?.userId,
        })
        .then((res) => {
          setWorkflowTitle(res?.data?.meta.name);
        })
        .finally(() => setLoading(false))
        .catch((err) => {
          console.error(err);
        });
    };
    setLoading(true);
    fetchWorkflowTitle();
  }, [project_id, isAuth]);
  ```

  In this example we fetch some data from a REST API and store the response value
  as state, which can then be accessed within our JSX template.

  ## Function placement

  In the example, the function is declared inside of the `useEffect` hook and then
  called. We do this to avoid adding the function to the dependency array, which
  we couldn't do if we defined it outside of the hook, somewhere in the component.
  If we did this, the function would run on every render by default and would be
  recalled again because of its placement in the dependency array, which leads to
  the 'too many rerenders' error.

  An alternative would be to define it outside of the component itself but this is
  difficult since it requires state from the component to run.

  ## Dependency array

  Note the array that is the second argument to `useEffect`. This is the
  **dependency array** and is how we manage the lifecycle of the side-effect.

  - After the initial call on render, the function within the `useEffect` block
    will run any time one of the dependencies update. The dependency array
    typically refers to variables that are defined within the hook but can also
    contain references to variables outside of it.

  - If you do not include the array, the effect runs on every render

  - If you pass an empty array, the effect will only run once on the initial
    render

  ## Cleanup functions

  The syntax of the `useEffect` hook also allows you to handle cleanup: something
  you want to do when the component unmounts (another example of how this hook
  recasts the traditional [lifecycle methods](Lifecycle_methods.md))
  . In addition to running on unmount, the cleanup function will run before the
  effect runs again (i.e. when it runs in response to a change in one of the
  elements of the dependency araray). This is chiefly used to prevent
  [memory leaks](Memory_leaks.md) and the
  ['update on unmounted component error'](React_errors.md#state-update-on-unmounted-component).

  You do this by having a `return` clause after the main effect. Schematically:

  ```js
  useEffect(() => {
    //  Run your effect;
    return () => {
      //   Put your cleanup function here
    };
  }, [input]);
  ```

  Here is an example of using a cleanup to cancel a subscription

  ```js
  useEffect(() => {
    let isApiSubscribed = true;
    axios.get(API).then((response) => {
      if (isApiSubscribed) {
        // handle success
      }
    });
    return () => {
      isApiSubscribed = false;
    };
  }, []);
  ```

  ## Resources

  [Understanding the React useEffect cleanup function]()

raw_content:
  ---
  tags:
    - javascript
    - react
  ---

  # `useEffect`

  `useEffect` should be used for any background process that does not arise as a
  result of a user interaction or standard state change. The canonical example
  would be dispatching a request to an API to retrieve data to display in a
  component's initial render.

  `useEffect` enshrines but also simplifies the
  [lifecyle methods](Lifecycle_methods.md) that are used with
  class-based React components.

  ## Demonstration

  ```jsx
  const [workflowTitle, setWorkflowTitle] = useState("");
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const fetchWorkflowTitle = () => {
      axios
        .post(`${process.env.REACT_APP_ENDPOINT}/load-workflows`, {
          workflow_id: project_id,
          user_id: isAuth?.userId,
        })
        .then((res) => {
          setWorkflowTitle(res?.data?.meta.name);
        })
        .finally(() => setLoading(false))
        .catch((err) => {
          console.error(err);
        });
    };
    setLoading(true);
    fetchWorkflowTitle();
  }, [project_id, isAuth]);
  ```

  In this example we fetch some data from a REST API and store the response value
  as state, which can then be accessed within our JSX template.

  ## Function placement

  In the example, the function is declared inside of the `useEffect` hook and then
  called. We do this to avoid adding the function to the dependency array, which
  we couldn't do if we defined it outside of the hook, somewhere in the component.
  If we did this, the function would run on every render by default and would be
  recalled again because of its placement in the dependency array, which leads to
  the 'too many rerenders' error.

  An alternative would be to define it outside of the component itself but this is
  difficult since it requires state from the component to run.

  ## Dependency array

  Note the array that is the second argument to `useEffect`. This is the
  **dependency array** and is how we manage the lifecycle of the side-effect.

  - After the initial call on render, the function within the `useEffect` block
    will run any time one of the dependencies update. The dependency array
    typically refers to variables that are defined within the hook but can also
    contain references to variables outside of it.

  - If you do not include the array, the effect runs on every render

  - If you pass an empty array, the effect will only run once on the initial
    render

  ## Cleanup functions

  The syntax of the `useEffect` hook also allows you to handle cleanup: something
  you want to do when the component unmounts (another example of how this hook
  recasts the traditional [lifecycle methods](Lifecycle_methods.md))
  . In addition to running on unmount, the cleanup function will run before the
  effect runs again (i.e. when it runs in response to a change in one of the
  elements of the dependency araray). This is chiefly used to prevent
  [memory leaks](Memory_leaks.md) and the
  ['update on unmounted component error'](React_errors.md#state-update-on-unmounted-component).

  You do this by having a `return` clause after the main effect. Schematically:

  ```js
  useEffect(() => {
    //  Run your effect;
    return () => {
      //   Put your cleanup function here
    };
  }, [input]);
  ```

  Here is an example of using a cleanup to cancel a subscription

  ```js
  useEffect(() => {
    let isApiSubscribed = true;
    axios.get(API).then((response) => {
      if (isApiSubscribed) {
        // handle success
      }
    });
    return () => {
      isApiSubscribed = false;
    };
  }, []);
  ```

  ## Resources

  [Understanding the React useEffect cleanup function]()


path: React_useReducer.md
sortable_path: React_useReducer.md
title: useReducer
checksum: 4600c79d0f79238fef08e60c2bc5e34d201e5ecba7070140155aef074d9e749c
created: 2025-10-01 13:31:00.831203518+00:00
modified: 2025-08-13 15:57:13.781830056+00:00
metadata: {"tags":["javascript","react"]}
lead:
  The `useReducer` hook is best used in scenarios where you are manipulating state
  in a way that is too complex for the trivial [React_useState](React_useState.md) use case.
  `useState` is best employed when you are updating a single value or toggling a
  boolean. If you are updating the state of an object or more complex data
  structure, it is often more efficient to employ `useReducer`.

body:
  The `useReducer` hook is best used in scenarios where you are manipulating state
  in a way that is too complex for the trivial [React_useState](React_useState.md) use case.
  `useState` is best employed when you are updating a single value or toggling a
  boolean. If you are updating the state of an object or more complex data
  structure, it is often more efficient to employ `useReducer`.

  This makes the code more manageable and also helps with separating state
  management from rendering.

  ## Syntax

  ```jsx
  const [state, dispatch] = useReducer(reducer, initialState);
  ```

  - `initialState`
    - The starting state, typically an object
  - `reducer`
    - A pure function that accepts two parameters:
      - The current state
      - An action object
    - The reducer function must update the current state (immutably) and return
      the new state
    - We can think of the reducer as working in the same manner as
      `state`/`setState` in the `useState` hook. The functional role is the same,
      it is just that the reducer offers more than one type of update.

  ### Example reducer

  ```js
  function reducer(state, action) {
    let newState;
    switch (action.type) {
      case "increase":
        newState = { counter: state.counter + 1 };
        break;
      case "descrease":
        newState = { counter: state.counter - 1 };
        break;
      default:
        throw new Error();
    }
    return newState;
  }
  ```

  In this example we are updating an object with the following shape:

  ```js
  {
      counter: 0,
  }
  ```

  This would be the `initialState` that we pass to the `useReducer` hook along
  with a reference to `reducer` above.

  To update the state we would invoke the `dispatch` function which applies one of
  the actions defined in the reducer. For example the following dispatch
  increments the counter by one:

  ```js
  dispatch({ type: "increase" });
  ```

  To view the updated value:

  ```js
  console.log(state.counter);
  ```

  ### Refining the syntax

  Because React doesn't mutate state, the reducer doesn't directly modify the
  current state in the `state` variable, it creates a new instance of the state
  object on each update.

  In the reducer example above this is achieved by declaring a variable `newState`
  that is updated by each `action` type and then returned. There is a more elegant
  way of doing this using spread syntax:

  ```js
  function reducer(state, action) {
    switch (action.type) {
      case "increase":
        return { ...state, counter: state.counter + 1 };
        break;
      case "decrease":
        return { ...state, counter: state.counter - 1 };
        break;
      default:
        throw new Error();
    }
  }
  ```

  ### Including payloads

  In the examples so far, we have updated the the state directly via the action
  type however it is also possible to pass data along with the `action.type` as
  `action.payload`.

  For example:

  ```js
  dispatch(
    {
      type: 'increase_by_payload'
      payload: 3,
    });
  ```

  Then we would update our reducer to handle this case:

  ```js
  function reducer(state, action) {
    switch (action.type) {
      ...
      case 'increase_by_payload':
      return {...state, counter: state.counter + action.payload}
      default:
        throw new Error();
    }
  }
  ```

raw_content:
  ---
  tags:
    - javascript
    - react
  ---

  # `useReducer`

  The `useReducer` hook is best used in scenarios where you are manipulating state
  in a way that is too complex for the trivial [React_useState](React_useState.md) use case.
  `useState` is best employed when you are updating a single value or toggling a
  boolean. If you are updating the state of an object or more complex data
  structure, it is often more efficient to employ `useReducer`.

  This makes the code more manageable and also helps with separating state
  management from rendering.

  ## Syntax

  ```jsx
  const [state, dispatch] = useReducer(reducer, initialState);
  ```

  - `initialState`
    - The starting state, typically an object
  - `reducer`
    - A pure function that accepts two parameters:
      - The current state
      - An action object
    - The reducer function must update the current state (immutably) and return
      the new state
    - We can think of the reducer as working in the same manner as
      `state`/`setState` in the `useState` hook. The functional role is the same,
      it is just that the reducer offers more than one type of update.

  ### Example reducer

  ```js
  function reducer(state, action) {
    let newState;
    switch (action.type) {
      case "increase":
        newState = { counter: state.counter + 1 };
        break;
      case "descrease":
        newState = { counter: state.counter - 1 };
        break;
      default:
        throw new Error();
    }
    return newState;
  }
  ```

  In this example we are updating an object with the following shape:

  ```js
  {
      counter: 0,
  }
  ```

  This would be the `initialState` that we pass to the `useReducer` hook along
  with a reference to `reducer` above.

  To update the state we would invoke the `dispatch` function which applies one of
  the actions defined in the reducer. For example the following dispatch
  increments the counter by one:

  ```js
  dispatch({ type: "increase" });
  ```

  To view the updated value:

  ```js
  console.log(state.counter);
  ```

  ### Refining the syntax

  Because React doesn't mutate state, the reducer doesn't directly modify the
  current state in the `state` variable, it creates a new instance of the state
  object on each update.

  In the reducer example above this is achieved by declaring a variable `newState`
  that is updated by each `action` type and then returned. There is a more elegant
  way of doing this using spread syntax:

  ```js
  function reducer(state, action) {
    switch (action.type) {
      case "increase":
        return { ...state, counter: state.counter + 1 };
        break;
      case "decrease":
        return { ...state, counter: state.counter - 1 };
        break;
      default:
        throw new Error();
    }
  }
  ```

  ### Including payloads

  In the examples so far, we have updated the the state directly via the action
  type however it is also possible to pass data along with the `action.type` as
  `action.payload`.

  For example:

  ```js
  dispatch(
    {
      type: 'increase_by_payload'
      payload: 3,
    });
  ```

  Then we would update our reducer to handle this case:

  ```js
  function reducer(state, action) {
    switch (action.type) {
      ...
      case 'increase_by_payload':
      return {...state, counter: state.counter + action.payload}
      default:
        throw new Error();
    }
  }
  ```


path: React_useState.md
sortable_path: React_useState.md
title: useState
checksum: e3bc20741b5029e4be18e645b02bae622e038b3e40b6f60627620481e4a59686
created: 2025-10-01 13:31:00.847145235+00:00
modified: 2025-08-13 15:57:13.785571361+00:00
metadata: {"tags":["javascript","react"]}
lead:
  `useState` is the primary way in which React updates the application state based
  on user interaction.

body:
  `useState` is the primary way in which React updates the application state based
  on user interaction.

  - `useState` **receives**: the initial state as an argument
  - `useState` **returns**: the current state and a function that updates it

  The two items that are returned are returned as an array. We could refer to them
  with array syntax (i.e with `[0]` and `[1]` ) but it is more concise to use the
  destructuring syntax. But all that's happening is that a method belonging to the
  `React` library (i.e. `useState` ) is taking an argument (the initial state) and
  returning two values as an array of two elements. The first of these values is a
  variable, the second is a function.

  ```jsx
  (1) const [count, setCount] = useState(0);
  (2) const handleClick = () => { setCount(count + 1) };

  (3) <span>{count}</span>
  (4) <button onClick={handleClick)>Add one</button>
  ```

  - At line 1 we initialise the `useState` hook.
    - We use destructuring syntax to declare two variables
    - The first variable stores our initial state. The value of the initial state
      is an argument passed to `useState` , i.e. `0`. Do not confuse the variable
      with the value it refers to.
    - The second variable is a method that mutates the state referred to by the
      first variable into some new value, i.e. from `0` to a different integer
  - At line 3, which in reality, will be within your JSX and part of the
    `render()` block of the function, we render the initial state in the React
    DOM. This will change and be re-rendered in accordance with the state logic
  - At line 4 we have a user interface that executes the function on line 2. This
    function applies the state change represented by the second variable in the
    destructuring assignment at line 1 (`setCount` ): it mutates the initial state
    (`0`) by the value of `1'.

  > You can utilise as many `useState` declarations as your component requires.

  ## Passing variables as initial state

  We don't always have to declare the data types within the destructuring
  assignment. We can store them in variables and pass the variables to the
  destructuring assignment on `useState` . Below we do this for a function that
  mutates a string value:

  ```jsx
  const hi = "hello";
  const bye = "goodbye";

  const [initText, changeText] = useState(hi);

  <p>{initText}</p>
  <button onClick={()=>changeText(bye)}>ChangeText</button>
  ```

  ## Lazily setting initial state

  Although you will typically use a literal value or variable as your initial
  state, React provides a way for you to set this value through a function. This
  will only run once at the first render so as not to interfere with the second
  update parameter of `useState`. This is called **lazy initialisation**

  ```jsx
  const getInitialState = () => Number(window.localStorage.getItem("count"));
  const [count, setCount] = React.useState(getInitialState);
  ```

  ## Accessing previous state

  It is also possible to access the previous state via the `useState` hook. We can
  access this as a callback on the updater function.

  Let's say we have a simple counter set up like so:

  ```js
  const [count, setCount] = useState(0);
  ```

  We can access the prior value of `count` with:

  ```js
  const getPrevValue = () => setCount((prev) => console.log(prev));
  ```

  ### Naming best practise

  When destructuring the two variables from `useState`, React follows uses the
  following semantics: `[something, setSomething]` . This isn't required but it
  helps to keep everything clear, particularly the fact that the first thing
  destructured is a variable and the second is a function.

  > https://stackoverflow.com/questions/54807454/what-is-prevstate-in-reactjs

raw_content:
  ---
  tags:
    - javascript
    - react
  ---

  # `useState`

  `useState` is the primary way in which React updates the application state based
  on user interaction.

  - `useState` **receives**: the initial state as an argument
  - `useState` **returns**: the current state and a function that updates it

  The two items that are returned are returned as an array. We could refer to them
  with array syntax (i.e with `[0]` and `[1]` ) but it is more concise to use the
  destructuring syntax. But all that's happening is that a method belonging to the
  `React` library (i.e. `useState` ) is taking an argument (the initial state) and
  returning two values as an array of two elements. The first of these values is a
  variable, the second is a function.

  ```jsx
  (1) const [count, setCount] = useState(0);
  (2) const handleClick = () => { setCount(count + 1) };

  (3) <span>{count}</span>
  (4) <button onClick={handleClick)>Add one</button>
  ```

  - At line 1 we initialise the `useState` hook.
    - We use destructuring syntax to declare two variables
    - The first variable stores our initial state. The value of the initial state
      is an argument passed to `useState` , i.e. `0`. Do not confuse the variable
      with the value it refers to.
    - The second variable is a method that mutates the state referred to by the
      first variable into some new value, i.e. from `0` to a different integer
  - At line 3, which in reality, will be within your JSX and part of the
    `render()` block of the function, we render the initial state in the React
    DOM. This will change and be re-rendered in accordance with the state logic
  - At line 4 we have a user interface that executes the function on line 2. This
    function applies the state change represented by the second variable in the
    destructuring assignment at line 1 (`setCount` ): it mutates the initial state
    (`0`) by the value of `1'.

  > You can utilise as many `useState` declarations as your component requires.

  ## Passing variables as initial state

  We don't always have to declare the data types within the destructuring
  assignment. We can store them in variables and pass the variables to the
  destructuring assignment on `useState` . Below we do this for a function that
  mutates a string value:

  ```jsx
  const hi = "hello";
  const bye = "goodbye";

  const [initText, changeText] = useState(hi);

  <p>{initText}</p>
  <button onClick={()=>changeText(bye)}>ChangeText</button>
  ```

  ## Lazily setting initial state

  Although you will typically use a literal value or variable as your initial
  state, React provides a way for you to set this value through a function. This
  will only run once at the first render so as not to interfere with the second
  update parameter of `useState`. This is called **lazy initialisation**

  ```jsx
  const getInitialState = () => Number(window.localStorage.getItem("count"));
  const [count, setCount] = React.useState(getInitialState);
  ```

  ## Accessing previous state

  It is also possible to access the previous state via the `useState` hook. We can
  access this as a callback on the updater function.

  Let's say we have a simple counter set up like so:

  ```js
  const [count, setCount] = useState(0);
  ```

  We can access the prior value of `count` with:

  ```js
  const getPrevValue = () => setCount((prev) => console.log(prev));
  ```

  ### Naming best practise

  When destructuring the two variables from `useState`, React follows uses the
  following semantics: `[something, setSomething]` . This isn't required but it
  helps to keep everything clear, particularly the fact that the first thing
  destructured is a variable and the second is a function.

  > https://stackoverflow.com/questions/54807454/what-is-prevstate-in-reactjs


path: Read_command__in_Bash.md
sortable_path: Read_command__in_Bash.md
title: read
checksum: c9fb9f3512d6c4406ed8ab423f11a31c5c9e23de462b89c7dd18af357cccc1d0
created: 2025-10-01 13:31:00.853520167+00:00
modified: 2025-08-13 15:57:13.946805883+00:00
metadata: {"tags":["shell"]}
lead:
  The primary use of `read` is to capture user input from `stdin`. It can also be
  used to parse strings or files that are redirected to it (with `<` and `<<`) or
  piped to it. In each case, what is read is stored as a variable.

body:
  The primary use of `read` is to capture user input from `stdin`. It can also be
  used to parse strings or files that are redirected to it (with `<` and `<<`) or
  piped to it. In each case, what is read is stored as a variable.

  `read` will parse line by line using a space (`\n`) as the default delimiter.
  You can use IFS to parse by other characters and/or
  [split the contents into an array](Split_into_array_in_Bash.md).

  ## Example of capturing user input

  When we use `read` to gather user input, the script will pause until the input
  is provided.

  ```bash
  echo "What is your name?"
  read name

  echo "What is your password?"
  read -s pass

  read

  ```

  > If you don't specify variables, `read` will automatically parse using
  > whitespace

  ## Example of piping to read

  Here we use [find](Find_Bash_command.md) to collate the files in
  the current directory and then pipe them to read.

  ```bash
  find -type -f  -not -path "./.git/" | read $fname
  ```

  ## Example of parsing a file

  We will typically read from a source and then do something with each variable
  that `read` returns, e.g:

  ```bash
  while read line; do
    if [ var == 'something' ]; then
      # do something
  done < './input-file.txt
  ```

  ## $REPLY

  If you do not assign a variable name to store the value that `read` reads a
  default (`$REPLY`) is applied. You can reference this value in your code.

  For example the following loop does something if `$REPLY` is equal to an empty
  string:

  ```bash
  while read;
  do
      ((count++))
      if [[ -z "$REPLY" ]]; then
          echo "$count"
      fi
  done < "$input
  ```

raw_content:
  ---
  tags:
    - shell
  ---

  # read

  The primary use of `read` is to capture user input from `stdin`. It can also be
  used to parse strings or files that are redirected to it (with `<` and `<<`) or
  piped to it. In each case, what is read is stored as a variable.

  `read` will parse line by line using a space (`\n`) as the default delimiter.
  You can use IFS to parse by other characters and/or
  [split the contents into an array](Split_into_array_in_Bash.md).

  ## Example of capturing user input

  When we use `read` to gather user input, the script will pause until the input
  is provided.

  ```bash
  echo "What is your name?"
  read name

  echo "What is your password?"
  read -s pass

  read

  ```

  > If you don't specify variables, `read` will automatically parse using
  > whitespace

  ## Example of piping to read

  Here we use [find](Find_Bash_command.md) to collate the files in
  the current directory and then pipe them to read.

  ```bash
  find -type -f  -not -path "./.git/" | read $fname
  ```

  ## Example of parsing a file

  We will typically read from a source and then do something with each variable
  that `read` returns, e.g:

  ```bash
  while read line; do
    if [ var == 'something' ]; then
      # do something
  done < './input-file.txt
  ```

  ## $REPLY

  If you do not assign a variable name to store the value that `read` reads a
  default (`$REPLY`) is applied. You can reference this value in your code.

  For example the following loop does something if `$REPLY` is equal to an empty
  string:

  ```bash
  while read;
  do
      ((count++))
      if [[ -z "$REPLY" ]]; then
          echo "$count"
      fi
  done < "$input
  ```


path: Reading_files_in_Python.md
sortable_path: Reading_files_in_Python.md
title: Reading files in Python
checksum: d4054381a2834c5d28cb3849e60d29f8763192767e0cef52c0c2b3c0856c510c
created: 2025-10-01 13:31:00.87245634+00:00
modified: 2025-08-13 15:57:14.009401815+00:00
metadata: {"created":"Friday, October 25, 2024","tags":["python","file-system","procedural"]}
lead:
  Once a file object has been intialised with `open()` there are several ways in
  which the content can be read:

body:
  Once a file object has been intialised with `open()` there are several ways in
  which the content can be read:

  | Read method | Behaviour                                                                                                                                |
  | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
  | `read`      | Return the entire contents of the file as a single string.                                                                               |
  | `readline`  | Read the contents of a file a line at a time. You would combine this with a loop so that you can do something with each individual line. |
  | `readlines` | Return a list of all the lines in a file. Each line will be an element in the list.                                                      |

  ## Read

  `read` reads the entire contents of a file and returns it as a single string.

  `read()` reads the entire file into memory at once, so it may not be suitable
  for very large files that exceed the available memory of your system. In such
  cases, you can use the `readline()` method to read the file line by line
  instead.

  The basic syntax is as follows:

  ```py
  # Open the file for reading
  file = open('filename.txt', 'r')

  # Read the entire contents of the file
  contents = file.read()

  # We could also limit the read to a number of characters:
  contents = file.read(100)

  # Close the file
  file.close()
  ```

  Once we have the file contents stored, we can then interact with it. The
  standard way of doing this is to parse it line by line. For example, say we were
  reading a CSV:

  ```py
  lines = content.split(',')
  for line in lines:
      if line: # if the line is not empty
          # do something with line
  ```

  ## Readline

  > The readline() method in Python is used to read a single line from a file. It
  > is typically used when you want to process a file line by line, rather than
  > reading the entire file into memory at once.

  `readline()` returns the line including the newline character at the end of the
  line, so you may need to strip this character off using the strip() method
  before processing the line further.

  ```python
  # Open the file for reading
  file = open('filename.txt', 'r')

  # Loop through the file, reading one line at a time
  line = file.readline()
  while line:
      # Strip off the newline character
      line = line.strip()

      # Do something with the line
      print(line)

      # Read the next line
      line = file.readline()

  # Close the file
  file.close()
  ```

  ## Readlines

  The `readlines()` method is used to read all the lines of a file and return them
  as a list of strings, where each element of the list is a line from the file.

  ```py
  # Open the file for reading
  file = open('filename.txt', 'r')

  # Read all the lines of the file and store them in a list
  lines = file.readlines()

  # Loop through the lines and print them to the console
  for line in lines:
      print(line)

  # Close the file
  file.close()
  `
  ```

raw_content:
  ---
  tags: [python, file-system, procedural]
  created: Friday, October 25, 2024
  ---

  # Reading files in Python

  Once a file object has been intialised with `open()` there are several ways in
  which the content can be read:

  | Read method | Behaviour                                                                                                                                |
  | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
  | `read`      | Return the entire contents of the file as a single string.                                                                               |
  | `readline`  | Read the contents of a file a line at a time. You would combine this with a loop so that you can do something with each individual line. |
  | `readlines` | Return a list of all the lines in a file. Each line will be an element in the list.                                                      |

  ## Read

  `read` reads the entire contents of a file and returns it as a single string.

  `read()` reads the entire file into memory at once, so it may not be suitable
  for very large files that exceed the available memory of your system. In such
  cases, you can use the `readline()` method to read the file line by line
  instead.

  The basic syntax is as follows:

  ```py
  # Open the file for reading
  file = open('filename.txt', 'r')

  # Read the entire contents of the file
  contents = file.read()

  # We could also limit the read to a number of characters:
  contents = file.read(100)

  # Close the file
  file.close()
  ```

  Once we have the file contents stored, we can then interact with it. The
  standard way of doing this is to parse it line by line. For example, say we were
  reading a CSV:

  ```py
  lines = content.split(',')
  for line in lines:
      if line: # if the line is not empty
          # do something with line
  ```

  ## Readline

  > The readline() method in Python is used to read a single line from a file. It
  > is typically used when you want to process a file line by line, rather than
  > reading the entire file into memory at once.

  `readline()` returns the line including the newline character at the end of the
  line, so you may need to strip this character off using the strip() method
  before processing the line further.

  ```python
  # Open the file for reading
  file = open('filename.txt', 'r')

  # Loop through the file, reading one line at a time
  line = file.readline()
  while line:
      # Strip off the newline character
      line = line.strip()

      # Do something with the line
      print(line)

      # Read the next line
      line = file.readline()

  # Close the file
  file.close()
  ```

  ## Readlines

  The `readlines()` method is used to read all the lines of a file and return them
  as a list of strings, where each element of the list is a line from the file.

  ```py
  # Open the file for reading
  file = open('filename.txt', 'r')

  # Read all the lines of the file and store them in a list
  lines = file.readlines()

  # Loop through the lines and print them to the console
  for line in lines:
      print(line)

  # Close the file
  file.close()
  `
  ```


path: Reciprocals.md
sortable_path: Reciprocals.md
title: Recipricols
checksum: ed560badcaa7ccb1a422db87818532d451e6e49d4b8d43d356089e8f9edf1af6
created: 2025-10-01 13:31:00.877468971+00:00
modified: 2025-08-13 15:57:14.015605024+00:00
metadata: {"tags":["prealgebra","fractions","theorems"]}
lead:
  The [Property of Multiplicative Identity](Multiplicative%20identity.md) applies
  to fractions as well as to whole numbers:

body:
  The [Property of Multiplicative Identity](Multiplicative%20identity.md) applies
  to fractions as well as to whole numbers:

  $$
  \frac{a}{b} \cdot 1 = \frac{a}{b}
  $$

  With fractions there is a related property: the **Multiplicative Inverse**.

  > If $\frac{a}{b}$ is any fraction, the fraction $\frac{b}{a}$ is called the
  > _multiplicative inverse_ or _reciprocol_ of $\frac{a}{b}$. The product of a
  > fraction multiplied by its reciprocol will always be 1. $$ \frac{a}{b} \cdot
  > \frac{b}{a} = 1$$

  For example:

  $$
  \frac{3}{4} \cdot \frac{4}{3} = \frac{12}{12} = 1
  $$

  In this case $\frac{4}{3}$ is the reciprocol or multiplicative inverse of
  $\frac{3}{4}$.

  This accords with what we know a fraction to be: a representation of an amount
  that is less than one whole. When we multiply a fraction by its reciprocol, we
  demonstrate that it makes up one whole.

  This also means that whenever we have a whole number $n$, we can represent it
  fractionally by expressing it as $\frac{n}{1}$

raw_content:
  ---
  tags:
    - prealgebra
    - fractions
    - theorems
  ---

  # Recipricols

  The [Property of Multiplicative Identity](Multiplicative%20identity.md) applies
  to fractions as well as to whole numbers:

  $$
  \frac{a}{b} \cdot 1 = \frac{a}{b}
  $$

  With fractions there is a related property: the **Multiplicative Inverse**.

  > If $\frac{a}{b}$ is any fraction, the fraction $\frac{b}{a}$ is called the
  > _multiplicative inverse_ or _reciprocol_ of $\frac{a}{b}$. The product of a
  > fraction multiplied by its reciprocol will always be 1. $$ \frac{a}{b} \cdot
  > \frac{b}{a} = 1$$

  For example:

  $$
  \frac{3}{4} \cdot \frac{4}{3} = \frac{12}{12} = 1
  $$

  In this case $\frac{4}{3}$ is the reciprocol or multiplicative inverse of
  $\frac{3}{4}$.

  This accords with what we know a fraction to be: a representation of an amount
  that is less than one whole. When we multiply a fraction by its reciprocol, we
  demonstrate that it makes up one whole.

  This also means that whenever we have a whole number $n$, we can represent it
  fractionally by expressing it as $\frac{n}{1}$


path: Recording_and_playback_of_sound.md
sortable_path: Recording_and_playback_of_sound.md
title: Recording and playback of sound
lead: ## Analogue
checksum: ba117d13d562a1cfffa839816844effd32d437afd558d0cb121f857c170ac5b1
created: 2025-10-01 13:31:00.894102159+00:00
modified: 2025-08-13 15:57:13.983963357+00:00
metadata: {"created":"Thursday, January 02, 2025","tags":["sound","analogue","physics"]}
body:
  ## Analogue

  ### Recording

  The microphone converts sound waves into a continuous electrical signal.

  The signal drives the recording equipment.

  In the case of a vinyl recording: the signal drives a cutting head that carves a
  groove into the master disk.

  In the case of a tape recording: the signal drives electro-magnets that align
  magnetic particles on the tape.

  In both cases, **the recording medium physically mirrors the shape of the sound
  wave**.

  ### Playback

  In the case of vinyl, the needle follows the groove, moving up and down to
  recreate the electrical signal.

  In the case of tape, the magnetic patterns induce electrical current in the
  playback head.

  In each case, the signal is transferred directly to amplifiers and speakers.

  ## Digital

  ### Recording

  Mostly covered in [Binary encoding of sound](Binary_encoding_of_sound.md).

  An important point to note is that the binary encoding that results from the
  sampling is lasered into the CD as microscopic impressions and depressions (pits
  and lands)

  ### Playback

  A laser in the reader reads the pits and lands and converts them back to binary
  numbers. A DAC then converts the numbers back into a continuous electrical
  signal which is then channelled to the amplifiers and speakers.

  ## From recording to production of storage medium

  With analogue production recordings would be made onto tape. Multiple takes are
  recorded, mixed and edited. This results in a master tape which is the final
  version of the recorded sound.

  This then goes to a mastering engineer for mastering which creates the master
  mix. This consists in optimising the sound for the given format (vinyl or tape).
  Also includes adjusting frequencies, levels and adding spacing between tracks.

  Then the master disk enters production. A recording is made onto lacquer disc
  which is very delicate. Often known as the "acetate". This is coated in metal to
  create the "metal master", after various processes this goes to the pressing
  plant who press vinyl copies from it.

  Each stage can introduce subtle variations, especially with re-pressings.
  Re-pressings require new stampers from the master which may have degraded in the
  interim. Plus there is a limit to the amount of pressings possible with a given
  stamper. The earlier pressings are therefore less degraded making them more
  valuable.

  ## Degradation

  With tape and vinyl each playback wears the medium, degrading the quality of the
  captured signal. With CDs, there is no degradation and every copy is a perfect
  copy of the original signal. However this capture, necessarily contains less
  information than the analogue version because of sampling.

raw_content:
  ---
  tags: [sound, analogue, physics]
  created: Thursday, January 02, 2025
  ---

  # Recording and playback of sound

  ## Analogue

  ### Recording

  The microphone converts sound waves into a continuous electrical signal.

  The signal drives the recording equipment.

  In the case of a vinyl recording: the signal drives a cutting head that carves a
  groove into the master disk.

  In the case of a tape recording: the signal drives electro-magnets that align
  magnetic particles on the tape.

  In both cases, **the recording medium physically mirrors the shape of the sound
  wave**.

  ### Playback

  In the case of vinyl, the needle follows the groove, moving up and down to
  recreate the electrical signal.

  In the case of tape, the magnetic patterns induce electrical current in the
  playback head.

  In each case, the signal is transferred directly to amplifiers and speakers.

  ## Digital

  ### Recording

  Mostly covered in [Binary encoding of sound](Binary_encoding_of_sound.md).

  An important point to note is that the binary encoding that results from the
  sampling is lasered into the CD as microscopic impressions and depressions (pits
  and lands)

  ### Playback

  A laser in the reader reads the pits and lands and converts them back to binary
  numbers. A DAC then converts the numbers back into a continuous electrical
  signal which is then channelled to the amplifiers and speakers.

  ## From recording to production of storage medium

  With analogue production recordings would be made onto tape. Multiple takes are
  recorded, mixed and edited. This results in a master tape which is the final
  version of the recorded sound.

  This then goes to a mastering engineer for mastering which creates the master
  mix. This consists in optimising the sound for the given format (vinyl or tape).
  Also includes adjusting frequencies, levels and adding spacing between tracks.

  Then the master disk enters production. A recording is made onto lacquer disc
  which is very delicate. Often known as the "acetate". This is coated in metal to
  create the "metal master", after various processes this goes to the pressing
  plant who press vinyl copies from it.

  Each stage can introduce subtle variations, especially with re-pressings.
  Re-pressings require new stampers from the master which may have degraded in the
  interim. Plus there is a limit to the amount of pressings possible with a given
  stamper. The earlier pressings are therefore less degraded making them more
  valuable.

  ## Degradation

  With tape and vinyl each playback wears the medium, degrading the quality of the
  captured signal. With CDs, there is no degradation and every copy is a perfect
  copy of the original signal. However this capture, necessarily contains less
  information than the analogue version because of sampling.


path: Recursion.md
sortable_path: Recursion.md
title: Schema
checksum: 4a8a39f5c37cf98784efe3d990418f7685f37a2348e7edcdb0b155b05a8e4b80
created: 2025-10-01 13:31:00.904358325+00:00
modified: 2025-08-13 15:57:13.998926575+00:00
metadata: {"tags":["algorithms","data-structures","recursion"]}
lead:
  The general structure of a recursive function is as follows:
  ![javascript-recursion.png](javascript-recursion.png)

body:
  The general structure of a recursive function is as follows:
  ![javascript-recursion.png](javascript-recursion.png)

  ## Why use recursive functions?

  Recursion is made for solving problems that can be broken down into smaller,
  repetitive problems. It is especially good for working on things that have many
  possible branches but are too complex for an iterative approach or too costly in
  terms of memory and time complexity.

  Recursive programming differs from **iterative** programming but both have
  similar use cases. Looping is a canonical example of working iteratively.

  ## Base condition

  > Once a condition is met, the function stops calling itself. This is called a
  > base condition.

  Because recursion has the potential for infinity, to use it, we must specify a
  point at which it ends. However as we are not using an iterative approach we
  cannot rely on `while` or `foreach` to specify the boundaries of its operation.
  We call this the **base condition** and this will typically be specified using
  conditional logic.

  The schema for a recursive function with a base condition is:

  ```jsx
  function recurse() {
    if (condition) {
      recurse();
    } else {
      // stop calling recurse()
    }
  }

  recurse();
  ```

  ## Demonstrations

  ### Countdown

  ```jsx
  // program to count down numbers to 1
  function countDown(number) {
    // display the number
    console.log(number);

    // decrease the number value
    let newNumber = number - 1;

    // base case
    if (newNumber > 0) {
      countDown(newNumber);
    }
  }

  countDown(4);
  ```

  - This code takes `4` as it's input and then outputs a countdown returning:
    `4, 3, 2, 1`
  - In each iteration, the number value is decreased by 1
  - The base condition is `newNumber > 0` . This breaks the recursive loop once
    the output reaches `1` and stops it continuing into negative integers.

  Each stage in the process is noted below:

  ```
  countDown(4) prints 4 and calls countDown(3)
  countDown(3) prints 3 and calls countDown(2)
  countDown(2) prints 2 and calls countDown(1)
  countDown(1) prints 1 and calls countDown(0)
  ```

  ### Finding factorials

  > The factorial of a positive integer **n** is the product of all the positive
  > integers less than or equal to **n**.

  To arrive at the factorial of **n** you subtract 1 from **n** and multiply the
  result of the subtraction by **n**. You repeat until the subtractive process
  runs out of positive integers. For example, if 4 is **n,** the factorial of
  **n** is **24:**

  $$ 4 _ 3 _ 2 \*1 $$

  4 multiplied by 3 gives you 12, 12 multiplied by 2 gives you 24. 24 multiplied
  by 1 is 24.

  This is clearly a process that could be implemented with a recursive function:

  ```js
  // program to find the factorial of a number
  function factorial(x) {
    // if number is 0
    if (x === 0) {
      return 1;
    }

    // if number is positive
    else {
      return x * factorial(x - 1);
    }
  }

  let num = 3;

  // calling factorial() if num is non-negative
  if (num > 0) {
    let result = factorial(num);
    console.log(`The factorial of ${num} is ${result}`);
  }
  ```

  ![javascript-factorial 1.png](javascript-factorial%201.png)

raw_content:
  ---
  tags:
    - algorithms
    - data-structures
    - recursion
  ---

  > A recursive function is a function that calls itself in its definition.

  More generally recursion means when a thing is defined in terms of itself. There
  are visual analogues that help to represent the idea such as the Droste effect
  where an image contains a version of itself within itself. The ouroboros is
  another example. Also fractals display recursive properties.

  ## Schema

  The general structure of a recursive function is as follows:
  ![javascript-recursion.png](javascript-recursion.png)

  ## Why use recursive functions?

  Recursion is made for solving problems that can be broken down into smaller,
  repetitive problems. It is especially good for working on things that have many
  possible branches but are too complex for an iterative approach or too costly in
  terms of memory and time complexity.

  Recursive programming differs from **iterative** programming but both have
  similar use cases. Looping is a canonical example of working iteratively.

  ## Base condition

  > Once a condition is met, the function stops calling itself. This is called a
  > base condition.

  Because recursion has the potential for infinity, to use it, we must specify a
  point at which it ends. However as we are not using an iterative approach we
  cannot rely on `while` or `foreach` to specify the boundaries of its operation.
  We call this the **base condition** and this will typically be specified using
  conditional logic.

  The schema for a recursive function with a base condition is:

  ```jsx
  function recurse() {
    if (condition) {
      recurse();
    } else {
      // stop calling recurse()
    }
  }

  recurse();
  ```

  ## Demonstrations

  ### Countdown

  ```jsx
  // program to count down numbers to 1
  function countDown(number) {
    // display the number
    console.log(number);

    // decrease the number value
    let newNumber = number - 1;

    // base case
    if (newNumber > 0) {
      countDown(newNumber);
    }
  }

  countDown(4);
  ```

  - This code takes `4` as it's input and then outputs a countdown returning:
    `4, 3, 2, 1`
  - In each iteration, the number value is decreased by 1
  - The base condition is `newNumber > 0` . This breaks the recursive loop once
    the output reaches `1` and stops it continuing into negative integers.

  Each stage in the process is noted below:

  ```
  countDown(4) prints 4 and calls countDown(3)
  countDown(3) prints 3 and calls countDown(2)
  countDown(2) prints 2 and calls countDown(1)
  countDown(1) prints 1 and calls countDown(0)
  ```

  ### Finding factorials

  > The factorial of a positive integer **n** is the product of all the positive
  > integers less than or equal to **n**.

  To arrive at the factorial of **n** you subtract 1 from **n** and multiply the
  result of the subtraction by **n**. You repeat until the subtractive process
  runs out of positive integers. For example, if 4 is **n,** the factorial of
  **n** is **24:**

  $$ 4 _ 3 _ 2 \*1 $$

  4 multiplied by 3 gives you 12, 12 multiplied by 2 gives you 24. 24 multiplied
  by 1 is 24.

  This is clearly a process that could be implemented with a recursive function:

  ```js
  // program to find the factorial of a number
  function factorial(x) {
    // if number is 0
    if (x === 0) {
      return 1;
    }

    // if number is positive
    else {
      return x * factorial(x - 1);
    }
  }

  let num = 3;

  // calling factorial() if num is non-negative
  if (num > 0) {
    let result = factorial(num);
    console.log(`The factorial of ${num} is ${result}`);
  }
  ```

  ![javascript-factorial 1.png](javascript-factorial%201.png)


path: Redirect_to_dev_null.md
sortable_path: Redirect_to_dev_null.md
title: Redirecting to /dev/null
lead: You'll see the following a lot when reading shell scripts:
checksum: 1864a7e2ce0dd078e01afeec825f780ffbceb38790e093fb936a971e522965c6
created: 2025-10-01 13:31:00.910888751+00:00
modified: 2025-08-13 15:57:13.866513451+00:00
metadata: {"tags":["shell"]}
body:
  You'll see the following a lot when reading shell scripts:

  ```bash
  [some_command] > /dev/null 2>&1
  ```

  This is a redirection statement. It is redirecting data to the `null` device on
  Unix systems. Basically to a black hole or shredder where you can't access it
  because you don't want it to be output to `stdout`.

  The `2>&1` argument is the content: any errors that the program may generate and
  try to show in stout. Notice we are using the
  [file descriptors](File_descriptors_and_redirection.md)
  `1` and `2`.

  If you just want the errors regardless of whether they appear in `stdout` you
  do:

  ```bash
  [some_command] > /dev/null 2>
  ```

  ## Example

  I have used this in my Mongo start-up script:

  ```
  mongodb-compass > /dev/null 2>&1
  ```

  Here, I just want the MongoDB Compass application to start, I don't care if it
  wants to output complaints to the stout.

raw_content:
  ---
  tags:
    - shell
  ---

  # Redirecting to `/dev/null`

  You'll see the following a lot when reading shell scripts:

  ```bash
  [some_command] > /dev/null 2>&1
  ```

  This is a redirection statement. It is redirecting data to the `null` device on
  Unix systems. Basically to a black hole or shredder where you can't access it
  because you don't want it to be output to `stdout`.

  The `2>&1` argument is the content: any errors that the program may generate and
  try to show in stout. Notice we are using the
  [file descriptors](File_descriptors_and_redirection.md)
  `1` and `2`.

  If you just want the errors regardless of whether they appear in `stdout` you
  do:

  ```bash
  [some_command] > /dev/null 2>
  ```

  ## Example

  I have used this in my Mongo start-up script:

  ```
  mongodb-compass > /dev/null 2>&1
  ```

  Here, I just want the MongoDB Compass application to start, I don't care if it
  wants to output complaints to the stout.


path: Redirection_in_Bash.md
sortable_path: Redirection_in_Bash.md
title: Redirection
lead: ## Redirecting outputs
checksum: e64c3fd247bb692dbe02ecb5f5d645298857b8d8675be4a8a9e3532475b2fc00
created: 2025-10-01 13:31:00.927226101+00:00
modified: 2025-08-13 15:57:13.996141162+00:00
metadata: {"tags":["shell"]}
body:
  ## Redirecting outputs

  The symbol `>` is called the **redirection operator** because it redirects
  `stdout` to another program or file. You most frequently use this when you want
  to save contents to a file rather than standard output.

  ```bash
  ls | grep d* > result.txt
  ```

  ### Combining redirection with file escriptors

  It is common practice to combine redirection with the
  [file descriptors](File_descriptors.md) to redirect
  the output of `stdout` and `stderr`. A common case is to
  [redirect error output to `/dev/null`](Redirect_to_dev_null.md).

  Redirection defaults to interpreting `>` as the redirection of `stdout` (`1`);

  ## Redirecting inputs

  We can also switch the direction of the redirection symbol and pass in a file to
  a command rather than command ouput to a file:

  ```bash
  sql-processing-program < data.sql
  ```

  We can redirect a string with three carets:

  ```bash
  program <<< "this is a string input"
  ```

  ## Appending

  We use `>>` to append contents on the next available line of a pre-existing
  file. Continuing on from the example above:

  ```bash
  echo 'These are the files I just grepped' >> result.txt
  ```

raw_content:
  ---
  tags:
    - shell
  ---

  # Redirection

  ## Redirecting outputs

  The symbol `>` is called the **redirection operator** because it redirects
  `stdout` to another program or file. You most frequently use this when you want
  to save contents to a file rather than standard output.

  ```bash
  ls | grep d* > result.txt
  ```

  ### Combining redirection with file escriptors

  It is common practice to combine redirection with the
  [file descriptors](File_descriptors.md) to redirect
  the output of `stdout` and `stderr`. A common case is to
  [redirect error output to `/dev/null`](Redirect_to_dev_null.md).

  Redirection defaults to interpreting `>` as the redirection of `stdout` (`1`);

  ## Redirecting inputs

  We can also switch the direction of the redirection symbol and pass in a file to
  a command rather than command ouput to a file:

  ```bash
  sql-processing-program < data.sql
  ```

  We can redirect a string with three carets:

  ```bash
  program <<< "this is a string input"
  ```

  ## Appending

  We use `>>` to append contents on the next available line of a pre-existing
  file. Continuing on from the example above:

  ```bash
  echo 'These are the files I just grepped' >> result.txt
  ```


path: Reducing_fractions.md
sortable_path: Reducing_fractions.md
title: Reducing fractions to their lowest terms
checksum: 68cf5bc8ce92610196555183479c98c61eca2b63e644783aada411a0031c2667
created: 2025-10-01 13:31:00.945347196+00:00
modified: 2025-08-13 15:57:13.760656798+00:00
metadata: {"tags":["prealgebra","fractions"]}
lead:
  > A fraction is said to be _reduced to its lowest terms_ if the
  > [greatest common divisor](Factors%20and%20divisors.md#greatest-common-divisor)
  > of the numerator and the denominator is $1$.

body:
  > A fraction is said to be _reduced to its lowest terms_ if the
  > [greatest common divisor](Factors%20and%20divisors.md#greatest-common-divisor)
  > of the numerator and the denominator is $1$.

  > Whenever we reduce a fraction, the resultant fraction will always be
  > [equivalent](Equivalent%20fractions.md) to the fraction we started with.

  Thus the fraction $\frac{2}{3}$ is reduced to its lowest terms because the
  greatest common divisor is 1. Neither the numerator or the denominator can be
  reduced to any lower terms. In contrast, the fraction $\frac{4}{6}$ is not
  reduced to its lowest terms because the greatest common divisor of both 4 and 6
  is 2, not 1.

  ### 1. Reducing with repeated application of divisors

  The following demonstrates the process of reducing a fraction to its lowest
  terms in a series of steps:

  $$
  \\frac{18}{24} = \frac{18/2}{24/2} = \frac{9}{12} = \frac{9/3}{12/3} = \frac{3}{4}
  $$

  \_Once we get to $\frac{3}{4}$ the greatest common divisor is 1, therefore
  $\frac{18}{24}$ has been reduced to its lowest terms \_.

  ### 2. Reducing in one step with the highest common divisor

  In the previous example the reduction took two steps: first we divided by two
  and then we divided by three. There is a more efficient way: find the
  [highest common divisor](Factors%20and%20divisors.md#greatest-common-divisor) of
  the numerator and denominator and then use this as the basis for the reduction.
  With this method, the reduction can be completed in a single step.

  The greatest common divisor of 18 and 24 is 6, thus:

  $$
  \frac{18}{24} = \frac{18/6}{24/6} = \frac{3}{4}
  $$

  Note how our earlier two divisors 2 and 3 are
  [factors](Factors%20and%20divisors.md#factors) of 6, showing the consistency
  between the two methods.

  ### 3. Reducing with factors and cancellation

  The two methods above are not very systematic and are quite heuristic. The third
  approach is more systematic and relies on the
  [interchangeability of factors and divisors](Factors%20and%20divisors.md).

  Instead of thinking asking what is the greatest common divisor of 18 and 24 we
  could ask: which single number can we multiply by to get 18 and 24? Obviously
  both numbers are in the six times table. This is therefore to say that 6 is a
  [factor](Factors%20and%20divisors.md#factors) of both: we can multiply some
  number by 6 to arrive at both 18 and 24. The numbers are 3 and 4 respectively:

  $$
  \\begin{split}
  3 \cdot 6 = 18 \\
  4 \cdot 6  = 24
  \\end{split}
  $$

  Here, 3 and 4 are the multiplicands of the factor 6. As $\frac{3}{4}$ doesn't
  have a lower common factor, it is therefore defined in its lowest terms.

  Once we have reached this point, we no longer need the common factor 6, we can
  therefore cancel it out, leaving the multiplicands as the reduced fraction:

  $$
  \\begin{split}
  3  \cancel{\cdot6= 18}\\
  4  \cancel{\cdot6= 24}
  \\end{split}
  $$

  ### 4. Reducing with prime factorisation

  This is still a bit long-winded however particularly when finding the factors of
  larger numbers because we have to go through the factors of both numbers to find
  the largest held in common.

  A better method is to utilise [prime factorization](Prime%20factorization.md)
  combined with the canceling technique.

  First we find the prime factors of both the numerator and denominator:
  ![drawio-Page-7.drawio.png](drawio-Page-7.drawio.png)

  This gives us:

  $$
  \\frac{18}{24} = \frac{2 \cdot 3 \cdot 3}{2 \cdot 2 \cdot 2 \cdot 3}
  $$

  We then cancel out the factors held in common between the numerator and
  denominator:

  $$
  \\frac{\cancel{2} \cdot \cancel{3} \cdot 3}{\cancel{2} \cdot 2 \cdot 2 \cdot \cancel{3}}
  $$

  This gives us:

  $$
  \\frac{3}{2 \cdot 2}
  $$

  We then simplify the fraction as normal to its lowest term (conducting any
  multiplications required by what is left from the prime factorization):

  $$
  \\frac{3}{4}
  $$

  ## Reducing fractions that contain variables

  Superficially this looks to be more difficult but in fact we can apply the same
  prime factorization method to get the result.

  ### Demonstration

  _Reduce the following fraction to its lowest terms: $$\frac{25a^3b}{40a^2b^3}$$_

  The prime factors of the numerator and denominator:

  $$
  \\begin{split}
  25 = {5, 5} \\
  40 = {2,2,2,5}
  \\end{split}
  $$

  Now we apply canceling but we include the variable parts, treating them exactly
  the same as the coefficients. We break them out of their exponents however.

  $$\frac{25a^3b}{40a^2b^3} =\frac{5 \cdot 5 \cdot a \cdot a \cdot a \cdot b}{2 \cdot 2 \cdot 2 \cdot 5 \cdot a \cdot a \cdot b \cdot b \cdot b }$$

  Canceled:

  $$\frac{\cancel{5} \cdot 5 \cdot  \cancel{a} \cdot \cancel{a} \cdot a \cdot \cancel{b}}{2 \cdot 2 \cdot 2 \cdot \cancel{5} \cdot \cancel{a} \cdot \cancel{a} \cdot \cancel{b} \cdot b \cdot b }$$

  Which gives us:

  $$
  \\frac{5 \cdot a}{2 \cdot 2 \cdot 2 \cdot b \cdot b} = \frac{5a}{8b^2}
  $$

  ## Reducing fractions that contain negative values

  _Reduce the following fraction to its lowest terms: $$\frac{14y^5}{-35y^3}$$_

  - This fraction is an instance of a
    [fraction with unlike terms](Handling%20negative%20fractions.md#fractions-with-unlike-terms).

  - Apply [Prime factorization](Prime%20factorization.md):

    ![draw.io-Page-8.drawio.png](draw.io-Page-8.drawio.png)

  - Cancel the coefficients and variable parts

    $$
    \\frac{14y^5}{-35y^3}=\frac{5 \cdot 7 \cdot 2 \cdot y \cdot y \cdot y \cdot y \cdot y}{-5 \cdot 7  \cdot y \cdot y \cdot y} = - \frac{2y^2}{5}
    $$

  _Reduce the following fraction to its lowest terms:
  $$\frac{- 12xy^2}{ - 18xy^2}$$_

  - This fraction is an instance of a
    [fraction with like terms](Handling%20negative%20fractions.md#fractions-with-like-terms).

  - Apply [Prime factorization](Prime%20factorization.md):

  ![draw.io-Page-8.drawio 1.png](draw.io-Page-8.drawio%201.png)

  - Cancel the coefficients and variable parts

    $$

    * \\frac{12xy^2}{18xy^2}=\frac{3 \cdot 2 \cdot 2 \cdot x \cdot y \cdot y}{3 \cdot 7  \cdot 3 \cdot 2 \cdot x \cdot x \cdot y} = - \frac{2y}{3x}
    $$

raw_content:
  ---
  tags:
    - prealgebra
    - fractions
  ---

  # Reducing fractions to their lowest terms

  > A fraction is said to be _reduced to its lowest terms_ if the
  > [greatest common divisor](Factors%20and%20divisors.md#greatest-common-divisor)
  > of the numerator and the denominator is $1$.

  > Whenever we reduce a fraction, the resultant fraction will always be
  > [equivalent](Equivalent%20fractions.md) to the fraction we started with.

  Thus the fraction $\frac{2}{3}$ is reduced to its lowest terms because the
  greatest common divisor is 1. Neither the numerator or the denominator can be
  reduced to any lower terms. In contrast, the fraction $\frac{4}{6}$ is not
  reduced to its lowest terms because the greatest common divisor of both 4 and 6
  is 2, not 1.

  ### 1. Reducing with repeated application of divisors

  The following demonstrates the process of reducing a fraction to its lowest
  terms in a series of steps:

  $$
  \\frac{18}{24} = \frac{18/2}{24/2} = \frac{9}{12} = \frac{9/3}{12/3} = \frac{3}{4}
  $$

  \_Once we get to $\frac{3}{4}$ the greatest common divisor is 1, therefore
  $\frac{18}{24}$ has been reduced to its lowest terms \_.

  ### 2. Reducing in one step with the highest common divisor

  In the previous example the reduction took two steps: first we divided by two
  and then we divided by three. There is a more efficient way: find the
  [highest common divisor](Factors%20and%20divisors.md#greatest-common-divisor) of
  the numerator and denominator and then use this as the basis for the reduction.
  With this method, the reduction can be completed in a single step.

  The greatest common divisor of 18 and 24 is 6, thus:

  $$
  \frac{18}{24} = \frac{18/6}{24/6} = \frac{3}{4}
  $$

  Note how our earlier two divisors 2 and 3 are
  [factors](Factors%20and%20divisors.md#factors) of 6, showing the consistency
  between the two methods.

  ### 3. Reducing with factors and cancellation

  The two methods above are not very systematic and are quite heuristic. The third
  approach is more systematic and relies on the
  [interchangeability of factors and divisors](Factors%20and%20divisors.md).

  Instead of thinking asking what is the greatest common divisor of 18 and 24 we
  could ask: which single number can we multiply by to get 18 and 24? Obviously
  both numbers are in the six times table. This is therefore to say that 6 is a
  [factor](Factors%20and%20divisors.md#factors) of both: we can multiply some
  number by 6 to arrive at both 18 and 24. The numbers are 3 and 4 respectively:

  $$
  \\begin{split}
  3 \cdot 6 = 18 \\
  4 \cdot 6  = 24
  \\end{split}
  $$

  Here, 3 and 4 are the multiplicands of the factor 6. As $\frac{3}{4}$ doesn't
  have a lower common factor, it is therefore defined in its lowest terms.

  Once we have reached this point, we no longer need the common factor 6, we can
  therefore cancel it out, leaving the multiplicands as the reduced fraction:

  $$
  \\begin{split}
  3  \cancel{\cdot6= 18}\\
  4  \cancel{\cdot6= 24}
  \\end{split}
  $$

  ### 4. Reducing with prime factorisation

  This is still a bit long-winded however particularly when finding the factors of
  larger numbers because we have to go through the factors of both numbers to find
  the largest held in common.

  A better method is to utilise [prime factorization](Prime%20factorization.md)
  combined with the canceling technique.

  First we find the prime factors of both the numerator and denominator:
  ![drawio-Page-7.drawio.png](drawio-Page-7.drawio.png)

  This gives us:

  $$
  \\frac{18}{24} = \frac{2 \cdot 3 \cdot 3}{2 \cdot 2 \cdot 2 \cdot 3}
  $$

  We then cancel out the factors held in common between the numerator and
  denominator:

  $$
  \\frac{\cancel{2} \cdot \cancel{3} \cdot 3}{\cancel{2} \cdot 2 \cdot 2 \cdot \cancel{3}}
  $$

  This gives us:

  $$
  \\frac{3}{2 \cdot 2}
  $$

  We then simplify the fraction as normal to its lowest term (conducting any
  multiplications required by what is left from the prime factorization):

  $$
  \\frac{3}{4}
  $$

  ## Reducing fractions that contain variables

  Superficially this looks to be more difficult but in fact we can apply the same
  prime factorization method to get the result.

  ### Demonstration

  _Reduce the following fraction to its lowest terms: $$\frac{25a^3b}{40a^2b^3}$$_

  The prime factors of the numerator and denominator:

  $$
  \\begin{split}
  25 = {5, 5} \\
  40 = {2,2,2,5}
  \\end{split}
  $$

  Now we apply canceling but we include the variable parts, treating them exactly
  the same as the coefficients. We break them out of their exponents however.

  $$\frac{25a^3b}{40a^2b^3} =\frac{5 \cdot 5 \cdot a \cdot a \cdot a \cdot b}{2 \cdot 2 \cdot 2 \cdot 5 \cdot a \cdot a \cdot b \cdot b \cdot b }$$

  Canceled:

  $$\frac{\cancel{5} \cdot 5 \cdot  \cancel{a} \cdot \cancel{a} \cdot a \cdot \cancel{b}}{2 \cdot 2 \cdot 2 \cdot \cancel{5} \cdot \cancel{a} \cdot \cancel{a} \cdot \cancel{b} \cdot b \cdot b }$$

  Which gives us:

  $$
  \\frac{5 \cdot a}{2 \cdot 2 \cdot 2 \cdot b \cdot b} = \frac{5a}{8b^2}
  $$

  ## Reducing fractions that contain negative values

  _Reduce the following fraction to its lowest terms: $$\frac{14y^5}{-35y^3}$$_

  - This fraction is an instance of a
    [fraction with unlike terms](Handling%20negative%20fractions.md#fractions-with-unlike-terms).

  - Apply [Prime factorization](Prime%20factorization.md):

    ![draw.io-Page-8.drawio.png](draw.io-Page-8.drawio.png)

  - Cancel the coefficients and variable parts

    $$
    \\frac{14y^5}{-35y^3}=\frac{5 \cdot 7 \cdot 2 \cdot y \cdot y \cdot y \cdot y \cdot y}{-5 \cdot 7  \cdot y \cdot y \cdot y} = - \frac{2y^2}{5}
    $$

  _Reduce the following fraction to its lowest terms:
  $$\frac{- 12xy^2}{ - 18xy^2}$$_

  - This fraction is an instance of a
    [fraction with like terms](Handling%20negative%20fractions.md#fractions-with-like-terms).

  - Apply [Prime factorization](Prime%20factorization.md):

  ![draw.io-Page-8.drawio 1.png](draw.io-Page-8.drawio%201.png)

  - Cancel the coefficients and variable parts

    $$

    * \\frac{12xy^2}{18xy^2}=\frac{3 \cdot 2 \cdot 2 \cdot x \cdot y \cdot y}{3 \cdot 7  \cdot 3 \cdot 2 \cdot x \cdot x \cdot y} = - \frac{2y}{3x}
    $$


path: Register_and_cache_memory.md
sortable_path: Register_and_cache_memory.md
title: Register and cache memory
lead: The CPU has its own memory devices in the form of registers and cache memory.
checksum: 51b2d2998fb892d96af6bbd7f6f496ba943b2aac343058bda58d60208e691687
created: 2025-10-01 13:31:01.055150592+00:00
modified: 2025-08-13 15:57:13.858811132+00:00
metadata: {"created":"Friday, July 12, 2024","tags":["memory","CPU"]}
body:
  The CPU has its own memory devices in the form of registers and cache memory.

  [Registers](./CPU_architecture.md#Registers) are a form of memory that are
  positioned on the same chip as the CPU. They are very fast but can only store a
  small amount of data. They are used to store the results of calculations and the
  addresses of the next instructions to be processed.

  The cache is SRAM memory that is separate from the DRAM memory which comprises
  the main memory. It exists in order to boost perfomance when executing the
  read/request cycles of the steps detailed above.

  There are two types of cache memory:

  - L1 cache
    - Situated on the CPU chip itself
    - Fastest to access but stores less
  - L2 cache
    - Situated outside of the CPU on its own chip
    - Slower to access than L1 but can store more data

  The L1 cache is the fastest since the data has less distance to travel when
  moving to and from the CPU. This said, the L2 cache is still very fast when
  compared to the main memory, both because it is SRAM rather than DRAM and
  because it is closer to the processor than the main memory.

  Cache controllers use complex algorithms to determine what should go into the
  cache to facilitate the best performance, but generally they work on the
  principle that what has been previously used by the CPU will be requested again
  soon. If the CPU has just asked for an instruction at memory location 555 it's
  very likely that it will next ask for the one at 556, and after that the one at
  557 and so on. The cache's controller circuits therefore go ahead and fetch
  these from slow [DRAM to fast SRAM](./DRAM_and_SRAM_memory.md).

raw_content:
  ---
  tags: [memory, CPU]
  created: Friday, July 12, 2024
  ---

  # Register and cache memory

  The CPU has its own memory devices in the form of registers and cache memory.

  [Registers](./CPU_architecture.md#Registers) are a form of memory that are
  positioned on the same chip as the CPU. They are very fast but can only store a
  small amount of data. They are used to store the results of calculations and the
  addresses of the next instructions to be processed.

  The cache is SRAM memory that is separate from the DRAM memory which comprises
  the main memory. It exists in order to boost perfomance when executing the
  read/request cycles of the steps detailed above.

  There are two types of cache memory:

  - L1 cache
    - Situated on the CPU chip itself
    - Fastest to access but stores less
  - L2 cache
    - Situated outside of the CPU on its own chip
    - Slower to access than L1 but can store more data

  The L1 cache is the fastest since the data has less distance to travel when
  moving to and from the CPU. This said, the L2 cache is still very fast when
  compared to the main memory, both because it is SRAM rather than DRAM and
  because it is closer to the processor than the main memory.

  Cache controllers use complex algorithms to determine what should go into the
  cache to facilitate the best performance, but generally they work on the
  principle that what has been previously used by the CPU will be requested again
  soon. If the CPU has just asked for an instruction at memory location 555 it's
  very likely that it will next ask for the one at 556, and after that the one at
  557 and so on. The cache's controller circuits therefore go ahead and fetch
  these from slow [DRAM to fast SRAM](./DRAM_and_SRAM_memory.md).


path: Regular_expressions_in_SQL.md
sortable_path: Regular_expressions_in_SQL.md
title: Regular expressions in SQL
lead:
  ```sql
  SELECT name FROM country WHERE name RLIKE '[xy][ai]' ORDER BY name;

checksum: 469db48f16db9b164763ed11a358fbaae7d72cb583f93941b711411ba3907f51
created: 2025-10-01 13:31:01.069177618+00:00
modified: 2025-08-13 15:57:13.871335089+00:00
metadata: {"tags":["SQL","regex","databases"]}
body:
  ```sql
  SELECT name FROM country WHERE name RLIKE '[xy][ai]' ORDER BY name;

  Guyana
  Mexico
  Myanmar
  ```

raw_content:
  ---
  tags:
    - SQL
    - regex
    - databases
  ---

  # Regular expressions in SQL

  ```sql
  SELECT name FROM country WHERE name RLIKE '[xy][ai]' ORDER BY name;

  Guyana
  Mexico
  Myanmar
  ```


path: Reiteration.md
sortable_path: Reiteration.md
title: Reiteration
checksum: c34e71c60a917d4c17d97eb702b766dd9e8abb7c8e7490c01b8dac6e50b052b0
created: 2025-10-01 13:31:01.07406536+00:00
modified: 2025-08-13 15:57:14.056140787+00:00
metadata: {"tags":["logic","propositional-logic"]}
lead:
  **Reiteration (R)** allows us to restate any proposition already in the proof
  within the main proof or a more deeply nested sub-proof. Reiteration allows us
  to reuse any assumptions, or propositions derived from assumptions, without
  having to introduce a new dependency with another assumption.

body:
  **Reiteration (R)** allows us to restate any proposition already in the proof
  within the main proof or a more deeply nested sub-proof. Reiteration allows us
  to reuse any assumptions, or propositions derived from assumptions, without
  having to introduce a new dependency with another assumption.

  ![](/img/reiteration.png)

raw_content:
  ---
  tags:
    - logic
    - propositional-logic
  ---

  # Reiteration

  **Reiteration (R)** allows us to restate any proposition already in the proof
  within the main proof or a more deeply nested sub-proof. Reiteration allows us
  to reuse any assumptions, or propositions derived from assumptions, without
  having to introduce a new dependency with another assumption.

  ![](/img/reiteration.png)


path: Relation_between_kernel_and_CPU.md
sortable_path: Relation_between_kernel_and_CPU.md
title: Relation between the kernel and CPU
checksum: 03708b1d4de3d38c26d1e4127f1c2ab1e63041df594afe2bcc8ea04d86533ce2
created: 2025-10-01 13:31:01.081159492+00:00
modified: 2025-08-13 15:57:13.886612595+00:00
metadata: {"tags":["CPU","computer-architecture","operating-systems"]}
lead:
  It can be confusing to understand how the kernel and CPU interact with one
  another. Whilst it is true to say the kernel mediates between the hardware and
  user processes, this led me to think that the kernel was somehow 'over and
  above' the actions of the CPU. This is wrong and if you think about it, how
  could this be since any process, kernel included, requires the processor? The
  kernel is executed by and loaded into the CPU just like any other instruction in
  the
  [fetch, decode, execute cycle](Fetch_decode_execute.md)
  of the CPU.

body:
  It can be confusing to understand how the kernel and CPU interact with one
  another. Whilst it is true to say the kernel mediates between the hardware and
  user processes, this led me to think that the kernel was somehow 'over and
  above' the actions of the CPU. This is wrong and if you think about it, how
  could this be since any process, kernel included, requires the processor? The
  kernel is executed by and loaded into the CPU just like any other instruction in
  the
  [fetch, decode, execute cycle](Fetch_decode_execute.md)
  of the CPU.

  However as a process, the kernel is the 'first amongst equals' given that it is
  the core embodiment of the operating system. At boot time, the kernel is
  injected into memory and at this point the CPU _looks to this address_ in memory
  in order to source its first instruction. That's how the kernel gets going. It
  is the first instruction that the CPU fetches and this is what allows the kernel
  to play its mediatory role. However most of the fetch, decode, execute cycles of
  the CPU take place independently of the kernel.

  ![](/img/kernel-cpu-interaction.svg)

  > Fetch decode and execute refer to processor pipeline stages. They occur
  > automatically as part of normal processor operation, the kernel doesn’t
  > generally have any direct control over how that happens...When the boot loader
  > loads the kernel, it points the CPU’s program counter to an entry point in the
  > kernel’s code. From there, the CPU will continue executing (fetching decoding
  > and executing) kernel code until you point the program counter to a userspace
  > program, where it will continue executing userspace code until an interrupt
  > points the program counter back into kernel code. That’s basically what the
  > CPU will be doing from boot up to shut down; switching between executing
  > kernel code and executing userspace code
  > ([Reddit]())

  This is because of [context switching](), when the CPU is running its cycle, the
  kernel is idle waiting for it to complete. Once control switches back to the
  kernel it can then run its next duty which will be either process, memory or
  device management or system calls. Then it will hand control over to either the
  processor or user space.

raw_content:
  ---
  tags:
    - CPU
    - computer-architecture
    - operating-systems
  ---

  # Relation between the kernel and CPU

  It can be confusing to understand how the kernel and CPU interact with one
  another. Whilst it is true to say the kernel mediates between the hardware and
  user processes, this led me to think that the kernel was somehow 'over and
  above' the actions of the CPU. This is wrong and if you think about it, how
  could this be since any process, kernel included, requires the processor? The
  kernel is executed by and loaded into the CPU just like any other instruction in
  the
  [fetch, decode, execute cycle](Fetch_decode_execute.md)
  of the CPU.

  However as a process, the kernel is the 'first amongst equals' given that it is
  the core embodiment of the operating system. At boot time, the kernel is
  injected into memory and at this point the CPU _looks to this address_ in memory
  in order to source its first instruction. That's how the kernel gets going. It
  is the first instruction that the CPU fetches and this is what allows the kernel
  to play its mediatory role. However most of the fetch, decode, execute cycles of
  the CPU take place independently of the kernel.

  ![](/img/kernel-cpu-interaction.svg)

  > Fetch decode and execute refer to processor pipeline stages. They occur
  > automatically as part of normal processor operation, the kernel doesn’t
  > generally have any direct control over how that happens...When the boot loader
  > loads the kernel, it points the CPU’s program counter to an entry point in the
  > kernel’s code. From there, the CPU will continue executing (fetching decoding
  > and executing) kernel code until you point the program counter to a userspace
  > program, where it will continue executing userspace code until an interrupt
  > points the program counter back into kernel code. That’s basically what the
  > CPU will be doing from boot up to shut down; switching between executing
  > kernel code and executing userspace code
  > ([Reddit]())

  This is because of [context switching](), when the CPU is running its cycle, the
  kernel is idle waiting for it to complete. Once control switches back to the
  kernel it can then run its next duty which will be either process, memory or
  device management or system calls. Then it will hand control over to either the
  processor or user space.


path: Relational_database_architecture.md
sortable_path: Relational_database_architecture.md
title: Relational database architecture
lead: Tables, fields and records are the basic building blocks of databases
checksum: e0e93a044653f33e6d84868926d59c0c445a11f54ef5c9b8f5f697fab468c4d1
created: 2025-10-01 13:31:01.090505447+00:00
modified: 2025-08-13 15:57:13.800683331+00:00
metadata: {"tags":["databases"]}
body:
  Tables, fields and records are the basic building blocks of databases

  ![](/img/FL-Databases-1.5_terminology.gif)

  ## Table

  A group of similar data with rows for **records** and columns for each
  **field**.

  ## Record

  A horizontal row: a collection of items which may be of different data types all
  relating to the individual or object that the record describes. A single _entry_
  in the table. Sometimes called **row** interchangeably.

  ## Field

  A vertical column: stores a single particular unit of data for each record. Each
  field must use the same data type. Sometimes called **field** interchangeably.

  Each individual field has **properties:** such as the data type, length or the
  total memory allocation.

raw_content:
  ---
  tags:
    - databases
  ---

  # Relational database architecture

  Tables, fields and records are the basic building blocks of databases

  ![](/img/FL-Databases-1.5_terminology.gif)

  ## Table

  A group of similar data with rows for **records** and columns for each
  **field**.

  ## Record

  A horizontal row: a collection of items which may be of different data types all
  relating to the individual or object that the record describes. A single _entry_
  in the table. Sometimes called **row** interchangeably.

  ## Field

  A vertical column: stores a single particular unit of data for each record. Each
  field must use the same data type. Sometimes called **field** interchangeably.

  Each individual field has **properties:** such as the data type, length or the
  total memory allocation.


path: Relays.md
sortable_path: Relays.md
title: Relays
lead: A relay is an electrically operated switch.
checksum: 9ac0d0a04e61d1e64dd26710c70c57a00103a50502c4bc15fb7f696c9336bc8d
created: 2025-10-01 13:31:01.095855448+00:00
modified: 2025-08-13 15:57:14.024865418+00:00
metadata: {"created":"Monday, September 09, 2024","tags":["electronics"]}
body:
  A relay is an electrically operated switch.

  It uses an electromagnet to mechancially operate a switch. A switch in one
  circuit can be used the trigger the operation of another circuit.

  ## Core components

  - electromagnet
    - a coil of wire around an iron core
  - armature
    - a movable magnetic strip
  - contacts
    - electrical connections that can be open or closed
  - spring
    - returns the armature to its resting position when not energised

  ## Operation

  ![Operation of a relay](../img/relay.gif)

  Current flows through the electromagnet which creates a magnetic field. This
  field attracts the armature which then moves to open or close the contacts. When
  the current stops, this returns the armature to its original position.

  ## Usage

  During the
  [electro-mechanical era of computing](The_History_of_Computing_Swade.md) they
  were used as precursors to vacuum tubes (and later, transistors) to implement
  logic gates. While they were superseded in this domain, they are still used in
  industrial control systems and automobiles.

raw_content:
  ---
  tags: [electronics]
  created: Monday, September 09, 2024
  ---

  # Relays

  A relay is an electrically operated switch.

  It uses an electromagnet to mechancially operate a switch. A switch in one
  circuit can be used the trigger the operation of another circuit.

  ## Core components

  - electromagnet
    - a coil of wire around an iron core
  - armature
    - a movable magnetic strip
  - contacts
    - electrical connections that can be open or closed
  - spring
    - returns the armature to its resting position when not energised

  ## Operation

  ![Operation of a relay](../img/relay.gif)

  Current flows through the electromagnet which creates a magnetic field. This
  field attracts the armature which then moves to open or close the contacts. When
  the current stops, this returns the armature to its original position.

  ## Usage

  During the
  [electro-mechanical era of computing](The_History_of_Computing_Swade.md) they
  were used as precursors to vacuum tubes (and later, transistors) to implement
  logic gates. While they were superseded in this domain, they are still used in
  industrial control systems and automobiles.


path: Remote_tracking_branches.md
sortable_path: Remote_tracking_branches.md
title: Remote tracking branches
checksum: 775d9cfcc8eb49533dfa647d6fc6911b93fc101e8c2d79da117d0865f0bb5f3b
created: 2025-10-01 13:31:01.114025595+00:00
modified: 2025-08-13 15:57:13.873983043+00:00
metadata: {"tags":["git"]}
lead:
  A remote tracking branch is a **local** snapshot or reference to the state of a
  branch on a remote repository.

body:
  A remote tracking branch is a **local** snapshot or reference to the state of a
  branch on a remote repository.

  When you clone a remote repository, Git automatically creates remote tracking
  branches for all the branches on the remote repository.

  The remote tracking branches have the prefix `origin/` followed by the name of
  the remote branch. For example, if you clone a repository with a branch named
  `develop`, Git creates a remote tracking branch named `origin/develop`.

  When you use commands like `git fetch` and `git pull`, you are interacting with
  the remote repository and having it reflected in the remote tracking branches.

  For instance, `git fetch` makes the remote tracking branch reflect the remote
  changes so that you have a local copy.

  The remote tracking branch is not the same as a local branch. A local branch is
  a branch that may or may not exist on the remote. Once it has been pushed to the
  remote repository, a remote tracking branch will be created for its remote
  version. When you make local changes, the snapshot of the remote tracking branch
  will no longer be up to date: your local branch will be "ahead" of it. Once you
  push, the remote tracking branch snapshot is update and reflects the local state
  of the branch and the two are in sync again.

  The same is true of remote branches. When you checkout a remote branch, your
  local version of it reflects a remote tracking version of it. This goes out of
  sync with your local version when changes are made on the remote.

raw_content:
  ---
  tags: [git]
  ---

  # Remote tracking branches

  A remote tracking branch is a **local** snapshot or reference to the state of a
  branch on a remote repository.

  When you clone a remote repository, Git automatically creates remote tracking
  branches for all the branches on the remote repository.

  The remote tracking branches have the prefix `origin/` followed by the name of
  the remote branch. For example, if you clone a repository with a branch named
  `develop`, Git creates a remote tracking branch named `origin/develop`.

  When you use commands like `git fetch` and `git pull`, you are interacting with
  the remote repository and having it reflected in the remote tracking branches.

  For instance, `git fetch` makes the remote tracking branch reflect the remote
  changes so that you have a local copy.

  The remote tracking branch is not the same as a local branch. A local branch is
  a branch that may or may not exist on the remote. Once it has been pushed to the
  remote repository, a remote tracking branch will be created for its remote
  version. When you make local changes, the snapshot of the remote tracking branch
  will no longer be up to date: your local branch will be "ahead" of it. Once you
  push, the remote tracking branch snapshot is update and reflects the local state
  of the branch and the two are in sync again.

  The same is true of remote branches. When you checkout a remote branch, your
  local version of it reflects a remote tracking version of it. This goes out of
  sync with your local version when changes are made on the remote.


path: Rename_a_branch.md
sortable_path: Rename_a_branch.md
title: Rename a branch
lead: ### In local development
checksum: e8c060552e8fa8aad44a72102793c1db506b6091b9f8a57b3b216a90c49c8030
created: 2025-10-01 13:31:01.119246796+00:00
modified: 2025-08-13 15:57:14.070499559+00:00
metadata: {"tags":["git","procedural"]}
body:
  ### In local development

  ```bash
  git branch -m <old_name> <new_name>
  ```

  ### Update the remote

  ```bash
  git push origin -u <new_name>
  ```

raw_content:
  ---
  tags: [git, procedural]
  ---

  # Rename a branch

  ### In local development

  ```bash
  git branch -m <old_name> <new_name>
  ```

  ### Update the remote

  ```bash
  git push origin -u <new_name>
  ```


path: Repair_disks-with_fsck.md
sortable_path: Repair_disks-with_fsck.md
title: Repair disks with fsck
lead: Identify file system errors on a disk.
checksum: b12bc1b1a20a16980fbe76bcdcae9a8dae223d41be6c72ea39cbe28517584dab
created: 2025-10-01 13:31:01.125873345+00:00
modified: 2025-08-13 15:57:13.912673875+00:00
metadata: {"created":"Saturday, April 26, 2025","tags":["disks","procedural","Linux"]}
body:
  Identify file system errors on a disk.

  Be sure to unmount the device beforehand.

  ```sh
  sudo fsck.vfat -a /dev/sdf1
  ```

  This will automatically apply repairs. An example output:

  ```
  fsck.fat 4.2 (2021-01-31)
  There are differences between boot sector and its backup.
  This is mostly harmless. Differences: (offset:original/backup)
    65:01/00
    Not automatically fixing this.
  /.Trash-1000/files/retropie
   Start does point to root directory. Deleting dir.
  Reclaimed 312130 unused clusters (2556968960 bytes) in 1553 chains.
  Dirty bit is set. Fs was not properly unmounted and some data may be corrupt.
   Automatically removing dirty bit.
  Free cluster summary wrong (1516247 vs. really 1516241)
    Auto-correcting.

  *** Filesystem was changed ***
  Writing changes.
  /dev/sdf1: 1582 files, 396097/1912338 clusters

  ```

raw_content:
  ---
  tags: [disks, procedural, Linux]
  created: Saturday, April 26, 2025
  ---

  # Repair disks with fsck

  Identify file system errors on a disk.

  Be sure to unmount the device beforehand.

  ```sh
  sudo fsck.vfat -a /dev/sdf1
  ```

  This will automatically apply repairs. An example output:

  ```
  fsck.fat 4.2 (2021-01-31)
  There are differences between boot sector and its backup.
  This is mostly harmless. Differences: (offset:original/backup)
    65:01/00
    Not automatically fixing this.
  /.Trash-1000/files/retropie
   Start does point to root directory. Deleting dir.
  Reclaimed 312130 unused clusters (2556968960 bytes) in 1553 chains.
  Dirty bit is set. Fs was not properly unmounted and some data may be corrupt.
   Automatically removing dirty bit.
  Free cluster summary wrong (1516247 vs. really 1516241)
    Auto-correcting.

  *** Filesystem was changed ***
  Writing changes.
  /dev/sdf1: 1582 files, 396097/1912338 clusters

  ```


path: Requerimiento.md
sortable_path: Requerimiento.md
title: c9d7492f_requerimiento
checksum: d6deba34cb598c5af3990c218985e07d74483368d97e451556392cb118e5e990
created: 2025-10-01 13:31:01.131339185+00:00
modified: 2025-08-13 15:57:13.95210102+00:00
metadata: {"created":"Monday, January 20, 2025","tags":["ecopolsoc","internet","surveillance-capitalism"]}
lead:
  Zuboff likens the expropriation of private information by surveillance
  capitalists to the behaviour of the Conquistadores when they first arrived in
  South America.

body:
  Zuboff likens the expropriation of private information by surveillance
  capitalists to the behaviour of the Conquistadores when they first arrived in
  South America.

  In order to legitimise their actions they were obliged to inform the native
  inhabitants of their intentions and tell them that they were now subordinate to
  the Spanish crown.

  This provided supposed justification for the violence and brutality that would
  follow if the natives did not comply. Sometimes the declaration would just be
  muttered moments before attack.

  "Conquest by declaration" is also the technique of Google, she claims. The
  equivalent of the _requerimiento_ being the opaque and incomprehensible terms of
  of service, _designed_ not to be read.

  _These twenty-first-century invaders do not ask permission; the forge ahead,
  papering the scorched earth with faux-legitimation practices. Instead of
  cynically conveyed monarchical edicts, they offer cynically conveyed
  terms-of-service agreements whose stipulations are just as obscured and
  incomprehensible. They build their fortifications, fiercely defending their
  claimed territories, while gathering strength for the next incursion.
  Eventually, they build their towns in intricate ecosystems of commerce, politics
  and culture that declare the legitimacy and inevitability of all that they have
  accomplished._

  _The Age of Surveillance Capitalism_ (2019): 179

raw_content:
  ---
  tags: [ecopolsoc, internet, surveillance-capitalism]
  created: Monday, January 20, 2025
  ---

  # c9d7492f_requerimiento

  Zuboff likens the expropriation of private information by surveillance
  capitalists to the behaviour of the Conquistadores when they first arrived in
  South America.

  In order to legitimise their actions they were obliged to inform the native
  inhabitants of their intentions and tell them that they were now subordinate to
  the Spanish crown.

  This provided supposed justification for the violence and brutality that would
  follow if the natives did not comply. Sometimes the declaration would just be
  muttered moments before attack.

  "Conquest by declaration" is also the technique of Google, she claims. The
  equivalent of the _requerimiento_ being the opaque and incomprehensible terms of
  of service, _designed_ not to be read.

  _These twenty-first-century invaders do not ask permission; the forge ahead,
  papering the scorched earth with faux-legitimation practices. Instead of
  cynically conveyed monarchical edicts, they offer cynically conveyed
  terms-of-service agreements whose stipulations are just as obscured and
  incomprehensible. They build their fortifications, fiercely defending their
  claimed territories, while gathering strength for the next incursion.
  Eventually, they build their towns in intricate ecosystems of commerce, politics
  and culture that declare the legitimacy and inevitability of all that they have
  accomplished._

  _The Age of Surveillance Capitalism_ (2019): 179


path: Reset_to_remote_version.md
sortable_path: Reset_to_remote_version.md
title: Reset to remote version of a branch
checksum: 4275e3738538e2f4224803c94c28cbb651c5bde268c007b9541dd886624806d9
created: 2025-10-01 13:31:01.13804025+00:00
modified: 2025-08-13 15:57:14.029310368+00:00
metadata: {"tags":["git","procedural"]}
lead:
  The scenario: your local Git history has become corrupted in some way and you
  want a clean history based on the current state of the remote. We will
  demonstrate with `main`.

body:
  The scenario: your local Git history has become corrupted in some way and you
  want a clean history based on the current state of the remote. We will
  demonstrate with `main`.

  ```
  git fetch origin
  git reset --hard origin/main
  ```

raw_content:
  ---
  tags: [git, procedural]
  ---

  # Reset to remote version of a branch

  The scenario: your local Git history has become corrupted in some way and you
  want a clean history based on the current state of the remote. We will
  demonstrate with `main`.

  ```
  git fetch origin
  git reset --hard origin/main
  ```


path: Resistance.md
sortable_path: Resistance.md
title: Resistance
lead: - Resistance is opposition to the flow of [current](./Current.md).
checksum: 7531375cbeecf1f1985d5dfaa5d6f7501bc12fa20ec74096a7b8a65343f11009
created: 2025-10-01 13:31:01.143672339+00:00
modified: 2025-08-13 15:57:14.033996387+00:00
metadata: {"tags":["physics","electricity"]}
body:
  - Resistance is opposition to the flow of [current](./Current.md).

  - Different materials have different levels of resistance. For example glass and
    rubber are excellent resistors whereas silver and copper offer little
    resistance to current flow.

  - We utilise **resistors** to control the flow of current in a circuit.

  ## Relationship between _resistance_ and _insulation_

  Resistance and insulation are not the same thing although they relate to the
  same natural phenomena.

  Resistance is a property of an electrical circuit whereas insularity is a
  property of substances found in the world.

  Similarly, insulators are naturally occuring materials that resist the flow of
  current to different degrees whereas a resistor is a man-made electrical
  component that is used to _control_ the flow of current in a circuit.

  ## Factors affecting resistance

  - The larger the diameter of an electric wire, the lower the electrical
    resistance to the current flow. (If we use the analogy of electricity as
    water-flow: the wider the pipe, the more water that can flow.)
  - As a conductor heats up (e.g. copper, aluminium wire), its overall resistance
    increases.

  ## Notation and scientific expression

  ### Resistance

  - We use $R$ to represent resistance
  - The unit of resistance is **ohms** ($\Omega$)

  > One ohm is the resistance of a circuit or circuit element that permits a
  > steady current flow of one [amp](Current.md#formal-expression) (one
  > coulomb/second) when one [volt](Voltage.md#voltage) is applied to the circuit.

  ### Conductance

  - We use $G$ to represent conductance
  - The unit of conductance is **Mho** (ohm spelled backwards) ($\mho$)

  > Conductance is the ability of a material to pass electrons

  > Given that resistance is the opposite of conductance, the relation between the
  > two quantities can be expressed via a recipricol: $R = 1/G$ and $G = 1/R$

  ## Ohm's Law

  The relationship between current, resistance and voltage is expressed in
  [Ohm's Law](Ohms_Law.md).

  ## Resistors

  A resistor is an electrical component that can be used in circuits to introduce
  specific amounts to resistance where needed. This is typically done in order to
  temper the total voltage and so keep the current flowing within certain set
  parameters.

raw_content:
  ---
  tags: [physics, electricity]
  ---

  # Resistance

  - Resistance is opposition to the flow of [current](./Current.md).

  - Different materials have different levels of resistance. For example glass and
    rubber are excellent resistors whereas silver and copper offer little
    resistance to current flow.

  - We utilise **resistors** to control the flow of current in a circuit.

  ## Relationship between _resistance_ and _insulation_

  Resistance and insulation are not the same thing although they relate to the
  same natural phenomena.

  Resistance is a property of an electrical circuit whereas insularity is a
  property of substances found in the world.

  Similarly, insulators are naturally occuring materials that resist the flow of
  current to different degrees whereas a resistor is a man-made electrical
  component that is used to _control_ the flow of current in a circuit.

  ## Factors affecting resistance

  - The larger the diameter of an electric wire, the lower the electrical
    resistance to the current flow. (If we use the analogy of electricity as
    water-flow: the wider the pipe, the more water that can flow.)
  - As a conductor heats up (e.g. copper, aluminium wire), its overall resistance
    increases.

  ## Notation and scientific expression

  ### Resistance

  - We use $R$ to represent resistance
  - The unit of resistance is **ohms** ($\Omega$)

  > One ohm is the resistance of a circuit or circuit element that permits a
  > steady current flow of one [amp](Current.md#formal-expression) (one
  > coulomb/second) when one [volt](Voltage.md#voltage) is applied to the circuit.

  ### Conductance

  - We use $G$ to represent conductance
  - The unit of conductance is **Mho** (ohm spelled backwards) ($\mho$)

  > Conductance is the ability of a material to pass electrons

  > Given that resistance is the opposite of conductance, the relation between the
  > two quantities can be expressed via a recipricol: $R = 1/G$ and $G = 1/R$

  ## Ohm's Law

  The relationship between current, resistance and voltage is expressed in
  [Ohm's Law](Ohms_Law.md).

  ## Resistors

  A resistor is an electrical component that can be used in circuits to introduce
  specific amounts to resistance where needed. This is typically done in order to
  temper the total voltage and so keep the current flowing within certain set
  parameters.


path: Restructure_URLs_lambda.md
sortable_path: Restructure_URLs_lambda.md
title: AWS Lambda examples
lead: ## Reconstruct CloudFront URLs
checksum: 6a911ce9d3aa21da4b42240dc00369ab6f54b0e35dca6f1cd3d11e804463b857
created: 2025-10-01 13:31:01.167913206+00:00
modified: 2025-08-13 15:57:14.046407068+00:00
metadata: {"tags":["AWS","aws-lambda"]}
body:
  ## Reconstruct CloudFront URLs

  ```js
  exports.handler = (event, context, callback) => {
    // Extract the request from the CloudFront event that is sent to Lambda@Edge
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/\/$/, "/index.html");

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;

    // Return to CloudFront
    return callback(null, request);
  };
  ```

  Let's walk through the above example making reference to the general structure
  of the
  [AWS Lambda handler function](Lambda_handler_function.md):

  1. The `event` parameter is invoked to gain access to the event that triggered
     the function. This is a CloudFront request event which is targetted with
     `event.Records[0].cf.request`
  2. We classify this request as the `olduri` since it doesn't have the form we
     want.
  3. We mutate the original request by replacing `/` with `/index.html`
  4. We then re-assign the `request.uri` value to the value of the new URI.
  5. Finally we invoke the `callback` parameter to signal the completion of the
     transformation and return the new request as the return value.

raw_content:
  ---
  tags:
    - AWS
    - aws-lambda
  ---

  # AWS Lambda examples

  ## Reconstruct CloudFront URLs

  ```js
  exports.handler = (event, context, callback) => {
    // Extract the request from the CloudFront event that is sent to Lambda@Edge
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/\/$/, "/index.html");

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;

    // Return to CloudFront
    return callback(null, request);
  };
  ```

  Let's walk through the above example making reference to the general structure
  of the
  [AWS Lambda handler function](Lambda_handler_function.md):

  1. The `event` parameter is invoked to gain access to the event that triggered
     the function. This is a CloudFront request event which is targetted with
     `event.Records[0].cf.request`
  2. We classify this request as the `olduri` since it doesn't have the form we
     want.
  3. We mutate the original request by replacing `/` with `/index.html`
  4. We then re-assign the `request.uri` value to the value of the new URI.
  5. Finally we invoke the `callback` parameter to signal the completion of the
     transformation and return the new request as the return value.


path: Retrieve_data_from_SQL_table.md
sortable_path: Retrieve_data_from_SQL_table.md
title: Retrieve data from table with SQL SELECT statement
checksum: bd9cfcf86d3db4b0d93097db4940a0538df1f7ee46e5928de789034637659e8b
created: 2025-10-01 13:31:01.178245933+00:00
modified: 2025-08-13 15:57:13.916062983+00:00
metadata: {"tags":["SQL","databases"]}
lead:
  > Select data from the database. The data returned is stored in a result table
  > called the **result-set**.

body:
  > Select data from the database. The data returned is stored in a result table
  > called the **result-set**.

  _A table named `models`:_

  | modelId | name                 | cores | releaseDate |
  | ------- | -------------------- | ----- | ----------- |
  | 2       | Raspberry Pi Model B | 2     | 2022-11-19  |
  | 3       | Raspberry Pi Model C | 4     | 2022-11-25  |
  | 4       | MacBook Pro M2       | 9     | 2022-03-18  |

  ## Basic usage

  ```sql
  SELECT name FROM models
  ```

  We can pass in a comma-separated **list of fields**:

  ```sql
  SELECT name, releaseDate FROM models
  ```

  ## With parameters

  ### `WHERE`

  The `WHERE` clause specifies a search criterion. The `WHERE` clause should
  always be last in the syntax. The clauses are always written in this order:
  `FROM` followed by `WHERE`

  ```sql
  SELECT name FROM models WHERE cores > 3
  ```

  ### Compound statements

  Compound statements allow you to apply more filters to your clauses within an
  SQL statement. SQL allows you to build complex, combinatorial `WHERE` clauses by
  using Boolean and mathematical operators (i.e `AND` , `OR` , `>` , `<` , `!=` ,
  `<=` ...)

  Multiple clauses:

  ```sql
  SELECT name, ram, release_date
  FROM model
  WHERE release_date > '2018-01-01' AND ram > 512;
  ```

  More complex logic achieve with parentheses:

  ```sql
  SELECT name, cores, release_date
  FROM model
  WHERE (manufacturer_id = 1 OR manufacturer_id = 2) AND cores >= 2;
  ```

  ## Transform returned data

  We can apply **ordering** to the return data

  ```sql
  SELECT name FROM models ORDER BY name, cores
  SELECT name FROM models ORDER BY name, cores DESC
  ```

  > `ORDER BY` always comes last, after the selection and any filtering clauses
  > but _before_ a `WHERE` clause

  ## Paginate

  We can break our returned data into blocks with `LIMIT`

  ```sql
  LIMIT 5 -- Return first five items
  LIMIT 5,5 -- Return first five items from the sixth row
  ```

raw_content:
  ---
  tags:
    - SQL
    - databases
  ---

  # Retrieve data from table with SQL `SELECT` statement

  > Select data from the database. The data returned is stored in a result table
  > called the **result-set**.

  _A table named `models`:_

  | modelId | name                 | cores | releaseDate |
  | ------- | -------------------- | ----- | ----------- |
  | 2       | Raspberry Pi Model B | 2     | 2022-11-19  |
  | 3       | Raspberry Pi Model C | 4     | 2022-11-25  |
  | 4       | MacBook Pro M2       | 9     | 2022-03-18  |

  ## Basic usage

  ```sql
  SELECT name FROM models
  ```

  We can pass in a comma-separated **list of fields**:

  ```sql
  SELECT name, releaseDate FROM models
  ```

  ## With parameters

  ### `WHERE`

  The `WHERE` clause specifies a search criterion. The `WHERE` clause should
  always be last in the syntax. The clauses are always written in this order:
  `FROM` followed by `WHERE`

  ```sql
  SELECT name FROM models WHERE cores > 3
  ```

  ### Compound statements

  Compound statements allow you to apply more filters to your clauses within an
  SQL statement. SQL allows you to build complex, combinatorial `WHERE` clauses by
  using Boolean and mathematical operators (i.e `AND` , `OR` , `>` , `<` , `!=` ,
  `<=` ...)

  Multiple clauses:

  ```sql
  SELECT name, ram, release_date
  FROM model
  WHERE release_date > '2018-01-01' AND ram > 512;
  ```

  More complex logic achieve with parentheses:

  ```sql
  SELECT name, cores, release_date
  FROM model
  WHERE (manufacturer_id = 1 OR manufacturer_id = 2) AND cores >= 2;
  ```

  ## Transform returned data

  We can apply **ordering** to the return data

  ```sql
  SELECT name FROM models ORDER BY name, cores
  SELECT name FROM models ORDER BY name, cores DESC
  ```

  > `ORDER BY` always comes last, after the selection and any filtering clauses
  > but _before_ a `WHERE` clause

  ## Paginate

  We can break our returned data into blocks with `LIMIT`

  ```sql
  LIMIT 5 -- Return first five items
  LIMIT 5,5 -- Return first five items from the sixth row
  ```


path: Rewilding_the_internet.md
sortable_path: Rewilding_the_internet.md
title: 0716531c_rewilding_the_internet
checksum: bf356c0a1ef11f4c0f98e42151962507661eb1e1b464a2a2fb1f085aa2ec5999
created: 2025-10-01 13:31:01.183036392+00:00
modified: 2025-08-13 15:57:14.080841519+00:00
metadata: {"created":"Thursday, November 07, 2024","tags":["ecopolsoc","internet"]}
lead:
  The following
  [analogy](https://www.noemamag.com/we-need-to-rewild-the-internet/) can be
  useful in understanding how the internet has become such a negative environment.
  How it has transmogrified from its original promise of a humanistic space that
  would facilitate the connection of individuals based on shared interests and
  values to an environment that is entirely mediated by capital, subject to
  control, censorship and the violation of privacy.

body:
  The following
  [analogy](https://www.noemamag.com/we-need-to-rewild-the-internet/) can be
  useful in understanding how the internet has become such a negative environment.
  How it has transmogrified from its original promise of a humanistic space that
  would facilitate the connection of individuals based on shared interests and
  values to an environment that is entirely mediated by capital, subject to
  control, censorship and the violation of privacy.

  In the 18th-century in the northern German states, officials decided to
  rationalise the production of timber to enable more systematic extraction.
  (Clearly a product of Enlightenment principles of applying reason and science to
  agriculture similar to Jethro Tull's invention of the seed drill and the
  suspension of three-field rotation to four-field all-round harvesting.)

  Instead of a sprawling forest ecosystem that had developed naturally over
  hundreds of thousands of years, which allowed for felling without upsetting the
  continuance of the system, the forests were stripped and trees were planted in
  rows and grids with the arrangement designed to maximise yield and access. This
  would be broadly analogous to the factory-farming of chickens compared to
  free-range rearing.

  For the first cycle it appeared as if this restructuring was a huge success.
  Yields were high and the timber was of excellent quality. This was a false dawn,
  however. The subsequent yields were a complete failure compared to the past.
  Fewer trees grew and those that did had a reduced yield and were subject to
  disease. The overall health of the forests declined precipitously.

  What explains the initial success? It was made possible by the preceding
  centuries of free-range growth and husbandry. The seeming success of the new
  system was a product of the generations of investment in the natural ecosystem.
  This was exhausted in one cycle of the new regime.

  Taking this back to the Web, the analogy is that the web was initially a natural
  ecosystem of different communities and technologies developing organically out
  of the original open and decentralised protocols. From this diversity emerged a
  formidably rich informational space.

  Since then, the Web has become highly centralised and homogenised with a tiny
  cadre of corporations determining how individuals communicate, share and access
  information (Google for search, Android or Apple for phone, Twitter or Facebook
  etc.).

  The initial fruits of this centralisation (just like the forest 'optimisation')
  appeared to be beneficial in the initial 'heyday' of the 2010s when social-media
  was new and full of prospect (the political benefits of Twitter and enriched
  public sphere, the 'Arab Spring', WikiLeaks etc). But this actually proved to be
  a nadir. The vitality on display was a product of the preceding era of the
  natural growth of the Web ecosystem.

  This decline in quality should be apparent to any reflective user:

  - the saturation of advertising to the point where many websites are unusable
  - the confection of low-quality content to game 'organic' search rankings
  - the surveillance of users across sites and devices to enable the extraction of
    profitable marketing data
  - the censorship of political content for the 'violation' of bogus terms of use
    on social media platforms if it does not the serve the broader interests of
    capital and western imperialism
  - the saturation of pornography and dehumanising media more generally

  Thbs has also involved the reshaping of Internet users themselves, from active
  and independent _agents_, to drone-like passive _consumers_ of drivel engineered
  to maximise 'engagement' (the monopolisation of attention), where users are like
  the viewers of _Infinite Jest_. See, e.g TikTok and its clones.

  There are many further points that can be made and ideas that can be
  extrapolated from this. Two examples:

  - the emergence of supposed 'AI' is going to lead to greater content
    homogenisation and the intensification of informational entropy as the
    technological mechanism consists in feeding the regurgitated content of the
    internet back into itself

  - reality itself has become infected by the disease that killed the Web
    (ecocide). The distinction between offline and online is becoming increasingly
    hard to draw (politics - the normalisation and ascendancy of the far right and
    subsequent destabilisation of western states)

raw_content:
  ---
  tags: [ecopolsoc, internet]
  created: Thursday, November 07, 2024
  ---

  # 0716531c_rewilding_the_internet

  The following
  [analogy](https://www.noemamag.com/we-need-to-rewild-the-internet/) can be
  useful in understanding how the internet has become such a negative environment.
  How it has transmogrified from its original promise of a humanistic space that
  would facilitate the connection of individuals based on shared interests and
  values to an environment that is entirely mediated by capital, subject to
  control, censorship and the violation of privacy.

  In the 18th-century in the northern German states, officials decided to
  rationalise the production of timber to enable more systematic extraction.
  (Clearly a product of Enlightenment principles of applying reason and science to
  agriculture similar to Jethro Tull's invention of the seed drill and the
  suspension of three-field rotation to four-field all-round harvesting.)

  Instead of a sprawling forest ecosystem that had developed naturally over
  hundreds of thousands of years, which allowed for felling without upsetting the
  continuance of the system, the forests were stripped and trees were planted in
  rows and grids with the arrangement designed to maximise yield and access. This
  would be broadly analogous to the factory-farming of chickens compared to
  free-range rearing.

  For the first cycle it appeared as if this restructuring was a huge success.
  Yields were high and the timber was of excellent quality. This was a false dawn,
  however. The subsequent yields were a complete failure compared to the past.
  Fewer trees grew and those that did had a reduced yield and were subject to
  disease. The overall health of the forests declined precipitously.

  What explains the initial success? It was made possible by the preceding
  centuries of free-range growth and husbandry. The seeming success of the new
  system was a product of the generations of investment in the natural ecosystem.
  This was exhausted in one cycle of the new regime.

  Taking this back to the Web, the analogy is that the web was initially a natural
  ecosystem of different communities and technologies developing organically out
  of the original open and decentralised protocols. From this diversity emerged a
  formidably rich informational space.

  Since then, the Web has become highly centralised and homogenised with a tiny
  cadre of corporations determining how individuals communicate, share and access
  information (Google for search, Android or Apple for phone, Twitter or Facebook
  etc.).

  The initial fruits of this centralisation (just like the forest 'optimisation')
  appeared to be beneficial in the initial 'heyday' of the 2010s when social-media
  was new and full of prospect (the political benefits of Twitter and enriched
  public sphere, the 'Arab Spring', WikiLeaks etc). But this actually proved to be
  a nadir. The vitality on display was a product of the preceding era of the
  natural growth of the Web ecosystem.

  This decline in quality should be apparent to any reflective user:

  - the saturation of advertising to the point where many websites are unusable
  - the confection of low-quality content to game 'organic' search rankings
  - the surveillance of users across sites and devices to enable the extraction of
    profitable marketing data
  - the censorship of political content for the 'violation' of bogus terms of use
    on social media platforms if it does not the serve the broader interests of
    capital and western imperialism
  - the saturation of pornography and dehumanising media more generally

  Thbs has also involved the reshaping of Internet users themselves, from active
  and independent _agents_, to drone-like passive _consumers_ of drivel engineered
  to maximise 'engagement' (the monopolisation of attention), where users are like
  the viewers of _Infinite Jest_. See, e.g TikTok and its clones.

  There are many further points that can be made and ideas that can be
  extrapolated from this. Two examples:

  - the emergence of supposed 'AI' is going to lead to greater content
    homogenisation and the intensification of informational entropy as the
    technological mechanism consists in feeding the regurgitated content of the
    internet back into itself

  - reality itself has become infected by the disease that killed the Web
    (ecocide). The distinction between offline and online is becoming increasingly
    hard to draw (politics - the normalisation and ascendancy of the far right and
    subsequent destabilisation of western states)


path: Role_of_memory_in_computation.md
sortable_path: Role_of_memory_in_computation.md
title: The role of memory in computation
checksum: 201e429a3109d53637859ac37e568ac5254ff329ef4620a4d68cc4b4cb3d4708
created: 2025-10-01 13:31:01.188582066+00:00
modified: 2025-08-13 15:57:14.035691778+00:00
metadata: {"created":"Friday, July 12, 2024","tags":["memory"]}
lead:
  The following steps outline the way in which memory interacts with the processor
  during computational cycles, once the [bootstrapping](Boot_process.md) process
  has completed and the OS kernel is itself loaded into memory.

body:
  The following steps outline the way in which memory interacts with the processor
  during computational cycles, once the [bootstrapping](Boot_process.md) process
  has completed and the OS kernel is itself loaded into memory.

  1. A file is loaded from the harddisk into memory.
  2. The instruction at the first address is sent to the CPU, travelling accross
     the data bus part of the [system bus](Bus.md).
  3. The CPU processes this instruction and then sends a request accross the
     address bus part of the system bus for the next instruction to the memory
     controller within the [chipset](Chipset_and_controllers.md).
  4. The chipset finds where this instruction is stored within the
     [DRAM](Memory.md#dram) and issues a request to have it read out and send to
     the CPU over the data bus.

  > This is a simplified account; it is not the case that only single requests are
  > passed back and forth. This would be inefficient and time-wasting. The kernel
  > sends to the CPU not just the first instruction in the requested file but also
  > a number of instructions that immediately follow it.

  ![Memory flow diagram](/img/memory-flow.svg)

  Every part of the above process - the journey accross the bus, the lookup in the
  controller, the operations on the DRAM, the journey back accross the bus - takes
  multiple CPU clock cycles.

raw_content:
  ---
  tags: [memory]
  created: Friday, July 12, 2024
  ---

  # The role of memory in computation

  The following steps outline the way in which memory interacts with the processor
  during computational cycles, once the [bootstrapping](Boot_process.md) process
  has completed and the OS kernel is itself loaded into memory.

  1. A file is loaded from the harddisk into memory.
  2. The instruction at the first address is sent to the CPU, travelling accross
     the data bus part of the [system bus](Bus.md).
  3. The CPU processes this instruction and then sends a request accross the
     address bus part of the system bus for the next instruction to the memory
     controller within the [chipset](Chipset_and_controllers.md).
  4. The chipset finds where this instruction is stored within the
     [DRAM](Memory.md#dram) and issues a request to have it read out and send to
     the CPU over the data bus.

  > This is a simplified account; it is not the case that only single requests are
  > passed back and forth. This would be inefficient and time-wasting. The kernel
  > sends to the CPU not just the first instruction in the requested file but also
  > a number of instructions that immediately follow it.

  ![Memory flow diagram](/img/memory-flow.svg)

  Every part of the above process - the journey accross the bus, the lookup in the
  controller, the operations on the DRAM, the journey back accross the bus - takes
  multiple CPU clock cycles.


path: Role_of_unique_key_in_relational_databases.md
sortable_path: Role_of_unique_key_in_relational_databases.md
title: Unique key
checksum: 7878d926038dcbc9f1511610d308b67f1133686457a748fc98cf72c4d659466f
created: 2025-10-01 13:31:01.213896707+00:00
modified: 2025-08-13 15:57:13.906697183+00:00
metadata: {"tags":["databases"]}
lead:
  > Every table in a relational database should have a **unique key**. A unique
  > key is one **field that uniquely identifies each record**.

body:
  > Every table in a relational database should have a **unique key**. A unique
  > key is one **field that uniquely identifies each record**.

  This is essential for carrying out operations across database tables and for
  creating and deleting database entires in accordance with the
  [ACID principle](ACID_principle.md). It is also a safeguard: it means
  you can always identify a record by itself and don't have to rely on generic
  queries to identify it.

  Sometimes you will have a dedicated field such as `UNIQUE_ID` for the unique
  key. Other times you can use an existing field to fulfil that function. When an
  existing, visible column is used as the unique key it is called the **primary
  key**. Other times the unique key can be hidden from the table.

  In both cases the following constraints **must be met:**

  1. No two records can have the **same** primary key data
  1. The primary key value should **never be reused**. Thus, if a record is
     deleted from the table, it should not be re-allocated to a new record.
  1. A primary key value **must not be modified** once it has been created
  1. A primary key **must have a value**; it cannot be `null`

raw_content:
  ---
  tags:
    - databases
  ---

  # Unique key

  > Every table in a relational database should have a **unique key**. A unique
  > key is one **field that uniquely identifies each record**.

  This is essential for carrying out operations across database tables and for
  creating and deleting database entires in accordance with the
  [ACID principle](ACID_principle.md). It is also a safeguard: it means
  you can always identify a record by itself and don't have to rely on generic
  queries to identify it.

  Sometimes you will have a dedicated field such as `UNIQUE_ID` for the unique
  key. Other times you can use an existing field to fulfil that function. When an
  existing, visible column is used as the unique key it is called the **primary
  key**. Other times the unique key can be hidden from the table.

  In both cases the following constraints **must be met:**

  1. No two records can have the **same** primary key data
  1. The primary key value should **never be reused**. Thus, if a record is
     deleted from the table, it should not be re-allocated to a new record.
  1. A primary key value **must not be modified** once it has been created
  1. A primary key **must have a value**; it cannot be `null`


path: Routing_on_link_click_in_React.md
sortable_path: Routing_on_link_click_in_React.md
title: Test: Routing on link click
lead: ## Component
checksum: 0935aa4e5e1e4051e4ca684aa0735d3b0fb3a555a93412746712f20724dee40b
created: 2025-10-01 13:31:01.226544002+00:00
modified: 2025-08-13 15:57:14.058446819+00:00
metadata: {"tags":["javascript","react","testing"]}
body:
  ## Component

  ```jsx
  const CertificateHtmlLink = () => {
    return (
      <div className="certificate-html-link html-version-message">
        <Link className="btn btn-primary ml-2" to="/some-location">
          View HTML version
        </Link>
      </div>
    );
  };
  ```

  ## Test

  ```js
  import { render, fireEvent } from "@testing-library/react";
  import { Router } from "react-router-dom";

  describe("<CertificateHtmlLink", () => {
    it("should link to dynamic HTML certificate page URL on click event", () => {
      // Arrange:
      const history = createMemoryHistory({ initialEntries: ["/"] });

      // Act:
      const { getByText } = render(
        <Router history={history}>
          <CertificateHtmlLink to="/certificate/123" />
        </Router>
      );

      // Assert:
      expect(history.location.pathname).toBe("/");
      fireEvent.click(getByText("View HTML version"));
      expect(history.location.pathname).toBe("/certificate/123");
    });
  });
  ```

raw_content:
  ---
  tags:
    - javascript
    - react
    - testing
  ---

  # Test: Routing on link click

  ## Component

  ```jsx
  const CertificateHtmlLink = () => {
    return (
      <div className="certificate-html-link html-version-message">
        <Link className="btn btn-primary ml-2" to="/some-location">
          View HTML version
        </Link>
      </div>
    );
  };
  ```

  ## Test

  ```js
  import { render, fireEvent } from "@testing-library/react";
  import { Router } from "react-router-dom";

  describe("<CertificateHtmlLink", () => {
    it("should link to dynamic HTML certificate page URL on click event", () => {
      // Arrange:
      const history = createMemoryHistory({ initialEntries: ["/"] });

      // Act:
      const { getByText } = render(
        <Router history={history}>
          <CertificateHtmlLink to="/certificate/123" />
        </Router>
      );

      // Assert:
      expect(history.location.pathname).toBe("/");
      fireEvent.click(getByText("View HTML version"));
      expect(history.location.pathname).toBe("/certificate/123");
    });
  });
  ```


path: Rules_for_operations_on_like_and_unlike_terms.md
sortable_path: Rules_for_operations_on_like_and_unlike_terms.md
title: Rules for operations on like and unlike terms
lead: ## Addition
checksum: c0f6bb553c1a03f13e05bed067559c4fa969af88e93a2efbf8de55d82bf3d7c4
created: 2025-10-01 13:31:01.231433547+00:00
modified: 2025-08-13 15:57:13.901924746+00:00
metadata: {"tags":["prealgebra"]}
body:
  ## Addition

  ### Like terms

  > Sum the absolute values and add the negative sign afterwards.

  $$
  \\begin{split}
  -4 + -3
  \\ = 4 + 3
  \\ = -7
  \\end{split}
  $$

  ### Unlike terms

  > Subtract smaller from larger amount and then affix the sign of the larger
  > amount to the sum.

  #### Negative plus positive

  $$
  \\begin{split}
  -8 + 5
  \\ = 8 - 5
  \\ = 3
  \\ = -3
  \\end{split}
  $$

  #### Positive plus negative

  $$
  \\begin{split}
  4 + -1
  \\ = 4 - 1
  \\ = 3
  \\end{split}
  $$

  ## Subtraction

  ### Like terms

  > Turn the operator and second negative into a plus sign and execute as an
  > addition.

  $$
  \\begin{split}
  -4 - -3 =
  \\ = -4 + 3
  \\ = -1
  \\end{split}
  $$

  ### Unlike terms

  #### Positive subtract negative

  > Turn the negative after the operator to a positive. (Same as previous.)
  >
  > $$
  > \\begin{split}
  > 2 - -3 =
  > \\ = 2 + 3
  > \\ = 5
  > \\end{split}
  > $$

  #### Negative subtract positive

  > Start at the negative value and count backwards on the number-line

  $$
  -2 - 3 = -5
  $$

  ## Multiplication

  ### Like terms

  > The product of two negative numbers will always be a positive number.

  $$
  -15 \cdot -3 = 45
  $$

  ### Unlike terms

  > The product of a positive and a negative number will always be a negative
  > number.

  $$
  -3 \cdot 5 = -15
  $$

  ## Division

  **Division follows the same rules as multiplication.**

  ### Like terms

  > The quotient of two negative numbers will always be a positive number.

  $$
  -15 / -3 = 5
  $$

  ### Unlike terms

  > The quotient of a positive and a negative number will always be a negative
  > number.

  $$
  -15 / 3 = -5
  $$

raw_content:
  ---
  tags:
    - prealgebra
  ---

  # Rules for operations on like and unlike terms

  ## Addition

  ### Like terms

  > Sum the absolute values and add the negative sign afterwards.

  $$
  \\begin{split}
  -4 + -3
  \\ = 4 + 3
  \\ = -7
  \\end{split}
  $$

  ### Unlike terms

  > Subtract smaller from larger amount and then affix the sign of the larger
  > amount to the sum.

  #### Negative plus positive

  $$
  \\begin{split}
  -8 + 5
  \\ = 8 - 5
  \\ = 3
  \\ = -3
  \\end{split}
  $$

  #### Positive plus negative

  $$
  \\begin{split}
  4 + -1
  \\ = 4 - 1
  \\ = 3
  \\end{split}
  $$

  ## Subtraction

  ### Like terms

  > Turn the operator and second negative into a plus sign and execute as an
  > addition.

  $$
  \\begin{split}
  -4 - -3 =
  \\ = -4 + 3
  \\ = -1
  \\end{split}
  $$

  ### Unlike terms

  #### Positive subtract negative

  > Turn the negative after the operator to a positive. (Same as previous.)
  >
  > $$
  > \\begin{split}
  > 2 - -3 =
  > \\ = 2 + 3
  > \\ = 5
  > \\end{split}
  > $$

  #### Negative subtract positive

  > Start at the negative value and count backwards on the number-line

  $$
  -2 - 3 = -5
  $$

  ## Multiplication

  ### Like terms

  > The product of two negative numbers will always be a positive number.

  $$
  -15 \cdot -3 = 45
  $$

  ### Unlike terms

  > The product of a positive and a negative number will always be a negative
  > number.

  $$
  -3 \cdot 5 = -15
  $$

  ## Division

  **Division follows the same rules as multiplication.**

  ### Like terms

  > The quotient of two negative numbers will always be a positive number.

  $$
  -15 / -3 = 5
  $$

  ### Unlike terms

  > The quotient of a positive and a negative number will always be a negative
  > number.

  $$
  -15 / 3 = -5
  $$


path: S3.md
sortable_path: S3.md
title: S3
checksum: 71de289fb1009995825d1050865f4e550269258bd276f23ef7e28099c78b7165
created: 2025-10-01 13:31:01.23581018+00:00
modified: 2025-08-13 15:57:14.068035214+00:00
metadata: {"tags":["AWS"]}
lead:
  You can think of S3 as an external mounted harddrive for storing raw binary data
  (images, soundfiles, documents etc).

body:
  You can think of S3 as an external mounted harddrive for storing raw binary data
  (images, soundfiles, documents etc).

  Your use of the S3 service is divided up into **buckets**. Buckets contain files
  and resources. These are just resource names in an online container, the data
  doesn't have any structure beyond that.

  The primary use of S3 is to store resources that an application needs and/or to
  facilitate the uploading and downloading of resources to and from an
  application.

  You can set access and authentication conditions for buckets, making the data
  public or restricted.

raw_content:
  ---
  tags: [AWS]
  ---

  # S3

  You can think of S3 as an external mounted harddrive for storing raw binary data
  (images, soundfiles, documents etc).

  Your use of the S3 service is divided up into **buckets**. Buckets contain files
  and resources. These are just resource names in an online container, the data
  doesn't have any structure beyond that.

  The primary use of S3 is to store resources that an application needs and/or to
  facilitate the uploading and downloading of resources to and from an
  application.

  You can set access and authentication conditions for buckets, making the data
  public or restricted.


path: SAM.md
sortable_path: SAM.md
title: AWS SAM
checksum: c0089593bfecd5e2774abc2268d3c33f84fbf9b626aff54ac4519d0e7171a7b0
created: 2025-10-01 13:31:01.243497669+00:00
modified: 2025-08-13 15:57:13.939150788+00:00
metadata: {"tags":["AWS"]}
lead:
  SAM stands for **serverless application model**. It is a framework developed by
  AWS to simplify the process of building, deploying and managing serverless
  applications. It provides a concise syntax for defining the components of a
  serverless application, such as
  [Lambda functions](zk/Lambda_programming_model.md),
  [API gateway](/zk/AWS_API_Gateway.md) and database tables.

body:
  SAM stands for **serverless application model**. It is a framework developed by
  AWS to simplify the process of building, deploying and managing serverless
  applications. It provides a concise syntax for defining the components of a
  serverless application, such as
  [Lambda functions](zk/Lambda_programming_model.md),
  [API gateway](/zk/AWS_API_Gateway.md) and database tables.

  The SAM infrastructure is defined in a YAML file which is then deployed to AWS.
  SAM syntax gets transformed into CloudFormation during the deployment process.
  (CloudFormation is a broader and more robust AWS tool for large, highly
  scaleable infrastructures).

  ## Key features of SAM

  - Single deployment configuration
  - Integration with development tools
  - Local testing and debugging
  - Built on AWS CloudFormation

  ## Main technologies required

  ### Docker

  Whilst SAM can be used to create a deployable file for AWS it can also be run as
  a container for local development with Docker.

  ### AWS CLI

  This is installed using Python and allows you to interact directly with AWS via
  the command-line.

  ### AWS SAM CLI

  See
  [https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)

  ## Setting up credentials for the AWS CLI

  You require an access key for the given
  [IAM user](zk/AWS_User_management_and_roles.md#iam). You should create an IAM
  account specific to the project with bounded permissions.

  ```
  aws configure
  AWS Access Key ID [None]: AK*******
  AWS Secret Access Key [None]: ukp******
  Default region name [None]:
  Default output format [None]:
  ```

  This information can be found in the Security Credentials section of the given
  [IAM](zk/AWS_User_management_and_roles.md#iam) user:

  ![](/img/access-key-aws.png)

  ### Switching between credentials

  You should set up a different IAM user for each project.

  You can do this with:

  ```sh
  aws configure --profile <profile-name>
  ```

  This will then ask you to add the credentials for the user.

  You can switch between different credentials for the user as follows:

  ```sh
  AWS_PROFILE=<profile-name> sam build

  ```

  ## Starting a SAM project

  First create a directory for your project which will serve as the repository:

  ```sh
  mkdir aws-sam-learning
  cd aws-sam-learning
  ```

  Then we can use the `sam` cli to bootstrap the project:

  ```sh
  sam init --runtime nodejs16.x
  ```

  We can just click through and accept the basic HelloWorld Lambda.

  This will create the Lambda as well as an API Gateway trigger URL.

  ### `template.yaml`

  This is autogenerated and details the main constituents of the project. There
  are lots of fields but the most important are the following:

  ```yaml
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs16.x
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get
  ```

  This details the location of the [handler function](/Lambda_handler_function.md)
  which is contained at the path `hello-world/app.js`:

  ```js
  exports.lambdaHandler = async (event, context) => {
    try {
      // const ret = await axios(url);
      response = {
        statusCode: 200,
        body: JSON.stringify({
          message: "hello world",
          // location: ret.data.trim()
        }),
      };
    } catch (err) {
      console.log(err);
      return err;
    }

    return response;
  };
  ```

  It also lists the `get` event that we can use to call API Gateway and trigger
  the Lambda.

  The full template is below:

  ![](/img/sam-template-yaml.png)

  ## Adding our own code

  We will create our own function and API Gateway trigger.

  We will place our function after the existing `HelloWorldFunction`

  ```yaml
  ClockFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: clock/
      Handler: handler.clock
      Runtime: nodejs16.x
    Events:
      ClockApi:
        Type: Api
        Properties:
          Path: /clock
          Method: get
  ```

  We can test the syntax with:

  ```sh
  sam validate
  ```

  Just like with `HelloWorld`, we will create a directory for this function:
  `clock` and we will initialise it as an `npm` project.

  ```sh
  mkdir clock
  cd clock
  npm init
  ```

  We will use `handler.js` as our root, handler function.

  We have said in the template file that our `Handler: handler.clock`, therefore
  the main function in the `handler` module should be `clock`:

  ```js
  const moment = require("moment");

  exports.clock = async (event) => {
    console.log("Clock function run");
    const message = moment().format();
    const response = {
      statusCode: 200,
      body: JSON.stringify(message),
    };
    return response;
  };
  ```

  The directory structure is as follows:

  ![](/img/sam-directory.png)

  When we call the API Gateway path `/clock` with `GET`, our function will be
  triggered.

  ## Deploying the project

  We will now deploy our project to AWS from the local environment.

  The process is as follows:

  1. Build
  2. Package
  3. Deploy

  ### Build

  We need to install the runtime dependencies for the function. We do this by
  running `sam build`. This ignores test files and development dependencies and
  installs the project dependencies and source files to a temporary subdirectory.

  ![](/img/sam-build.png)

  The build directory is `.aws-sam/build/`. There will be a subdirectory for each
  of our files.

  ### Package

  As noted, CloudFront handles the deployment of the application. It can only
  receive one file as an input. The packaging process consists in creating that
  single file.

  The packaging proces will first archive all of the project artefacts into a zip
  file and then upload that to [S3](zk/AWS_S3.md). A reference to this S3 entity
  is then provided to CloudFormation.

  ![](/img/s3-package-again.svg)

  The command is as follows:

  ```sh
  sam package
    --template-file template.yaml
    --output-template-file pkg.yml
    --region eu-west-1
  ```

  This will automatically create a hashed bucket name for you in S3 (I have tried
  to add my own naming but it doesn't comply.)

  ### Local development with Docker

  In order to work with your application locally without actually sending requests
  to AWS and using credit, you can run a local instance.

  See [Local AWS Development with SAM](zk/Local_AWS_development_with_SAM.md).

  ### Deploy

  Once you have packaged the app you can deploy with `sam deploy --guided`. This
  will talk you through the defaults and will deploy the package to
  CloudFormation. In CloudFormation each individual project is called a **stack**.

  If we then go to Cloud Formation we will see the deployed application.

  ![](/img/cloud-formation-stack.png)

  ## Call the endpoint

  If we now go to the Lambda console, we will see our function listed, and the API
  Gateway endpoint under `triggers`:

  ![](/img/gateway-trigger.png)

  We can then call this from Postman to check everything is working as it should:

  ![](/img/postman-aws-output.png)

raw_content:
  ---
  tags: [AWS]
  ---

  # AWS SAM

  SAM stands for **serverless application model**. It is a framework developed by
  AWS to simplify the process of building, deploying and managing serverless
  applications. It provides a concise syntax for defining the components of a
  serverless application, such as
  [Lambda functions](zk/Lambda_programming_model.md),
  [API gateway](/zk/AWS_API_Gateway.md) and database tables.

  The SAM infrastructure is defined in a YAML file which is then deployed to AWS.
  SAM syntax gets transformed into CloudFormation during the deployment process.
  (CloudFormation is a broader and more robust AWS tool for large, highly
  scaleable infrastructures).

  ## Key features of SAM

  - Single deployment configuration
  - Integration with development tools
  - Local testing and debugging
  - Built on AWS CloudFormation

  ## Main technologies required

  ### Docker

  Whilst SAM can be used to create a deployable file for AWS it can also be run as
  a container for local development with Docker.

  ### AWS CLI

  This is installed using Python and allows you to interact directly with AWS via
  the command-line.

  ### AWS SAM CLI

  See
  [https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)

  ## Setting up credentials for the AWS CLI

  You require an access key for the given
  [IAM user](zk/AWS_User_management_and_roles.md#iam). You should create an IAM
  account specific to the project with bounded permissions.

  ```
  aws configure
  AWS Access Key ID [None]: AK*******
  AWS Secret Access Key [None]: ukp******
  Default region name [None]:
  Default output format [None]:
  ```

  This information can be found in the Security Credentials section of the given
  [IAM](zk/AWS_User_management_and_roles.md#iam) user:

  ![](/img/access-key-aws.png)

  ### Switching between credentials

  You should set up a different IAM user for each project.

  You can do this with:

  ```sh
  aws configure --profile <profile-name>
  ```

  This will then ask you to add the credentials for the user.

  You can switch between different credentials for the user as follows:

  ```sh
  AWS_PROFILE=<profile-name> sam build

  ```

  ## Starting a SAM project

  First create a directory for your project which will serve as the repository:

  ```sh
  mkdir aws-sam-learning
  cd aws-sam-learning
  ```

  Then we can use the `sam` cli to bootstrap the project:

  ```sh
  sam init --runtime nodejs16.x
  ```

  We can just click through and accept the basic HelloWorld Lambda.

  This will create the Lambda as well as an API Gateway trigger URL.

  ### `template.yaml`

  This is autogenerated and details the main constituents of the project. There
  are lots of fields but the most important are the following:

  ```yaml
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs16.x
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get
  ```

  This details the location of the [handler function](/Lambda_handler_function.md)
  which is contained at the path `hello-world/app.js`:

  ```js
  exports.lambdaHandler = async (event, context) => {
    try {
      // const ret = await axios(url);
      response = {
        statusCode: 200,
        body: JSON.stringify({
          message: "hello world",
          // location: ret.data.trim()
        }),
      };
    } catch (err) {
      console.log(err);
      return err;
    }

    return response;
  };
  ```

  It also lists the `get` event that we can use to call API Gateway and trigger
  the Lambda.

  The full template is below:

  ![](/img/sam-template-yaml.png)

  ## Adding our own code

  We will create our own function and API Gateway trigger.

  We will place our function after the existing `HelloWorldFunction`

  ```yaml
  ClockFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: clock/
      Handler: handler.clock
      Runtime: nodejs16.x
    Events:
      ClockApi:
        Type: Api
        Properties:
          Path: /clock
          Method: get
  ```

  We can test the syntax with:

  ```sh
  sam validate
  ```

  Just like with `HelloWorld`, we will create a directory for this function:
  `clock` and we will initialise it as an `npm` project.

  ```sh
  mkdir clock
  cd clock
  npm init
  ```

  We will use `handler.js` as our root, handler function.

  We have said in the template file that our `Handler: handler.clock`, therefore
  the main function in the `handler` module should be `clock`:

  ```js
  const moment = require("moment");

  exports.clock = async (event) => {
    console.log("Clock function run");
    const message = moment().format();
    const response = {
      statusCode: 200,
      body: JSON.stringify(message),
    };
    return response;
  };
  ```

  The directory structure is as follows:

  ![](/img/sam-directory.png)

  When we call the API Gateway path `/clock` with `GET`, our function will be
  triggered.

  ## Deploying the project

  We will now deploy our project to AWS from the local environment.

  The process is as follows:

  1. Build
  2. Package
  3. Deploy

  ### Build

  We need to install the runtime dependencies for the function. We do this by
  running `sam build`. This ignores test files and development dependencies and
  installs the project dependencies and source files to a temporary subdirectory.

  ![](/img/sam-build.png)

  The build directory is `.aws-sam/build/`. There will be a subdirectory for each
  of our files.

  ### Package

  As noted, CloudFront handles the deployment of the application. It can only
  receive one file as an input. The packaging process consists in creating that
  single file.

  The packaging proces will first archive all of the project artefacts into a zip
  file and then upload that to [S3](zk/AWS_S3.md). A reference to this S3 entity
  is then provided to CloudFormation.

  ![](/img/s3-package-again.svg)

  The command is as follows:

  ```sh
  sam package
    --template-file template.yaml
    --output-template-file pkg.yml
    --region eu-west-1
  ```

  This will automatically create a hashed bucket name for you in S3 (I have tried
  to add my own naming but it doesn't comply.)

  ### Local development with Docker

  In order to work with your application locally without actually sending requests
  to AWS and using credit, you can run a local instance.

  See [Local AWS Development with SAM](zk/Local_AWS_development_with_SAM.md).

  ### Deploy

  Once you have packaged the app you can deploy with `sam deploy --guided`. This
  will talk you through the defaults and will deploy the package to
  CloudFormation. In CloudFormation each individual project is called a **stack**.

  If we then go to Cloud Formation we will see the deployed application.

  ![](/img/cloud-formation-stack.png)

  ## Call the endpoint

  If we now go to the Lambda console, we will see our function listed, and the API
  Gateway endpoint under `triggers`:

  ![](/img/gateway-trigger.png)

  We can then call this from Postman to check everything is working as it should:

  ![](/img/postman-aws-output.png)


path: SQLite.md
sortable_path: SQLite.md
title: SQLite
lead: ## Enabling foreign key constraints
checksum: 2eb67715c75bdedf756b1e5b91c55501863d3698d1c868a22f736eda6d9055ec
created: 2025-10-01 13:31:01.319004059+00:00
modified: 2025-08-13 15:57:13.861335798+00:00
metadata: {"created":"Wednesday, November 13, 2024","tags":["databases","SQL","SQLite"]}
body:
  ## Enabling foreign key constraints

  Foreign key constraints are not enabled by default - it is very permissive. You
  must manually turn them on, as part of the connection process:

  ```py
  connection = sqlite3.connect("my_database.db")
  connection.execute("PRAGMA foreign_keys = ON")
  ```

  ## INSERT OR IGNORE INTO

  If table has a `UNIQUE` constraint on a field, insert if it is unique otherwise
  skip without throwing a constraint error.

  ```sql
  INSERT OR IGNORE INTO table_name (value) VALUES (:value)
  ```

  ## exec and fetchall

  For `CREATE`, `INSERT`, `UPDATE`, `DELETE` operations it is sufficient to simply
  use `execute` to carry out the operations:

  ```py
  cursor = connection.cursor()
  cursor.execute(sql)
  ```

  For `SELECT` operations, you must add a return statement that uses `fetchall`:

  ```py
  sql = "SELECT * FROM table"
  cursor = connection.cursor()
  cursor.execute(sql)
  return cursor.fetchall()
  ```

  ## SELECT response data type

  A `SELECT` operation returns a [list](Lists_in_Python.md) of
  [tuples](Tuples_in_Python.md) where each entry in the tuple is a returned field.

  For example:

  ```py
  entries_sql = "SELECT title, size FROM entries"

  entries_response = cursor.execute(entries_sql)
  print(cursor.fetchall())
  # [('Lorem ipsum', 127), ('Dolar sit', 4231)]
  ```

raw_content:
  ---
  tags: [databases, SQL, SQLite]
  created: Wednesday, November 13, 2024
  ---

  # SQLite

  ## Enabling foreign key constraints

  Foreign key constraints are not enabled by default - it is very permissive. You
  must manually turn them on, as part of the connection process:

  ```py
  connection = sqlite3.connect("my_database.db")
  connection.execute("PRAGMA foreign_keys = ON")
  ```

  ## INSERT OR IGNORE INTO

  If table has a `UNIQUE` constraint on a field, insert if it is unique otherwise
  skip without throwing a constraint error.

  ```sql
  INSERT OR IGNORE INTO table_name (value) VALUES (:value)
  ```

  ## exec and fetchall

  For `CREATE`, `INSERT`, `UPDATE`, `DELETE` operations it is sufficient to simply
  use `execute` to carry out the operations:

  ```py
  cursor = connection.cursor()
  cursor.execute(sql)
  ```

  For `SELECT` operations, you must add a return statement that uses `fetchall`:

  ```py
  sql = "SELECT * FROM table"
  cursor = connection.cursor()
  cursor.execute(sql)
  return cursor.fetchall()
  ```

  ## SELECT response data type

  A `SELECT` operation returns a [list](Lists_in_Python.md) of
  [tuples](Tuples_in_Python.md) where each entry in the tuple is a returned field.

  For example:

  ```py
  entries_sql = "SELECT title, size FROM entries"

  entries_response = cursor.execute(entries_sql)
  print(cursor.fetchall())
  # [('Lorem ipsum', 127), ('Dolar sit', 4231)]
  ```


path: SSH.md
sortable_path: SSH.md
title: SSH
lead: SSH is the de facto standard for remote access to a Unix machine.
checksum: 496db00e65369a5bc34427698d3d94edaa4f5c38d636031a6c1061485d8a8629
created: 2025-10-01 13:31:01.344182315+00:00
modified: 2025-08-13 15:57:13.822339642+00:00
metadata: {"created":"Tuesday, March 04, 2025","tags":["encryption","shell","servers"]}
body:
  SSH is the de facto standard for remote access to a Unix machine.

  `ssh` is the client which you use to connect to another machine.

  `sshd` is the server that manages incoming client requests for access.

  ## sshd

  Typically the SSH server will be turned off.

  To run at boot:

  ```sh
  sudo systemctl enable sshd
  ```

  To start immediately:

  ```sh
  sudo systemctl start sshd
  ```

  The `sshd` configuration is found in the directory `/etc/ssh`.

  The config file is `/etc/ssh/sshd_config`.

  Mostly you can leave this alone but the following is a useful property to set:

  ```
  PermitRootLogin no
  ```

  See [Disable non-root ssh access](./Disable_non-root_ssh_access.md) for more.

  ## Known hosts

  Within your home directory at `./ssh/known_hosts` you will find a record of all
  the public keys of the servers you have connected. This file exists for both
  servers and clients, e.g:

  ```sh
  cat ./ssh/known_hosts
  # systemsobscure.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKn6vyv9b+Nk5r
  # YVSAk5KvsTiC24K6uSpzCHzgLNoqt2
  ```

  This shows the public key of my server at `systemsobscure.net` along with
  others.

  ## Authorized keys

  On servers only, there is also an `authorized_keys` file which shows the
  server's own public keys that it presents to clients.

  If I go to my server I see that this key matches the one I have on my client
  computer `known_hosts`:

  ```sh
  sudo cat /etc/ssh/ssh_host_ed25519_key.pub
  # ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKn6vyv9b+Nk5rYVSAk5KvsTiC24K6uSpzCHzgLNoqt2 root@self-host-server

  ```

  Each user on a server will also have a `~/.ssh` directory also containing an
  `authorized_keys` file. This contains the public keys of clients who are allowed
  to connect to that user account.

  Hence I see the same public key of my desktop client machine in both places.

  ## How the tunnel is created

  ## Generating a key pair

  ```sh
  ssh-keygen
  ```

  ## Add a new public key to a server so that it can be accessed from client

  ```sh
  # On server

  vim .ssh/authorized_keys

  ```

  Then add public key of client

  Then, if you typically connect with the default SSH key, you need to specify the
  specific key when connecting:

  ```sh
  ssh -o "IdentitiesOnly=yes" -i ~/.ssh/public_key_file user@server
  ```

raw_content:
  ---
  tags: [encryption, shell, servers]
  created: Tuesday, March 04, 2025
  ---

  # SSH

  SSH is the de facto standard for remote access to a Unix machine.

  `ssh` is the client which you use to connect to another machine.

  `sshd` is the server that manages incoming client requests for access.

  ## sshd

  Typically the SSH server will be turned off.

  To run at boot:

  ```sh
  sudo systemctl enable sshd
  ```

  To start immediately:

  ```sh
  sudo systemctl start sshd
  ```

  The `sshd` configuration is found in the directory `/etc/ssh`.

  The config file is `/etc/ssh/sshd_config`.

  Mostly you can leave this alone but the following is a useful property to set:

  ```
  PermitRootLogin no
  ```

  See [Disable non-root ssh access](./Disable_non-root_ssh_access.md) for more.

  ## Known hosts

  Within your home directory at `./ssh/known_hosts` you will find a record of all
  the public keys of the servers you have connected. This file exists for both
  servers and clients, e.g:

  ```sh
  cat ./ssh/known_hosts
  # systemsobscure.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKn6vyv9b+Nk5r
  # YVSAk5KvsTiC24K6uSpzCHzgLNoqt2
  ```

  This shows the public key of my server at `systemsobscure.net` along with
  others.

  ## Authorized keys

  On servers only, there is also an `authorized_keys` file which shows the
  server's own public keys that it presents to clients.

  If I go to my server I see that this key matches the one I have on my client
  computer `known_hosts`:

  ```sh
  sudo cat /etc/ssh/ssh_host_ed25519_key.pub
  # ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKn6vyv9b+Nk5rYVSAk5KvsTiC24K6uSpzCHzgLNoqt2 root@self-host-server

  ```

  Each user on a server will also have a `~/.ssh` directory also containing an
  `authorized_keys` file. This contains the public keys of clients who are allowed
  to connect to that user account.

  Hence I see the same public key of my desktop client machine in both places.

  ## How the tunnel is created

  ## Generating a key pair

  ```sh
  ssh-keygen
  ```

  ## Add a new public key to a server so that it can be accessed from client

  ```sh
  # On server

  vim .ssh/authorized_keys

  ```

  Then add public key of client

  Then, if you typically connect with the default SSH key, you need to specify the
  specific key when connecting:

  ```sh
  ssh -o "IdentitiesOnly=yes" -i ~/.ssh/public_key_file user@server
  ```


path: Save_readonly_Vim_file.md
sortable_path: Save_readonly_Vim_file.md
title: Save read only Vim file
lead:
  ```
  :w !sudo tee % >/dev/null
  ```

body:
  ```
  :w !sudo tee % >/dev/null
  ```

checksum: 13c4e831cb314f4643cba5f5b4c5916209be8b3e3ba9aad98fae1ca25f315bc4
created: 2025-10-01 13:31:01.357000155+00:00
modified: 2025-08-13 15:57:13.885323066+00:00
metadata: {"tags":["Linux","procedural"]}
raw_content:
  ---
  tags:
    - Linux
    - procedural
  ---

  # Save read only Vim file

  ```
   :w !sudo tee % >/dev/null
  ```


path: Schema_Definition_Language_in_GraphQL.md
sortable_path: Schema_Definition_Language_in_GraphQL.md
title: Schema Definition Language
lead: SDL is the formal name for the syntax of GraphQL schemas.
checksum: c50d5b10c7f9a915e1d4d5d9bb67ef337b59f126f97bfda5c6bfeba74d25ac1c
created: 2025-10-01 13:31:01.364064979+00:00
modified: 2025-08-13 15:57:13.797799559+00:00
metadata: {"tags":["graphql"]}
body:
  SDL is the formal name for the syntax of GraphQL schemas.

  ## Types

  A schema is a collection of object types that contain fields. Each field has a
  type of its own. A field's type can be a primitive/scalar value (such as an
  `Int` or a `String`), or it can be another object type (just like a custom type
  in TS).

  A schema's type can be non-nullable which is to say, a required field. We
  indicate this with `!`.

  A type for a field can be a collection/array of a given type.

  The following example indicates these properties:

  ```gql
  type Person {
    age: Int
    name: String
    pets: [Pet]!
  }

  type Pet {
    species: String
    name: String
    age: Int
  }
  ```

  ## Queries

  A query is also a schema type but of a special sort.

  > The fields of this type are entry points into the rest of the schema. These
  > are the top-level fields that the client can query for.

  For example if we had this type:

  ```graphql
  type Track {
    id: ID!
      author: Author!
    thumbnail: String
    length: Int
    modulesCount: Int
  }
  ```

  We could define a type to access a give `Track` as follows:

  ```graphql
  type Query {
    tracksForHomePage: [Track!]!
  }
  ```

  Then use this type as the basis for a query:

  ```

  ```

  ## Descriptions

  Descriptions are comments that allow you to document your Schema

  Single line:

  ```gql
  "Single line comment"
  ```

  ```gql
  """
  Multi
  line
  comment
  """
  ```

raw_content:
  ---
  tags: [graphql]
  ---

  # Schema Definition Language

  SDL is the formal name for the syntax of GraphQL schemas.

  ## Types

  A schema is a collection of object types that contain fields. Each field has a
  type of its own. A field's type can be a primitive/scalar value (such as an
  `Int` or a `String`), or it can be another object type (just like a custom type
  in TS).

  A schema's type can be non-nullable which is to say, a required field. We
  indicate this with `!`.

  A type for a field can be a collection/array of a given type.

  The following example indicates these properties:

  ```gql
  type Person {
    age: Int
    name: String
    pets: [Pet]!
  }

  type Pet {
    species: String
    name: String
    age: Int
  }
  ```

  ## Queries

  A query is also a schema type but of a special sort.

  > The fields of this type are entry points into the rest of the schema. These
  > are the top-level fields that the client can query for.

  For example if we had this type:

  ```graphql
  type Track {
    id: ID!
      author: Author!
    thumbnail: String
    length: Int
    modulesCount: Int
  }
  ```

  We could define a type to access a give `Track` as follows:

  ```graphql
  type Query {
    tracksForHomePage: [Track!]!
  }
  ```

  Then use this type as the basis for a query:

  ```

  ```

  ## Descriptions

  Descriptions are comments that allow you to document your Schema

  Single line:

  ```gql
  "Single line comment"
  ```

  ```gql
  """
  Multi
  line
  comment
  """
  ```


path: Secrets_or_env_vars_in_AWS.md
sortable_path: Secrets_or_env_vars_in_AWS.md
title: Secrets or environment variables?
checksum: 5dbb25aea37698bb6cf861e39dfd15ee9823b0e0e928f76e9d1d4e3899538a9b
created: 2025-10-01 13:31:01.368507627+00:00
modified: 2025-08-13 15:57:14.043463647+00:00
metadata: {"tags":["AWS","aws-lambda"]}
lead:
  Choosing between environment variables and AWS Secrets Manager hinges on factors
  such as use case, security needs, and the data type. Environment variables are
  easier to use, free, and offer fast access but are less secure and lack features
  like versioning. On the other hand, AWS Secrets Manager provides robust security
  through encryption, access control, audit trails, and supports secret versioning
  and rotation. However, it comes with additional costs and can introduce latency
  and rate limits.

body:
  Choosing between environment variables and AWS Secrets Manager hinges on factors
  such as use case, security needs, and the data type. Environment variables are
  easier to use, free, and offer fast access but are less secure and lack features
  like versioning. On the other hand, AWS Secrets Manager provides robust security
  through encryption, access control, audit trails, and supports secret versioning
  and rotation. However, it comes with additional costs and can introduce latency
  and rate limits.

  General recommendations suggest using AWS Secrets Manager for storing sensitive
  data like API keys and passwords, due to its enhanced security features. For
  less sensitive, non-critical data such as feature flags or environment-specific
  URLs, environment variables are often adequate. Cost-conscious users who don't
  need advanced features may find environment variables more economical.
  Ultimately, the best choice depends on your specific requirements and
  limitations.

raw_content:
  ---
  tags: [AWS, aws-lambda]
  ---

  # Secrets or environment variables?

  Choosing between environment variables and AWS Secrets Manager hinges on factors
  such as use case, security needs, and the data type. Environment variables are
  easier to use, free, and offer fast access but are less secure and lack features
  like versioning. On the other hand, AWS Secrets Manager provides robust security
  through encryption, access control, audit trails, and supports secret versioning
  and rotation. However, it comes with additional costs and can introduce latency
  and rate limits.

  General recommendations suggest using AWS Secrets Manager for storing sensitive
  data like API keys and passwords, due to its enhanced security features. For
  less sensitive, non-critical data such as feature flags or environment-specific
  URLs, environment variables are often adequate. Cost-conscious users who don't
  need advanced features may find environment variables more economical.
  Ultimately, the best choice depends on your specific requirements and
  limitations.


path: Secure_disk_wipe.md
sortable_path: Secure_disk_wipe.md
title: Secure disk wipe
lead:
  ```sh
  sudo shred -v -n 2 -z /dev/sda1
  ```

checksum: 7546b1c37f691d847eadc93916c465451bfeed81a8f6f8c860bb496555ea38db
created: 2025-10-01 13:31:01.37353593+00:00
modified: 2025-08-13 15:57:13.897388433+00:00
metadata: {"created":"Saturday, April 26, 2025","tags":["disks","procedural"]}
body:
  ```sh
  sudo shred -v -n 2 -z /dev/sda1
  ```

  Overwrites the disk with random data multiple times (`-n 2`) and finishes with
  zeros (`-z`).

  The more overwrites you specify, the longer it takes. Three overwrites on a USB
  flash disk can take like three hours so use advisedly.

raw_content:
  ---
  tags: [disks, procedural]
  created: Saturday, April 26, 2025
  ---

  # Secure disk wipe

  ```sh
  sudo shred -v -n 2 -z /dev/sda1
  ```

  Overwrites the disk with random data multiple times (`-n 2`) and finishes with
  zeros (`-z`).

  The more overwrites you specify, the longer it takes. Three overwrites on a USB
  flash disk can take like three hours so use advisedly.


path: Semantic_versioning.md
sortable_path: Semantic_versioning.md
title: Semantic versioning
lead:
  ```
  3.4.1 === major.minor.patch
  ```

checksum: 594b1e9ce9125afba02b6d41efe4af9a53aff06bff3ab7739bc2e89e65f6d664
created: 2025-10-01 13:31:01.379592847+00:00
modified: 2025-08-13 15:57:14.020451533+00:00
metadata: {"tags":[]}
body:
  ```
  3.4.1 === major.minor.patch
  ```

  - Major

    - New feature which may potentially cause breaking changes to applications
      dependent on the previous major version.

  - Minor

    - New features that do not break the existing API

  - Patch

    - Bug fixes for the current minor version

  ## Glob patterns for versioning

  ### Caret

  Interested in any version so long as the major version remains at $n$. E.g if we
  are at `^4.2.1` and we upgrade, we are ok with `4.5.3` or `4.8.2`. We are not
  bothered about the minor or patch version.

  This is equivalent to `4.x`

  ### Tilde

  Interested in any patch version within set major and minor parameters. For
  example `~1.8.3` means you don't mind any patch version so long as it is a patch
  for `1.8`. This is equivalent to `1.8.x`.

  ### No tilde or caret

  Use the _exact_ version specified

raw_content:
  ---
  tags: []
  ---

  # Semantic versioning

  ```
  3.4.1 === major.minor.patch
  ```

  - Major

    - New feature which may potentially cause breaking changes to applications
      dependent on the previous major version.

  - Minor

    - New features that do not break the existing API

  - Patch

    - Bug fixes for the current minor version

  ## Glob patterns for versioning

  ### Caret

  Interested in any version so long as the major version remains at $n$. E.g if we
  are at `^4.2.1` and we upgrade, we are ok with `4.5.3` or `4.8.2`. We are not
  bothered about the minor or patch version.

  This is equivalent to `4.x`

  ### Tilde

  Interested in any patch version within set major and minor parameters. For
  example `~1.8.3` means you don't mind any patch version so long as it is a patch
  for `1.8`. This is equivalent to `1.8.x`.

  ### No tilde or caret

  Use the _exact_ version specified


path: Set_DNS_settings.md
sortable_path: Set_DNS_settings.md
title: Set DNS settings
lead: ## Change the default DNS server
checksum: 8738741f92558b074e041faf3977111bd051bb9d94f0023312135b2c883d4927
created: 2025-10-01 13:31:01.385967649+00:00
modified: 2025-10-06 18:12:53.766402148+00:00
metadata: {"created":"Wednesday, June 12, 2024","id":"2w0e","tags":["Linux","networks"]}
body:
  ## Change the default DNS server

  On Arch and most modern Linux distributions domain name resolution is handled
  via the `systemd-resolved` #systemd configuration.

  Within the system systemd files this will be handled in
  `/etc/systemd/network/wired.network` or `/etc/systemd/network/wlan.network`
  files etc.

  In the file below I have turned of DHCP routing and specified the address of my
  Pi-Hole device to handle domain name resolution:

  ```
  #wlan.network

  [Match]
  Name=wl*

  [Link]
  RequiredForOnline=routable

  [Network]
  DHCP=yes
  DNS=192.168.0.4
  MulticastDNS=yes

  [DHCPv4]
  UseDNS=no
  RouteMetric=600

  [IPv6AcceptRA]
  RouteMetric=600

  ```

  This stops it using the default DNS server of my router and runs the resolutions
  against Pi-Hole.

  This should automatically update the two `resolv.conf` files (which should be in
  syc), viz:

  ```
  # File: /run/NetworkManager/resolv.conf
  # Generated by NetworkManager
  nameserver 192.168.0.4
  nameserver fded:2060:8671:0:681:9bff:fe9b:37f0

  ```

  ```
  # File: /etc/resolv.conf
  # Generated by NetworkManager
  nameserver 192.168.0.4
  nameserver fded:2060:8671:0:681:9bff:fe9b:37f0

  ```

  ## Related notes

  ![Network scanning](./Network_scanning.md)
  ![Network debugging](Network_debugging.md)

raw_content:
  ---
  id: 2w0e
  tags: [Linux, networks]
  created: Wednesday, June 12, 2024
  ---

  # Set DNS settings

  ## Change the default DNS server

  On Arch and most modern Linux distributions domain name resolution is handled
  via the `systemd-resolved` #systemd configuration.

  Within the system systemd files this will be handled in
  `/etc/systemd/network/wired.network` or `/etc/systemd/network/wlan.network`
  files etc.

  In the file below I have turned of DHCP routing and specified the address of my
  Pi-Hole device to handle domain name resolution:

  ```
  #wlan.network

  [Match]
  Name=wl*

  [Link]
  RequiredForOnline=routable

  [Network]
  DHCP=yes
  DNS=192.168.0.4
  MulticastDNS=yes

  [DHCPv4]
  UseDNS=no
  RouteMetric=600

  [IPv6AcceptRA]
  RouteMetric=600

  ```

  This stops it using the default DNS server of my router and runs the resolutions
  against Pi-Hole.

  This should automatically update the two `resolv.conf` files (which should be in
  syc), viz:

  ```
  # File: /run/NetworkManager/resolv.conf
  # Generated by NetworkManager
  nameserver 192.168.0.4
  nameserver fded:2060:8671:0:681:9bff:fe9b:37f0

  ```

  ```
  # File: /etc/resolv.conf
  # Generated by NetworkManager
  nameserver 192.168.0.4
  nameserver fded:2060:8671:0:681:9bff:fe9b:37f0

  ```

  ## Related notes

  ![Network scanning](./Network_scanning.md)
  ![Network debugging](Network_debugging.md)


path: Sets_in_Python.md
sortable_path: Sets_in_Python.md
title: Sets in Python
checksum: 766c8d1f8a0736bf3d4e5e1f15ba881fe068dd8f6f2b0d8888c184a25608328a
created: 2025-10-01 13:31:01.392267668+00:00
modified: 2025-08-13 15:57:13.919927265+00:00
metadata: {"tags":["python","data-structures"]}
lead:
  - They are **unordered**
  - You can increase/decrease their length by adding/removing new members
  - They **do not allow duplicate members**
  - **Can only hold immutable objects**

body:
  - They are **unordered**
  - You can increase/decrease their length by adding/removing new members
  - They **do not allow duplicate members**
  - **Can only hold immutable objects**

  > Sets are denoted with `{...}`

  ## Basic usage

  ```python
  basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
  print(basket)  # show that duplicates have been removed
  print(len(basket))
  # {'apple', 'pear', 'banana', 'orange'}
  # 4
  ```

  ## Looping through sets

  ```python
  for item in basket:
      print(item)

  """
  apple
  pear
  banana
  orange
  """
  ```

  ## Check for membership

  ```python
  basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
  print('apple' in basket)
  # True
  ```

  ## Remove items from set

  > `remove` will raise an error if the specified item does not exist, `discard`
  > will not

  ```python
  basket.remove('apple')
  basket.discard('apricot')
  print(basket)
  # {'pear', 'banana', 'orange'}

  basket.clear()
  print(basket)
  #set

  ```

  ## Add items to a set

  ```python
  basket.add('apricot')
  print(basket)
  # {'apricot', 'pear', 'banana', 'orange'}
  ```

  ## Start with empty set

  To declare an empty set you cannot just do:

  ```py
  my_set = {}
  ```

  You have to use a constructor:

  ```py
  my_set = set()
  ```

  ## Apply unions and intersections

  ```python
  s1 = {'apple', 'orange', 'banana'}
  s2 = {'grapefruit', 'lime', 'banana'}
  print('Union:', s1 | s2)
  # Union: {'apple', 'orange', 'grapefruit', 'lime', 'banana'}

  print('Intersection:', s1 & s2)
  # Intersection: {'banana'}


  print('Difference:', s1 - s2)
  # Difference: {'orange', 'apple'}

  print('Symmetric Difference:', s1 ^ s2)
  #Symmetric Difference: {'apple', 'orange', 'grapefruit', 'lime'}

  ```

raw_content:
  ---
  tags: [python, data-structures]
  ---

  # Sets in Python

  - They are **unordered**
  - You can increase/decrease their length by adding/removing new members
  - They **do not allow duplicate members**
  - **Can only hold immutable objects**

  > Sets are denoted with `{...}`

  ## Basic usage

  ```python
  basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
  print(basket)  # show that duplicates have been removed
  print(len(basket))
  # {'apple', 'pear', 'banana', 'orange'}
  # 4
  ```

  ## Looping through sets

  ```python
  for item in basket:
      print(item)

  """
  apple
  pear
  banana
  orange
  """
  ```

  ## Check for membership

  ```python
  basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
  print('apple' in basket)
  # True
  ```

  ## Remove items from set

  > `remove` will raise an error if the specified item does not exist, `discard`
  > will not

  ```python
  basket.remove('apple')
  basket.discard('apricot')
  print(basket)
  # {'pear', 'banana', 'orange'}

  basket.clear()
  print(basket)
  #set

  ```

  ## Add items to a set

  ```python
  basket.add('apricot')
  print(basket)
  # {'apricot', 'pear', 'banana', 'orange'}
  ```

  ## Start with empty set

  To declare an empty set you cannot just do:

  ```py
  my_set = {}
  ```

  You have to use a constructor:

  ```py
  my_set = set()
  ```

  ## Apply unions and intersections

  ```python
  s1 = {'apple', 'orange', 'banana'}
  s2 = {'grapefruit', 'lime', 'banana'}
  print('Union:', s1 | s2)
  # Union: {'apple', 'orange', 'grapefruit', 'lime', 'banana'}

  print('Intersection:', s1 & s2)
  # Intersection: {'banana'}


  print('Difference:', s1 - s2)
  # Difference: {'orange', 'apple'}

  print('Symmetric Difference:', s1 ^ s2)
  #Symmetric Difference: {'apple', 'orange', 'grapefruit', 'lime'}

  ```


path: Setting_up_and_configuring_TypeScript.md
sortable_path: Setting_up_and_configuring_TypeScript.md
title: Setup and configuration
lead: ## Installation and configuration
checksum: 7ad962fc516dcea03815580140ae449dfaeb4c74b9e330cc4b8199af5454edf1
created: 2025-10-01 13:31:01.398514102+00:00
modified: 2025-08-13 15:57:14.010580096+00:00
metadata: {"tags":["typescript"]}
body:
  ## Installation and configuration

  TypeScript offers custom installations for most modern JS-based frameworks
  including Webpack, React.js and Vue.js. The instructions below cover minimal TS
  set-up outside of a specific framework. TypeScript adds an additional step to
  any build process since your code must compile to JS before any bundling and
  transpilation can occur.

  ## Installation

  ```
  mkdir typescript-project
  cd typescript-project
  npm i typescript --save-dev
  ```

  ## Initialise project

  ```
  npx tsc --init
  ```

  ## Basic configuration

  ```json
  "compilerOptions": {
  	"target" : "es2020", //es2015 for prod
  	"module" : "es2020",
    	"allowJs": true,
    	"checkJs": true,
    	"strict": true,
    	"esModuleInterop": true
  }
  ```

  ### Specify output paths (for production code)

  ```json
  "compilerOptions": {
  	...
  	"outDir": "dist",
  	"sourceMap": true,
  }
  ```

  ### Compile-time commands

  ```
  tsc --noEmit
  ```

  ```
  tsc --noEmit --watch
  ```

  ## Global requirements

  ```
  npm install -g typescript
  npm install -g ts-node
  ```

  `ts-node` allows you to run TS files the way you would with standard JS, i.e.
  `node [filename]`, you just use `ts-node filename` .

  This is a convenience that saves you compiling from TS → JS and then running
  Node against the compiled JS. Which is useful for debugging and checking values
  as you work.

  ## Imports and exports

  You may wish to define your custom types outside of their application, for
  instance in a `/types/` directory. The custom type or types can then be imported
  using standard ES6 imports:

  ```tsx
  export type Article = {
  		price: number,
  }

  export type AnotherType = {
  ...
  }
  ```

  ```tsx
  import { Article, AnotherType } from "./types/allTypes.js";
  import Article from "./types/allTypes.js";
  ```

  TypeScript also provides a specific import keyword `type` so that you can
  distinguish type imports from other module imports. This is handy when you have
  multiple components in the one file:

  ```tsx
  import type { Article } from "./types/allTypes.js";
  ```

raw_content:
  ---
  tags:
    - typescript
  ---

  # Setup and configuration

  ## Installation and configuration

  TypeScript offers custom installations for most modern JS-based frameworks
  including Webpack, React.js and Vue.js. The instructions below cover minimal TS
  set-up outside of a specific framework. TypeScript adds an additional step to
  any build process since your code must compile to JS before any bundling and
  transpilation can occur.

  ## Installation

  ```
  mkdir typescript-project
  cd typescript-project
  npm i typescript --save-dev
  ```

  ## Initialise project

  ```
  npx tsc --init
  ```

  ## Basic configuration

  ```json
  "compilerOptions": {
  	"target" : "es2020", //es2015 for prod
  	"module" : "es2020",
    	"allowJs": true,
    	"checkJs": true,
    	"strict": true,
    	"esModuleInterop": true
  }
  ```

  ### Specify output paths (for production code)

  ```json
  "compilerOptions": {
  	...
  	"outDir": "dist",
  	"sourceMap": true,
  }
  ```

  ### Compile-time commands

  ```
  tsc --noEmit
  ```

  ```
  tsc --noEmit --watch
  ```

  ## Global requirements

  ```
  npm install -g typescript
  npm install -g ts-node
  ```

  `ts-node` allows you to run TS files the way you would with standard JS, i.e.
  `node [filename]`, you just use `ts-node filename` .

  This is a convenience that saves you compiling from TS → JS and then running
  Node against the compiled JS. Which is useful for debugging and checking values
  as you work.

  ## Imports and exports

  You may wish to define your custom types outside of their application, for
  instance in a `/types/` directory. The custom type or types can then be imported
  using standard ES6 imports:

  ```tsx
  export type Article = {
  		price: number,
  }

  export type AnotherType = {
  ...
  }
  ```

  ```tsx
  import { Article, AnotherType } from "./types/allTypes.js";
  import Article from "./types/allTypes.js";
  ```

  TypeScript also provides a specific import keyword `type` so that you can
  distinguish type imports from other module imports. This is handy when you have
  multiple components in the one file:

  ```tsx
  import type { Article } from "./types/allTypes.js";
  ```


path: Setup encrypted harddrive.md
sortable_path: Setup encrypted harddrive.md
title: Setup an encrypted harddrive
checksum: 6eb802bbca6795f4feca4f0acf11b34b5e2cbe944e9c6e6ec815dfbfafdbd0ea
created: 2025-10-01 13:31:01.403358014+00:00
modified: 2025-02-11 18:11:41.796385106+00:00
metadata: {"created":"Monday, February 10, 2025","tags":["procedural","disks","encryption"]}
lead:
  Firstly [create a new partition](./Creating_a_Linux_partition_table.md) on the
  unencrypted drive with `fdisk`.

body:
  Firstly [create a new partition](./Creating_a_Linux_partition_table.md) on the
  unencrypted drive with `fdisk`.

  Create LUKs encryption:

  ```sh
  sudo cryptsetup luksFormat /dev/sdX
  ```

  Enter password when prompted.

  Open the encrypted drive with the name you want to use henceforth:

  ```sh
  sudo cryptsetup luksOpen /dev/sdX my_device_name
  ```

  Create filesystem:

  ```sh
  sudo mkfs.ext4 /dev/mapper/my_device_name
  ```

  Set mount point:

  ```sh
  sudo mkdir -p /media/my_device_name
  ```

  Mount:

  ```sh
  sudo mount /dev/mapper/my_device_name /media/my_device_name
  ```

  Add it to the crypttab:

  ```sh
  vim /etc/crypttab
  ```

  Get UUID for device with:

  ```
  sudo blkid /dev/sdx
  ```

  Add entry:

  ```txt
  my_device_name UUID="ae028027-20c5-40b6-9311-11f5a886f125" none noauto
  ```

  Then add it as a lint in the fstab for auto-mount:

  ```sh
  /dev/mapper/my_device_name /media/my_device_name ext4 defaults,nofail,noauto,user 0 2
  ```

  Give yourself full permissions (set once, then permanent):

  ```sh
  sudo chown thomas:thomas /meda/my_device_name
  sudo chmod 755 /media/my_device_name
  ```

  Make sure it shows up with its intended name:

  ```sh
  sudo e2label /dev/mapper/samsung-T3 samsung-T3
  ```

  (Where second value is the name we want it to show as.)

  Test auto-mount and loading from crypttab:

  First reload `systemd`:

  ```sh
  sudo systemctl daemon-reload
  ```

  Then, remount all disks.

  ```sh
  sudo mount -a
  ```

  Should be prompted for password and disk decrypts and mounts to specified mount
  point.

  ## Additional points

  Close LUKS (if you make a mistake):

  ```sh
  sudo cryptsetup luksClose device_name

  ```

  Remove vendor data to unlock more space:

  ```sh
  sudo tune2fs -m 0 /dev/mapper/samsung-T3
  ```

raw_content:
  ---
  tags: [procedural, disks, encryption]
  created: Monday, February 10, 2025
  ---

  # Setup an encrypted harddrive

  Firstly [create a new partition](./Creating_a_Linux_partition_table.md) on the
  unencrypted drive with `fdisk`.

  Create LUKs encryption:

  ```sh
  sudo cryptsetup luksFormat /dev/sdX
  ```

  Enter password when prompted.

  Open the encrypted drive with the name you want to use henceforth:

  ```sh
  sudo cryptsetup luksOpen /dev/sdX my_device_name
  ```

  Create filesystem:

  ```sh
  sudo mkfs.ext4 /dev/mapper/my_device_name
  ```

  Set mount point:

  ```sh
  sudo mkdir -p /media/my_device_name
  ```

  Mount:

  ```sh
  sudo mount /dev/mapper/my_device_name /media/my_device_name
  ```

  Add it to the crypttab:

  ```sh
  vim /etc/crypttab
  ```

  Get UUID for device with:

  ```
  sudo blkid /dev/sdx
  ```

  Add entry:

  ```txt
  my_device_name UUID="ae028027-20c5-40b6-9311-11f5a886f125" none noauto
  ```

  Then add it as a lint in the fstab for auto-mount:

  ```sh
  /dev/mapper/my_device_name /media/my_device_name ext4 defaults,nofail,noauto,user 0 2
  ```

  Give yourself full permissions (set once, then permanent):

  ```sh
  sudo chown thomas:thomas /meda/my_device_name
  sudo chmod 755 /media/my_device_name
  ```

  Make sure it shows up with its intended name:

  ```sh
  sudo e2label /dev/mapper/samsung-T3 samsung-T3
  ```

  (Where second value is the name we want it to show as.)

  Test auto-mount and loading from crypttab:

  First reload `systemd`:

  ```sh
  sudo systemctl daemon-reload
  ```

  Then, remount all disks.

  ```sh
  sudo mount -a
  ```

  Should be prompted for password and disk decrypts and mounts to specified mount
  point.

  ## Additional points

  Close LUKS (if you make a mistake):

  ```sh
  sudo cryptsetup luksClose device_name

  ```

  Remove vendor data to unlock more space:

  ```sh
  sudo tune2fs -m 0 /dev/mapper/samsung-T3
  ```


path: Shell_sessions.md
sortable_path: Shell_sessions.md
title: Shell sessions
lead: ## **Types of shell session**
checksum: 26f3c11dcd8dbb538a894ab5e4ce2d6cb0c116f02b0ae59b2745a90995db3502
created: 2025-10-01 13:31:01.414883279+00:00
modified: 2025-08-13 15:57:13.82165336+00:00
metadata: {"tags":["shell"]}
body:
  ## **Types of shell session**

  Shell sessions can be one of or several instances of the following types:

  - **login shell**
    - A session that must be authenticated such as when you access remote
      resources using SSH
  - **non-login shell**
    - Not the above
  - **interactive shell**
    - A shell session that runs in the terminal and thus that the user can
      _interact_ with
  - **non-interactive shell**
    - A shell session that runs without a terminal

  If you are working with a remote server you will be in an **interactive login
  shell**. If you run a script from the command line you will be in a
  **non-interactive non-login shell**.

  ## Shell sessions and access

  The type of shell session that you are currently in affects the
  [environmental and shell variables](Environmental-and-shell-variables-04d5ec7e8e2b486a93f002bf686e4bbb)
  that you can access. This is because the order in which configuration files are
  read on initialisation differs depending on the type of shell.

  - a session defined as a non-login shell will read `/etc/bash.bashrc` and then
    the user-specific `~/.bashrc` file to build its environment.
  - A session started as a login session will read configuration details from the
    `/etc/profile` file first. It will then look for the first login shell
    configuration file in the user’s home directory to get user-specific
    configuration details.

  In Linux, if you want the environmental variable to be accessible from both
  login and non-login shells, you must put them in `~/.bashrc`

raw_content:
  ---
  tags:
    - shell
  ---

  # Shell sessions

  ## **Types of shell session**

  Shell sessions can be one of or several instances of the following types:

  - **login shell**
    - A session that must be authenticated such as when you access remote
      resources using SSH
  - **non-login shell**
    - Not the above
  - **interactive shell**
    - A shell session that runs in the terminal and thus that the user can
      _interact_ with
  - **non-interactive shell**
    - A shell session that runs without a terminal

  If you are working with a remote server you will be in an **interactive login
  shell**. If you run a script from the command line you will be in a
  **non-interactive non-login shell**.

  ## Shell sessions and access

  The type of shell session that you are currently in affects the
  [environmental and shell variables](Environmental-and-shell-variables-04d5ec7e8e2b486a93f002bf686e4bbb)
  that you can access. This is because the order in which configuration files are
  read on initialisation differs depending on the type of shell.

  - a session defined as a non-login shell will read `/etc/bash.bashrc` and then
    the user-specific `~/.bashrc` file to build its environment.
  - A session started as a login session will read configuration details from the
    `/etc/profile` file first. It will then look for the first login shell
    configuration file in the user’s home directory to get user-specific
    configuration details.

  In Linux, if you want the environmental variable to be accessible from both
  login and non-login shells, you must put them in `~/.bashrc`


path: Signed_and_unsigned_numbers.md
sortable_path: Signed_and_unsigned_numbers.md
title: Signed and unsigned numbers
lead: ## Summary
checksum: 0dd060a4662e8b9daf6a58073529520afc171a28313f6d60e2b57179598a782c
created: 2025-10-01 13:31:01.439215471+00:00
modified: 2025-08-13 15:57:13.966592758+00:00
metadata: {"tags":["binary"]}
body:
  ## Summary

  - To represent negative integers in binary we use signed numbers._Signed binary_
    includes negative integers, _unsigned binary_ does not.

  - There are different methods of implementing the encoding of signed numbers.
    Two prominant approaches are **two's complement** and **signed magnitude
    representation**.

  ## Related notes

  [[Twos_complement]], [[Binary_encoding]], [[Signed_magnitude_representation]]

raw_content:
  ---
  tags:
    - binary
  ---

  # Signed and unsigned numbers

  ## Summary

  - To represent negative integers in binary we use signed numbers._Signed binary_
    includes negative integers, _unsigned binary_ does not.

  - There are different methods of implementing the encoding of signed numbers.
    Two prominant approaches are **two's complement** and **signed magnitude
    representation**.

  ## Related notes

  [[Twos_complement]], [[Binary_encoding]], [[Signed_magnitude_representation]]


path: Signed_magnitude_representation.md
sortable_path: Signed_magnitude_representation.md
title: Signed magnitude representation
lead: ## Summary
checksum: e67bf5f2f83b3ec515f89bcc2427c89b3922143c936bd0c8130a383a4c654f62
created: 2025-10-01 13:31:01.479977624+00:00
modified: 2025-08-13 15:57:13.746921824+00:00
metadata: {"created":"Wednesday, March 20, 2024","id":"3wsh","tags":["binary"]}
body:
  ## Summary

  ## Detail

  The concept behind SMR is similar to how we designate positive and negative
  integers in denary mathematics: we use a dedicated symbol (`-`) to signpost that
  the integer is negative. In the binary application the dedicated symbol is one
  of the binary digits that comprise the number.

  Typically `0` is used to indicate an unsigned (positive) integer and `1` to
  indicate a signed (negative) number. The rest of the bits are the magnitude (the
  actual numerical value).

  We can demonstrate with an 8-bit binary system, encoding `5`: `0000 0101`. Here
  the furthest bit (aka. the "most significant bit" (MSB)) at the $2^8$ position
  is `0`, designating that the number is unsigned. The signed equivalent is
  `1000 0101`, with the MSB being `1` designating the number as signed. When we
  are working with signed numbers, the MSB is known as the **signed bit**.

  ### Advantages

  ### Limitations

  ## Applications

  ## Related notes

  [[Signed_and_unsigned_numbers|signed_and_unsigned_numbers]]

raw_content:
  ---
  id: 3wsh
  tags:
    - binary
  created: Wednesday, March 20, 2024
  ---

  # Signed magnitude representation

  ## Summary

  ## Detail

  The concept behind SMR is similar to how we designate positive and negative
  integers in denary mathematics: we use a dedicated symbol (`-`) to signpost that
  the integer is negative. In the binary application the dedicated symbol is one
  of the binary digits that comprise the number.

  Typically `0` is used to indicate an unsigned (positive) integer and `1` to
  indicate a signed (negative) number. The rest of the bits are the magnitude (the
  actual numerical value).

  We can demonstrate with an 8-bit binary system, encoding `5`: `0000 0101`. Here
  the furthest bit (aka. the "most significant bit" (MSB)) at the $2^8$ position
  is `0`, designating that the number is unsigned. The signed equivalent is
  `1000 0101`, with the MSB being `1` designating the number as signed. When we
  are working with signed numbers, the MSB is known as the **signed bit**.

  ### Advantages

  ### Limitations

  ## Applications

  ## Related notes

  [[Signed_and_unsigned_numbers|signed_and_unsigned_numbers]]


path: Single_file_Python_scripts.md
sortable_path: Single_file_Python_scripts.md
title: Single file Python scripts
lead: ## Basic architecture
checksum: 2d0d41cfcee32ec153064d4c0d1406b519060f4d9e532ac7c3ec99c23417e087
created: 2025-10-01 13:31:01.490073884+00:00
modified: 2025-08-13 15:57:13.927972445+00:00
metadata: {"created":"Friday, April 26, 2024","id":"atzw","tags":[]}
body:
  ## Basic architecture

  ```py
  #! /usr/local/bin/python3

  import sys

  if __name__ == "__main__":
      all_args = sys.argv
      specific_arg = sys.argv[0]
      # Main functionality...
  ```

  When you run a script (module) Python assigns the string `__main__` to the
  `__name__` attribute to the script that is being executed.

  If you run the script as an import into another script, the `__name__` attribute
  of the imported module is set to the module name, not `__main__`.

  Everything can go under the `__main__` conditional, or, for better readability,
  you can define a `main` function that is then invoked, e.g:

  ```py

  def main():
      # Do some stuff


  if __name__ == "__main__":
      main()

  ```

  ## Related notes

  ![Python modules and imports](./Python_modules_and_imports.md)

raw_content:
  ---
  id: atzw
  tags: []
  created: Friday, April 26, 2024
  ---

  # Single file Python scripts

  ## Basic architecture

  ```py
  #! /usr/local/bin/python3

  import sys

  if __name__ == "__main__":
      all_args = sys.argv
      specific_arg = sys.argv[0]
      # Main functionality...
  ```

  When you run a script (module) Python assigns the string `__main__` to the
  `__name__` attribute to the script that is being executed.

  If you run the script as an import into another script, the `__name__` attribute
  of the imported module is set to the module name, not `__main__`.

  Everything can go under the `__main__` conditional, or, for better readability,
  you can define a `main` function that is then invoked, e.g:

  ```py

  def main():
      # Do some stuff


  if __name__ == "__main__":
      main()

  ```

  ## Related notes

  ![Python modules and imports](./Python_modules_and_imports.md)


path: Singleton_pattern.md
sortable_path: Singleton_pattern.md
title: Singleton pattern
checksum: ebd298f9be5d23d7e04ae08f387e54cf7a68057fd40d34209959ea08cbbe4e70
created: 2025-10-01 13:31:01.495024064+00:00
modified: 2025-08-13 15:57:13.811632613+00:00
metadata: {"tags":["OOP","design-patterns"]}
lead:
  As the name suggests, the Singleton pattern is best used in scenarios where you
  only want to use a single, unique instance of a class. This is for functionality
  that should only be executed once in the lifecycle of an application. The
  canonical case would be some kind of bootstrapping process required at
  initialisation, or initial configuration for an app.

body:
  As the name suggests, the Singleton pattern is best used in scenarios where you
  only want to use a single, unique instance of a class. This is for functionality
  that should only be executed once in the lifecycle of an application. The
  canonical case would be some kind of bootstrapping process required at
  initialisation, or initial configuration for an app.

  ## Use-cases

  - Establishing connection to backend database
  - API connection (managing tokens so that you are not sending multiple
    unnecessary calls)
  - Configuration settings for an app
  - Global state stores in Redux and the React Context API

  > With this pattern only one instance of the class can exist. If no instance of
  > the singleton class exists then a new instance is created and returned, but if
  > an instance already exists, then the reference to the existing instance is
  > returned. A singleton should be immutable by the consuming code, and there
  > should be no danger of instantiating more than one of them.

  ## Implementation

  This pattern can be implemented either with a object or a class.

  In the example below, a global store for a modern JS application is created
  using an object.

  ### Using an object

  We ensure singularity by:

  - using `const` for the object so that it cannot be reassigned
  - using `Object.freeze` so that the fields cannot be overwritten, deleted, or
    additional fields added

  ```js
  const _data = [];

  // Methods to add and retrieve data from the store
  const UserStore = {
    add: (item) => _data.push(item),
    get: (id) => _data.find((d) => d.id === id),
  };

  Object.freeze(UserStore);
  export default UserStore;
  ```

  ### Using a class

  The same process can be created using classes:

  ```js
  class UserStore {
    constructor() {
      this._data = [];
    }

    add(item) {
      this._data.push(item);
    }

    get(id) {
      return this._data.find((d) => d.id === id);
    }
  }

  const instance = new UserStore();
  Object.freeze(instance);

  export default instance;
  ```

  Bear in mind that this is really just an ES6 module with `freeze` applied. The
  only real difference between a singleton and a module is that there should only
  be one instance of it.

  With classes, there is a further step that can be taken to prevent more than
  once instance of the class being created. This is necessary if you want to be
  really strict because it is of course possible for a well motivated person to
  get around the safeguards we established above. We do this by having the class
  itself check whether there is already an instance of itself. If so, it just
  returns the already existing instance. We do this by using the self-reference
  inherent in `this` :

  ```jsx
  class UserStore {
    constructor() {
      if (!UserStore.instance) {
        this._data = [];
        UserStore.instance = this;
      }

      return UserStore.instance;
    }

    //rest is the same code as preceding example
  }

  const instance = new UserStore();
  Object.freeze(instance);

  export default instance;
  ```

raw_content:
  ---
  tags:
    - OOP
    - design-patterns
  ---

  # Singleton pattern

  As the name suggests, the Singleton pattern is best used in scenarios where you
  only want to use a single, unique instance of a class. This is for functionality
  that should only be executed once in the lifecycle of an application. The
  canonical case would be some kind of bootstrapping process required at
  initialisation, or initial configuration for an app.

  ## Use-cases

  - Establishing connection to backend database
  - API connection (managing tokens so that you are not sending multiple
    unnecessary calls)
  - Configuration settings for an app
  - Global state stores in Redux and the React Context API

  > With this pattern only one instance of the class can exist. If no instance of
  > the singleton class exists then a new instance is created and returned, but if
  > an instance already exists, then the reference to the existing instance is
  > returned. A singleton should be immutable by the consuming code, and there
  > should be no danger of instantiating more than one of them.

  ## Implementation

  This pattern can be implemented either with a object or a class.

  In the example below, a global store for a modern JS application is created
  using an object.

  ### Using an object

  We ensure singularity by:

  - using `const` for the object so that it cannot be reassigned
  - using `Object.freeze` so that the fields cannot be overwritten, deleted, or
    additional fields added

  ```js
  const _data = [];

  // Methods to add and retrieve data from the store
  const UserStore = {
    add: (item) => _data.push(item),
    get: (id) => _data.find((d) => d.id === id),
  };

  Object.freeze(UserStore);
  export default UserStore;
  ```

  ### Using a class

  The same process can be created using classes:

  ```js
  class UserStore {
    constructor() {
      this._data = [];
    }

    add(item) {
      this._data.push(item);
    }

    get(id) {
      return this._data.find((d) => d.id === id);
    }
  }

  const instance = new UserStore();
  Object.freeze(instance);

  export default instance;
  ```

  Bear in mind that this is really just an ES6 module with `freeze` applied. The
  only real difference between a singleton and a module is that there should only
  be one instance of it.

  With classes, there is a further step that can be taken to prevent more than
  once instance of the class being created. This is necessary if you want to be
  really strict because it is of course possible for a well motivated person to
  get around the safeguards we established above. We do this by having the class
  itself check whether there is already an instance of itself. If so, it just
  returns the already existing instance. We do this by using the self-reference
  inherent in `this` :

  ```jsx
  class UserStore {
    constructor() {
      if (!UserStore.instance) {
        this._data = [];
        UserStore.instance = this;
      }

      return UserStore.instance;
    }

    //rest is the same code as preceding example
  }

  const instance = new UserStore();
  Object.freeze(instance);

  export default instance;
  ```


path: Sliding_window.md
sortable_path: Sliding_window.md
title: Sliding window
checksum: 0875187e1b5247dc2b2f87bb9c15e41780ada662f3b8e6efbbcd79a6d0a7b251
created: 2025-10-01 13:31:01.501439587+00:00
modified: 2025-08-13 15:57:14.027392941+00:00
metadata: {"tags":["design-patterns"]}
lead:
  Whereas the [multiple pointer](Multiple_pointers.md) pattern works by keeping
  two array indices running at once and comparing their values on each iteration,
  the sliding window has a running value (the 'window') that is updated at each
  iteration and which compares itself against its most recent previous value.

body:
  Whereas the [multiple pointer](Multiple_pointers.md) pattern works by keeping
  two array indices running at once and comparing their values on each iteration,
  the sliding window has a running value (the 'window') that is updated at each
  iteration and which compares itself against its most recent previous value.

  This is what makes it 'sliding': the value isn't constant, it changes (or
  doesn't) based on what it was previously.

  ## Example: maximum sum of sub-array

  We create a function that takes an array and a sub-array length _n_. The
  objective is to find the maximum value that can be created by summing _n_
  elements of the array. It moves through the array, summing by _n_ keeping track
  of the highest sum value so far and the current sum value. At the end it should
  return the highest possible sum value.

  Here we do this for a sub-array of length 2:

  ```ts
  function maxSubarraySum(arr, subArrLength) {
    let maxSum = 0; // Largest sum value so far
    let tempSum = 0; // Current sum value

    //  Establish the first 'maxSum'
    // At the beginning this will just be the sum of the first two array elements
    for (let i = 0; i < subArrLength; i++) {
      maxSum += arr[i];
    }

    // Map temporary sum to maxSum
    // Accordingly, as we have only mapped the first sub-array, the max sum will be the same
    // as the current sum
    tempSum = maxSum;

    // Move through the array one element at a time (`i++`) via a window starting from the element that is equal to `subArrLength`
    // The first sum calculation is already taken care of in the earlier loop and stored in `maxSum`, so we don't have to worry about missing the elements in indices less than subArrLength
    for (let i = subArrLength; i < arr.length; i++) {
      // Temp sum becomes a moveable window value equal to the subtraction of the previous element and the addition of next element in line
      tempSum = tempSum - arr[i - subArrLength] + arr[i];
      // Max sum is redefined as the largest subArrLengthber between the previous highest and the current value of tempSum
      maxSum = Math.max(maxSum, tempSum);
    }
    return maxSum;
  }

  console.log(maxSubarraySum([100, 200, 300, 400], 2)); // 700
  ```

raw_content:
  ---
  tags:
    - design-patterns
  ---

  # Sliding window

  Whereas the [multiple pointer](Multiple_pointers.md) pattern works by keeping
  two array indices running at once and comparing their values on each iteration,
  the sliding window has a running value (the 'window') that is updated at each
  iteration and which compares itself against its most recent previous value.

  This is what makes it 'sliding': the value isn't constant, it changes (or
  doesn't) based on what it was previously.

  ## Example: maximum sum of sub-array

  We create a function that takes an array and a sub-array length _n_. The
  objective is to find the maximum value that can be created by summing _n_
  elements of the array. It moves through the array, summing by _n_ keeping track
  of the highest sum value so far and the current sum value. At the end it should
  return the highest possible sum value.

  Here we do this for a sub-array of length 2:

  ```ts
  function maxSubarraySum(arr, subArrLength) {
    let maxSum = 0; // Largest sum value so far
    let tempSum = 0; // Current sum value

    //  Establish the first 'maxSum'
    // At the beginning this will just be the sum of the first two array elements
    for (let i = 0; i < subArrLength; i++) {
      maxSum += arr[i];
    }

    // Map temporary sum to maxSum
    // Accordingly, as we have only mapped the first sub-array, the max sum will be the same
    // as the current sum
    tempSum = maxSum;

    // Move through the array one element at a time (`i++`) via a window starting from the element that is equal to `subArrLength`
    // The first sum calculation is already taken care of in the earlier loop and stored in `maxSum`, so we don't have to worry about missing the elements in indices less than subArrLength
    for (let i = subArrLength; i < arr.length; i++) {
      // Temp sum becomes a moveable window value equal to the subtraction of the previous element and the addition of next element in line
      tempSum = tempSum - arr[i - subArrLength] + arr[i];
      // Max sum is redefined as the largest subArrLengthber between the previous highest and the current value of tempSum
      maxSum = Math.max(maxSum, tempSum);
    }
    return maxSum;
  }

  console.log(maxSubarraySum([100, 200, 300, 400], 2)); // 700
  ```


path: Solving_equations.md
sortable_path: Solving_equations.md
title: Solving equations
lead: ## Use inversion of operators
checksum: 9e92801bf8f641a6153875adfecdb611e634a9cc7d61d3dc7f72993961c41550
created: 2025-10-01 13:31:01.51277109+00:00
modified: 2025-08-13 15:57:13.937399033+00:00
metadata: {"tags":["algebra"]}
body:
  ## Use inversion of operators

  When solving equations we frequently make use of the
  [ operator inversion rules](Inversion%20of%20operators.md) to find the
  solutions.

  ### Example: inversion of addition

  For example, the equation $9 = 3 + x$ has the solution $6$ ($x$ is equal to
  $6$). To arrive at this, we can use the inverse of the main operator in the
  equation (addition): $9-3 = 6$.

  ### Example: inversion of subtraction

  Now consider $19 = x - 3$. The solution to this equation is $22$ ($x$ is equal
  to $22$). To arrive at this, we can use the inverse of the main operator in the
  equation (subtraction): $19 + 3 = 22$.

  ### Example: inversion of division

  The equation we want to solve: $$\frac{x}{6} = 4$$

  Now we invert it by multiplying the denominator by the quotient:
  $6\cdot 4 = 24$. Therefore: $$ \frac{24}{6} = 4$$
  The solution is $24$

  ### Example: inversion of multiplication

  The equation we want to solve: $$4x = 36$$ Now we invert it by dividing the
  product by the coefficient: !Add link to 'coefficient'

  $$\frac{36}{4} = 9$$

  Therefore the solution is $9$: $$ 4(9) = 36$$

raw_content:
  ---
  tags: [algebra]
  ---

  # Solving equations

  ## Use inversion of operators

  When solving equations we frequently make use of the
  [ operator inversion rules](Inversion%20of%20operators.md) to find the
  solutions.

  ### Example: inversion of addition

  For example, the equation $9 = 3 + x$ has the solution $6$ ($x$ is equal to
  $6$). To arrive at this, we can use the inverse of the main operator in the
  equation (addition): $9-3 = 6$.

  ### Example: inversion of subtraction

  Now consider $19 = x - 3$. The solution to this equation is $22$ ($x$ is equal
  to $22$). To arrive at this, we can use the inverse of the main operator in the
  equation (subtraction): $19 + 3 = 22$.

  ### Example: inversion of division

  The equation we want to solve: $$\frac{x}{6} = 4$$

  Now we invert it by multiplying the denominator by the quotient:
  $6\cdot 4 = 24$. Therefore: $$ \frac{24}{6} = 4$$
  The solution is $24$

  ### Example: inversion of multiplication

  The equation we want to solve: $$4x = 36$$ Now we invert it by dividing the
  product by the coefficient: !Add link to 'coefficient'

  $$\frac{36}{4} = 9$$

  Therefore the solution is $9$: $$ 4(9) = 36$$


path: Sorting_lists_in_Python.md
sortable_path: Sorting_lists_in_Python.md
title: Sorting lists in Python
lead: ### Using `sorted()` Function:
checksum: 9221787e96eb2c6b657c951b2a64d8c748f1442f2e807aec3800d2c7b948731f
created: 2025-10-01 13:31:01.528942579+00:00
modified: 2025-08-13 15:57:13.835125218+00:00
metadata: {"tags":["python"]}
body:
  ### Using `sorted()` Function:

  The built-in `sorted()` function returns a new list containing all the elements
  of the original list sorted in the specified order (either ascending, which is
  default, or descending).

  ```python
  my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
  sorted_list = sorted(my_list)
  print(sorted_list)  # Output: [1, 1, 2, 3, 4, 5, 5, 6, 9]
  ```

  For sorting in descending order, you can use the `reverse=True` argument:

  ```python
  sorted_list_desc = sorted(my_list, reverse=True)
  print(sorted_list_desc)  # Output: [9, 6, 5, 5, 4, 3, 2, 1, 1]
  ```

  > This method is best used for sorting a list of string values

  ### Using `.sort()` Method:

  The `.sort()` method sorts the elements of a list in-place and returns `None`.
  This modifies the original list.

  ```python
  my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
  my_list.sort()
  print(my_list)  # Output: [1, 1, 2, 3, 4, 5, 5, 6, 9]
  ```

  For sorting in descending order:

  ```python
  my_list.sort(reverse=True)
  print(my_list)  # Output: [9, 6, 5, 5, 4, 3, 2, 1, 1]
  ```

  ### Combine sorting with comprehension

  ```python
  tags = sorted([tag[0] for tag in tags])
  ```

  ### Using a Custom Key Function:

  Both `sorted()` and `.sort()` accept a `key` parameter that allows you to
  specify a function to determine the sorting order. The function should take a
  single argument and return a value that will be used for sorting purposes.

  For example, if you have a list of strings and you want to sort them by their
  length:

  ```python
  my_str_list = ["apple", "banana", "cherry", "date"]
  sorted_by_length = sorted(my_str_list, key=len)
  print(sorted_by_length)  # Output: ['date', 'apple', 'cherry', 'banana']
  ```

raw_content:
  ---
  tags: [python]
  ---

  # Sorting lists in Python

  ### Using `sorted()` Function:

  The built-in `sorted()` function returns a new list containing all the elements
  of the original list sorted in the specified order (either ascending, which is
  default, or descending).

  ```python
  my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
  sorted_list = sorted(my_list)
  print(sorted_list)  # Output: [1, 1, 2, 3, 4, 5, 5, 6, 9]
  ```

  For sorting in descending order, you can use the `reverse=True` argument:

  ```python
  sorted_list_desc = sorted(my_list, reverse=True)
  print(sorted_list_desc)  # Output: [9, 6, 5, 5, 4, 3, 2, 1, 1]
  ```

  > This method is best used for sorting a list of string values

  ### Using `.sort()` Method:

  The `.sort()` method sorts the elements of a list in-place and returns `None`.
  This modifies the original list.

  ```python
  my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
  my_list.sort()
  print(my_list)  # Output: [1, 1, 2, 3, 4, 5, 5, 6, 9]
  ```

  For sorting in descending order:

  ```python
  my_list.sort(reverse=True)
  print(my_list)  # Output: [9, 6, 5, 5, 4, 3, 2, 1, 1]
  ```

  ### Combine sorting with comprehension

  ```python
  tags = sorted([tag[0] for tag in tags])
  ```

  ### Using a Custom Key Function:

  Both `sorted()` and `.sort()` accept a `key` parameter that allows you to
  specify a function to determine the sorting order. The function should take a
  single argument and return a value that will be used for sorting purposes.

  For example, if you have a list of strings and you want to sort them by their
  length:

  ```python
  my_str_list = ["apple", "banana", "cherry", "date"]
  sorted_by_length = sorted(my_str_list, key=len)
  print(sorted_by_length)  # Output: ['date', 'apple', 'cherry', 'banana']
  ```


