├── .freeCodeCamp ├── .bashrc ├── .psqlrc ├── pg_hba.conf ├── postgresql.conf └── test │ ├── .cwd │ └── .next_command ├── .gitignore ├── .gitpod.yml ├── .vscode └── settings.json ├── CHANGELOG.md ├── TUTORIAL.md ├── coderoad.yaml └── tutorial.json /.freeCodeCamp/.bashrc: -------------------------------------------------------------------------------- 1 | # ~/.bashrc: executed by bash(1) for non-login shells. 2 | # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) 3 | # for examples 4 | 5 | # If not running interactively, don't do anything 6 | case $- in 7 | *i*) ;; 8 | *) return;; 9 | esac 10 | 11 | # don't put duplicate lines or lines starting with space in the history. 12 | # See bash(1) for more options 13 | # I commented this out 14 | #HISTCONTROL=ignoreboth 15 | 16 | # append to the history file, don't overwrite it 17 | shopt -s histappend 18 | 19 | # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) 20 | HISTSIZE=1000 21 | HISTFILESIZE=2000 22 | 23 | # check the window size after each command and, if necessary, 24 | # update the values of LINES and COLUMNS. 25 | shopt -s checkwinsize 26 | 27 | # If set, the pattern "**" used in a pathname expansion context will 28 | # match all files and zero or more directories and subdirectories. 29 | #shopt -s globstar 30 | 31 | # make less more friendly for non-text input files, see lesspipe(1) 32 | # I commented this out 33 | #[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" 34 | 35 | # set variable identifying the chroot you work in (used in the prompt below) 36 | if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then 37 | debian_chroot=$(cat /etc/debian_chroot) 38 | fi 39 | 40 | # set a fancy prompt (non-color, unless we know we "want" color) 41 | case "$TERM" in 42 | xterm-color|*-256color) color_prompt=yes;; 43 | esac 44 | 45 | # uncomment for a colored prompt, if the terminal has the capability; turned 46 | # off by default to not distract the user: the focus in a terminal window 47 | # should be on the output of commands, not on the prompt 48 | #force_color_prompt=yes 49 | 50 | if [ -n "$force_color_prompt" ]; then 51 | if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then 52 | # We have color support; assume it's compliant with Ecma-48 53 | # (ISO/IEC-6429). (Lack of such support is extremely rare, and such 54 | # a case would tend to support setf rather than setaf.) 55 | color_prompt=yes 56 | else 57 | color_prompt= 58 | fi 59 | fi 60 | 61 | if [ "$color_prompt" = yes ]; then 62 | PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' 63 | else 64 | PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' 65 | fi 66 | unset color_prompt force_color_prompt 67 | 68 | # If this is an xterm set the title to user@host:dir 69 | case "$TERM" in 70 | xterm*|rxvt*) 71 | PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" 72 | ;; 73 | *) 74 | ;; 75 | esac 76 | 77 | # enable color support of ls and also add handy aliases 78 | if [ -x /usr/bin/dircolors ]; then 79 | test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" 80 | alias ls='ls --color=auto' 81 | #alias dir='dir --color=auto' 82 | #alias vdir='vdir --color=auto' 83 | 84 | # I commented these out 85 | # alias grep='grep --color=auto' 86 | # alias fgrep='fgrep --color=auto' 87 | # alias egrep='egrep --color=auto' 88 | fi 89 | 90 | # colored GCC warnings and errors 91 | #export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01' 92 | 93 | # some more ls aliases - # I commented these out 94 | # alias ll='ls -alF' 95 | # alias la='ls -A' 96 | # alias l='ls -CF' 97 | 98 | # Add an "alert" alias for long running commands. Use like so: 99 | # sleep 10; alert 100 | # I commented this out 101 | #alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' 102 | 103 | # Alias definitions. 104 | # You may want to put all your additions into a separate file like 105 | # ~/.bash_aliases, instead of adding them here directly. 106 | # See /usr/share/doc/bash-doc/examples in the bash-doc package. 107 | 108 | if [ -f ~/.bash_aliases ]; then 109 | . ~/.bash_aliases 110 | fi 111 | 112 | # enable programmable completion features (you don't need to enable 113 | # this, if it's already enabled in /etc/bash.bashrc and /etc/profile 114 | # sources /etc/bash.bashrc). 115 | if ! shopt -oq posix; then 116 | if [ -f /usr/share/bash-completion/bash_completion ]; then 117 | . /usr/share/bash-completion/bash_completion 118 | elif [ -f /etc/bash_completion ]; then 119 | . /etc/bash_completion 120 | fi 121 | fi 122 | 123 | # I commented this out 124 | #for i in $(ls -A $HOME/.bashrc.d/); do source $HOME/.bashrc.d/$i; done 125 | 126 | # Add RVM to PATH for scripting. Make sure this is the last PATH variable change. 127 | export PATH="$PATH:$HOME/.rvm/bin" 128 | 129 | # stuff I added 130 | PS1='camper: \[\033[01;34m\]/${PWD##*/}\[\033[00m\]\$ ' 131 | HISTFILE=/workspace/.bash_history 132 | PROMPT_COMMAND='echo $PWD >> /workspace/project/.freeCodeCamp/test/.cwd; history -a' 133 | trap 'echo $BASH_COMMAND >> /workspace/project/.freeCodeCamp/test/.next_command' DEBUG -------------------------------------------------------------------------------- /.freeCodeCamp/.psqlrc: -------------------------------------------------------------------------------- 1 | \out | tee /workspace/queryResults.log 2 | \pset border 2 3 | \pset title ' ' 4 | \pset pager off -------------------------------------------------------------------------------- /.freeCodeCamp/pg_hba.conf: -------------------------------------------------------------------------------- 1 | # PostgreSQL Client Authentication Configuration File 2 | # =================================================== 3 | # 4 | # Refer to the "Client Authentication" section in the PostgreSQL 5 | # documentation for a complete description of this file. A short 6 | # synopsis follows. 7 | # 8 | # This file controls: which hosts are allowed to connect, how clients 9 | # are authenticated, which PostgreSQL user names they can use, which 10 | # databases they can access. Records take one of these forms: 11 | # 12 | # local DATABASE USER METHOD [OPTIONS] 13 | # host DATABASE USER ADDRESS METHOD [OPTIONS] 14 | # hostssl DATABASE USER ADDRESS METHOD [OPTIONS] 15 | # hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] 16 | # 17 | # (The uppercase items must be replaced by actual values.) 18 | # 19 | # The first field is the connection type: "local" is a Unix-domain 20 | # socket, "host" is either a plain or SSL-encrypted TCP/IP socket, 21 | # "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a 22 | # plain TCP/IP socket. 23 | # 24 | # DATABASE can be "all", "sameuser", "samerole", "replication", a 25 | # database name, or a comma-separated list thereof. The "all" 26 | # keyword does not match "replication". Access to replication 27 | # must be enabled in a separate record (see example below). 28 | # 29 | # USER can be "all", a user name, a group name prefixed with "+", or a 30 | # comma-separated list thereof. In both the DATABASE and USER fields 31 | # you can also write a file name prefixed with "@" to include names 32 | # from a separate file. 33 | # 34 | # ADDRESS specifies the set of hosts the record matches. It can be a 35 | # host name, or it is made up of an IP address and a CIDR mask that is 36 | # an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that 37 | # specifies the number of significant bits in the mask. A host name 38 | # that starts with a dot (.) matches a suffix of the actual host name. 39 | # Alternatively, you can write an IP address and netmask in separate 40 | # columns to specify the set of hosts. Instead of a CIDR-address, you 41 | # can write "samehost" to match any of the server's own IP addresses, 42 | # or "samenet" to match any address in any subnet that the server is 43 | # directly connected to. 44 | # 45 | # METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", 46 | # "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert". 47 | # Note that "password" sends passwords in clear text; "md5" or 48 | # "scram-sha-256" are preferred since they send encrypted passwords. 49 | # 50 | # OPTIONS are a set of options for the authentication in the format 51 | # NAME=VALUE. The available options depend on the different 52 | # authentication methods -- refer to the "Client Authentication" 53 | # section in the documentation for a list of which options are 54 | # available for which authentication methods. 55 | # 56 | # Database and user names containing spaces, commas, quotes and other 57 | # special characters must be quoted. Quoting one of the keywords 58 | # "all", "sameuser", "samerole" or "replication" makes the name lose 59 | # its special character, and just match a database or username with 60 | # that name. 61 | # 62 | # This file is read on server startup and when the server receives a 63 | # SIGHUP signal. If you edit the file on a running system, you have to 64 | # SIGHUP the server for the changes to take effect, run "pg_ctl reload", 65 | # or execute "SELECT pg_reload_conf()". 66 | # 67 | # Put your actual configuration here 68 | # ---------------------------------- 69 | # 70 | # If you want to allow non-local connections, you need to add more 71 | # "host" records. In that case you will also need to make PostgreSQL 72 | # listen on a non-local interface via the listen_addresses 73 | # configuration parameter, or via the -i or -h command line switches. 74 | 75 | 76 | 77 | 78 | # DO NOT DISABLE! 79 | # If you change this first entry you will need to make sure that the 80 | # database superuser can access the database using some other method. 81 | # Noninteractive access to all databases is required during automatic 82 | # maintenance (custom daily cronjobs, replication, and similar tasks). 83 | # 84 | # Database administrative login by Unix domain socket 85 | local all postgres trust 86 | 87 | # TYPE DATABASE USER ADDRESS METHOD 88 | 89 | # "local" is for Unix domain socket connections only 90 | local all all trust 91 | # IPv4 local connections: 92 | host all all 127.0.0.1/32 trust 93 | # IPv6 local connections: 94 | host all all ::1/128 trust 95 | # Allow replication connections from localhost, by a user with the 96 | # replication privilege. 97 | local replication all trust 98 | host replication all 127.0.0.1/32 trust 99 | host replication all ::1/128 trust -------------------------------------------------------------------------------- /.freeCodeCamp/postgresql.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------- 2 | # PostgreSQL configuration file 3 | # ----------------------------- 4 | # 5 | # This file consists of lines of the form: 6 | # 7 | # name = value 8 | # 9 | # (The "=" is optional.) Whitespace may be used. Comments are introduced with 10 | # "#" anywhere on a line. The complete list of parameter names and allowed 11 | # values can be found in the PostgreSQL documentation. 12 | # 13 | # The commented-out settings shown in this file represent the default values. 14 | # Re-commenting a setting is NOT sufficient to revert it to the default value; 15 | # you need to reload the server. 16 | # 17 | # This file is read on server startup and when the server receives a SIGHUP 18 | # signal. If you edit the file on a running system, you have to SIGHUP the 19 | # server for the changes to take effect, run "pg_ctl reload", or execute 20 | # "SELECT pg_reload_conf()". Some parameters, which are marked below, 21 | # require a server shutdown and restart to take effect. 22 | # 23 | # Any parameter can also be given as a command-line option to the server, e.g., 24 | # "postgres -c log_connections=on". Some parameters can be changed at run time 25 | # with the "SET" SQL command. 26 | # 27 | # Memory units: kB = kilobytes Time units: ms = milliseconds 28 | # MB = megabytes s = seconds 29 | # GB = gigabytes min = minutes 30 | # TB = terabytes h = hours 31 | # d = days 32 | 33 | 34 | #------------------------------------------------------------------------------ 35 | # FILE LOCATIONS 36 | #------------------------------------------------------------------------------ 37 | 38 | # The default values of these variables are driven from the -D command-line 39 | # option or PGDATA environment variable, represented here as ConfigDir. 40 | 41 | data_directory = '/var/lib/postgresql/12/main' # use data in another directory 42 | # (change requires restart) 43 | hba_file = '/etc/postgresql/12/main/pg_hba.conf' # host-based authentication file 44 | # (change requires restart) 45 | ident_file = '/etc/postgresql/12/main/pg_ident.conf' # ident configuration file 46 | # (change requires restart) 47 | 48 | # If external_pid_file is not explicitly set, no extra PID file is written. 49 | external_pid_file = '/var/run/postgresql/12-main.pid' # write an extra PID file 50 | # (change requires restart) 51 | 52 | 53 | #------------------------------------------------------------------------------ 54 | # CONNECTIONS AND AUTHENTICATION 55 | #------------------------------------------------------------------------------ 56 | 57 | # - Connection Settings - 58 | 59 | #listen_addresses = 'localhost' # what IP address(es) to listen on; 60 | # comma-separated list of addresses; 61 | # defaults to 'localhost'; use '*' for all 62 | # (change requires restart) 63 | port = 5432 # (change requires restart) 64 | max_connections = 100 # (change requires restart) 65 | #superuser_reserved_connections = 3 # (change requires restart) 66 | unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories 67 | # (change requires restart) 68 | #unix_socket_group = '' # (change requires restart) 69 | #unix_socket_permissions = 0777 # begin with 0 to use octal notation 70 | # (change requires restart) 71 | #bonjour = off # advertise server via Bonjour 72 | # (change requires restart) 73 | #bonjour_name = '' # defaults to the computer name 74 | # (change requires restart) 75 | 76 | # - TCP settings - 77 | # see "man 7 tcp" for details 78 | 79 | #tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds; 80 | # 0 selects the system default 81 | #tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds; 82 | # 0 selects the system default 83 | #tcp_keepalives_count = 0 # TCP_KEEPCNT; 84 | # 0 selects the system default 85 | #tcp_user_timeout = 0 # TCP_USER_TIMEOUT, in milliseconds; 86 | # 0 selects the system default 87 | 88 | # - Authentication - 89 | 90 | #authentication_timeout = 1min # 1s-600s 91 | #password_encryption = md5 # md5 or scram-sha-256 92 | #db_user_namespace = off 93 | 94 | # GSSAPI using Kerberos 95 | #krb_server_keyfile = '' 96 | #krb_caseins_users = off 97 | 98 | # - SSL - 99 | 100 | ssl = on 101 | #ssl_ca_file = '' 102 | ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem' 103 | #ssl_crl_file = '' 104 | ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key' 105 | #ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers 106 | #ssl_prefer_server_ciphers = on 107 | #ssl_ecdh_curve = 'prime256v1' 108 | #ssl_min_protocol_version = 'TLSv1' 109 | #ssl_max_protocol_version = '' 110 | #ssl_dh_params_file = '' 111 | #ssl_passphrase_command = '' 112 | #ssl_passphrase_command_supports_reload = off 113 | 114 | 115 | #------------------------------------------------------------------------------ 116 | # RESOURCE USAGE (except WAL) 117 | #------------------------------------------------------------------------------ 118 | 119 | # - Memory - 120 | 121 | shared_buffers = 128MB # min 128kB 122 | # (change requires restart) 123 | #huge_pages = try # on, off, or try 124 | # (change requires restart) 125 | #temp_buffers = 8MB # min 800kB 126 | #max_prepared_transactions = 0 # zero disables the feature 127 | # (change requires restart) 128 | # Caution: it is not advisable to set max_prepared_transactions nonzero unless 129 | # you actively intend to use prepared transactions. 130 | #work_mem = 4MB # min 64kB 131 | #maintenance_work_mem = 64MB # min 1MB 132 | #autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem 133 | #max_stack_depth = 2MB # min 100kB 134 | #shared_memory_type = mmap # the default is the first option 135 | # supported by the operating system: 136 | # mmap 137 | # sysv 138 | # windows 139 | # (change requires restart) 140 | dynamic_shared_memory_type = posix # the default is the first option 141 | # supported by the operating system: 142 | # posix 143 | # sysv 144 | # windows 145 | # mmap 146 | # (change requires restart) 147 | 148 | # - Disk - 149 | 150 | #temp_file_limit = -1 # limits per-process temp file space 151 | # in kB, or -1 for no limit 152 | 153 | # - Kernel Resources - 154 | 155 | #max_files_per_process = 1000 # min 25 156 | # (change requires restart) 157 | 158 | # - Cost-Based Vacuum Delay - 159 | 160 | #vacuum_cost_delay = 0 # 0-100 milliseconds (0 disables) 161 | #vacuum_cost_page_hit = 1 # 0-10000 credits 162 | #vacuum_cost_page_miss = 10 # 0-10000 credits 163 | #vacuum_cost_page_dirty = 20 # 0-10000 credits 164 | #vacuum_cost_limit = 200 # 1-10000 credits 165 | 166 | # - Background Writer - 167 | 168 | #bgwriter_delay = 200ms # 10-10000ms between rounds 169 | #bgwriter_lru_maxpages = 100 # max buffers written/round, 0 disables 170 | #bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round 171 | #bgwriter_flush_after = 512kB # measured in pages, 0 disables 172 | 173 | # - Asynchronous Behavior - 174 | 175 | #effective_io_concurrency = 1 # 1-1000; 0 disables prefetching 176 | #max_worker_processes = 8 # (change requires restart) 177 | #max_parallel_maintenance_workers = 2 # taken from max_parallel_workers 178 | #max_parallel_workers_per_gather = 2 # taken from max_parallel_workers 179 | #parallel_leader_participation = on 180 | #max_parallel_workers = 8 # maximum number of max_worker_processes that 181 | # can be used in parallel operations 182 | #old_snapshot_threshold = -1 # 1min-60d; -1 disables; 0 is immediate 183 | # (change requires restart) 184 | #backend_flush_after = 0 # measured in pages, 0 disables 185 | 186 | 187 | #------------------------------------------------------------------------------ 188 | # WRITE-AHEAD LOG 189 | #------------------------------------------------------------------------------ 190 | 191 | # - Settings - 192 | 193 | #wal_level = replica # minimal, replica, or logical 194 | # (change requires restart) 195 | #fsync = on # flush data to disk for crash safety 196 | # (turning this off can cause 197 | # unrecoverable data corruption) 198 | #synchronous_commit = on # synchronization level; 199 | # off, local, remote_write, remote_apply, or on 200 | #wal_sync_method = fsync # the default is the first option 201 | # supported by the operating system: 202 | # open_datasync 203 | # fdatasync (default on Linux) 204 | # fsync 205 | # fsync_writethrough 206 | # open_sync 207 | #full_page_writes = on # recover from partial page writes 208 | #wal_compression = off # enable compression of full-page writes 209 | #wal_log_hints = off # also do full page writes of non-critical updates 210 | # (change requires restart) 211 | #wal_init_zero = on # zero-fill new WAL files 212 | #wal_recycle = on # recycle WAL files 213 | #wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers 214 | # (change requires restart) 215 | #wal_writer_delay = 200ms # 1-10000 milliseconds 216 | #wal_writer_flush_after = 1MB # measured in pages, 0 disables 217 | 218 | #commit_delay = 0 # range 0-100000, in microseconds 219 | #commit_siblings = 5 # range 1-1000 220 | 221 | # - Checkpoints - 222 | 223 | #checkpoint_timeout = 5min # range 30s-1d 224 | max_wal_size = 1GB 225 | min_wal_size = 80MB 226 | #checkpoint_completion_target = 0.5 # checkpoint target duration, 0.0 - 1.0 227 | #checkpoint_flush_after = 256kB # measured in pages, 0 disables 228 | #checkpoint_warning = 30s # 0 disables 229 | 230 | # - Archiving - 231 | 232 | #archive_mode = off # enables archiving; off, on, or always 233 | # (change requires restart) 234 | #archive_command = '' # command to use to archive a logfile segment 235 | # placeholders: %p = path of file to archive 236 | # %f = file name only 237 | # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' 238 | #archive_timeout = 0 # force a logfile segment switch after this 239 | # number of seconds; 0 disables 240 | 241 | # - Archive Recovery - 242 | 243 | # These are only used in recovery mode. 244 | 245 | #restore_command = '' # command to use to restore an archived logfile segment 246 | # placeholders: %p = path of file to restore 247 | # %f = file name only 248 | # e.g. 'cp /mnt/server/archivedir/%f %p' 249 | # (change requires restart) 250 | #archive_cleanup_command = '' # command to execute at every restartpoint 251 | #recovery_end_command = '' # command to execute at completion of recovery 252 | 253 | # - Recovery Target - 254 | 255 | # Set these only when performing a targeted recovery. 256 | 257 | #recovery_target = '' # 'immediate' to end recovery as soon as a 258 | # consistent state is reached 259 | # (change requires restart) 260 | #recovery_target_name = '' # the named restore point to which recovery will proceed 261 | # (change requires restart) 262 | #recovery_target_time = '' # the time stamp up to which recovery will proceed 263 | # (change requires restart) 264 | #recovery_target_xid = '' # the transaction ID up to which recovery will proceed 265 | # (change requires restart) 266 | #recovery_target_lsn = '' # the WAL LSN up to which recovery will proceed 267 | # (change requires restart) 268 | #recovery_target_inclusive = on # Specifies whether to stop: 269 | # just after the specified recovery target (on) 270 | # just before the recovery target (off) 271 | # (change requires restart) 272 | #recovery_target_timeline = 'latest' # 'current', 'latest', or timeline ID 273 | # (change requires restart) 274 | #recovery_target_action = 'pause' # 'pause', 'promote', 'shutdown' 275 | # (change requires restart) 276 | 277 | 278 | #------------------------------------------------------------------------------ 279 | # REPLICATION 280 | #------------------------------------------------------------------------------ 281 | 282 | # - Sending Servers - 283 | 284 | # Set these on the master and on any standby that will send replication data. 285 | 286 | #max_wal_senders = 10 # max number of walsender processes 287 | # (change requires restart) 288 | #wal_keep_segments = 0 # in logfile segments; 0 disables 289 | #wal_sender_timeout = 60s # in milliseconds; 0 disables 290 | 291 | #max_replication_slots = 10 # max number of replication slots 292 | # (change requires restart) 293 | #track_commit_timestamp = off # collect timestamp of transaction commit 294 | # (change requires restart) 295 | 296 | # - Master Server - 297 | 298 | # These settings are ignored on a standby server. 299 | 300 | #synchronous_standby_names = '' # standby servers that provide sync rep 301 | # method to choose sync standbys, number of sync standbys, 302 | # and comma-separated list of application_name 303 | # from standby(s); '*' = all 304 | #vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed 305 | 306 | # - Standby Servers - 307 | 308 | # These settings are ignored on a master server. 309 | 310 | #primary_conninfo = '' # connection string to sending server 311 | # (change requires restart) 312 | #primary_slot_name = '' # replication slot on sending server 313 | # (change requires restart) 314 | #promote_trigger_file = '' # file name whose presence ends recovery 315 | #hot_standby = on # "off" disallows queries during recovery 316 | # (change requires restart) 317 | #max_standby_archive_delay = 30s # max delay before canceling queries 318 | # when reading WAL from archive; 319 | # -1 allows indefinite delay 320 | #max_standby_streaming_delay = 30s # max delay before canceling queries 321 | # when reading streaming WAL; 322 | # -1 allows indefinite delay 323 | #wal_receiver_status_interval = 10s # send replies at least this often 324 | # 0 disables 325 | #hot_standby_feedback = off # send info from standby to prevent 326 | # query conflicts 327 | #wal_receiver_timeout = 60s # time that receiver waits for 328 | # communication from master 329 | # in milliseconds; 0 disables 330 | #wal_retrieve_retry_interval = 5s # time to wait before retrying to 331 | # retrieve WAL after a failed attempt 332 | #recovery_min_apply_delay = 0 # minimum delay for applying changes during recovery 333 | 334 | # - Subscribers - 335 | 336 | # These settings are ignored on a publisher. 337 | 338 | #max_logical_replication_workers = 4 # taken from max_worker_processes 339 | # (change requires restart) 340 | #max_sync_workers_per_subscription = 2 # taken from max_logical_replication_workers 341 | 342 | 343 | #------------------------------------------------------------------------------ 344 | # QUERY TUNING 345 | #------------------------------------------------------------------------------ 346 | 347 | # - Planner Method Configuration - 348 | 349 | #enable_bitmapscan = on 350 | #enable_hashagg = on 351 | #enable_hashjoin = on 352 | #enable_indexscan = on 353 | #enable_indexonlyscan = on 354 | #enable_material = on 355 | #enable_mergejoin = on 356 | #enable_nestloop = on 357 | #enable_parallel_append = on 358 | #enable_seqscan = on 359 | #enable_sort = on 360 | #enable_tidscan = on 361 | #enable_partitionwise_join = off 362 | #enable_partitionwise_aggregate = off 363 | #enable_parallel_hash = on 364 | #enable_partition_pruning = on 365 | 366 | # - Planner Cost Constants - 367 | 368 | #seq_page_cost = 1.0 # measured on an arbitrary scale 369 | #random_page_cost = 4.0 # same scale as above 370 | #cpu_tuple_cost = 0.01 # same scale as above 371 | #cpu_index_tuple_cost = 0.005 # same scale as above 372 | #cpu_operator_cost = 0.0025 # same scale as above 373 | #parallel_tuple_cost = 0.1 # same scale as above 374 | #parallel_setup_cost = 1000.0 # same scale as above 375 | 376 | #jit_above_cost = 100000 # perform JIT compilation if available 377 | # and query more expensive than this; 378 | # -1 disables 379 | #jit_inline_above_cost = 500000 # inline small functions if query is 380 | # more expensive than this; -1 disables 381 | #jit_optimize_above_cost = 500000 # use expensive JIT optimizations if 382 | # query is more expensive than this; 383 | # -1 disables 384 | 385 | #min_parallel_table_scan_size = 8MB 386 | #min_parallel_index_scan_size = 512kB 387 | #effective_cache_size = 4GB 388 | 389 | # - Genetic Query Optimizer - 390 | 391 | #geqo = on 392 | #geqo_threshold = 12 393 | #geqo_effort = 5 # range 1-10 394 | #geqo_pool_size = 0 # selects default based on effort 395 | #geqo_generations = 0 # selects default based on effort 396 | #geqo_selection_bias = 2.0 # range 1.5-2.0 397 | #geqo_seed = 0.0 # range 0.0-1.0 398 | 399 | # - Other Planner Options - 400 | 401 | #default_statistics_target = 100 # range 1-10000 402 | #constraint_exclusion = partition # on, off, or partition 403 | #cursor_tuple_fraction = 0.1 # range 0.0-1.0 404 | #from_collapse_limit = 8 405 | #join_collapse_limit = 8 # 1 disables collapsing of explicit 406 | # JOIN clauses 407 | #force_parallel_mode = off 408 | #jit = on # allow JIT compilation 409 | #plan_cache_mode = auto # auto, force_generic_plan or 410 | # force_custom_plan 411 | 412 | 413 | #------------------------------------------------------------------------------ 414 | # REPORTING AND LOGGING 415 | #------------------------------------------------------------------------------ 416 | 417 | # - Where to Log - 418 | 419 | #log_destination = 'stderr' # Valid values are combinations of 420 | # stderr, csvlog, syslog, and eventlog, 421 | # depending on platform. csvlog 422 | # requires logging_collector to be on. 423 | 424 | # This is used when logging to stderr: 425 | #logging_collector = off # Enable capturing of stderr and csvlog 426 | # into log files. Required to be on for 427 | # csvlogs. 428 | # (change requires restart) 429 | 430 | # These are only used if logging_collector is on: 431 | #log_directory = 'log' # directory where log files are written, 432 | # can be absolute or relative to PGDATA 433 | #log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern, 434 | # can include strftime() escapes 435 | #log_file_mode = 0600 # creation mode for log files, 436 | # begin with 0 to use octal notation 437 | #log_truncate_on_rotation = off # If on, an existing log file with the 438 | # same name as the new log file will be 439 | # truncated rather than appended to. 440 | # But such truncation only occurs on 441 | # time-driven rotation, not on restarts 442 | # or size-driven rotation. Default is 443 | # off, meaning append to existing files 444 | # in all cases. 445 | #log_rotation_age = 1d # Automatic rotation of logfiles will 446 | # happen after that time. 0 disables. 447 | #log_rotation_size = 10MB # Automatic rotation of logfiles will 448 | # happen after that much log output. 449 | # 0 disables. 450 | 451 | # These are relevant when logging to syslog: 452 | #syslog_facility = 'LOCAL0' 453 | #syslog_ident = 'postgres' 454 | #syslog_sequence_numbers = on 455 | #syslog_split_messages = on 456 | 457 | # This is only relevant when logging to eventlog (win32): 458 | # (change requires restart) 459 | #event_source = 'PostgreSQL' 460 | 461 | # - When to Log - 462 | 463 | #log_min_messages = warning # values in order of decreasing detail: 464 | # debug5 465 | # debug4 466 | # debug3 467 | # debug2 468 | # debug1 469 | # info 470 | # notice 471 | # warning 472 | # error 473 | # log 474 | # fatal 475 | # panic 476 | 477 | #log_min_error_statement = error # values in order of decreasing detail: 478 | # debug5 479 | # debug4 480 | # debug3 481 | # debug2 482 | # debug1 483 | # info 484 | # notice 485 | # warning 486 | # error 487 | # log 488 | # fatal 489 | # panic (effectively off) 490 | 491 | #log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements 492 | # and their durations, > 0 logs only 493 | # statements running at least this number 494 | # of milliseconds 495 | 496 | #log_transaction_sample_rate = 0.0 # Fraction of transactions whose statements 497 | # are logged regardless of their duration. 1.0 logs all 498 | # statements from all transactions, 0.0 never logs. 499 | 500 | # - What to Log - 501 | 502 | #debug_print_parse = off 503 | #debug_print_rewritten = off 504 | #debug_print_plan = off 505 | #debug_pretty_print = on 506 | #log_checkpoints = off 507 | #log_connections = off 508 | #log_disconnections = off 509 | #log_duration = off 510 | #log_error_verbosity = default # terse, default, or verbose messages 511 | #log_hostname = off 512 | #log_line_prefix = '%m [%p] %q%u@%d ' # special values: 513 | # %a = application name 514 | # %u = user name 515 | # %d = database name 516 | # %r = remote host and port 517 | # %h = remote host 518 | # %p = process ID 519 | # %t = timestamp without milliseconds 520 | # %m = timestamp with milliseconds 521 | # %n = timestamp with milliseconds (as a Unix epoch) 522 | # %i = command tag 523 | # %e = SQL state 524 | # %c = session ID 525 | # %l = session line number 526 | # %s = session start timestamp 527 | # %v = virtual transaction ID 528 | # %x = transaction ID (0 if none) 529 | # %q = stop here in non-session 530 | # processes 531 | # %% = '%' 532 | # e.g. '<%u%%%d> ' 533 | #log_lock_waits = off # log lock waits >= deadlock_timeout 534 | #log_statement = 'none' # none, ddl, mod, all 535 | #log_replication_commands = off 536 | #log_temp_files = -1 # log temporary files equal or larger 537 | # than the specified size in kilobytes; 538 | # -1 disables, 0 logs all temp files 539 | log_timezone = 'Europe/Warsaw' 540 | 541 | #------------------------------------------------------------------------------ 542 | # PROCESS TITLE 543 | #------------------------------------------------------------------------------ 544 | 545 | cluster_name = '12/main' # added to process titles if nonempty 546 | # (change requires restart) 547 | #update_process_title = on 548 | 549 | 550 | #------------------------------------------------------------------------------ 551 | # STATISTICS 552 | #------------------------------------------------------------------------------ 553 | 554 | # - Query and Index Statistics Collector - 555 | 556 | #track_activities = on 557 | #track_counts = on 558 | #track_io_timing = off 559 | #track_functions = none # none, pl, all 560 | #track_activity_query_size = 1024 # (change requires restart) 561 | stats_temp_directory = '/var/run/postgresql/12-main.pg_stat_tmp' 562 | 563 | 564 | # - Monitoring - 565 | 566 | #log_parser_stats = off 567 | #log_planner_stats = off 568 | #log_executor_stats = off 569 | #log_statement_stats = off 570 | 571 | 572 | #------------------------------------------------------------------------------ 573 | # AUTOVACUUM 574 | #------------------------------------------------------------------------------ 575 | 576 | #autovacuum = on # Enable autovacuum subprocess? 'on' 577 | # requires track_counts to also be on. 578 | #log_autovacuum_min_duration = -1 # -1 disables, 0 logs all actions and 579 | # their durations, > 0 logs only 580 | # actions running at least this number 581 | # of milliseconds. 582 | #autovacuum_max_workers = 3 # max number of autovacuum subprocesses 583 | # (change requires restart) 584 | #autovacuum_naptime = 1min # time between autovacuum runs 585 | #autovacuum_vacuum_threshold = 50 # min number of row updates before 586 | # vacuum 587 | #autovacuum_analyze_threshold = 50 # min number of row updates before 588 | # analyze 589 | #autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum 590 | #autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze 591 | #autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum 592 | # (change requires restart) 593 | #autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age 594 | # before forced vacuum 595 | # (change requires restart) 596 | #autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for 597 | # autovacuum, in milliseconds; 598 | # -1 means use vacuum_cost_delay 599 | #autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for 600 | # autovacuum, -1 means use 601 | # vacuum_cost_limit 602 | 603 | 604 | #------------------------------------------------------------------------------ 605 | # CLIENT CONNECTION DEFAULTS 606 | #------------------------------------------------------------------------------ 607 | 608 | # - Statement Behavior - 609 | 610 | #client_min_messages = notice # values in order of decreasing detail: 611 | # debug5 612 | # debug4 613 | # debug3 614 | # debug2 615 | # debug1 616 | # log 617 | # notice 618 | # warning 619 | # error 620 | #search_path = '"$user", public' # schema names 621 | #row_security = on 622 | #default_tablespace = '' # a tablespace name, '' uses the default 623 | #temp_tablespaces = '' # a list of tablespace names, '' uses 624 | # only default tablespace 625 | #default_table_access_method = 'heap' 626 | #check_function_bodies = on 627 | #default_transaction_isolation = 'read committed' 628 | #default_transaction_read_only = off 629 | #default_transaction_deferrable = off 630 | #session_replication_role = 'origin' 631 | #statement_timeout = 0 # in milliseconds, 0 is disabled 632 | #lock_timeout = 0 # in milliseconds, 0 is disabled 633 | #idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled 634 | #vacuum_freeze_min_age = 50000000 635 | #vacuum_freeze_table_age = 150000000 636 | #vacuum_multixact_freeze_min_age = 5000000 637 | #vacuum_multixact_freeze_table_age = 150000000 638 | #vacuum_cleanup_index_scale_factor = 0.1 # fraction of total number of tuples 639 | # before index cleanup, 0 always performs 640 | # index cleanup 641 | #bytea_output = 'hex' # hex, escape 642 | #xmlbinary = 'base64' 643 | #xmloption = 'content' 644 | #gin_fuzzy_search_limit = 0 645 | #gin_pending_list_limit = 4MB 646 | 647 | # - Locale and Formatting - 648 | 649 | datestyle = 'iso, mdy' 650 | #intervalstyle = 'postgres' 651 | timezone = 'Europe/Warsaw' 652 | #timezone_abbreviations = 'Default' # Select the set of available time zone 653 | # abbreviations. Currently, there are 654 | # Default 655 | # Australia (historical usage) 656 | # India 657 | # You can create your own file in 658 | # share/timezonesets/. 659 | #extra_float_digits = 1 # min -15, max 3; any value >0 actually 660 | # selects precise output mode 661 | #client_encoding = sql_ascii # actually, defaults to database 662 | # encoding 663 | 664 | # These settings are initialized by initdb, but they can be changed. 665 | lc_messages = 'C.UTF-8' # locale for system error message 666 | # strings 667 | lc_monetary = 'C.UTF-8' # locale for monetary formatting 668 | lc_numeric = 'C.UTF-8' # locale for number formatting 669 | lc_time = 'C.UTF-8' # locale for time formatting 670 | 671 | # default configuration for text search 672 | default_text_search_config = 'pg_catalog.english' 673 | 674 | # - Shared Library Preloading - 675 | 676 | #shared_preload_libraries = '' # (change requires restart) 677 | #local_preload_libraries = '' 678 | #session_preload_libraries = '' 679 | #jit_provider = 'llvmjit' # JIT library to use 680 | 681 | # - Other Defaults - 682 | 683 | #dynamic_library_path = '$libdir' 684 | 685 | 686 | #------------------------------------------------------------------------------ 687 | # LOCK MANAGEMENT 688 | #------------------------------------------------------------------------------ 689 | 690 | #deadlock_timeout = 1s 691 | #max_locks_per_transaction = 64 # min 10 692 | # (change requires restart) 693 | #max_pred_locks_per_transaction = 64 # min 10 694 | # (change requires restart) 695 | #max_pred_locks_per_relation = -2 # negative values mean 696 | # (max_pred_locks_per_transaction 697 | # / -max_pred_locks_per_relation) - 1 698 | #max_pred_locks_per_page = 2 # min 0 699 | 700 | 701 | #------------------------------------------------------------------------------ 702 | # VERSION AND PLATFORM COMPATIBILITY 703 | #------------------------------------------------------------------------------ 704 | 705 | # - Previous PostgreSQL Versions - 706 | 707 | #array_nulls = on 708 | #backslash_quote = safe_encoding # on, off, or safe_encoding 709 | #escape_string_warning = on 710 | #lo_compat_privileges = off 711 | #operator_precedence_warning = off 712 | #quote_all_identifiers = off 713 | #standard_conforming_strings = on 714 | #synchronize_seqscans = on 715 | 716 | # - Other Platforms and Clients - 717 | 718 | #transform_null_equals = off 719 | 720 | 721 | #------------------------------------------------------------------------------ 722 | # ERROR HANDLING 723 | #------------------------------------------------------------------------------ 724 | 725 | #exit_on_error = off # terminate session on any error? 726 | #restart_after_crash = on # reinitialize after backend crash? 727 | #data_sync_retry = off # retry or panic on failure to fsync 728 | # data? 729 | # (change requires restart) 730 | 731 | 732 | #------------------------------------------------------------------------------ 733 | # CONFIG FILE INCLUDES 734 | #------------------------------------------------------------------------------ 735 | 736 | # These options allow settings to be loaded from files other than the 737 | # default postgresql.conf. Note that these are directives, not variable 738 | # assignments, so they can usefully be given more than once. 739 | 740 | include_dir = 'conf.d' # include files ending in '.conf' from 741 | # a directory, e.g., 'conf.d' 742 | #include_if_exists = '...' # include file only if it exists 743 | #include = '...' # include file 744 | 745 | 746 | #------------------------------------------------------------------------------ 747 | # CUSTOMIZED OPTIONS 748 | #------------------------------------------------------------------------------ 749 | 750 | # Add settings for extensions here 751 | 752 | # Settings I changed from the defaults above 753 | log_statement = 'all' 754 | log_min_error_statement = INFO 755 | log_min_messages = INFO 756 | logging_collector = on 757 | log_directory = '/workspace/' 758 | log_filename = 'pg.log' 759 | log_connections = on 760 | log_line_prefix = '%u ' -------------------------------------------------------------------------------- /.freeCodeCamp/test/.cwd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freeCodeCamp/learn-bash-and-sql-by-building-a-bike-rental-shop/1ec5007d0ce94a8586f54fa31a8ebe13a7eea712/.freeCodeCamp/test/.cwd -------------------------------------------------------------------------------- /.freeCodeCamp/test/.next_command: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freeCodeCamp/learn-bash-and-sql-by-building-a-bike-rental-shop/1ec5007d0ce94a8586f54fa31a8ebe13a7eea712/.freeCodeCamp/test/.next_command -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: gitpod/workspace-postgres:2024-01-24-09-19-42 2 | 3 | workspaceLocation: 'project' 4 | checkoutLocation: 'project' 5 | 6 | tasks: 7 | - before: | 8 | sudo cp /workspace/project/.freeCodeCamp/.bashrc ~/.bashrc 9 | sudo cp /workspace/project/.freeCodeCamp/.psqlrc ~/.psqlrc 10 | sudo cp /workspace/project/.freeCodeCamp/postgresql.conf /etc/postgresql/12/main/postgresql.conf 11 | sudo cp /workspace/project/.freeCodeCamp/pg_hba.conf /etc/postgresql/12/main/pg_hba.conf 12 | sudo touch /workspace/.bash_history 13 | sudo touch /workspace/pg.log 14 | sudo touch /workspace/queryResults.log 15 | sudo chmod -R 777 /workspace 16 | sudo chown -R postgres:postgres /var/lib/postgresql/12/main 17 | 18 | command: | 19 | sudo rm /workspace/project/CHANGELOG.md 20 | sudo rm /workspace/project/coderoad.yaml 21 | sudo rm /workspace/project/tutorial.json 22 | sudo rm /workspace/project/TUTORIAL.md 23 | pg_stop && sudo service postgresql start && echo "SELECT 'CREATE USER freecodecamp WITH CREATEDB' WHERE NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname='freecodecamp')\gexec" | psql -U postgres -X 24 | exit 25 | 26 | vscode: 27 | extensions: 28 | - CodeRoad.coderoad 29 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "breadcrumbs.enabled": false, 3 | "debug.internalConsoleOptions": "neverOpen", 4 | "debug.showInStatusBar": "never", 5 | "editor.acceptSuggestionOnCommitCharacter": false, 6 | "editor.acceptSuggestionOnEnter": "off", 7 | "editor.autoClosingBrackets": "never", 8 | "editor.codeActionsOnSave": { 9 | "source.fixAll": "explicit" 10 | }, 11 | "editor.hover.enabled": false, 12 | "editor.inlineSuggest.enabled": false, 13 | "editor.minimap.enabled": false, 14 | "editor.parameterHints.enabled": false, 15 | "editor.quickSuggestions": { 16 | "other": false, 17 | "comments": false, 18 | "strings": false 19 | }, 20 | "editor.referenceInfos": false, 21 | "editor.snippetSuggestions": "none", 22 | "editor.suggest.statusBar.visible": false, 23 | "editor.suggestOnTriggerCharacters": false, 24 | "editor.tabSize": 2, 25 | "explorer.autoReveal": false, 26 | "explorer.openEditors.visible": 0, 27 | "extensions.autoCheckUpdates": false, 28 | "extensions.ignoreRecommendations": true, 29 | "files.autoSave": "afterDelay", 30 | "files.exclude": { 31 | "**/.git": true, 32 | "**/.svn": true, 33 | "**/.hg": true, 34 | "**/CVS": true, 35 | "**/.DS_Store": true, 36 | ".vscode": true, 37 | ".gitignore": true, 38 | ".freeCodeCamp": true, 39 | "learn-bash-and-sql-by-building-a-bike-rental-shop": true, 40 | ".gitpod.Dockerfile": true, 41 | ".gitpod.yml": true, 42 | "CHANGELOG.md": true, 43 | "coderoad.yaml": true, 44 | "tutorial.json": true, 45 | "TUTORIAL.md": true 46 | }, 47 | "html.autoClosingTags": false, 48 | "npm.fetchOnlinePackageInfo": false, 49 | "task.slowProviderWarning": false, 50 | "terminal.integrated.allowChords": false, 51 | "terminal.integrated.commandsToSkipShell": ["coderoad.enter"], 52 | "terminal.integrated.enableFileLinks": false, 53 | "terminal.integrated.environmentChangesIndicator": "off", 54 | "terminal.integrated.macOptionIsMeta": true, 55 | "terminal.integrated.showExitAlert": false, 56 | "telemetry.enableTelemetry": false, 57 | "update.mode": "none", 58 | "update.showReleaseNotes": false, 59 | "workbench.enableExperiments": false, 60 | "workbench.startupEditor": "none", 61 | "workbench.colorTheme": "Tomorrow Night Blue", 62 | "workbench.colorCustomizations": { 63 | "[Tomorrow Night Blue]": { 64 | "menu.background": "#0a0a23", 65 | "menu.foreground": "#ffffff", 66 | "activityBar.background": "#0a0a23", 67 | "activityBar.foreground": "#ffffff", 68 | "activityBar.activeBorder": "#ffffff", 69 | "activityBar.border": "#2a2a40", 70 | "editorWidget.background": "#0a0a23", 71 | "editorWidget.foreground": "#ffffff", 72 | "sideBar.background": "#1b1b32", 73 | "sideBarTitle.foreground": "#858591", 74 | "sideBar.foreground": "#f5f6f7", 75 | "sideBar.border": "#2a2a40", 76 | "editor.background": "#2a2a40", 77 | "editor.foreground": "#dfdfe2", 78 | "tab.activeForeground": "#ffffff", 79 | "tab.inactiveBackground": "#1b1b32", 80 | "tab.inactiveForeground": "#d0d0d5", 81 | "tab.border": "#2a2a40", 82 | "editorGroupHeader.tabsBackground": "#0a0a23", 83 | "editorIndentGuide.background": "#3b3b4f", 84 | "terminal.background": "#0a0a23", 85 | "terminal.foreground": "#ffffff", 86 | "terminal.ansiBrightGreen": "#ffffff", 87 | "panel.background": "#1b1b32", 88 | "panelTitle.inactiveForeground": "#858591", 89 | "panelTitle.activeBorder": "#f5f6f7" 90 | } 91 | }, 92 | "workbench.iconTheme": null, 93 | "workbench.statusBar.visible": false, 94 | "workbench.tips.enabled": false, 95 | "workbench.tree.renderIndentGuides": "none", 96 | "zenMode.centerLayout": false 97 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | Please read the guidelines in the [contributing docs](https://contribute.freecodecamp.org/#/how-to-work-on-tutorials-that-use-coderoad) before contributing. Contributions to this project need to follow the correct workflow. 4 | 5 | # Change Log 6 | 7 | Whenever a new version is created, add the new branch name and the changes here 8 | 9 | ## [v1.0.0] 10 | 11 | - Initial soft release with news article 12 | 13 | ## [v1.0.1] 14 | 15 | - Move startup commands to `setup.sh` 16 | - Run `setup.sh` on start, continue and reset 17 | - Move SQL log files out of workspace 18 | - Add `IF EXISTS` to `db.sql` when dropping database to stop warnings 19 | - Terminate only user `freeCodeCamp` from db when resetting 20 | 21 | ## [v1.0.2] 22 | 23 | - fix https://github.com/freeCodeCamp/freeCodeCamp/issues/44795 24 | 25 | ## [v1.0.3] 26 | 27 | - Restructure commits to use new style. Instead of loading a new test file, and commenting out the old one on each commit, this loads all the tests in the `INIT` commit and uses mocha settings to only run tests in a specific file. The commits now just change the test file that should run. 28 | - There was an issue with the last commit not loading after using the reset button in a tutorial. I added a final commit at end that seems to have resolved it. 29 | - Add `exit` flag to mocha so the tests can't hang 30 | - Fix hints on steps 1428 and 1760 31 | 32 | ## [v1.0.4] 33 | 34 | - Fix regex tests that weren't working with space literals. Change to use `\s` on steps 1428-1438. 35 | 36 | ## [v2.0.0] 37 | 38 | - Add Gitpod config 39 | -------------------------------------------------------------------------------- /TUTORIAL.md: -------------------------------------------------------------------------------- 1 | # Learn Bash and SQL by Building a Bike Rental Shop 2 | 3 | > Welcome to the Bash and SQL lessons! 4 | 5 | ## 10. Start the Terminal 6 | 7 | ### 10.1 8 | 9 | **The first thing you need to do is start the terminal.** Do that by clicking the "hamburger" menu at the top left of the screen, going to the "terminal" section, and clicking "new terminal". Once you open a new one, type `echo hello terminal` into the terminal and press enter. 10 | 11 | #### HINTS 12 | 13 | - Capitalization matters 14 | - If the tests don't run automatically, try typing `exit` into the terminal and redoing the instructions 15 | 16 | ## 20. Log in to Psql 17 | 18 | ### 20.1 19 | 20 | You are going to build a bike rental shop. It will have a database, and a bash script to interact with the database. Use the terminal to connect to PostgreSQL by entering `psql --username=freecodecamp --dbname=postgres`. 21 | 22 | #### HINTS 23 | 24 | - Type the above command into the terminal and press enter 25 | - Type `psql --username=freecodecamp --dbname=postgres` into the terminal and press enter 26 | 27 | ## 30. List Databases 28 | 29 | ### 30.1 30 | 31 | List the databases with `\l` to see what databases are here. 32 | 33 | #### HINTS 34 | 35 | - Type `\l` into the psql prompt and press enter 36 | - Type `psql --username=freecodecamp --dbname=postgres` into the terminal to log in to psql if you aren't logged in first 37 | 38 | ## 40. Create Database `bikes` 39 | 40 | ### 40.1 41 | 42 | You need your own database for the bike shop. Create a new database named `bikes`. 43 | 44 | #### HINTS 45 | 46 | - Use the `CREATE DATABASE` keywords 47 | - Here's an example: `CREATE DATABASE database_name;` 48 | - Type `CREATE DATABASE bikes;` into the psql prompt and press enter 49 | - Type `psql --username=freecodecamp --dbname=postgres` into the terminal to log in to psql if you aren't logged in first 50 | 51 | ## 50. List Databases 52 | 53 | ### 50.1 54 | 55 | List databases again to make sure your database got created. 56 | 57 | #### HINTS 58 | 59 | - Use the **l**ist shortcut command 60 | - Type `\l` into the psql prompt 61 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 62 | 63 | ## 60. Connect to `bikes` 64 | 65 | ### 60.1 66 | 67 | There it is. **C**onnect to it so you can start building the structure of your bike shop database. 68 | 69 | #### HINTS 70 | 71 | - Use the **c**onnect shortcut command 72 | - Add the database name to the command 73 | - It's the `\c` command 74 | - Here's an example: `\c database_name` 75 | - Try entering `\c bikes` into the psql prompt 76 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 77 | 78 | ## 70. Create table `bikes` 79 | 80 | ### 70.1 81 | 82 | Your database needs three tables. One for your bike inventory, one for your customers, and one for the bikes that are rented out. Create a table named `bikes` in your database for the inventory. 83 | 84 | #### HINTS 85 | 86 | - Use the `CREATE TABLE` keywords 87 | - Don't forget the parenthesis 88 | - Here's an example: `CREATE TABLE table_name();` 89 | - Try entering `CREATE TABLE bikes();` in the psql prompt 90 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 91 | 92 | ## 80. Display the tables 93 | 94 | ### 80.1 95 | 96 | **D**isplay the tables to make sure your table got created. 97 | 98 | #### HINTS 99 | 100 | - Use the **d**isplay shortcut command 101 | - It's the `\d` command 102 | - Type `\d` into the psql prompt and press enter 103 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 104 | 105 | ## 90. Add column `bike_id` 106 | 107 | ### 90.1 108 | 109 | The table will have a few columns for bike information. First, is a unique ID column. Add a column to the `bikes` table named `bike_id`. Give it a type of `SERIAL` and make it a `PRIMARY KEY`. 110 | 111 | #### HINTS 112 | 113 | - Use the `ALTER TABLE`, `ADD COLUMN`, `SERIAL`, and `PRIMARY KEY` keywords 114 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 115 | - Try entering `ALTER TABLE bikes ADD COLUMN bike_id SERIAL PRIMARY KEY;` in the psql prompt 116 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 117 | 118 | ## 100. Display `bikes` Details 119 | 120 | ### 100.1 121 | 122 | Use the **d**isplay command to view the details of the `bikes` table. 123 | 124 | #### HINTS 125 | 126 | - It's the `\d` command 127 | - Add the table name to the command 128 | - Try entering `\d bikes` in the psql prompt 129 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 130 | 131 | ## 110. Add `type` column 132 | 133 | ### 110.1 134 | 135 | The first column is set. Add a column named `type` for the type of bike. Make it a `VARCHAR(50)` and give it a constraint of `NOT NULL`. 136 | 137 | #### HINTS 138 | 139 | - Use the `ALTER TABLE`, `ADD COLUMN`, `VARCHAR(50)`, and `PRIMARY KEY` keywords 140 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 141 | - Try entering `ALTER TABLE bikes ADD COLUMN type VARCHAR(50) NOT NULL;` in the psql prompt 142 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 143 | 144 | ## 120. Display `bikes` details 145 | 146 | ### 120.1 147 | 148 | Display the details of the `bikes` table again. 149 | 150 | #### HINTS 151 | 152 | - Use the **d**isplay shortcut command 153 | - Add the table name to the command 154 | - Here's an example: `\d table_name` 155 | - Try entering `\d bikes` in the psql prompt 156 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in 157 | 158 | ## 130. Add Column `size` 159 | 160 | ### 130.1 161 | 162 | The first two columns look good. Add a column named `size` to the `bikes` table that is an `INT` and has the `NOT NULL` constraint. This will be for the size of each bike. 163 | 164 | #### HINTS 165 | 166 | - Use the `ALTER TABLE`, `ADD COLUMN`, `INT`, and `NOT NULL` keywords 167 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 168 | - Try entering `ALTER TABLE bikes ADD COLUMN size INT NOT NULL;` in the psql prompt 169 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in 170 | 171 | ## 140. Add Column `available` 172 | 173 | ### 140.1 174 | 175 | Add another column to the table named `available`. Make it a `boolean` and has a constraint of `NOT NULL`. Also give it a default value of `TRUE`. This will be set to `false` when someone rents out a bike. 176 | 177 | #### HINTS 178 | 179 | - Use the `ALTER TABLE`, `ADD COLUMN`, `BOOLEAN`, `NOT NULL` and `DEFAULT TRUE` keywords 180 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS DEFAULT;` 181 | - Try entering `ALTER TABLE bikes ADD COLUMN available BOOLEAN NOT NULL DEFAULT TRUE;` in the psql prompt 182 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in 183 | 184 | ## 150. Display `bikes` details 185 | 186 | ### 150.1 187 | 188 | Display the details of the `bikes` table again so you can make sure it's how you want it. 189 | 190 | #### HINTS 191 | 192 | - Use the **d**isplay shortcut command 193 | - Add the table name to the command 194 | - Here's an example: `\d table_name` 195 | - Try entering `\d bikes` in the psql prompt 196 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 197 | 198 | ## 160. Create Table `customers` 199 | 200 | ### 160.1 201 | 202 | That table is done for now. Create another table named `customers`. It will store a name and phone number for each customer that rents a bike. 203 | 204 | #### HINTS 205 | 206 | - Use the `CREATE TABLE` keywords 207 | - Don't forget the parenthesis 208 | - Here's an example: `CREATE TABLE table_name();` 209 | - Try entering `CREATE TABLE customers();` in the psql prompt 210 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 211 | 212 | ## 170. Add Column `customer_id` 213 | 214 | ### 170.1 215 | 216 | Add a `customer_id` column to your new table that is a type of `SERIAL` and make it a `PRIMARY KEY`. 217 | 218 | #### HINTS 219 | 220 | - Use the `ALTER TABLE`, `ADD COLUMN`, `SERIAL`, and `PRIMARY KEY` keywords 221 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 222 | - Try entering `ALTER TABLE customers ADD COLUMN customer_id SERIAL PRIMARY KEY;` in the psql prompt 223 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 224 | 225 | ## 180. Display `customers` Details 226 | 227 | ### 180.1 228 | 229 | Display the details of the `customers` table so you can make sure your new column is there. 230 | 231 | #### HINTS 232 | 233 | - Use the **d**isplay shortcut command 234 | - Add the table name to the command 235 | - Here's an example: `\d table_name` 236 | - Try entering `\d customers` in the psql prompt 237 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 238 | 239 | ## 190. Add Column `phone` 240 | 241 | ### 190.1 242 | 243 | There it is. Add a column named `phone` for customers phone numbers. Make it a varying character that has a maximum length of `15` characters. Also make sure it can't be null, and that it has to be unique. 244 | 245 | #### HINTS 246 | 247 | - Use the `ALTER TABLE`, `ADD COLUMN`, `VARCHAR()`, `NOT NULL`, and `UNIQUE` keywords 248 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 249 | - Try entering `ALTER TABLE customers ADD COLUMN phone VARCHAR(15) NOT NULL UNIQUE;` in the psql prompt 250 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 251 | 252 | ## 200. Add Column `name` 253 | 254 | ### 200.1 255 | 256 | Add the last column. Call it `name` and make it a `VARCHAR(40)` that can't be null. 257 | 258 | #### HINTS 259 | 260 | - Use the `ALTER TABLE`, `ADD COLUMN`, `VARCHAR()`, and `NOT NULL` keywords 261 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 262 | - Try entering `ALTER TABLE customers ADD COLUMN name VARCHAR(40) NOT NULL;` in the psql prompt 263 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 264 | 265 | ## 210. Display `customers` Details 266 | 267 | ### 210.1 268 | 269 | Display the details of the `customers` table. 270 | 271 | #### HINTS 272 | 273 | - Use the **d**isplay shortcut command 274 | - Add the table name to the command 275 | - Here's an example: `\d table_name` 276 | - Try entering `\d customers` in the psql prompt 277 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 278 | 279 | ## 220. Create Table `rentals` 280 | 281 | ### 220.1 282 | 283 | That table is finished. Lastly, you need a table to store which bikes are rented and who has rented them. Create a new table named `rentals`. 284 | 285 | #### HINTS 286 | 287 | - Use the `CREATE TABLE` keywords 288 | - Don't forget the parenthesis 289 | - Here's an example: `CREATE TABLE table_name();` 290 | - Try entering `CREATE TABLE rentals();` in the psql prompt 291 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 292 | 293 | ## 230. Add Column `rental_id` 294 | 295 | ### 230.1 296 | 297 | Add a `rental_id` column to your new table. Make it automatically increment with `SERIAL` and make it the primary key for this table. 298 | 299 | #### HINTS 300 | 301 | - The other two properties are `SERIAL` and `PRIMARY KEY` 302 | - Use the `ALTER TABLE`, `ADD COLUMN`, `SERIAL`, and `PRIMARY KEY` keywords 303 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 304 | - Try entering `ALTER TABLE rentals ADD COLUMN rental_id SERIAL PRIMARY KEY;` in the psql prompt 305 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 306 | 307 | ## 240. Display `rentals` Details 308 | 309 | ### 240.1 310 | 311 | Display the details of the `rentals` table. 312 | 313 | #### HINTS 314 | 315 | - Use the **d**isplay shortcut command 316 | - Add the table name to the command 317 | - Here's an example: `\d table_name` 318 | - Try entering `\d rentals` in the psql prompt 319 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 320 | 321 | ## 250. Add Column `customer_id` 322 | 323 | ### 250.1 324 | 325 | Next, you need a column for the customer who is renting a bike. Add column named `customer_id`. This will have an id of a customer from the customers table. Make the column an `INT` and `NOT NULL` to start. 326 | 327 | #### HINTS 328 | 329 | - Add the column to the `rentals` table 330 | - Use the `ALTER TABLE`, `ADD COLUMN`, `INT`, and `NOT NULL` keywords 331 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 332 | - Try entering `ALTER TABLE rentals ADD COLUMN customer_id INT NOT NULL;` in the psql prompt 333 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 334 | 335 | ## 260. Set `customer_id` Foreign Key 336 | 337 | ### 260.1 338 | 339 | Make the column you just added a foreign key that references the `customer_id` column from the `customers` table. Here's an example of how you can do that: 340 | 341 | ```sql 342 | ALTER TABLE table_name ADD FOREIGN KEY(column_name) REFERENCES referenced_table(referenced_column); 343 | ``` 344 | 345 | #### HINTS 346 | 347 | - Without the keywords, it looks like tihs: `rentals customer_id customers(customer_id)` 348 | - Try entering `ALTER TABLE rentals ADD FOREIGN KEY(customer_id) REFERENCES customers(customer_id);` in the psql prompt 349 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 350 | 351 | ## 270. Display `rentals` Details 352 | 353 | ### 270.1 354 | 355 | Display the details of the `rentals` table to make sure your key is set. 356 | 357 | #### HINTS 358 | 359 | - Use the **d**isplay shortcut command 360 | - Add the table name to the command 361 | - Here's an example: `\d table_name` 362 | - Try entering `\d rentals` in the psql prompt 363 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 364 | 365 | ## 280. Add Column `bike_id` 366 | 367 | ### 280.1 368 | 369 | That foreign key is set. You need another column so you know what bike a customer is renting. Add a column named `bike_id` and make it an `INT` and `NOT NULL`. 370 | 371 | #### HINTS 372 | 373 | - Add the column to the `rentals` table 374 | - Use the `ALTER TABLE`, `ADD COLUMN`, `INT`, and `NOT NULL` keywords 375 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 376 | - Try entering `ALTER TABLE rentals ADD COLUMN bike_id INT NOT NULL;` in the psql prompt 377 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 378 | 379 | ## 290. Add `bike_id` Foreign Key 380 | 381 | ### 290.1 382 | 383 | Make that column a foreign key that references the `bike_id` column from the `bikes` table so you know what bike the id is for. 384 | 385 | #### HINTS 386 | 387 | - Here's the example again: `ALTER TABLE table_name ADD FOREIGN KEY(column_name) REFERENCES referenced_table(referenced_column);` 388 | - Without the keywords, it looks like tihs: `rentals bike_id bikes(bike_id)` 389 | - Try entering `ALTER TABLE rentals ADD FOREIGN KEY(bike_id) REFERENCES bikes(bike_id);` in the psql prompt 390 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 391 | 392 | ## 300. Display `rentals` Details 393 | 394 | ### 300.1 395 | 396 | Display the details of the `rentals` table so you can make sure the key is correct. 397 | 398 | #### HINTS 399 | 400 | - Use the **d**isplay shortcut command 401 | - Add the table name to the command 402 | - Here's an example: `\d table_name` 403 | - Try entering `\d rentals` in the psql prompt 404 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 405 | 406 | ## 310. Add `date_rented` Column 407 | 408 | ### 310.1 409 | 410 | Moving along. You want to know when a customer rents a bike, and when it gets returned. Add a column to your `rentals` table named `date_rented` that's a type of `DATE`. Make sure the entry can't be null, and give it a default value of `NOW()`. 411 | 412 | #### HINTS 413 | 414 | - Add the column to the `rentals` table 415 | - Use the `ALTER TABLE`, `ADD COLUMN`, `DATE`, `NOT NULL`, and `DEFAULT NOW()` keywords 416 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE CONSTRAINTS;` 417 | - Try entering `ALTER TABLE rentals ADD COLUMN date_rented DATE NOT NULL DEFAULT NOW();` in the psql prompt 418 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 419 | 420 | ## 320. Display `rentals` Details 421 | 422 | ### 320.1 423 | 424 | Display the details of the `rentals` table again. 425 | 426 | #### HINTS 427 | 428 | - Use the **d**isplay shortcut command 429 | - Add the table name to the command 430 | - Here's an example: `\d table_name` 431 | - Try entering `\d rentals` in the psql prompt 432 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 433 | 434 | ## 330. Add Column `date_returned` 435 | 436 | ### 330.1 437 | 438 | It looks good. Lastly, you need a column for when a customer returns a bike. Add a column named `date_returned` that's a type of `DATE`. 439 | 440 | #### HINTS 441 | 442 | - Use the `ALTER TABLE`, `ADD COLUMN`, `DATE` keywords 443 | - Add the column to the `rentals` table 444 | - Here's an example: `ALTER TABLE table_name ADD COLUMN column_name TYPE;` 445 | - Try entering `ALTER TABLE rentals ADD COLUMN date_returned DATE;` in the psql prompt 446 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 447 | 448 | ## 340. Display `rentals` Details 449 | 450 | ### 340.1 451 | 452 | View the details of the table again. 453 | 454 | #### HINTS 455 | 456 | - It's the `rentals` table 457 | - Use the **d**isplay shortcut command 458 | - Add the table name to the command 459 | - Here's an example: `\d table_name` 460 | - Try entering `\d rentals` in the psql prompt 461 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 462 | 463 | ## 350. Display Tables 464 | 465 | ### 350.1 466 | 467 | The tables are all finished. Display all the tables so you can see what you ended up with. 468 | 469 | #### HINTS 470 | 471 | - Use the **d**isplay shortcut command 472 | - It's the `\d` command 473 | - Enter `\d` in the psql prompt 474 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 475 | 476 | ## 360. Insert 27 inch Mountain Bike 477 | 478 | ### 360.1 479 | 480 | You have nine bikes in your inventory. Add the first one to your `bikes` table. It has a `type` of `Mountain` and a `size` of `27`. Make sure to put your `VARCHAR` values in single quotes. The `bike_id` and `available` columns should be filled in automatically, so you don't need to worry about those. 481 | 482 | #### HINTS 483 | 484 | - Use the `INSERT INTO` and `VALUES` keywords 485 | - Here's an example: `INSERT INTO table_name(column_name, column_name) VALUES(value, value);` 486 | - View the details of the `bikes` table with `\d bikes` to see what values it expects 487 | - Try entering `INSERT INTO bikes(type, size) VALUES('Mountain', 27);` in the psql prompt 488 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 489 | 490 | ## 370. Select all from Bikes 491 | 492 | ### 370.1 493 | 494 | View all the columns in your bikes table with `SELECT`. 495 | 496 | #### HINTS 497 | 498 | - Use `*` to view all the columns 499 | - Here's an example: `SELECT * FROM table_name;` 500 | - Try entering `SELECT * from bikes;` in the psql prompt 501 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 502 | 503 | ## 380. Insert 28 inch Mountain Bike 504 | 505 | ### 380.1 506 | 507 | Looks like it's all working, the `bike_id` and `available` columns were filled in automatically. Insert another bike. Give it a `type` of `Mountain` and a `size` of `28`. 508 | 509 | #### HINTS 510 | 511 | - Make sure to put your `VARCHAR` values in single quotes 512 | - Use the `INSERT INTO` and `VALUES` keywords 513 | - Here's an example: `INSERT INTO table_name(column_name, column_name) VALUES(value, value);` 514 | - Try entering `INSERT INTO bikes(type, size) VALUES('Mountain', 28);` in the psql prompt 515 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 516 | 517 | ## 390. Insert 29 inch Mountain Bike 518 | 519 | ### 390.1 520 | 521 | Add another `Mountain` bike to your inventory. Make it a `29` inch bike. 522 | 523 | #### HINTS 524 | 525 | - Use the `INSERT INTO` and `VALUES` keywords 526 | - Make sure to put your `VARCHAR` values in single quotes 527 | - Here's an example: `INSERT INTO table_name(column_name, column_name) VALUES(value, value);` 528 | - Try entering `INSERT INTO bikes(type, size) VALUES('Mountain', 29);` in the psql prompt 529 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 530 | 531 | ## 400. Insert 27 inch Road Bike 532 | 533 | ### 400.1 534 | 535 | Add a `27` inch `Road` bike to the table. 536 | 537 | #### HINTS 538 | 539 | - Use the `INSERT INTO` and `VALUES` keywords 540 | - Make sure to put your `VARCHAR` values in single quotes 541 | - Here's an example: `INSERT INTO table_name(column_name, column_name) VALUES(value, value);` 542 | - Try entering `INSERT INTO bikes(type, size) VALUES('Road', 27);` in the psql prompt 543 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 544 | 545 | ## 410. Select all from Bikes 546 | 547 | ### 410.1 548 | 549 | Use `SELECT` to view all the data in the `bikes` table again. 550 | 551 | #### HINTS 552 | 553 | - Use `*` to view all the columns 554 | - Here's an example: `SELECT * FROM table_name;` 555 | - Try entering `SELECT * from bikes;` in the psql prompt 556 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 557 | 558 | ## 420. Insert 28 and 29 inch Road Bikes 559 | 560 | ### 420.1 561 | 562 | Add the two bikes to your inventory, they are `28` and `29` inch `Road` bikes. Try to add them both with one command. 563 | 564 | #### HINTS 565 | 566 | - Here's an example: `INSERT INTO table_name(column_name, column_name) VALUES(value, value), (value, value);` 567 | - Make sure to put your `VARCHAR` values in single quotes 568 | - Try entering `INSERT INTO bikes(type, size) VALUES('Road', 28), ('Road', 29);` in the psql prompt 569 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 570 | 571 | ## 430. Insert 19, 20, 21 inch BMX Bikes 572 | 573 | ### 430.1 574 | 575 | There's three more bikes. Add `19`, `20`, and `21` inch `BMX` bikes to your table. Try to add them with one command. 576 | 577 | #### HINTS 578 | 579 | - Here's an example: `INSERT INTO table_name(column_name, column_name) VALUES(value, value), (value, value), (value, value);` 580 | - Make sure to put your `VARCHAR` values in single quotes 581 | - Try entering `INSERT INTO bikes(type, size) VALUES('BMX', 19), ('BMX', 20), ('BMX', 21);` in the psql prompt 582 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 583 | 584 | ## 440. Select all from Bikes 585 | 586 | ### 440.1 587 | 588 | View all the data in your bikes table. 589 | 590 | #### HINTS 591 | 592 | - Use `SELECT` with `*` to view all the columns 593 | - Here's an example: `SELECT * FROM table_name;` 594 | - Try entering `SELECT * from bikes;` in the psql prompt 595 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in first 596 | 597 | ## 450. touch bike-shop.sh 598 | 599 | ### 450.1 600 | 601 | Your current inventory is all added. For the rest of the project, I recommend leaving that terminal open and connected, and that you should "split" the terminal so you have a second one to use for bash commands. Do that by clicking the "hamburger" menu at the top left of the window, going to the "terminal" section, and clicking "split terminal". After you have opened it, use the `touch` command to create a file named `bike-shop.sh` in the `project` folder. 602 | 603 | #### HINTS 604 | 605 | - Try entering `touch bike-shop.sh` in the terminal 606 | - Make sure it's the regular terminal, and not the psql one 607 | - Make sure you are in the `project` folder first 608 | - If you opened a new terminal instead of splitting it, you can close it by entering `exit` and try again 609 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you want 610 | 611 | ## 460. Add shebang! 612 | 613 | ### 460.1 614 | 615 | This file will be the program for your bike rental shop. Open the file and add a "shebang" at the top so it uses `bash` when it's executed. If you don't remember, it looks like this: `#!/bin/bash`. 616 | 617 | #### HINTS 618 | 619 | - Add `#!/bin/bash` to the top of your `bike-shop.sh` file 620 | 621 | ## 470. Add echo Bike Rental Shop 622 | 623 | ### 470.1 624 | 625 | In the file, use `echo` with the `-e` flag to print `~~~~~ Bike Rental Shop ~~~~~` with a new line at the beginning and end. 626 | 627 | #### HINTS 628 | 629 | - The newline character is `\n` 630 | - Use double quotes around the message so the new lines are printed 631 | - Here's an example: `echo -e "\n\n"` 632 | - Add `echo -e "\n~~~~~ Bike Rental Shop ~~~~~\n"` to the `bike-shop-sh` file 633 | 634 | ## 480. chmod +x bike-shop.sh 635 | 636 | ### 480.1 637 | 638 | Use the terminal (not the psql one) and the `chmod` command to make your file executable. Add the `+x` flag and `bike-shop.sh` to the command to do that. 639 | 640 | #### HINTS 641 | 642 | - Here's an example: `chmod +x ` 643 | - Try entering `chmod +x bike-shop.sh` in the terminal 644 | - Make sure you are in the `project` folder first 645 | 646 | ## 490. ./bike-shop.sh 647 | 648 | ### 490.1 649 | 650 | Type `./bike-shop.sh` in the terminal to run your script. 651 | 652 | #### HINTS 653 | 654 | - Make sure to use the regular terminal and not the psql one 655 | - Make sure you are in the `project` folder first 656 | 657 | ## 510. Add MAIN_MENU 658 | 659 | ### 510.1 660 | 661 | :smile: In the script, create an empty function named `MAIN_MENU`. This will have a few options to enter when the script runs to rent or return a bike. 662 | 663 | #### HINTS 664 | 665 | - Here's an example: 666 | ```sh 667 | FUNCTION_NAME() { 668 | 669 | } 670 | ``` 671 | - Add this to the bottom of the script: 672 | ```sh 673 | MAIN_MENU() { 674 | 675 | } 676 | ``` 677 | 678 | ## 520. Add echo How may I help you? 679 | 680 | ### 520.1 681 | 682 | In your function, echo the text `How may I help you?` so that there's a greeting when you go to the menu. 683 | 684 | #### HINTS 685 | 686 | - Add `echo "How may I help you?"` in the designated area 687 | 688 | ## 530. Add MAIN_MENU function call 689 | 690 | ### 530.1 691 | 692 | Call your `MAIN_MENU` at the bottom of the file so the function runs when you start the script. 693 | 694 | #### HINTS 695 | 696 | - Add `MAIN_MENU` at the bottom of the file 697 | 698 | ## 540. ./bike-shop.sh 699 | 700 | ### 540.1 701 | 702 | Run the file in the terminal again so you can see what it is outputting. 703 | 704 | #### HINTS 705 | 706 | - Enter `./bike-shop.sh` in the terminal and press enter 707 | - Make sure you are in the `project` folder first 708 | 709 | ## 630. Add MAIN_MENU Options 710 | 711 | ### 630.1 712 | 713 | It's coming along. Add another `echo` command **in the function** below the other one. Make it output text that looks like this: 714 | 715 | ```sh 716 | 717 | 1. Rent a bike 718 | 2. Return a bike 719 | 3. Exit 720 | ``` 721 | 722 | Note that there's an empty line at the start. 723 | 724 | #### HINTS 725 | 726 | - Use the `echo` command with the `-e` flag and line breaks (`\n`) to produce the suggested output 727 | - Without the words, it looks like this: `echo -e "\n1. \n2. \n3. "` 728 | - Run your script if you need to see if the output matches 729 | - Add `echo -e "\n1. Rent a bike\n2. Return a bike\n3. Exit"` to your function 730 | 731 | ## 640. Run the file 732 | 733 | ### 640.1 734 | 735 | Run the file to make sure it worked. 736 | 737 | #### HINTS 738 | 739 | - Enter `./bike-shop.sh` in the terminal and press enter 740 | - Make sure you are in the `project` folder first 741 | 742 | ## 650. Read MAIN_MENU_SELECTION 743 | 744 | ### 650.1 745 | 746 | You have some options displaying. Next, you need to get input from whoever is using the program. Use the `read` command to read input into a variable called `MAIN_MENU_SELECTION` below the options. 747 | 748 | #### HINTS 749 | 750 | - Here's an example: `read ` 751 | - Here's what the code looks like: `read MAIN_MENU_SELECTION` 752 | - Add the code at the bottom of the `MAIN_MENU` function 753 | - The `MAIN_MENU` function should look like this: 754 | ```sh 755 | MAIN_MENU() { 756 | echo "How may I help you?" 757 | echo -e "\n1. Rent a bike\n2. Return a bike\n3. Exit" 758 | read MAIN_MENU_SELECTION 759 | } 760 | ``` 761 | 762 | ## 660. Add RENT_MENU 763 | 764 | ### 660.1 765 | 766 | When an option gets entered, you need to take a user to one of those other menus. Add an empty `RENT_MENU` function below the `MAIN_MENU` function. 767 | 768 | #### HINTS 769 | 770 | - Make sure the `RENT_MENU` function is below the `MAIN_MENU` function and above where you call `MAIN_MENU` 771 | - Add this in the suggested area: 772 | ```sh 773 | RENT_MENU() { 774 | 775 | } 776 | ``` 777 | 778 | ## 670. Add echo Rent Menu 779 | 780 | ### 670.1 781 | 782 | For the time being, just echo `Rent Menu` in the function so you can see if it's working. 783 | 784 | #### HINTS 785 | 786 | - Don't use any flags with the command 787 | - Add `echo "Rent Menu"` in the `RENT_MENU` function 788 | 789 | ## 680. Add RETURN_MENU function 790 | 791 | ### 680.1 792 | 793 | Add an empty `RETURN_MENU` function below the `RENT_MENU` function for when a user enters the option to return a bike. 794 | 795 | #### HINTS 796 | 797 | - Make sure the `RETURN_MENU` function is below the `RENT_MENU` function and above where you call `MAIN_MENU` 798 | - Add this in the suggested area: 799 | ```sh 800 | RETURN_MENU() { 801 | 802 | } 803 | ``` 804 | 805 | ## 690. Add echo Return Menu 806 | 807 | ### 690.1 808 | 809 | Use `echo` to print `Return Menu` in the function you just added. You will change these later. 810 | 811 | #### HINTS 812 | 813 | - Don't use any flags with the command 814 | - Add `echo "Return Menu"` in the `RETURN_MENU` function 815 | 816 | ## 700. Add EXIT function 817 | 818 | ### 700.1 819 | 820 | Add an empty `EXIT` function below the `RETURN_MENU` function for when a user wants to exit the program. 821 | 822 | #### HINTS 823 | 824 | - Make sure the `EXIT` function is below the `RETURN_MENU` function and above where you call `MAIN_MENU` 825 | - Add this in the suggested area: 826 | ```sh 827 | EXIT() { 828 | 829 | } 830 | ``` 831 | 832 | ## 710. Add EXIT Message 833 | 834 | ### 710.1 835 | 836 | This one probably doesn't need a placeholder message. In the `EXIT` function, use `echo` to print `Thank you for stopping in.` with a new line at the beginning and end of the message. 837 | 838 | #### HINTS 839 | 840 | - The newline character is `\n` 841 | - Use double quotes around the message so the new lines are printed 842 | - Here's an example: `echo -e "\n\n"` 843 | - Add `echo -e "\nThank you for stopping in.\n"` to the `EXIT` function 844 | 845 | ## 720. Add case statement to `MAIN_MENU` 846 | 847 | ### 720.1 848 | 849 | When a user enters an option at the main menu, you want to take them to the appropriate sub-menu. You can use a `case` statement for this. Here's an example: 850 | 851 | ```sh 852 | case EXPRESSION in 853 | PATTERN) STATEMENTS ;; 854 | PATTERN) STATEMENTS ;; 855 | PATTERN) STATEMENTS ;; 856 | *) STATEMENTS ;; 857 | esac 858 | ``` 859 | 860 | The expression you want is the `$MAIN_MENU_SELECTION` variable. You are expecting it to be a `1`, `2`, or `3` for your various menus. Add a `case` statement that takes users to their corresponding menus. The `*` is for when anything else is entered. Take users to the `MAIN_MENU` when the variable isn't a `1`, `2`, or `3`. 861 | 862 | #### HINTS 863 | 864 | - Add the `case` statement in the `MAIN_MENU` function below the `read MAIN_MENU_SELECTION` line 865 | - Here's how it starts: 866 | ```sh 867 | case $MAIN_MENU_SELECTION in 868 | 1) RENT_MENU ;; 869 | ``` 870 | - Add this case statement below the; 871 | ```sh 872 | case $MAIN_MENU_SELECTION in 873 | 1) RENT_MENU ;; 874 | 2) RETURN_MENU ;; 875 | 3) EXIT ;; 876 | *) MAIN_MENU ;; 877 | esac 878 | ``` 879 | 880 | ## 730. ./bike-shop.sh 881 | 882 | ### 730.1 883 | 884 | Run the script a few times and try out the different menus. Be sure to enter something other than one of the options to go to the main menu. 885 | 886 | #### HINTS 887 | 888 | - Enter `./bike-shop.sh` in the terminal and press enter 889 | - Make sure you are in the `project` folder first 890 | 891 | ## 740. Add arg to MAIN_MENU call in case 892 | 893 | ### 740.1 894 | 895 | Add an argument to where you call `MAIN_MENU` in the `case` statement. It should be `Please enter a valid option.`. The next step will adjust the function so the message is printed when a user enters an invalid option. 896 | 897 | #### HINTS 898 | 899 | - Here's an example: `FUNCTION_CALL ""` 900 | - Here's how the function call should look: 901 | ```sh 902 | *) MAIN_MENU "Please enter a valid option." ;; 903 | ``` 904 | - The whole `case` statement should look like this: 905 | ```sh 906 | case $MAIN_MENU_SELECTION in 907 | 1) RENT_MENU ;; 908 | 2) RETURN_MENU ;; 909 | 3) EXIT ;; 910 | *) MAIN_MENU "Please enter a valid option." ;; 911 | esac 912 | ``` 913 | 914 | ## 750. Add if $1 to MAIN_MENU 915 | 916 | ### 750.1 917 | 918 | At the top of the `MAIN_MENU` function, add an `if` condition that checks if there's an argument (`$1`) passed to the function. If there is, print the message with a new line in front of it. 919 | 920 | #### HINTS 921 | 922 | - Here's an example of an `if`: 923 | ```sh 924 | if [[ ]] 925 | then 926 | 927 | fi 928 | ``` 929 | - The condition you want is `$1` 930 | - Use `echo` with the `-e` flag and a new line character (`\n`) to print the argument with a new line at the beginning in the `` area 931 | - Here's an example of that part: `echo -e "\n"` 932 | - The `if` statement should look like this: 933 | ```sh 934 | if [[ $1 ]] 935 | then 936 | echo -e "\n$1" 937 | fi 938 | ``` 939 | - Make sure to put it at the top of the `MAIN_MENU` function 940 | 941 | ## 760. ./bike-shop.sh 942 | 943 | ### 760.1 944 | 945 | Run the script and enter an invalid option to see the message. Exit the program when you are done. 946 | 947 | #### HINTS 948 | 949 | - Enter `./bike-shop.sh` in the terminal and press enter 950 | - Make sure you are in the `project` folder first 951 | 952 | ## 850. Delete echo Rent Menu 953 | 954 | ### 850.1 955 | 956 | Looks good. Delete the `echo "Rent Menu"` from the `RENT_MENU` function so you can start adding the ability to rent a bike from the database. 957 | 958 | #### HINTS 959 | 960 | - The `RENT_MENU` function should be empty 961 | - The `RENT_MENU` function should look like this: 962 | ```sh 963 | RENT_MENU() { 964 | 965 | } 966 | ``` 967 | 968 | ## 860. Add comments to RENT_MENU 969 | 970 | ### 860.1 971 | 972 | In the `RENT_MENU` function, add three single line comments; `get available bikes`, `if no bikes available`, and `send to main menu`, in that order. 973 | 974 | #### HINTS 975 | 976 | - Here's an example of a single line comment: `# ` 977 | - The `RENT_MENU` function should look like this: 978 | ```sh 979 | RENT_MENU() { 980 | # get available bikes 981 | 982 | # if no bikes available 983 | 984 | # send to main menu 985 | 986 | } 987 | ``` 988 | 989 | ## 920. Add PSQL Variable 990 | 991 | ### 920.1 992 | 993 | To get the bikes available, you need to query the database from your script. Below the "shebang", add a `PSQL` variable that looks like this: `PSQL="psql -X --username=freecodecamp --dbname=bikes --tuples-only -c"`. You will then be able to use it to query the database like this: `$($PSQL "")`. 994 | 995 | #### HINTS 996 | 997 | - Add the suggested variable below the "shebang" and above where you print the `Bike Rental Shop` line 998 | 999 | ## 970. Add AVAILABLE_BIKES 1000 | 1001 | ### 970.1 1002 | 1003 | Below the `get available bikes` comment. Create an `AVAILABLE_BIKES` variable that gets the `bike_id`, `type`, and `size` columns from the `bikes` table for the bikes that are available. Order the results by their `bike_id` column. Here's an example: `AVAILABLE_BIKES=$($PSQL "")` 1004 | 1005 | #### HINTS 1006 | 1007 | - Use the `SELECT`, `FROM`, `WHERE`, and `ORDER BY` keywords in your query 1008 | - Get the three suggested columns in the same order they are listed; `bike_id, type, size` 1009 | - The condition you want is `WHERE available = true` 1010 | - Without the keywords, the query looks like this: `bike_id, type, size bikes available = true bike_id` 1011 | - The query should be `SELECT bike_id, type, size FROM bikes WHERE available = true ORDER BY bike_id` 1012 | - Add `AVAILABLE_BIKES=$($PSQL "SELECT bike_id, type, size FROM bikes WHERE available = true ORDER BY bike_id")` below the `get available bikes` comment 1013 | 1014 | ## 980. echo AVAILABLE_BIKES 1015 | 1016 | ### 980.1 1017 | 1018 | Below the new variable, use `echo` to print it. Place it in double quotes so it prints any new lines. 1019 | 1020 | #### HINTS 1021 | 1022 | - Here's an example: `echo ""` 1023 | - Use the variable with `$AVAILABLE_BIKES` 1024 | - Add `echo "$AVAILABLE_BIKES"` to the suggested area 1025 | 1026 | ## 990. ./bike-shop.sh 1027 | 1028 | ### 990.1 1029 | 1030 | Run your script and go to the rent menu to see if the available bikes are being printed. 1031 | 1032 | #### HINTS 1033 | 1034 | - Enter `./bike-shop.sh` in the terminal and press enter 1035 | - Make sure you are in the `project` folder first 1036 | 1037 | ## 993. psql UPDATE bikes SET available = false 1038 | 1039 | ### 990.1 1040 | 1041 | Awesome. In the psql prompt, set the `available` column to `false` for all the bikes so you can see what it prints when there's no bikes available. 1042 | 1043 | #### HINTS 1044 | 1045 | - Use the `UPDATE`, `SET`, and `WHERE` keywords 1046 | - Here's an example: `UPDATE SET = WHERE ` 1047 | - You want to set `available` to `false` for columns that are `true` 1048 | - After the `SET` can look like this: `available = false WHERE available = true` 1049 | - Try entering `UPDATE bikes SET available = false WHERE available = true;` in the psql prompt 1050 | - Type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. I recommend "splitting" the terminal so you can have one for bash commands and one for psql commands. You can do that by clicking the "hamburger" menu at the top left of the window, going to the "terminal" section, and clicking "split terminal". 1051 | 1052 | ## 995. ./bike-shop.sh 1053 | 1054 | ### 995.1 1055 | 1056 | Run your script and go to the rent menu to see the output. 1057 | 1058 | #### HINTS 1059 | 1060 | - Enter `./bike-shop.sh` in the terminal and press enter 1061 | - Make sure it's the regular terminal and not the psql one 1062 | - Make sure you are in the `project` folder first 1063 | 1064 | ## 1000. Add if -z AVAILABLE_BIKES 1065 | 1066 | ### 1000.1 1067 | 1068 | So if there's no bike available, the variable will be empty. In the script, below the `if no bikes available` comment, add an `if` condition that checks if the variable is empty. Use `-z` to check if it's empty. Place the `send to main menu` comment in its `STATEMENTS` area. 1069 | 1070 | #### HINTS 1071 | 1072 | - Use `-z ` to see if a variable is empty 1073 | - Here's an example: 1074 | ```sh 1075 | if [[ -z ]] 1076 | then 1077 | 1078 | fi 1079 | ``` 1080 | - The `if` condition should look like this: 1081 | ```sh 1082 | if [[ -z $AVAILABLE_BIKES ]] 1083 | then 1084 | # send to main menu 1085 | fi 1086 | ``` 1087 | - Make sure it's right below the suggested comment 1088 | 1089 | ## 1010. Add MAIN_MENU Sorry, we don't have any bikes available right now 1090 | 1091 | ### 1010.1 1092 | 1093 | Below the comment in the `if` you just added. Send users to the main menu and give them the message, `Sorry, we don't have any bikes available right now.` 1094 | 1095 | #### HINTS 1096 | 1097 | - Here's an example `MAIN MENU ""` 1098 | - Make sure it's in the `if` condition below the `send to main menu` comment 1099 | - The function call should look like this: `MAIN_MENU "Sorry, we don't have any bikes available right now."` 1100 | - The `if` condition should look like this: 1101 | ```sh 1102 | if [[ -z $AVAILABLE_BIKES ]] 1103 | then 1104 | # send to main menu 1105 | MAIN_MENU "Sorry, we don't have any bikes available right now." 1106 | fi 1107 | ``` 1108 | 1109 | ## 1020. ./bike-shop.sh 1110 | 1111 | ### 1020.1 1112 | 1113 | Run the script and go to the rent menu to see the message. When you are done, exit the program. 1114 | 1115 | #### HINTS 1116 | 1117 | - Enter `./bike-shop.sh` in the terminal and press enter 1118 | - Make sure you are in the `project` folder first 1119 | 1120 | ## 1100. Add else with comments 1121 | 1122 | ### 1100.1 1123 | 1124 | If no bikes are available, you will get that message. Add an `else` to the `if` condition for when there is bikes available. In it, add four single line comments; `display available bikes`, `ask for bike to rent`, `if input is not a number`, and `send to main menu`. 1125 | 1126 | #### HINTS 1127 | 1128 | - Here's an example of a single line comment: `# ` 1129 | - Make sure the comments are in the same order listed 1130 | - An `if/else` statement looks like this: 1131 | ```sh 1132 | if [[ ]] 1133 | then 1134 | 1135 | else 1136 | 1137 | fi 1138 | ``` 1139 | - The `else` should look like this: 1140 | ```sh 1141 | else 1142 | # display available bikes 1143 | 1144 | # ask for bike to rent 1145 | 1146 | # if input is not a number 1147 | 1148 | # send to main menu 1149 | 1150 | ``` 1151 | - The whole `if` should look like this: 1152 | ```sh 1153 | if [[ -z $AVAILABLE_BIKES ]] 1154 | then 1155 | # send to main menu 1156 | MAIN_MENU "Sorry, we don't have any bikes available right now." 1157 | else 1158 | # display available bikes 1159 | 1160 | # ask for bike to rent 1161 | 1162 | # if input is not a number 1163 | 1164 | # send to main menu 1165 | 1166 | fi 1167 | ``` 1168 | 1169 | ## 1105. Add echo Here are the bikes we have available 1170 | 1171 | ### 1105.1 1172 | 1173 | Below the `display available bikes` comment you just added, use `echo` to print `Here are the bikes we have available:` with a new line in front of the message 1174 | 1175 | #### HINTS 1176 | 1177 | - Use `echo` with the `-e` flag and the new line character (`\n`) to print the suggested message 1178 | - Use double quotes around the message 1179 | - Here's an example: `echo -e "\n"` 1180 | - Add `echo -e "\nHere are the bikes we have available:"` below the suggested comment 1181 | 1182 | ## 1110. Move echo AVAILABLE_BIKES 1183 | 1184 | ### 1110.1 1185 | 1186 | Move the `echo` command that prints all the available bikes below the message you just added. 1187 | 1188 | #### HINTS 1189 | 1190 | - It's the `echo $AVAILABLE_BIKES` command 1191 | - It should be below the `Here are the bikes we have available:` message 1192 | - You should only print the bikes available in that one spot 1193 | - Place the `echo "$AVAILABLE_BIKES"` line in the suggested spot 1194 | 1195 | ## 1115. psql UPDATE bikes SET all != BMX to TRUE 1196 | 1197 | ### 1115.1 1198 | 1199 | In the psql prompt, set all the bikes, except for the `BMX` bikes, back to true so you can see a list of bikes to rent. 1200 | 1201 | #### HINTS 1202 | 1203 | - Use the `UPDATE`, `SET`, and `WHERE` keywords 1204 | - Here's an example: `UPDATE
SET = WHERE ` 1205 | - You want to set `available` to `true` for columns that don't have a `type` of `BMX` 1206 | - You can use the `!=` operator to check for columns not equal to a value 1207 | - After the `SET` can look like this: `available = true WHERE type != 'BMX'` 1208 | - Try entering `UPDATE bikes SET available = true WHERE type != 'BMX';` in the psql prompt 1209 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 1210 | 1211 | ## 1130. ./bike-shop.sh 1212 | 1213 | ### 1130.1 1214 | 1215 | Run the script and go to the rent menu to see the list of bikes available. 1216 | 1217 | #### HINTS 1218 | 1219 | - Enter `./bike-shop.sh` in the terminal and press enter 1220 | - Make sure you are in the `project` folder first 1221 | 1222 | ## 1140. pipe AVAILABLE_BIKES into while loop 1223 | 1224 | ### 1140.1 1225 | 1226 | Instead of directly printing the list, `pipe` the output into a `while` loop that reads each line. Here's how that looks: 1227 | 1228 | ```sh 1229 | echo "$AVAILABLE_BIKES" | while read 1230 | do 1231 | 1232 | done 1233 | ``` 1234 | 1235 | It will read the first line of your `AVAILABLE_BIKES` variable into the five variables. Each variable being the next word in the line. Read each line into variables, `BIKE_ID BAR TYPE BAR SIZE`. In the `` area, use `echo` to print the `BIKE_ID`, `TYPE`, and `SIZE` variables, in that order. 1236 | 1237 | #### HINTS 1238 | 1239 | - The first line should be `echo "$AVAILABLE_BIKES" | while read BIKE_ID BAR TYPE BAR SIZE` 1240 | - The `` area looks like this: `echo "$BIKE_ID $TYPE $SIZE"` 1241 | - Here's how it should look: 1242 | ```sh 1243 | echo "$AVAILABLE_BIKES" | while read BIKE_ID BAR TYPE BAR SIZE 1244 | do 1245 | echo "$BIKE_ID $TYPE $SIZE" 1246 | done 1247 | ``` 1248 | 1249 | ## 1142. Run the script 1250 | 1251 | ### 1142.1 1252 | 1253 | Run the script and go to the rent menu again to see if it's working. 1254 | 1255 | #### HINTS 1256 | 1257 | - Enter `./bike-shop.sh` in the terminal and press enter 1258 | - Make sure you are in the `project` folder first 1259 | 1260 | ## 1145. Adjust Available Bikes Display 1261 | 1262 | ### 1145.1 1263 | 1264 | It's working :smile: Adjust the echo command that prints the bike info so that the first line printed would look like this: `1) 27" Mountain Bike`. The rest would look the same, but with their bike info. Make sure to escape any characters you need to. 1265 | 1266 | #### HINTS 1267 | 1268 | - Be sure to use double quotes and escape the `"` after `SIZE` 1269 | - Run your script and check the output if you want to see if it matches the suggestion 1270 | - Escape a `"` with `\"` 1271 | - Here's an example: `echo ") " Bike"` 1272 | - Make the suggested line look like this: `echo "$BIKE_ID) $SIZE\" $TYPE Bike"` 1273 | - The whole loop should look like this: 1274 | ```sh 1275 | echo "$AVAILABLE_BIKES" | while read BIKE_ID BAR TYPE BAR SIZE 1276 | do 1277 | echo "$BIKE_ID) $SIZE\" $TYPE Bike" 1278 | done 1279 | ``` 1280 | 1281 | ## 1150. Run the script 1282 | 1283 | ### 1150.1 1284 | 1285 | Run the script and go to the rent menu again to see what it looks like now. 1286 | 1287 | #### HINTS 1288 | 1289 | - Enter `./bike-shop.sh` in the terminal and press enter 1290 | - Make sure you are in the `project` folder first 1291 | 1292 | ## 1160. Add echo Which one would you like to rent? 1293 | 1294 | ### 1160.1 1295 | 1296 | That's better. Below the `ask for bike to rent` comment, print `Which one would you like to rent?` with a new line in front of it. 1297 | 1298 | #### HINTS 1299 | 1300 | - Use `echo` with the `-e` flag and the new line character (`\n`) to print the suggested message 1301 | - Use double quotes around the message 1302 | - Here's an example: `echo -e "\n"` 1303 | - Add `echo -e "\nWhich one would you like to rent?"` below the suggested comment 1304 | 1305 | ## 1162. read BIKE_ID_TO_RENT 1306 | 1307 | ### 1162.1 1308 | 1309 | Just below that, add a command to `read` input into a variable named `BIKE_ID_TO_RENT`. 1310 | 1311 | #### HINTS 1312 | 1313 | - Here's an example: `read ` 1314 | - Add this to the suggested area: `read BIKE_ID_TO_RENT` 1315 | 1316 | ## 1164. [[ a =~ [0-9] ]]; echo $? 1317 | 1318 | ### 1164.1 1319 | 1320 | Next, you want to find out how to test if the user input is a number. In the terminal, enter `[[ a =~ [0-9] ]]; echo $?` to see if `a` is a number. The conditional expression will run, and `echo $?` will print the exit code of it (the last command). 1321 | 1322 | #### HINTS 1323 | 1324 | - Enter `[[ a =~ [0-9] ]]; echo $?` in the terminal 1325 | - It's the regular terminal, not the psql one 1326 | 1327 | ## 1165. echo [[ a1 =~ [0-9] ]]; echo $? 1328 | 1329 | ### 1165.1 1330 | 1331 | It printed `1` for false. Meaning that `a` did not match the pattern [0-9], or `a` did not contain a number from `0-9`. Enter the same commands, but check if `a1` matches the pattern. 1332 | 1333 | #### HINTS 1334 | 1335 | - The previous command was `[[ a =~ [0-9] ]]; echo $?` 1336 | - Enter `[[ a1 =~ [0-9] ]]; echo $?` in the terminal 1337 | 1338 | ## 1166. echo [[ a1 =~ ^[0-9]$ ]]; echo $? 1339 | 1340 | ### 1166.1 1341 | 1342 | That printed `0` for true. `a1` does contain a number from `0-9`. Enter the same command, but change the pattern to `^[0-9]$`. The `^` signifies the start of the pattern, and `$` means the end. So the input will have to start, contain a number `0-9`, and end. 1343 | 1344 | #### HINTS 1345 | 1346 | - The previous command was `[[ a1 =~ [0-9] ]]; echo $?` 1347 | - Enter `[[ a1 =~ ^[0-9]$ ]]; echo $?` in the terminal 1348 | 1349 | ## 1167. echo [[ 1 =~ ^[0-9]$ ]]; echo $? 1350 | 1351 | ### 1167.1 1352 | 1353 | `1` for false. `a1` does not match the pattern. Using the same syntax, check if `1` matches the pattern. 1354 | 1355 | #### HINTS 1356 | 1357 | - The previous command was `[[ a1 =~ ^[0-9]$ ]]; echo $?` 1358 | - Enter `[[ 1 =~ ^[0-9]$ ]]; echo $?` in the terminal 1359 | 1360 | ## 1168. echo [[ 11 =~ ^[0-9]$ ]]; echo $? 1361 | 1362 | ### 1168.1 1363 | 1364 | `1` does match the pattern. It starts, contains a number, and ends. Check if `11` matches the same pattern. 1365 | 1366 | #### HINTS 1367 | 1368 | - The previous command was `[[ 1 =~ ^[0-9]$ ]]; echo $?` 1369 | - Enter `[[ 11 =~ ^[0-9]$ ]]; echo $?` in the terminal 1370 | 1371 | ## 1169. echo [[ 11 =~ ^[0-9]+$ ]]; echo $? 1372 | 1373 | ### 1169.1 1374 | 1375 | That did not match because the pattern only allows a single number. Add a `+` after the `[0-9]` to allow any strings that start, contain one or more numbers, and end. 1376 | 1377 | #### HINTS 1378 | 1379 | - Enter the previous command with the suggested changed 1380 | - The previous command was `[[ 11 =~ ^[0-9]$ ]]; echo $?` 1381 | - Enter `[[ 11 =~ ^[0-9]+$ ]]; echo $?` in the terminal 1382 | 1383 | ## 1170. echo [[ ! 11 =~ ^[0-9]+$ ]]; echo $? 1384 | 1385 | ### 1170.1 1386 | 1387 | So that pattern will match any positive integers. You want to check if the input is not a number. Add `!` in front of the comparison of the previous command to do that. 1388 | 1389 | #### HINTS 1390 | 1391 | - Enter the previous command with the suggested changed 1392 | - The previous command was `[[ 11 =~ ^[0-9]+$ ]]; echo $?` 1393 | - Enter `[[ ! 11 =~ ^[0-9]+$ ]]; echo $?` in the terminal 1394 | 1395 | ## 1176. Add if [[ ! $BIKE_ID_TO_RENT =~ ^[0-9]+$ ]] 1396 | 1397 | ### 1176.1 1398 | 1399 | Back in your script, below the `if input is not a number` comment, add an `if` condition that checks if the input is not a number using the method you just practiced. Add the `send to main menu` comment in the `then` area of the `if`. 1400 | 1401 | #### HINTS 1402 | 1403 | - You want to check if the `$BIKE_ID_TO_RENT` variable is not a number 1404 | - You entered `[[ ! 11 =~ ^[0-9]+$ ]]; echo $?` in the terminal on the last step 1405 | - Here's an example: 1406 | ```sh 1407 | if [[ ]] 1408 | then 1409 | # send to main menu 1410 | fi 1411 | ``` 1412 | - The condition you want is `[[ ! $BIKE_ID_TO_RENT =~ ^[0-9]+$ ]]` 1413 | - Add this in the suggestion area: 1414 | ```sh 1415 | if [[ ! $BIKE_ID_TO_RENT =~ ^[0-9]+$ ]] 1416 | then 1417 | # send to main menu 1418 | fi 1419 | ``` 1420 | 1421 | ## 1177. Add MAIN_MENU That is not a valid bike number 1422 | 1423 | ### 1177.1 1424 | 1425 | If the `$BIKE_ID_TO_RENT` variable is not a number, add the code to send users to the main menu with the message, `That is not a valid bike number.` 1426 | 1427 | #### HINTS 1428 | 1429 | - You want to call the `MAIN_MENU` function with the message as an argument 1430 | - Here's an example: `MAIN_MENU ""` 1431 | - Add `MAIN_MENU "That is not a valid bike number."` below the `send to main menu` comment 1432 | 1433 | ## 1178. ./bike-shop.sh 1434 | 1435 | ### 1178.1 1436 | 1437 | Run the script, go to the rent menu, and enter something that isn't a number to make sure it is working. When you are done, exit the program. 1438 | 1439 | #### HINTS 1440 | 1441 | - Enter `./bike-shop.sh` in the terminal and press enter 1442 | - Make sure you are in the `project` folder first 1443 | 1444 | ## 1179. Add else with comments 1445 | 1446 | ### 1179.1 1447 | 1448 | Add an `else` area for when the input is a number. Add these three single line comments in it; `get bike availability`, `if not available`, `send to main menu`. 1449 | 1450 | #### HINTS 1451 | 1452 | - Here's an example of a single line comment: `# ` 1453 | - Make sure the comments are in the same order listed 1454 | - An `if/else` statement looks like this: 1455 | ```sh 1456 | if [[ ]] 1457 | then 1458 | 1459 | else 1460 | 1461 | fi 1462 | ``` 1463 | - The `else` area should look like this: 1464 | ```sh 1465 | else 1466 | # get bike availability 1467 | 1468 | # if not available 1469 | 1470 | # send to main menu 1471 | 1472 | ``` 1473 | - The whole `if` should look like this: 1474 | ```sh 1475 | if [[ ! $BIKE_ID_TO_RENT =~ ^[0-9]+$ ]] 1476 | then 1477 | # send to main menu 1478 | MAIN_MENU "That is not a valid bike number." 1479 | else 1480 | # get bike availability 1481 | 1482 | # if not available 1483 | 1484 | # send to main menu 1485 | 1486 | fi 1487 | ``` 1488 | 1489 | ## 1180. Add BIKE_AVAILABILITY 1490 | 1491 | ### 1180.1 1492 | 1493 | Below the `get bike availability` comment you just added, create a `BIKE_AVAILABILITY` variable. Set it equal to a query that gets the `available` column from the `bikes` table for the input. Also, make sure to only get the row if it is available. 1494 | 1495 | #### HINTS 1496 | 1497 | - Here's an example: `BIKE_AVAILABILITY=$($PSQL "")` 1498 | - Use the `SELECT`, `FROM`, `WHERE`, and `AND` keywords 1499 | - Here's an example of the query: `SELECT FROM
WHERE AND ` 1500 | - You only want the `available` column for the bike with a `bike_id` equal to the `$BIKE_ID_TO_RENT` variable and only if the bike is available 1501 | - You want two conditions, `WHERE bike_id = $BIKE_ID_TO_RENT AND available = true` 1502 | - Add `BIKE_AVAILABILITY=$($PSQL "SELECT available FROM bikes WHERE bike_id = $BIKE_ID_TO_RENT AND available = true")` below the `get bike availability` comment 1503 | 1504 | ## 1190. Add echo BIKE_AVAILABILITY 1505 | 1506 | ### 1190.1 1507 | 1508 | Right below the variable you just created, use echo to print it so you can see what it looks like. 1509 | 1510 | #### HINTS 1511 | 1512 | - Print a variable like this: `echo $` 1513 | - The variable you want is `BIKE_AVAILABILITY` 1514 | - Add `echo $BIKE_AVAILABILITY` in the suggested area 1515 | 1516 | ## 1200. ./bike-shop.sh 1517 | 1518 | ### 1200.1 1519 | 1520 | Run the script a few times, go to the rent menu, enter a bike that is available and one that isn't. 1521 | 1522 | #### HINTS 1523 | 1524 | - Enter `./bike-shop.sh` in the terminal and press enter 1525 | - Make sure you are in the `project` folder first 1526 | 1527 | ## 1210. Add if -z BIKE_AVAILABILITY 1528 | 1529 | ### 1210.1 1530 | 1531 | The variable will be `t` or empty. Below the `if not available` comment, add an `if` condition that checks if it's empty. Put the `send to main menu` comment in it's statements area. 1532 | 1533 | #### HINTS 1534 | 1535 | - Here's an example: 1536 | ```sh 1537 | if [[ ]] 1538 | then 1539 | 1540 | fi 1541 | ``` 1542 | - The condition you want is `-z $BIKE_AVAILABILITY` 1543 | - Place the `# send to main menu` comment in the `` area 1544 | - The `if` condition should look like this: 1545 | ```sh 1546 | if [[ -z $BIKE_AVAILABILITY ]] 1547 | then 1548 | # send to main menu 1549 | fi 1550 | ``` 1551 | 1552 | ## 1215. Add MAIN_MENU That bike is not available 1553 | 1554 | ### 1215.1 1555 | 1556 | In the `if` condition you just added, send users to the main menu with the message `That bike is not available.` if they input a number that isn't available. 1557 | 1558 | #### HINTS 1559 | 1560 | - You want to call the `MAIN_MENU` function with the message as an argument 1561 | - Here's an example: `MAIN_MENU ""` 1562 | - Add `MAIN_MENU "That bike is not available."` below the `send to main menu` comment 1563 | 1564 | ## 1220. Remove echo BIKE_AVAILABILITY 1565 | 1566 | ### 1220.1 1567 | 1568 | Remove the line where you print the `BIKE_AVAILABILITY` variable. You don't need it anymore. 1569 | 1570 | #### HINTS 1571 | 1572 | - Remove the `echo $BIKE_AVAILABILITY` line 1573 | 1574 | ## 1230. ./bike-shop.sh 1575 | 1576 | ### 1230.1 1577 | 1578 | Run the script and go to the rent menu, enter a bike that isn't available to make sure it's working. When you are done, exit the program. 1579 | 1580 | #### HINTS 1581 | 1582 | - Enter `./bike-shop.sh` in the terminal and press enter 1583 | - Make sure you are in the `project` folder first 1584 | 1585 | ## 1233. psql UPDATE bikes SET add to true 1586 | 1587 | ### 1233.1 1588 | 1589 | In the psql prompt, set all the bikes availability back to true. 1590 | 1591 | #### HINTS 1592 | 1593 | - Use the `UPDATE`, `SET`, and `WHERE` keywords 1594 | - Here's an example: `UPDATE
SET = WHERE ` 1595 | - You want to set `available` to `true` for all the bikes 1596 | - After the `SET` can look like this: `available = true WHERE available = false` 1597 | - Try entering `UPDATE bikes SET available = true WHERE available = false;` in the psql prompt 1598 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 1599 | 1600 | ## 1236. Add else with comments 1601 | 1602 | ### 1236.1 1603 | 1604 | In your script, add an `else` for when a bike is available. Add these four comments in the `else` area `get customer info`, `if customer doesn't exist`, `get new customer name`, and `insert new customer`. 1605 | 1606 | #### HINTS 1607 | 1608 | - Here's an example of a single line comment: `# ` 1609 | - Make sure the comments are in the same order listed 1610 | - An `if/else` statement looks like this: 1611 | ```sh 1612 | if [[ ]] 1613 | then 1614 | 1615 | else 1616 | 1617 | fi 1618 | ``` 1619 | - The `else` area should look like this: 1620 | ```sh 1621 | else 1622 | # get customer info 1623 | 1624 | # if customer doesn't exist 1625 | 1626 | # get new customer name 1627 | 1628 | # insert new customer 1629 | 1630 | ``` 1631 | - The whole `if` should look like this: 1632 | ```sh 1633 | if [[ -z $BIKE_AVAILABILITY ]] 1634 | then 1635 | # send to main menu 1636 | MAIN_MENU "That bike is not available." 1637 | else 1638 | # get customer info 1639 | 1640 | # if customer doesn't exist 1641 | 1642 | # get new customer name 1643 | 1644 | # insert new customer 1645 | 1646 | fi 1647 | ``` 1648 | 1649 | ## 1240. Add echo What's your phone number? 1650 | 1651 | ### 1240.1 1652 | 1653 | As the comments say, you need to get the customer info and find out if they are an existing customer. Below the `get customer info` comment, print `What's your phone number?` with a new line in front of it. 1654 | 1655 | #### HINTS 1656 | 1657 | - Use `echo` with the `-e` flag and the new line character (`\n`) to print the suggested message 1658 | - Use double quotes around the message 1659 | - Here's an example: `echo -e "\n"` 1660 | - Add `echo -e "\nWhat's your phone number?"` below the suggested comment 1661 | 1662 | ## 1250. read PHONE_NUMBER 1663 | 1664 | ### 1250.1 1665 | 1666 | Below the line you just printed, read input into a `PHONE_NUMBER` variable. Since the phone number is unique, you can use it to identify a customer. 1667 | 1668 | #### HINTS 1669 | 1670 | - Here's an example: `read ` 1671 | - Add `read PHONE_NUMBER` to the suggested area 1672 | - Add it below where you print `What's your phone number?` 1673 | 1674 | ## 1260. Add CUSTOMER_NAME 1675 | 1676 | ### 1260.1 1677 | 1678 | With the customer's phone number, you can get their name. Below where you get the phone number, create a `CUSTOMER_NAME` variable that gets the customers name from the database using the phone number. 1679 | 1680 | #### HINTS 1681 | 1682 | - Query the database to set the `CUSTOMER_NAME` variable 1683 | - Here's an example: `CUSTOMER_NAME=$($PSQL "")` 1684 | - Use the `SELECT`, `FROM` and `WHERE` keywords for your query 1685 | - You want only the `name` column from the `customers` table 1686 | - The condition you want is `phone = '$PHONE_NUMBER'` 1687 | - The query should look like this: `SELECT name FROM customers WHERE phone = '$PHONE_NUMBER'` 1688 | - Add `CUSTOMER_NAME=$($PSQL "SELECT name FROM customers WHERE phone = '$PHONE_NUMBER'")` below the `read PHONE_NUMBER` line 1689 | 1690 | ## 1265. Add if -z CUSTOMER_NAME 1691 | 1692 | ### 1265.1 1693 | 1694 | If the customer is in the database with the phone number used, the variable will be set to the name. If not, it will be empty. Add an `if` condition below the `if customer doesn't exist` comment that checks if the variable is empty. Place the next two comments in the `then` area. 1695 | 1696 | #### HINTS 1697 | 1698 | - Here's an example: 1699 | ```sh 1700 | if [[ ]] 1701 | then 1702 | 1703 | fi 1704 | ``` 1705 | - The condition you want is `-z $CUSTOMER_NAME` 1706 | - Place the `# get new customer name` and `# insert new customer` comments in the `` area 1707 | - The `if` condition should look like this: 1708 | ```sh 1709 | if [[ -z $CUSTOMER_NAME ]] 1710 | then 1711 | # get new customer name 1712 | 1713 | # insert new customer 1714 | 1715 | fi 1716 | ``` 1717 | - Make sure it's below the `if customer doesn't exist` comment 1718 | 1719 | ## 1270. Add echo What's your name? 1720 | 1721 | ### 1270.1 1722 | 1723 | If the customer isn't in the database, you need to get their name so you can add them. Below the `get new customer name` comment, print `What's your name?` with a new line in front of the message. 1724 | 1725 | #### HINTS 1726 | 1727 | - Use `echo` with the `-e` flag and the new line character (`\n`) to print the suggested message 1728 | - Use double quotes around the message 1729 | - Here's an example: `echo -e "\n"` 1730 | - Add `echo -e "\nWhat's your name?"` below the suggested comment 1731 | 1732 | ## 1280. read CUSTOMER_NAME 1733 | 1734 | ### 1280.1 1735 | 1736 | Below the question you just printed, read input into a variable named `CUSTOMER_NAME`. 1737 | 1738 | #### HINTS 1739 | 1740 | - Here's an example: `read ` 1741 | - Add `read CUSTOMER_NAME` to the suggested area 1742 | - Add it below where you print `What's your name?` 1743 | 1744 | ## 1290. Add INSERT_CUSTOMER_RESULT 1745 | 1746 | ### 1290.1 1747 | 1748 | You have the two pieces of information you need. Below the `insert new customer` comment, create an `INSERT_CUSTOMER_RESULT` variable that inserts the customer into the database. 1749 | 1750 | #### HINTS 1751 | 1752 | - Here's an example: `INSERT_CUSTOMER_RESULT=$($PSQL "")` 1753 | - View the `customers` table in the psql prompt with `\d customers` to see the columns you need to add data to 1754 | - Be sure to use single quotes around `VARCHAR` values 1755 | - The query looks similar to this: `INSERT INTO customers(column1, column2) VALUES('value1', 'value2')` 1756 | - You want to use the `CUSTOMER_NAME` and `PHONE_NUMBER` variables for the values 1757 | - Here's the query: `INSERT INTO customers(name, phone) VALUES('$CUSTOMER_NAME', '$PHONE_NUMBER')` 1758 | - Add `INSERT_CUSTOMER_RESULT=$($PSQL "INSERT INTO customers(name, phone) VALUES('$CUSTOMER_NAME', '$PHONE_NUMBER')")` below the `insert new customer` comment 1759 | 1760 | ## 1300. Run the script 1761 | 1762 | ### 1300.1 1763 | 1764 | Run your script and go to the rent menu. Pick a bike to rent, then enter `555-5555` when it asks for a phone number, and `Me` when it asks for your name. 1765 | 1766 | #### HINTS 1767 | 1768 | - Enter `./bike-shop.sh` in the terminal and press enter 1769 | - Follow the instructions closely 1770 | - Make sure to use `555-5555` for the phone number and `Me` for the name 1771 | - The database should have a customer with `555-5555` as their phone number, and `Me` as their name in it 1772 | 1773 | ## 1310. psql SELECT * FROM customers 1774 | 1775 | ### 1310.1 1776 | 1777 | That should have added a new customer to the database. In the psql prompt, view all the data in the `customers` table to see if it's working. 1778 | 1779 | #### HINTS 1780 | 1781 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 1782 | - Enter `SELECT * FROM customers;` in the psql prompt 1783 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 1784 | 1785 | ## 1311. psql SELECT * FROM rentals 1786 | 1787 | ### 1311.1 1788 | 1789 | Excellent. View all the data in the rentals table. 1790 | 1791 | #### HINTS 1792 | 1793 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 1794 | - Enter `SELECT * FROM rentals;` in the psql prompt 1795 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 1796 | 1797 | ## 1312. psql SELECT * FROM bikes 1798 | 1799 | ### 1312.1 1800 | 1801 | So you still need to add the rental to the rentals table when a bike is picked out. View all the data in the `bikes` table. 1802 | 1803 | #### HINTS 1804 | 1805 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 1806 | - Enter `SELECT * FROM bikes;` in the psql prompt 1807 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 1808 | 1809 | ## 1315. Add comments 1810 | 1811 | ### 1315.1 1812 | 1813 | And set the `available` column to false for the bike rented. Below the end of the `if` statement that inserts a new customer, add five more comments; `get customer_id`, `insert bike rental`, `set bike availability to false`, `get bike info`, and `send to main menu` 1814 | 1815 | #### HINTS 1816 | 1817 | - Here's an example of a single line comment: `# ` 1818 | - Make sure the comments are in the same order listed 1819 | - The comments should be below (not in) the `if [[ -z $CUSTOMER_NAME ]]` statement 1820 | - The comments should look like this: 1821 | ```sh 1822 | if [[ -z $CUSTOMER_NAME ]] 1823 | then 1824 | # get new customer name 1825 | echo -e "\nWhat's your name?" 1826 | read CUSTOMER_NAME 1827 | 1828 | # insert new customer 1829 | INSERT_CUSTOMER_RESULT=$($PSQL "INSERT INTO customers(name, phone) VALUES('$CUSTOMER_NAME', '$PHONE_NUMBER')") 1830 | fi 1831 | 1832 | # get customer_id 1833 | 1834 | # insert bike rental 1835 | 1836 | # set bike availability to false 1837 | 1838 | # get bike info 1839 | 1840 | # send to main menu 1841 | 1842 | ``` 1843 | 1844 | ## 1320. Add CUSTOMER_ID 1845 | 1846 | ### 1320.1 1847 | 1848 | You're getting close to done with the rent functionality. To add a rental to the database, you need the customer ID. Below the `get customer_id` comment, create a `CUSTOMER_ID` variable that gets the `customer_id` using the phone number. 1849 | 1850 | #### HINTS 1851 | 1852 | - Here's an example: `CUSTOMER_ID=$($PSQL "")` 1853 | - You want to get the `customer_id` column from the customers table using the `PHONE_NUMBER` variable in your condition to get it 1854 | - The condition you want is `WHERE phone = '$PHONE_NUMBER'` 1855 | - The query looks like this: `SELECT customer_id FROM customers WHERE phone = '$PHONE_NUMBER'` 1856 | - Add `CUSTOMER_ID=$($PSQL "SELECT customer_id FROM customers WHERE phone = '$PHONE_NUMBER'")` below the `get customer_id` comment 1857 | 1858 | ## 1330. Add INSERT_RENTAL_RESULT 1859 | 1860 | ### 1330.1 1861 | 1862 | Now that you have the bike ID and customer ID, you can add the rental to the database. Below the `insert bike rental` comment, create a `INSERT_RENTAL_RESULT` variable that adds the rental to the database. 1863 | 1864 | #### HINTS 1865 | 1866 | - Here's an example: `INSERT_RENTAL_RESULT=$($PSQL "")` 1867 | - View the `rentals` table by entering `\d rentals` in the psql prompt to see what the columns are 1868 | - The query looks similar to this: `INSERT INTO rentals(column1, column2) VALUES(value1, value2)` 1869 | - You want to insert the `BIKE_ID_TO_RENT` and `CUSTOMER_ID` variables into the `bike_id` and `customer_id` columns 1870 | - The query should look like this: `INSERT INTO rentals(bike_id, customer_id) VALUES($BIKE_ID_TO_RENT, $CUSTOMER_ID)` 1871 | - Add `INSERT_RENTAL_RESULT=$($PSQL "INSERT INTO rentals(customer_id, bike_id) VALUES($CUSTOMER_ID, $BIKE_ID_TO_RENT)")` below the `insert bike rental` comment 1872 | 1873 | ## 1370. Add SET_TO_FALSE_RESULT 1874 | 1875 | ### 1370.1 1876 | 1877 | That should add the rental to the database. The last thing to do is set `available` to false for the bike. Below the `set bike availability to false` comment, create a `SET_TO_FALSE_RESULT` variable that does that. 1878 | 1879 | #### HINTS 1880 | 1881 | - Here's an example: `SET_TO_FALSE_RESULT=$($PSQL "")` 1882 | - You want to use the `UPDATE`, `SET`, and `WHERE` keywords 1883 | - You want to set the `available` column to `false` for the `bike_id` of `BIKE_ID_TO_RENT` 1884 | - The query looks similar to this: `UPDATE
SET = WHERE ` 1885 | - The query looks like this: `UPDATE bikes SET available = false WHERE bike_id = $BIKE_ID_TO_RENT` 1886 | - Add `SET_TO_FALSE_RESULT=$($PSQL "UPDATE bikes SET available = false WHERE bike_id = $BIKE_ID_TO_RENT")` below the `set bike availability to false` comment 1887 | 1888 | ## 1380. Run the script 1889 | 1890 | ### 1380.1 1891 | 1892 | Run the script and go to the rent menu. Pick the first bike on the list and enter `555-5555` when it asks for a phone number again. That phone number should already be in the database, so it won't ask for a name or insert a customer. 1893 | 1894 | #### HINTS 1895 | 1896 | - Enter `./bike-shop.sh` in the terminal and press enter 1897 | - Make sure to enter the correct bike number and phone number 1898 | - There should be a rental in the database for customer with phone number `555-5555` and name `Me` 1899 | 1900 | ## 1390. psql SELECT * FROM rentals 1901 | 1902 | ### 1390.1 1903 | 1904 | In the psql prompt, view all the data in the `rentals` table. There should be a new rental. 1905 | 1906 | #### HINTS 1907 | 1908 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 1909 | - Enter `SELECT * FROM rentals;` in the psql prompt 1910 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 1911 | 1912 | ## 1400. psql SELECT * FROM bikes ORDER BY bike_id 1913 | 1914 | ### 1400.1 1915 | 1916 | The rental was added and the `date_rented` was filled in automatically. :smile: Next, view all the data in the `bikes` table. Order the results by `bike_id` 1917 | 1918 | #### HINTS 1919 | 1920 | - Use the `SELECT`, `FROM`, and `ORDER BY` keywords with `*` to view all the data 1921 | - Enter `SELECT * FROM bikes ORDER BY bike_id;` in the psql prompt 1922 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 1923 | 1924 | ## 1401. Add BIKE_INFO 1925 | 1926 | ### 1401.1 1927 | 1928 | The available column was set to false for the bike you rented. The last thing to do is give a nice message about the rental. Below the `get bike info` comment, create a `BIKE_INFO` variable that gets the `size` and `type`, in that order, of the bike rented. 1929 | 1930 | #### HINTS 1931 | 1932 | - Here's an example: `BIKE_INFO=$($PSQL "")` 1933 | - You want to use the `SELECT`, `FROM`, and `WHERE` keywords 1934 | - Use the `BIKE_ID_TO_RENT` variable to find the needed info for the bike 1935 | - The query looks similar to this: `SELECT size, type FROM
WHERE ` 1936 | - The condition you want is `WHERE bike_id = $BIKE_ID_TO_RENT` 1937 | - The query looks like this: `SELECT size, type FROM bikes WHERE bike_id = $BIKE_ID_TO_RENT` 1938 | - Add `BIKE_INFO=$($PSQL "SELECT size, type FROM bikes WHERE bike_id = $BIKE_ID_TO_RENT")` below the `get bike info` comment 1939 | 1940 | ## 1402. Add echo BIKE_INFO 1941 | 1942 | ### 1402.1 1943 | 1944 | Below the variable you just created, use `echo` to print it. 1945 | 1946 | #### HINTS 1947 | 1948 | - Print a variable like this: `echo $` 1949 | - The variable you want is `BIKE_INFO` 1950 | - Add `echo $BIKE_INFO` in the suggested area 1951 | 1952 | ## 1403. ./bike-shop.sh 1953 | 1954 | ### 1403.1 1955 | 1956 | Run the script again and go to the rent menu, there should now be one less bike displayed. Pick the next bike on the list and rent it using the customer with phone number `555-5555` again so you can see the variable. 1957 | 1958 | #### HINTS 1959 | 1960 | - Enter `./bike-shop.sh` in the terminal and press enter 1961 | - There should be at least two rentals for the customer with phone nummber `555-5555` and name `Me` 1962 | 1963 | ## 1404. echo '28 | Mountain' | sed 's/ /=/g' 1964 | 1965 | ### 1404.1 1966 | 1967 | It should have printed `28 | Mountain`. The message you want to print after someone rents a bike would have said `I have put you down for the 28" Mountain Bike, Me.`. You need to format that variable for the message. The `sed` command can be used to replace characters and patterns in text. It looks like this: `sed s///`. In the terminal, enter `echo '28 | Mountain' | sed 's/ /=/g'` to practice. 1968 | 1969 | #### HINTS 1970 | 1971 | - Enter the suggested command in the terminal 1972 | - Not the psql one 1973 | 1974 | ## 1405. echo '28 | Mountain' | sed 's/ //g' 1975 | 1976 | ### 1405.1 1977 | 1978 | The command you used, "piped" a string (`28 | Mountain`) to the `sed` command, where it replaced all the spaces with `=`. Enter the same command, but replace all the spaces with nothing. 1979 | 1980 | #### HINTS 1981 | 1982 | - The previous command was `echo '28 | Mountain' | sed 's/ /=/g'` 1983 | - Remove the `=` from the previous command 1984 | - Enter `echo '28 | Mountain' | sed 's/ //g'` in the terminal 1985 | 1986 | ## 1407. echo '28 | Mountain' | sed 's/ //' 1987 | 1988 | ### 1407.1 1989 | 1990 | The `g` regex flag stands for "global". It will replace all instance of the pattern. In this case, it replaced all the spaces. Enter the same command but without that flag. 1991 | 1992 | #### HINTS 1993 | 1994 | - The previous command was `echo '28 | Mountain' | sed 's/ //g` 1995 | - Remove the `g` flag from the previous command 1996 | - Enter `echo '28 | Mountain' | sed 's/ //'` in the terminal 1997 | 1998 | ## 1408. echo '28 | Mountain' | sed 's/ |//' 1999 | 2000 | ### 1408.1 2001 | 2002 | That time, only the first instance of the pattern was replaced. The first space was removed. Enter the same command, but replace the first instance of  | (`|`) with nothing. 2003 | 2004 | #### HINTS 2005 | 2006 | - The previous command was `echo '28 | Mountain' | sed 's/ //` 2007 | - You want to replace the space in the pattern of the last command with  | (`|`) 2008 | - Enter `echo '28 | Mountain' | sed 's/ |//'` in the terminal 2009 | 2010 | ## 1410. echo '28 | Mountain' | sed 's/ |/"/' 2011 | 2012 | ### 1410.1 2013 | 2014 | Enter the same command, but make the output look like how you want in the message, `28" Mountain`. 2015 | 2016 | #### HINTS 2017 | 2018 | - The previous command was `echo '28 | Mountain' | sed 's/ |//` 2019 | - Use `"` as the character to replace  | (`|`) with 2020 | - Enter `echo '28 | Mountain' | sed 's/ |/"/'` in the terminal 2021 | 2022 | ## 1411. Add echo BIKE_INFO | sed 's/ |/"/' 2023 | 2024 | ### 1411.1 2025 | 2026 | Back in your script, where you `echo` the `BIKE_INFO`, pipe the output into a `sed` command that replaces  | (`|`) with `"` so the text will read `" `. `28 | Mountain` would become `28" Mountain`, for instance. 2027 | 2028 | #### HINTS 2029 | 2030 | - The previous command was `echo '28 | Mountain' | sed 's/ |/"/'` 2031 | - You want to add the `| sed 's/ |/"/'` part of the previous command after your `echo $BIKE_INFO` line 2032 | - Make the suggested area look like this: 2033 | ```sh 2034 | echo $BIKE_INFO | sed 's/ |/"/' 2035 | ``` 2036 | 2037 | ## 1413. ./bike-shop.sh 2038 | 2039 | ### 1413.1 2040 | 2041 | Run the script and rent another bike using the customer with phone number `555-5555` again. Make sure the bike info printed looks like you want. 2042 | 2043 | #### HINTS 2044 | 2045 | - Enter `./bike-shop.sh` in the terminal and press enter 2046 | - The customer with phone number `555-5555` and name `Me` should have at least three bikes rented 2047 | 2048 | ## 1415. Add BIKE_INFO_FORMATTED 2049 | 2050 | ### 1415.1 2051 | 2052 | Now it is formatted for the message. Take that `echo` command and the part that formats it, put it in a sub shell, and set the output into a variable named `BIKE_INFO_FORMATTED`. Here's an example: `BIKE_INFO_FORMATTED=$()` 2053 | 2054 | #### HINTS 2055 | 2056 | - You want to put the `echo $BIKE_INFO | sed 's/ |/"/'` part in the subshell 2057 | - It should look like this: `BIKE_INFO_FORMATTED=$(echo $BIKE_INFO | sed 's/ |/"/')` 2058 | 2059 | ## 1417. Add MAIN_MENU I have put you down for bike 2060 | 2061 | ### 1417.1 2062 | 2063 | What you put in the subshell (`$(...)`) will be executed, and the result of it will replace the subshell. In this case, the formatted bike info was printed when you ran the script before, so the `BIKE_INFO_FORMATTED` variable will be set to that. Below the `send to main menu` comment, send users to the main menu with a message that would print `I have put you down for the 28" Mountain Bike, Me.` if `Me` rented the 28 inch Mountain Bike. 2064 | 2065 | #### HINTS 2066 | 2067 | - Use dynamic info for the bike info and the customer's name 2068 | - You want to use the `BIKE_INFO_FORMATTED` and `CUSTOMER_NAME` variables 2069 | - The message should look like this: `I have put you down for the $BIKE_INFO_FORMATTED Bike, $CUSTOMER_NAME.` 2070 | - Add `MAIN_MENU "I have put you down for the $BIKE_INFO_FORMATTED Bike, $CUSTOMER_NAME."` below the `send to main menu` comment 2071 | 2072 | ## 1418. ./bike-shop.sh 2073 | 2074 | ### 1418.1 2075 | 2076 | Run the script and rent the next bike on the list. Use the customer with `555-5555` as their phone number. When you are done, exit the program. 2077 | 2078 | #### HINTS 2079 | 2080 | - Enter `./bike-shop.sh` in the terminal and press enter 2081 | - The customer with phone number `555-5555` and name `Me` should have at least four bikes rented 2082 | 2083 | ## 1420. echo ' M e ' 2084 | 2085 | ### 1420.1 2086 | 2087 | There's an extra space around the customer's name. You can use `sed` again to fix that. In the terminal, enter `echo ' M e '` to print `M e` with spaces around it to see if you can find out how. 2088 | 2089 | #### HINTS 2090 | 2091 | - Enter the `echo ' M e '` in the terminal 2092 | - Not the psql one 2093 | 2094 | ## 1422. echo "$(echo ' M e ')." 2095 | 2096 | ### 1422.1 2097 | 2098 | It printed, but you can only assume there's a space at the end. Place the last command in a subshell with quotes around it. Put a period right after the subshell and echo the whole thing in the terminal. Here's how it looks: `echo "$(echo ' M e ')."` 2099 | 2100 | #### HINTS 2101 | 2102 | - Enter `echo "$(echo ' M e ')."` in the terminal 2103 | 2104 | ## 1424. echo "$(echo ' M e ' | sed 's/ //')." 2105 | 2106 | ### 1424.1 2107 | 2108 | Now you can be certain there's a space at the end. Within the subshell of the last command, use a pipe and the `sed` command to replace the first space with no space. Here's the `sed` replacement pattern you want: `'s/ //'`. 2109 | 2110 | #### HINTS 2111 | 2112 | - The previous command was `echo "$(echo ' M e ')."` 2113 | - Here's an example of how the subshell should look: `$(echo ' M e ' | sed )` 2114 | - This is the exact subshell: `$(echo ' M e ' | sed )` 2115 | - Enter `echo "$(echo ' M e ' | sed 's/ //')."` in the terminal 2116 | 2117 | ## 1425. echo "$(echo ' M e ' | sed 's/ //g')." 2118 | 2119 | ### 1425.1 2120 | 2121 | That removed only the first space it found. Change the previous command to replace all instances of a space instead of just the first one. 2122 | 2123 | #### HINTS 2124 | 2125 | - The previous command was `echo "$(echo ' M e ' | sed 's/ //')."` 2126 | - Use a regex flag to make the suggested modification 2127 | - You want to add the `g` flag to the `sed` replacement pattern. 2128 | - The `sed` pattern should look like this: `'s/ //g'` 2129 | - Enter `echo "$(echo ' M e ' | sed 's/ //g')."` in the terminal 2130 | 2131 | ## 1427. echo "$(echo ' M e ' | sed 's/^ //g')." 2132 | 2133 | ### 1427.1 2134 | 2135 | That replaced all the spaces. You only had an extra space at the beginning of the customer name. Add a `^` in front of the space in the replacement pattern of the last command to only replace a space at the beginning of the text. 2136 | 2137 | #### HINTS 2138 | 2139 | - The previous command was `echo "$(echo ' M e ' | sed 's/ //g')."` 2140 | - You want to change the matching pattern to (`^`) 2141 | - The matching pattern is between the first and second forward slashes 2142 | - The `sed` pattern should look like this: `s/^ //g` 2143 | - Enter `echo "$(echo ' M e ' | sed 's/^ //g')."` in the terminal 2144 | 2145 | ## 1428. echo "$(echo ' M e ' | sed 's/^ //g')." 2146 | 2147 | ### 1428.1 2148 | 2149 | The caret you added means that's the start of the text. So it will replace a space only if it's at the beginning. Enter the last command, but add two more spaces (three total) at the beginning of the **text**. 2150 | 2151 | #### HINTS 2152 | 2153 | - The previous command was `echo "$(echo ' M e ' | sed 's/^ //g')."` 2154 | - Change the `' M e '` part to include the suggestion 2155 | - The new text should be '   M e ' (`'M e '`) 2156 | - In the terminal, enter echo "$(echo '   M e ' | sed 's/^ //g')." 2157 | 2158 | ## 1430. echo "$(echo ' M e ' | sed 's/^ *//g')." 2159 | 2160 | ### 1430.1 2161 | 2162 | The (`^`) pattern only replaced the first space. Add `*` at the end of the matching pattern to replace all spaces at the beginning of text. 2163 | 2164 | #### HINTS 2165 | 2166 | - The previous command was echo "$(echo '   M e ' | sed 's/^ //g')." 2167 | - The matching pattern is between the first and second forward slash 2168 | - The new pattern is: `'s/^ *//g'` 2169 | - Enter echo "$(echo '   M e ' | sed 's/^ *//g')." in the terminal 2170 | 2171 | ## 1432. echo "$(echo ' M e ' | sed 's/ $//g')." 2172 | 2173 | ### 1432.1 2174 | 2175 | The customer name only had an extra space at the beginning. Unsure as to why, but there may be others with extra spaces at the end as well. You can match the end of text with `$`. Change the matching pattern of the last command so it replaces a single space at the end. The pattern is  $ (`$`). 2176 | 2177 | #### HINTS 2178 | 2179 | - The previous command was echo "$(echo '   M e ' | sed 's/^ *//g')." 2180 | - The matching pattern is between the first and second forward slash 2181 | - Change the matching pattern to the suggestion 2182 | - Enter echo "$(echo '   M e ' | sed 's/ $//g')." in the terminal 2183 | 2184 | ## 1433. echo "$(echo ' M e ' | sed 's/ $//g')." 2185 | 2186 | ### 1433.1 2187 | 2188 | Add two more spaces to the end of the **text** in the previous command (three spaces total). 2189 | 2190 | #### HINTS 2191 | 2192 | - The previous command was echo "$(echo '   M e ' | sed 's/ $//g')." 2193 | - The matching pattern is between the first and second forward slash 2194 | - Change the matching pattern to the suggestion 2195 | - Enter echo "$(echo '   M e   ' | sed 's/ $//g')." in the terminal 2196 | 2197 | ## 1435. echo "$(echo ' M e ' | sed 's/ *$//g')." 2198 | 2199 | ### 1435.1 2200 | 2201 | The pattern only replaces a single space at the end. Change the last command so it replaces all spaces at the end of the text. 2202 | 2203 | #### HINTS 2204 | 2205 | - The previous command was echo "$(echo '   M e   ' | sed 's/ $//g')." 2206 | - Use `*` in a pattern after a character to replace zero or more of that character 2207 | - The matching pattern you want is  *$ (`*$`) 2208 | - Change the matching pattern to the suggestion 2209 | - Enter echo "$(echo '   M e   ' | sed 's/ *$//g')." in the terminal 2210 | 2211 | ## 1436. echo "$(echo ' M e ' | sed 's/^ *| *$//g')." 2212 | 2213 | ### 1436.1 2214 | 2215 | That replaced all the spaces at the end of the text. You can use `|` as an "or" operator in a matching pattern to replace one pattern or another. Use it to change the matching pattern so it would replace any amount of spaces at the beginning and any amount of spaces at the end of the text. 2216 | 2217 | #### HINTS 2218 | 2219 | - The previous command was echo "$(echo '   M e   ' | sed 's/ *$//g')." 2220 | - You want to replace the ^ * (`^*`) pattern 2221 | - And the  *$ (`*$`) pattern 2222 | - The matching pattern should look like this: `'s/^ *| *$//g'` 2223 | - Enter echo "$(echo '   M e   ' | sed 's/^ *| *$//g')." 2224 | 2225 | ## 1437. man sed 2226 | 2227 | ### 1437.1 2228 | 2229 | That didn't work. It doesn't like that "or" (`|`) operator for some reason. Check the manual of the `sed` command to see if you can find anything. 2230 | 2231 | #### HINTS 2232 | 2233 | - Here's an example of how to see a manual: `man ` 2234 | - Enter `man sed` in the terminal 2235 | - Press enter until you have seen the whole manual 2236 | 2237 | ## 1438. echo "$(echo ' M e ' | sed -r 's/^ *| *$//g')." 2238 | 2239 | ### 1438.1 2240 | 2241 | Somewhere in there is a flag for using extended regular expressions with `sed`. That might work. Add it to the echo "$(echo '   M e   ' | sed 's/^ *| *$//g')." command that didn't work to find out. 2242 | 2243 | #### HINTS 2244 | 2245 | - :point_down: 2246 | - Find the flag in the terminal output for using extended regular expressions with `sed` 2247 | - It's the `-E` flag 2248 | - You previously entered echo "$(echo '   M e   ' | sed 's/^ *| *$//g')." 2249 | - Add the `-E` flag to the `sed` part of that command 2250 | - Enter echo "$(echo '   M e   ' | sed -E 's/^ *| *$//g')." in the terminal 2251 | 2252 | ## 1440. Change to trim CUSTOMER_NAME 2253 | 2254 | ### 1440.1 2255 | 2256 | :wink: That trimmed all spaces from the front and end of the text. Back in the last message of your script, place the `CUSTOMER_NAME` variable in a subshell, echo and pipe it into a `sed` command that removes all spaces from the front and back. Use the same method you used in the terminal. 2257 | 2258 | #### HINTS 2259 | 2260 | - Here's an example: `$(echo $CUSTOMER_NAME | sed ...)` 2261 | - `^ *` will match all spaces at the beginning of text, and  *$ will match spaces at the end 2262 | - The previous command was echo "$(echo '   M e   ' | sed -r 's/^ *| *$//g')." 2263 | - Change the `$CUSTOMER_NAME` variable in the last message to `$(echo $CUSTOMER_NAME | sed -r 's/^ *| *$//g')` 2264 | 2265 | ## 1442. Run the script 2266 | 2267 | ### 1442.1 2268 | 2269 | Run the script and rent another bike with the customer whose phone number is `555-5555`. When you are done, exit the program. 2270 | 2271 | #### HINTS 2272 | 2273 | - Enter `./bike-shop.sh` in the terminal and press enter 2274 | - The customer with phone number `555-5555` and name `Me` should have at least five bikes rented 2275 | 2276 | ## 1444. Run the script 2277 | 2278 | ### 1444.1 2279 | 2280 | Run the script again. Rent another bike, use `000-0000` as the phone number this time, and `Test` as the name to create a new customer. When you are done, exit the program. 2281 | 2282 | #### HINTS 2283 | 2284 | - Enter `./bike-shop.sh` in the terminal and press enter 2285 | - The customer with phone number `000-0000` and name `Test` should have at least one bike rented 2286 | 2287 | ## 1446. Run the script 2288 | 2289 | ### 1446.1 2290 | 2291 | Run the script again. Rent another bike with the customer you just created. When you are done, exit the program. 2292 | 2293 | #### HINTS 2294 | 2295 | - Enter `./bike-shop.sh` in the terminal and press enter 2296 | - The customer with phone number `000-0000` and name `Test` should have at least two bikes rented 2297 | 2298 | ## 1448. SELECT * FROM bikes ORDER BY bike_id 2299 | 2300 | ### 1448.1 2301 | 2302 | In the psql prompt, view all the data in your bikes table in order by the `bike_id`. 2303 | 2304 | #### HINTS 2305 | 2306 | - Use the `SELECT`, `FROM`, and `ORDER BY` keywords with `*` to view all the data 2307 | - Enter `SELECT * FROM bikes ORDER BY bike_id;` in the psql prompt 2308 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2309 | 2310 | ## 1449. SELECT * FROM bikes ORDER BY bike_id 2311 | 2312 | ### 1449.1 2313 | 2314 | There should be two bikes left available to rent. Next, look at all the data in the customers table. 2315 | 2316 | #### HINTS 2317 | 2318 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 2319 | - Enter `SELECT * FROM customers;` in the psql prompt 2320 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2321 | 2322 | ## 1450. SELECT * FROM bikes ORDER BY bike_id 2323 | 2324 | ### 1450.1 2325 | 2326 | There should two customers in that table now. Lastly, look at all the data in the rentals table. 2327 | 2328 | #### HINTS 2329 | 2330 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 2331 | - Enter `SELECT * FROM rentals;` in the psql prompt 2332 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2333 | 2334 | ## 1453. Delete echo Return Menu 2335 | 2336 | ### 1453.1 2337 | 2338 | The rent functionality looks like it all works. Delete the `echo Return Menu` line in the `RETURN_MENU` function so you can get started with that. 2339 | 2340 | #### HINTS 2341 | 2342 | - The `RETURN_MENU` function should be empty 2343 | - The `RETURN_MENU` function should look like this: 2344 | ```sh 2345 | RETURN_MENU() { 2346 | 2347 | } 2348 | ``` 2349 | 2350 | ## 1457. Add comments to RETURN_MENU 2351 | 2352 | ### 1457.1 2353 | 2354 | Add three single line comments to the return menu function; `get customer info`, `if not found`, and `send to main menu`, in that order. 2355 | 2356 | #### HINTS 2357 | 2358 | - Here's an example of a single line comment: `# ` 2359 | - Make sure the comments are in the same order listed 2360 | - The comments should be in the `RETURN_MENU` function 2361 | - The `RETURN_MENU` function should look like this: 2362 | ```sh 2363 | RETURN_MENU() { 2364 | # get customer info 2365 | 2366 | # if not found 2367 | 2368 | # send to main menu 2369 | 2370 | } 2371 | ``` 2372 | 2373 | ## 1460. Start the Return Bike Functionality 2374 | 2375 | ### 1460.1 2376 | 2377 | Below the `get customer info` comment you just added, print `What's your phone number?` with a new line in front of the sentence. 2378 | 2379 | #### HINTS 2380 | 2381 | - Use `echo` with the `-e` flag and the new line character (`\n`) to print the suggested message 2382 | - Use double quotes around the message 2383 | - Here's an example: `echo -e "\n"` 2384 | - Add `echo -e "\nWhat's your phone number?"` below the suggested comment 2385 | 2386 | ## 1470. Read PHONE_NUMBER 2387 | 2388 | ### 1470.1 2389 | 2390 | Just below that, use `read` to get input into a `PHONE_NUMBER` variable. 2391 | 2392 | #### HINTS 2393 | 2394 | - Here's an example: `read ` 2395 | - Add `read PHONE_NUMBER` to the suggested area 2396 | - Add it below where you print `What's your phone number?` 2397 | 2398 | ## 1472. Add CUSTOMER_ID 2399 | 2400 | ### 1472.1 2401 | 2402 | Just below that, set the `CUSTOMER_ID` variable to a query that gets the customer ID from the database using the phone number they gave you. 2403 | 2404 | #### HINTS 2405 | 2406 | - Here's an example: `CUSTOMER_ID=$($PSQL "")` 2407 | - You want to get the `customer_id` column from the customers table using the `PHONE_NUMBER` variable in your condition to get it 2408 | - The condition you want is `WHERE phone = '$PHONE_NUMBER'` 2409 | - The query looks like this: `SELECT customer_id FROM customers WHERE phone = '$PHONE_NUMBER'` 2410 | - Add `CUSTOMER_ID=$($PSQL "SELECT customer_id FROM customers WHERE phone = '$PHONE_NUMBER'")` below the `read PHONE_NUMBER` line in the `RETURN_MENU` function 2411 | 2412 | ## 1474. Add if -z CUSTOMER_ID 2413 | 2414 | ### 1474.1 2415 | 2416 | If they are in the database, the variable will be their `customer_id`. If not, it will be empty. Below the `if not found` comment, add an `if` statement that checks if it's empty. Put the `send to main menu` comment in the `then` area. 2417 | 2418 | #### HINTS 2419 | 2420 | - Here's an example: 2421 | ```sh 2422 | if [[ ]] 2423 | then 2424 | 2425 | fi 2426 | ``` 2427 | - The condition you want is `-z $CUSTOMER_ID` 2428 | - Place the `# send to main menu` comment in the `` area 2429 | - The `if` condition should look like this: 2430 | ```sh 2431 | if [[ -z $CUSTOMER_ID ]] 2432 | then 2433 | # send to main menu 2434 | 2435 | fi 2436 | ``` 2437 | 2438 | ## 1475. Add MAIN_MENU I could not find a record for that phone number 2439 | 2440 | ### 1475.1 2441 | 2442 | If the customer isn't found, send them to the main menu with the message `I could not find a record for that phone number.` 2443 | 2444 | #### HINTS 2445 | 2446 | - You want to call the `MAIN_MENU` function with the message as an argument 2447 | - Here's an example: `MAIN_MENU ""` 2448 | - Add `MAIN_MENU "I could not find a record for that phone number."` below the `send to main menu` comment 2449 | 2450 | ## 1476. ./bike-shop.sh 2451 | 2452 | ### 1476.1 2453 | 2454 | Run the script and go to the return menu. Enter a phone number that is not in the database. When you are done, exit the program. 2455 | 2456 | #### HINTS 2457 | 2458 | - Enter `./bike-shop.sh` in the terminal and press enter 2459 | - Make sure you are in the `project` folder first 2460 | 2461 | ## 1478. Add else with comments 2462 | 2463 | ### 1478.1 2464 | 2465 | Add an `else` to the `if` condition for if the phone number is found in the database. Place `get customer's rentals`, `if no rentals`, and `send to main menu` in the `else` area as single line comments. 2466 | 2467 | #### HINTS 2468 | 2469 | - Here's an example of a single line comment: `# ` 2470 | - Make sure the comments are in the same order listed 2471 | - The comments should be in the `else` area of the `if [[ -z CUSTOMER_ID ]]` statement 2472 | - An `if/else` statement looks like this: 2473 | ```sh 2474 | if [[ ]] 2475 | then 2476 | 2477 | else 2478 | 2479 | fi 2480 | ``` 2481 | - The `else` area should look like this: 2482 | ```sh 2483 | else 2484 | # get customer's rentals 2485 | 2486 | # if no rentals 2487 | 2488 | # send to main menu 2489 | 2490 | fi 2491 | ``` 2492 | - The whole `if` should look like this: 2493 | ```sh 2494 | if [[ -z $CUSTOMER_ID ]] 2495 | then 2496 | # send to main menu 2497 | MAIN_MENU "I could not find a record for that phone number." 2498 | else 2499 | # get customer's rentals 2500 | 2501 | # if no rentals 2502 | 2503 | # send to main menu 2504 | 2505 | fi 2506 | ``` 2507 | 2508 | ## 1480. psql SELECT * FROM bikes 2509 | 2510 | ### 1480.1 2511 | 2512 | You want to find out what rentals a customer has using their phone number and display them. You will need to join all the tables. Start by using the psql prompt to view all the data in the `bikes` table. 2513 | 2514 | #### HINTS 2515 | 2516 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 2517 | - Enter `SELECT * FROM bikes;` in the psql prompt 2518 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2519 | 2520 | ## 1485. psql SELECT * FROM bikes LEFT JOIN rentals 2521 | 2522 | ### 1485.1 2523 | 2524 | Next, use a `LEFT JOIN` with `bikes` as the left table to join the bikes and rentals tables. Use the `USING` keyword to join the two tables. 2525 | 2526 | #### HINTS 2527 | 2528 | - You need the `SELECT`, `FROM`, `LEFT JOIN`, and `USING` keywords 2529 | - Here's an example: `SELECT FROM LEFT JOIN USING()` 2530 | - Enter `\d bikes` or `\d rentals` in the psql prompt to view the details of the table and find the foreign key column 2531 | - It's the `bike_id` column 2532 | - Enter `SELECT * FROM bikes LEFT JOIN rentals USING(bike_id);` in the psql prompt 2533 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2534 | 2535 | ## 1490. psql SELECT bikes INNER JOIN rentals 2536 | 2537 | ### 1490.1 2538 | 2539 | You only need the bikes that are being rented. Use an inner join with the same two tables to only get those. Use the `USING` keyword again. 2540 | 2541 | #### HINTS 2542 | 2543 | - It's an `INNER JOIN` 2544 | - You need the `SELECT`, `FROM`, `INNER JOIN`, and `USING` keywords 2545 | - Here's an example: `SELECT FROM INNER JOIN USING()` 2546 | - Enter `SELECT * FROM bikes INNER JOIN rentals USING(bike_id);` in the psql prompt 2547 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2548 | 2549 | ## 1500. psql SELECT bikes INNER JOIN rentals INNER JOIN customers 2550 | 2551 | ### 1500.1 2552 | 2553 | Add a join to the previous command that joins the last table so you can get the customer information. Use an `INNER JOIN` and the `USING` keyword again. 2554 | 2555 | #### HINTS 2556 | 2557 | - The previous query was `SELECT * FROM bikes INNER JOIN rentals USING(bike_id);` 2558 | - Here's an example: `SELECT FROM INNER JOIN USING() INNER JOIN USING(foreign_key)` 2559 | - Enter `\d rentals` or `\d customers` in the psql prompt to view the details of the table and find the foreign key column 2560 | - It's the `customer_id` column 2561 | - Enter `SELECT * FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id);` in the psql prompt 2562 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2563 | 2564 | ## 1510. psql Add conditions to the query 2565 | 2566 | ### 1510.1 2567 | 2568 | Add two conditions to the last query to narrow down the results to the bikes that are currently being rented by customer with `555-5555` as their phone number. The second condition should check the `date_returned` column 2569 | 2570 | #### HINTS 2571 | 2572 | - The previous query was `SELECT * FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id);` 2573 | - You want to add a `WHERE AND ` to the last query 2574 | - Use the `IS NULL` keyword to check the `date_returned` in one of the conditions 2575 | - The two conditions are `WHERE phone = '555-5555' AND date_returned IS NULL` 2576 | - Enter `SELECT * FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND date_returned IS NULL;` in the psql prompt 2577 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2578 | 2579 | ## 1520. psql SELECT only columns 2580 | 2581 | ### 1520.1 2582 | 2583 | Now you have all the rentals for one specific customer. Only get the columns you need to display the bike information to them. They are the same three columns you used to display the list of available bikes. 2584 | 2585 | #### HINTS 2586 | 2587 | - The previous query was `SELECT * FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND date_returned IS NULL;` 2588 | - The three columns you want are `bike_id`, `type`, and `size` 2589 | - Enter `SELECT bike_id, type, size FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND date_returned IS NULL;` in the psql prompt 2590 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2591 | 2592 | ## 1525. psql SELECT ORDER BY 2593 | 2594 | ### 1525.1 2595 | 2596 | One more thing, order the results of the last query by their `bike_id` column. 2597 | 2598 | #### HINTS 2599 | 2600 | - The previous query was `SELECT bike_id, type, size FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND date_returned IS NULL;` 2601 | - Add `ORDER BY bike_id` to the end of the last query 2602 | - Enter `SELECT bike_id, type, size FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND date_returned IS NULL ORDER BY bike_id;` in the psql prompt 2603 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2604 | 2605 | ## 1530. Add CUSTOMER_RENTALS 2606 | 2607 | ### 1530.1 2608 | 2609 | That's the query you will need to use to get the bikes a customer is renting. In your script below the `get customer's rentals` comment. Create a `CUSTOMER_RENTALS` variable that gets the rentals for the customer. Use the `PHONE_NUMBER` variable to get them. 2610 | 2611 | #### HINTS 2612 | 2613 | - Here's an example: `CUSTOMER_RENTALS=$($PSQL "")` 2614 | - You previously entered `SELECT bike_id, type, size FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND date_returned IS NULL ORDER BY bike_id;` in the psql prompt 2615 | - All the columns and tables should be in the same order as in the above query 2616 | - The query looks like this: `SELECT bike_id, type, size FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id) WHERE phone = '$PHONE_NUMBER' AND date_returned IS NULL ORDER BY bike_id` 2617 | - Add `CUSTOMER_RENTALS=$($PSQL "SELECT bike_id, type, size FROM bikes INNER JOIN rentals USING(bike_id) INNER JOIN customers USING(customer_id) WHERE phone = '$PHONE_NUMBER' AND date_returned IS NULL ORDER BY bike_id")` below the `get customer's rentals` comment 2618 | 2619 | ## 1540. Add echo CUSTOMER_RENTALS 2620 | 2621 | ### 1540.1 2622 | 2623 | Below the variable you just created, use `echo` to print it. Make sure to put double quotes around it. 2624 | 2625 | #### HINTS 2626 | 2627 | - Here's an example: `echo ""` 2628 | - Use the variable with `$CUSTOMER_RENTALS` 2629 | - Add `echo "$CUSTOMER_RENTALS"` to the suggested area 2630 | 2631 | ## 1550. ./bike-shop.sh 2632 | 2633 | ### 1550.1 2634 | 2635 | Run the script and go to the return menu. Enter `555-5555` for the phone number to see the rentals for `Me`. 2636 | 2637 | #### HINTS 2638 | 2639 | - Enter `./bike-shop.sh` in the terminal and press enter 2640 | - Make sure you are in the `project` folder first 2641 | 2642 | ## 1560. Add if -z CUSTOMER_RENTALS 2643 | 2644 | ### 1560.1 2645 | 2646 | The query is working. If the customer has no rentals, the variable will be empty. Below the `if no rentals` comment, add an `if` condition that checks if it's empty. Put the `send to main` menu comment in the `then` area again. 2647 | 2648 | #### HINTS 2649 | 2650 | - Here's an example: 2651 | ```sh 2652 | if [[ ]] 2653 | then 2654 | 2655 | fi 2656 | ``` 2657 | - The condition you want is `-z $CUSTOMER_RENTALS` 2658 | - Place the `# send to main menu` comment in the `` area 2659 | - The `if` condition should look like this: 2660 | ```sh 2661 | if [[ -z $CUSTOMER_RENTALS ]] 2662 | then 2663 | # send to main menu 2664 | 2665 | fi 2666 | ``` 2667 | 2668 | ## 1563. Add MAIN_MENU You do not have any bikes rented 2669 | 2670 | ### 1563.1 2671 | 2672 | If the customer has no rentals, send them to the main menu with the message `You do not have any bikes rented.` Add the code below the next comment. 2673 | 2674 | #### HINTS 2675 | 2676 | - You want to call the `MAIN_MENU` function with the message as an argument 2677 | - Here's an example: `MAIN_MENU ""` 2678 | - Add `MAIN_MENU "You do not have any bikes rented."` below the `send to main menu` comment 2679 | 2680 | ## 1570. Add else with comments 2681 | 2682 | ### 1570.1 2683 | 2684 | Add an `else` to the condition for when the customer does have rentals. Place four single line comments in it; `display rented bikes`, `ask for bike to return`, `if not a number`, and `send to main menu`. 2685 | 2686 | #### HINTS 2687 | 2688 | - Here's an example of a single line comment: `# ` 2689 | - Make sure the comments are in the same order listed 2690 | - The comments should be in the `else` area of the `if [[ -z CUSTOMER_RENTALS ]]` statement 2691 | - The `else` area should look like this: 2692 | ```sh 2693 | else 2694 | # display rented bikes 2695 | 2696 | # ask for bike to return 2697 | 2698 | # if not a number 2699 | 2700 | # send to main menu 2701 | 2702 | fi 2703 | ``` 2704 | - The whole `if` should look like this: 2705 | ```sh 2706 | if [[ -z $CUSTOMER_RENTALS ]] 2707 | then 2708 | # send to main menu 2709 | MAIN_MENU "You do not have any bikes rented." 2710 | else 2711 | # display rented bikes 2712 | 2713 | # ask for bike to return 2714 | 2715 | # if not a number 2716 | 2717 | # send to main menu 2718 | 2719 | fi 2720 | ``` 2721 | 2722 | ## 1572. Add echo Here are your rentals 2723 | 2724 | ### 1572.1 2725 | 2726 | Below the `display rented bikes` comment, print `Here are your rentals:` with a new line in front of it. 2727 | 2728 | #### HINTS 2729 | 2730 | - Use `echo` with the `-e` flag and the new line character (`\n`) to print the suggested message 2731 | - Use double quotes around the message 2732 | - Here's an example: `echo -e "\n"` 2733 | - Add `echo -e "\nHere are your rentals:"` below the suggested comment 2734 | 2735 | ## 1575. Add echo CUSTOMER_RENTALS 2736 | 2737 | ### 1575.1 2738 | 2739 | Move the `echo $CUSTOMER_RENTALS` line to below the line you just printed. 2740 | 2741 | #### HINTS 2742 | 2743 | - Move the suggested code below where you print `Here are your rentals:` 2744 | - You should only print the variable in that one spot 2745 | - Place the `echo "$CUSTOMER_RENTALS"` line in the suggested spot 2746 | 2747 | ## 1578. ./bike-shop.sh 2748 | 2749 | ### 1578.1 2750 | 2751 | Run the script and go to the return menu. Enter `555-5555` for the phone number to see the rented bikes. 2752 | 2753 | #### HINTS 2754 | 2755 | - Enter `./bike-shop.sh` in the terminal and press enter 2756 | - Make sure you are in the `project` folder first 2757 | 2758 | ## 1580. Add pipe and while loop 2759 | 2760 | ### 1580.1 2761 | 2762 | Where you print the list of rented bikes, pipe the command into a `while` loop that reads the data. You should read the data into `BIKE_ID`, `BAR`, `TYPE`, `BAR`, and `SIZE` variables. Make it print each rented bike in the same fashion as the list of available bikes. 2763 | 2764 | #### HINTS 2765 | 2766 | - Here's an example: 2767 | ```sh 2768 | echo "$CUSTOMER_RENTALS" | while read 2769 | do 2770 | echo 2771 | done 2772 | ``` 2773 | - The first line should look like this: `echo "$CUSTOMER_RENTALS" | while read BIKE_ID BAR TYPE BAR SIZE` 2774 | - The loop should print `1) 27" Mountain Bike` for each bike with the appropriate bike info 2775 | - The whole thing looks like this: 2776 | ```sh 2777 | echo "$CUSTOMER_RENTALS" | while read BIKE_ID BAR TYPE BAR SIZE 2778 | do 2779 | echo "$BIKE_ID) $SIZE\" $TYPE Bike" 2780 | done 2781 | ``` 2782 | 2783 | ## 1585. ./bike-shop.sh 2784 | 2785 | ### 1585.1 2786 | 2787 | Run the script and go to the return menu. Enter the same phone number again to make sure the list is showing up correctly. 2788 | 2789 | #### HINTS 2790 | 2791 | - Enter `./bike-shop.sh` in the terminal and press enter 2792 | - Make sure you are in the `project` folder first 2793 | 2794 | ## 1590. Add echo Which bike would you like to return? 2795 | 2796 | ### 1590.1 2797 | 2798 | Below the `ask for bike to return` comment, print `Which one would you like to return?` with a new line in front of it. 2799 | 2800 | #### HINTS 2801 | 2802 | - Use `echo` with the `-e` flag and the new line character (`\n`) to print the suggested message 2803 | - Use double quotes around the message 2804 | - Here's an example: `echo -e "\n"` 2805 | - Add `echo -e "\nWhich one would you like to return?"` below the suggested comment 2806 | 2807 | ## 1600. read BIKE_ID_TO_RETURN 2808 | 2809 | ### 1600.1 2810 | 2811 | Below the line you just printed, read input into a `BIKE_ID_TO_RETURN` variable. 2812 | 2813 | #### HINTS 2814 | 2815 | - Here's an example: `read ` 2816 | - Add `read BIKE_ID_TO_RETURN` to the suggested area 2817 | - Add it below where you print `Which one would you like to return?` 2818 | 2819 | ## 1602. Add if BIKE_ID_TO_RETURN not a number 2820 | 2821 | ### 1602.1 2822 | 2823 | Below the `if not a number` comment, check if the input for the bike ID to return is a number using the same method you did earlier. Place the `send to main menu` comment in the statement. 2824 | 2825 | #### HINTS 2826 | 2827 | - Here's an example: 2828 | ```sh 2829 | if [[ ]] 2830 | then 2831 | 2832 | fi 2833 | ``` 2834 | - The condition should check that the `$BIKE_ID_TO_RETURN` variable is not a number using the pattern matching operator (`=~`) and the pattern `^[0-9]+$` 2835 | - The condition you want is `[[ ! $BIKE_ID_TO_RETURN =~ ^[0-9]+$ ]]` 2836 | - Place the `# send to main menu` comment in the `` area 2837 | - The `if` condition should look like this: 2838 | ```sh 2839 | if [[ ! $BIKE_ID_TO_RETURN =~ ^[0-9]+$ ]] 2840 | then 2841 | # send to main menu 2842 | 2843 | fi 2844 | ``` 2845 | 2846 | ## 1605. Add MAIN_MENU That is not a valid bike number 2847 | 2848 | ### 1605.1 2849 | 2850 | If they don't input a number, send them to the main menu with `That is not a valid bike number.` as the message. 2851 | 2852 | #### HINTS 2853 | 2854 | - You want to call the `MAIN_MENU` function with the message as an argument 2855 | - Here's an example: `MAIN_MENU ""` 2856 | - Add `MAIN_MENU "That is not a valid bike number."` below the `send to main menu` comment 2857 | 2858 | ## 1607. Add else with comments 2859 | 2860 | ### 1607.1 2861 | 2862 | Add an `else` for when they do input a number. Place `check if input is rented`, `if input not rented`, and `send to main menu` single line comments in it. 2863 | 2864 | #### HINTS 2865 | 2866 | - Here's an example of a single line comment: `# ` 2867 | - Make sure the comments are in the same order listed 2868 | - The comments should be in the `else` area of the `if [[ ! $BIKE_ID_TO_RETURN =~ ^[0-9]+$ ]]` statement 2869 | - The `else` area should look like this: 2870 | ```sh 2871 | else 2872 | # check if input is rented 2873 | 2874 | # if input not rented 2875 | 2876 | # send to main menu 2877 | 2878 | fi 2879 | ``` 2880 | - The whole `if` should look like this: 2881 | ```sh 2882 | if [[ ! $BIKE_ID_TO_RETURN =~ ^[0-9]+$ ]] 2883 | then 2884 | # send to main menu 2885 | MAIN_MENU "That is not a valid bike number." 2886 | else 2887 | # check if input is rented 2888 | 2889 | # if input not rented 2890 | 2891 | # send to main menu 2892 | 2893 | fi 2894 | ``` 2895 | 2896 | ## 1610. psql SELECT rentals INNER JOIN customers 2897 | 2898 | ### 1610.1 2899 | 2900 | You need to check if the input is a `bike_id` rented by the customer so you can return it. In the psql prompt, join the `rentals` and `customers` tables with an `INNER JOIN` using the `USING` keyword. 2901 | 2902 | #### HINTS 2903 | 2904 | - You need the `SELECT`, `FROM`, `INNER JOIN`, and `USING` keywords 2905 | - Here's an example: `SELECT FROM INNER JOIN USING()` 2906 | - Enter `\d rentals` or `\d customers` in the psql prompt to view the details of the table and find the foreign key column 2907 | - It's the `customer_id` column 2908 | - Enter `SELECT * FROM rentals INNER JOIN customers USING(customer_id);` in the psql prompt 2909 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2910 | 2911 | ## 1620. psql Add conditions to the query 2912 | 2913 | ### 1620.1 2914 | 2915 | Add three conditions to the previous query. Check the `phone`, `bike_id`, and `date_returned` columns to narrow the results to the first bike you rented with `Me`. 2916 | 2917 | #### HINTS 2918 | 2919 | - The previous query was `SELECT * FROM rentals INNER JOIN customers USING(customer_id);` 2920 | - You want to add a `WHERE AND AND ` to the last query 2921 | - Use the `IS NULL` keyword to check the `date_returned` in one of the conditions 2922 | - The other two conditions should check the `phone` and `bike_id` of the first rental 2923 | - The three conditions are `WHERE phone = '555-5555' AND bike_id = 1 AND date_returned IS NULL` 2924 | - Enter `SELECT * FROM rentals INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND bike_id = 1 AND date_returned IS NULL;` in the psql prompt 2925 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2926 | 2927 | ## 1625. psql Only get columns needed 2928 | 2929 | ### 1625.1 2930 | 2931 | You only need to know what bike is going to be returned. Narrow the columns from the last query to only get the one column you would need for returning a bike. 2932 | 2933 | #### HINTS 2934 | 2935 | - The previous query was `SELECT * FROM rentals INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND bike_id = 1 AND date_returned IS NULL;` 2936 | - Only column you need is the `rental_id` column 2937 | - Enter `SELECT rental_id FROM rentals INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND bike_id = 1 AND date_returned IS NULL;` in the psql prompt 2938 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 2939 | 2940 | ## 1630. Add RENTAL_ID 2941 | 2942 | ### 1630.1 2943 | 2944 | Back in the script, below the `check if input is rented` comment, create a `RENTAL_ID` variable that gets the rental ID of the bike that was input. 2945 | 2946 | #### HINTS 2947 | 2948 | - The input is the `BIKE_ID_TO_RETURN` variable 2949 | - Here's an example: `RENTAL_ID=$($PSQL "")` 2950 | - You previously entered `SELECT rental_id FROM rentals INNER JOIN customers USING(customer_id) WHERE phone = '555-5555' AND bike_id = 1 AND date_returned IS NULL;` in the psql prompt 2951 | - Be sure to use the same columns from the above query for the conditions with the `PHONE_NUMBER` and `BIKE_ID_TO_RETURN` variables 2952 | - Add `RENTAL_ID=$($PSQL "SELECT rental_id FROM rentals INNER JOIN customers USING(customer_id) WHERE phone = '$PHONE_NUMBER' AND bike_id = $BIKE_ID_TO_RETURN AND date_returned IS NULL")` below the `check if input is rented` comment 2953 | 2954 | ## 1640. Add if -z RENTAL_ID 2955 | 2956 | ### 1640.1 2957 | 2958 | Below the `if input not rented` comment, add an `if` that checks if the `RENTAL_ID` variable is empty. Place the `send to main menu` comment in the `then` area. 2959 | 2960 | #### HINTS 2961 | 2962 | - Here's an example: 2963 | ```sh 2964 | if [[ ]] 2965 | then 2966 | 2967 | fi 2968 | ``` 2969 | - The condition you want is `-z $RENTAL_ID` 2970 | - Place the `# send to main menu` comment in the `` area 2971 | - The `if` condition should look like this: 2972 | ```sh 2973 | if [[ -z $RENTAL_ID ]] 2974 | then 2975 | # send to main menu 2976 | 2977 | fi 2978 | ``` 2979 | 2980 | ## 1645. Add MAIN_MENU You do not have that bike rented 2981 | 2982 | ### 1645.1 2983 | 2984 | If the input isn't rented by the given customer, send them to the main menu with `You do not have that bike rented.` as the message. 2985 | 2986 | #### HINTS 2987 | 2988 | - You want to call the `MAIN_MENU` function with the message as an argument 2989 | - Here's an example: `MAIN_MENU ""` 2990 | - Add `MAIN_MENU "You do not have that bike rented."` below the `send to main menu` comment 2991 | 2992 | ## 1648. Add else echo Rental ID RENTAL_ID found 2993 | 2994 | ### 1648.1 2995 | 2996 | Add an `else` to the `if` condition you just added. Use `echo` to print `Rental ID $RENTAL_ID found` in it so you can see if it's all working. 2997 | 2998 | #### HINTS 2999 | 3000 | - Here's an example: 3001 | ```sh 3002 | if [[ ]] 3003 | then 3004 | 3005 | else 3006 | 3007 | fi 3008 | ``` 3009 | - Place `echo "Rental ID $RENTAL_ID found"` in the else area 3010 | - The `if` condition should look like this: 3011 | ```sh 3012 | if [[ -z $RENTAL_ID ]] 3013 | then 3014 | # send to main menu 3015 | MAIN_MENU "You do not have that bike rented." 3016 | else 3017 | echo "Rental ID $RENTAL_ID found" 3018 | fi 3019 | ``` 3020 | 3021 | ## 1650. Run the script 3022 | 3023 | ### 1650.1 3024 | 3025 | Run the script and go to the return menu. Enter `555-5555` to see the rented bikes. Input a bike that isn't on the list, then go to the menu again and input a bike that is on the list. 3026 | 3027 | #### HINTS 3028 | 3029 | - Enter `./bike-shop.sh` in the terminal and press enter 3030 | - Make sure you are in the `project` folder first 3031 | 3032 | ## 1660. Delete echo Rental ID RENTAL_ID found 3033 | 3034 | ### 1660.1 3035 | 3036 | Looks like it works. Delete the line where you print the rental ID. 3037 | 3038 | #### HINTS 3039 | 3040 | - Delete the `echo "Rental ID $RENTAL_ID found"` line 3041 | 3042 | ## 1680. Add else with comments 3043 | 3044 | ### 1680.1 3045 | 3046 | Add three single line comments in the `else` area; `update date_returned`, `set bike availability to true`, and `send to main menu`. 3047 | 3048 | #### HINTS 3049 | 3050 | - Here's an example of a single line comment: `# ` 3051 | - Make sure the comments are in the same order listed 3052 | - The comments should be in the `else` area of the `if [[ -z $RENTAL_ID ]]` statement 3053 | - The `else` area should look like this: 3054 | ```sh 3055 | else 3056 | # update date_returned 3057 | 3058 | # set bike availability to true 3059 | 3060 | # send to main menu 3061 | 3062 | fi 3063 | ``` 3064 | - The whole `if` should look like this: 3065 | ```sh 3066 | if [[ -z $RENTAL_ID ]] 3067 | then 3068 | # send to main menu 3069 | MAIN_MENU "You do not have that bike rented." 3070 | else 3071 | # update date_returned 3072 | 3073 | # set bike availability to true 3074 | 3075 | # send to main menu 3076 | 3077 | fi 3078 | ``` 3079 | 3080 | ## 1690. Add RETURN_BIKE_RESULT 3081 | 3082 | ### 1690.1 3083 | 3084 | After a person picks a bike to return and you know that it's a bike they have rented, you need to update all the info in the database to return it. Below the `update date_returned` comment, create a `RETURN_BIKE_RESULT` variable that sets the `date_returned` column to `NOW()` for the bike rented. Use the `RENTAL_ID` to figure out which row to update. 3085 | 3086 | #### HINTS 3087 | 3088 | - Here's an example: `RETURN_BIKE_RESULT=$($PSQL "")` 3089 | - You want to use the `UPDATE`, `SET`, `NOW()`, and `WHERE` keywords in the query 3090 | - Here's an example of the query: `UPDATE
SET = WHERE ` 3091 | - The query you want is `UPDATE rentals SET date_returned = NOW() WHERE rental_id = $RENTAL_ID` 3092 | - Add `RETURN_BIKE_RESULT=$($PSQL "UPDATE rentals SET date_returned = NOW() WHERE rental_id = $RENTAL_ID")` below the `update date_returned` comment 3093 | 3094 | ## 1710. Add SET_TO_TRUE_RESULT 3095 | 3096 | ### 1710.1 3097 | 3098 | That should update the rentals table. Lastly, you need to make the bike available again. Below the `set bike availability to true` comment, create a `SET_TO_TRUE_RESULT` variable that makes the bike available again. 3099 | 3100 | #### HINTS 3101 | 3102 | - Here's an example: `SET_TO_TRUE_RESULT=$($PSQL "")` 3103 | - You want to use the `UPDATE`, `SET`, and `WHERE` keywords in the query 3104 | - You want to update the `available` column to `true` for the bike with `BIKE_ID_TO_RETURN` 3105 | - The query you want is `UPDATE bikes SET available = true WHERE bike_id = $BIKE_ID_TO_RETURN` 3106 | - Add `SET_TO_TRUE_RESULT=$($PSQL "UPDATE bikes SET available = true WHERE bike_id = $BIKE_ID_TO_RETURN")` below the `set bike availability to true` comment 3107 | 3108 | ## 1730. Add MAIN_MENU Thank you for returning your bike 3109 | 3110 | ### 1730.1 3111 | 3112 | After all that is done, send them to the main menu with `Thank you for returning your bike.` as the message. 3113 | 3114 | #### HINTS 3115 | 3116 | - Add the code below the last `send to main menu` comment 3117 | - You want to call the `MAIN_MENU` function with the message as an argument 3118 | - Here's an example: `MAIN_MENU ""` 3119 | - Add `MAIN_MENU "Thank you for returning your bike."` below the `send to main menu` comment 3120 | 3121 | ## 1740. ./bike-shop.sh 3122 | 3123 | ### 1740.1 3124 | 3125 | Run the script and return one of the bikes that `Me` has rented out. When you are done, exit the program. 3126 | 3127 | #### HINTS 3128 | 3129 | - Enter `./bike-shop.sh` in the terminal and press enter 3130 | - The customer with phone number `555-5555` and name `Me` should have at least one rental with the `date_returned` column not null 3131 | 3132 | ## 1750. psql SELECT * FROM rentals 3133 | 3134 | ### 1750.1 3135 | 3136 | In the psql prompt, view all the data in the `rentals` table. 3137 | 3138 | #### HINTS 3139 | 3140 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 3141 | - Enter `SELECT * FROM rentals;` in the psql prompt 3142 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 3143 | 3144 | ## 1760. psql SELECT * FROM bikes ORDER BY bike_id 3145 | 3146 | ### 1760.1 3147 | 3148 | Now the rental has been returned. View all the data in the bikes table in order by their `bike_id`. 3149 | 3150 | #### HINTS 3151 | 3152 | - Use the `SELECT` and `FROM` keywords with `*` to view all the data 3153 | - Enter `SELECT * FROM bikes ORDER BY bike_id;` in the psql prompt 3154 | - You can type `psql --username=freecodecamp --dbname=bikes` into the terminal to log in to psql if you aren't logged in. 3155 | 3156 | ## 1770. ./bike-shop.sh 3157 | 3158 | ### 1770.1 3159 | 3160 | And the bike is available again. This is the last step. Run the script once more. Feel free to play around, rent and return some bikes. When you are ready to be done, return all the bikes you rented and exit the program. 3161 | 3162 | #### HINTS 3163 | 3164 | - Enter `./bike-shop.sh` in the terminal and press enter 3165 | - All rentals should have a `date_returned` value, and all bikes should have `available` set to `true` 3166 | -------------------------------------------------------------------------------- /coderoad.yaml: -------------------------------------------------------------------------------- 1 | id: 'freeCodeCamp/learn-bash-and-sql-by-building-a-bike-rental-shop:v1.0.0' 2 | version: '2.0.0' 3 | config: 4 | setup: 5 | commands: 6 | - ./.freeCodeCamp/setup.sh 7 | - cd .freeCodeCamp && npm install 8 | testRunner: 9 | command: npm run programmatic-test 10 | args: 11 | tap: --reporter=mocha-tap-reporter 12 | directory: .freeCodeCamp 13 | repo: 14 | uri: https://github.com/freeCodeCamp/learn-bash-and-sql-by-building-a-bike-rental-shop 15 | branch: v2.0.0 16 | continue: 17 | commands: 18 | - './.freeCodeCamp/setup.sh' 19 | - './.freeCodeCamp/reset.sh' 20 | reset: 21 | commands: 22 | - './.freeCodeCamp/setup.sh' 23 | - './.freeCodeCamp/reset.sh' 24 | dependencies: 25 | - name: node 26 | version: '>=10' 27 | webhook: 28 | url: 'https://api.freecodecamp.org/coderoad-challenge-completed' 29 | events: 30 | init: false 31 | reset: false 32 | step_complete: false 33 | level_complete: false 34 | tutorial_complete: true 35 | levels: 36 | - id: '10' 37 | steps: 38 | - id: '10.1' 39 | setup: 40 | watchers: 41 | - ../.bash_history 42 | - id: '20' 43 | steps: 44 | - id: '20.1' 45 | setup: 46 | watchers: 47 | - ../pg.log 48 | - id: '30' 49 | steps: 50 | - id: '30.1' 51 | setup: 52 | watchers: 53 | - ../queryResults.log 54 | - id: '40' 55 | steps: 56 | - id: '40.1' 57 | setup: 58 | watchers: 59 | - ../queryResults.log 60 | - id: '50' 61 | steps: 62 | - id: '50.1' 63 | setup: 64 | watchers: 65 | - ../queryResults.log 66 | - id: '60' 67 | steps: 68 | - id: '60.1' 69 | setup: 70 | watchers: 71 | - ../pg.log 72 | - id: '70' 73 | steps: 74 | - id: '70.1' 75 | setup: 76 | watchers: 77 | - ../queryResults.log 78 | - id: '80' 79 | steps: 80 | - id: '80.1' 81 | setup: 82 | watchers: 83 | - ../queryResults.log 84 | - id: '90' 85 | steps: 86 | - id: '90.1' 87 | setup: 88 | watchers: 89 | - ../queryResults.log 90 | - id: '100' 91 | steps: 92 | - id: '100.1' 93 | setup: 94 | watchers: 95 | - ../queryResults.log 96 | - id: '110' 97 | steps: 98 | - id: '110.1' 99 | setup: 100 | watchers: 101 | - ../queryResults.log 102 | - id: '120' 103 | steps: 104 | - id: '120.1' 105 | setup: 106 | watchers: 107 | - ../queryResults.log 108 | - id: '130' 109 | steps: 110 | - id: '130.1' 111 | setup: 112 | watchers: 113 | - ../queryResults.log 114 | - id: '140' 115 | steps: 116 | - id: '140.1' 117 | setup: 118 | watchers: 119 | - ../queryResults.log 120 | - id: '150' 121 | steps: 122 | - id: '150.1' 123 | setup: 124 | watchers: 125 | - ../queryResults.log 126 | - id: '160' 127 | steps: 128 | - id: '160.1' 129 | setup: 130 | watchers: 131 | - ../queryResults.log 132 | - id: '170' 133 | steps: 134 | - id: '170.1' 135 | setup: 136 | watchers: 137 | - ../queryResults.log 138 | - id: '180' 139 | steps: 140 | - id: '180.1' 141 | setup: 142 | watchers: 143 | - ../queryResults.log 144 | - id: '190' 145 | steps: 146 | - id: '190.1' 147 | setup: 148 | watchers: 149 | - ../queryResults.log 150 | - id: '200' 151 | steps: 152 | - id: '200.1' 153 | setup: 154 | watchers: 155 | - ../queryResults.log 156 | - id: '210' 157 | steps: 158 | - id: '210.1' 159 | setup: 160 | watchers: 161 | - ../queryResults.log 162 | - id: '220' 163 | steps: 164 | - id: '220.1' 165 | setup: 166 | watchers: 167 | - ../queryResults.log 168 | - id: '230' 169 | steps: 170 | - id: '230.1' 171 | setup: 172 | watchers: 173 | - ../queryResults.log 174 | - id: '240' 175 | steps: 176 | - id: '240.1' 177 | setup: 178 | watchers: 179 | - ../queryResults.log 180 | - id: '250' 181 | steps: 182 | - id: '250.1' 183 | setup: 184 | watchers: 185 | - ../queryResults.log 186 | - id: '260' 187 | steps: 188 | - id: '260.1' 189 | setup: 190 | watchers: 191 | - ../queryResults.log 192 | - id: '270' 193 | steps: 194 | - id: '270.1' 195 | setup: 196 | watchers: 197 | - ../queryResults.log 198 | - id: '280' 199 | steps: 200 | - id: '280.1' 201 | setup: 202 | watchers: 203 | - ../queryResults.log 204 | - id: '290' 205 | steps: 206 | - id: '290.1' 207 | setup: 208 | watchers: 209 | - ../queryResults.log 210 | - id: '300' 211 | steps: 212 | - id: '300.1' 213 | setup: 214 | watchers: 215 | - ../queryResults.log 216 | - id: '310' 217 | steps: 218 | - id: '310.1' 219 | setup: 220 | watchers: 221 | - ../queryResults.log 222 | - id: '320' 223 | steps: 224 | - id: '320.1' 225 | setup: 226 | watchers: 227 | - ../queryResults.log 228 | - id: '330' 229 | steps: 230 | - id: '330.1' 231 | setup: 232 | watchers: 233 | - ../queryResults.log 234 | - id: '340' 235 | steps: 236 | - id: '340.1' 237 | setup: 238 | watchers: 239 | - ../queryResults.log 240 | - id: '350' 241 | steps: 242 | - id: '350.1' 243 | setup: 244 | watchers: 245 | - ../queryResults.log 246 | - id: '360' 247 | steps: 248 | - id: '360.1' 249 | setup: 250 | watchers: 251 | - ../queryResults.log 252 | - id: '370' 253 | steps: 254 | - id: '370.1' 255 | setup: 256 | watchers: 257 | - ../queryResults.log 258 | - id: '380' 259 | steps: 260 | - id: '380.1' 261 | setup: 262 | watchers: 263 | - ../queryResults.log 264 | - id: '390' 265 | steps: 266 | - id: '390.1' 267 | setup: 268 | watchers: 269 | - ../queryResults.log 270 | - id: '400' 271 | steps: 272 | - id: '400.1' 273 | setup: 274 | watchers: 275 | - ../queryResults.log 276 | - id: '410' 277 | steps: 278 | - id: '410.1' 279 | setup: 280 | watchers: 281 | - ../queryResults.log 282 | - id: '420' 283 | steps: 284 | - id: '420.1' 285 | setup: 286 | watchers: 287 | - ../queryResults.log 288 | - id: '430' 289 | steps: 290 | - id: '430.1' 291 | setup: 292 | watchers: 293 | - ../queryResults.log 294 | - id: '440' 295 | steps: 296 | - id: '440.1' 297 | setup: 298 | watchers: 299 | - ../queryResults.log 300 | - id: '450' 301 | steps: 302 | - id: '450.1' 303 | setup: 304 | watchers: 305 | - ../.bash_history 306 | - id: '460' 307 | steps: 308 | - id: '460.1' 309 | setup: 310 | watchers: 311 | - ./bike-shop.sh 312 | - id: '470' 313 | steps: 314 | - id: '470.1' 315 | setup: 316 | watchers: 317 | - ./bike-shop.sh 318 | - id: '480' 319 | steps: 320 | - id: '480.1' 321 | setup: 322 | watchers: 323 | - ../.bash_history 324 | - id: '490' 325 | steps: 326 | - id: '490.1' 327 | setup: 328 | watchers: 329 | - ../.bash_history 330 | - id: '510' 331 | steps: 332 | - id: '510.1' 333 | setup: 334 | watchers: 335 | - ./bike-shop.sh 336 | - id: '520' 337 | steps: 338 | - id: '520.1' 339 | setup: 340 | watchers: 341 | - ./bike-shop.sh 342 | - id: '530' 343 | steps: 344 | - id: '530.1' 345 | setup: 346 | watchers: 347 | - ./bike-shop.sh 348 | - id: '540' 349 | steps: 350 | - id: '540.1' 351 | setup: 352 | watchers: 353 | - ../.bash_history 354 | - id: '630' 355 | steps: 356 | - id: '630.1' 357 | setup: 358 | watchers: 359 | - ./bike-shop.sh 360 | - id: '640' 361 | steps: 362 | - id: '640.1' 363 | setup: 364 | watchers: 365 | - ../.bash_history 366 | - id: '650' 367 | steps: 368 | - id: '650.1' 369 | setup: 370 | watchers: 371 | - ./bike-shop.sh 372 | - id: '660' 373 | steps: 374 | - id: '660.1' 375 | setup: 376 | watchers: 377 | - ./bike-shop.sh 378 | - id: '670' 379 | steps: 380 | - id: '670.1' 381 | setup: 382 | watchers: 383 | - ./bike-shop.sh 384 | - id: '680' 385 | steps: 386 | - id: '680.1' 387 | setup: 388 | watchers: 389 | - ./bike-shop.sh 390 | - id: '690' 391 | steps: 392 | - id: '690.1' 393 | setup: 394 | watchers: 395 | - ./bike-shop.sh 396 | - id: '700' 397 | steps: 398 | - id: '700.1' 399 | setup: 400 | watchers: 401 | - ./bike-shop.sh 402 | - id: '710' 403 | steps: 404 | - id: '710.1' 405 | setup: 406 | watchers: 407 | - ./bike-shop.sh 408 | - id: '720' 409 | steps: 410 | - id: '720.1' 411 | setup: 412 | watchers: 413 | - ./bike-shop.sh 414 | - id: '730' 415 | steps: 416 | - id: '730.1' 417 | setup: 418 | watchers: 419 | - ../.bash_history 420 | - id: '740' 421 | steps: 422 | - id: '740.1' 423 | setup: 424 | watchers: 425 | - ./bike-shop.sh 426 | - id: '750' 427 | steps: 428 | - id: '750.1' 429 | setup: 430 | watchers: 431 | - ./bike-shop.sh 432 | - id: '760' 433 | steps: 434 | - id: '760.1' 435 | setup: 436 | watchers: 437 | - ../.bash_history 438 | - id: '850' 439 | steps: 440 | - id: '850.1' 441 | setup: 442 | watchers: 443 | - ./bike-shop.sh 444 | - id: '860' 445 | steps: 446 | - id: '860.1' 447 | setup: 448 | watchers: 449 | - ./bike-shop.sh 450 | - id: '920' 451 | steps: 452 | - id: '920.1' 453 | setup: 454 | watchers: 455 | - ./bike-shop.sh 456 | - id: '970' 457 | steps: 458 | - id: '970.1' 459 | setup: 460 | watchers: 461 | - ./bike-shop.sh 462 | - id: '980' 463 | steps: 464 | - id: '980.1' 465 | setup: 466 | watchers: 467 | - ./bike-shop.sh 468 | - id: '990' 469 | steps: 470 | - id: '990.1' 471 | setup: 472 | watchers: 473 | - ../.bash_history 474 | - id: '993' 475 | steps: 476 | - id: '993.1' 477 | setup: 478 | watchers: 479 | - ../queryResults.log 480 | - id: '995' 481 | steps: 482 | - id: '995.1' 483 | setup: 484 | watchers: 485 | - ../.bash_history 486 | - id: '1000' 487 | steps: 488 | - id: '1000.1' 489 | setup: 490 | watchers: 491 | - ./bike-shop.sh 492 | - id: '1010' 493 | steps: 494 | - id: '1010.1' 495 | setup: 496 | watchers: 497 | - ./bike-shop.sh 498 | - id: '1020' 499 | steps: 500 | - id: '1020.1' 501 | setup: 502 | watchers: 503 | - ../.bash_history 504 | - id: '1100' 505 | steps: 506 | - id: '1100.1' 507 | setup: 508 | watchers: 509 | - ./bike-shop.sh 510 | - id: '1105' 511 | steps: 512 | - id: '1105.1' 513 | setup: 514 | watchers: 515 | - ./bike-shop.sh 516 | - id: '1110' 517 | steps: 518 | - id: '1110.1' 519 | setup: 520 | watchers: 521 | - ./bike-shop.sh 522 | - id: '1115' 523 | steps: 524 | - id: '1115.1' 525 | setup: 526 | watchers: 527 | - ../queryResults.log 528 | - id: '1130' 529 | steps: 530 | - id: '1130.1' 531 | setup: 532 | watchers: 533 | - ../.bash_history 534 | - id: '1140' 535 | steps: 536 | - id: '1140.1' 537 | setup: 538 | watchers: 539 | - ./bike-shop.sh 540 | - id: '1142' 541 | steps: 542 | - id: '1142.1' 543 | setup: 544 | watchers: 545 | - ../.bash_history 546 | - id: '1145' 547 | steps: 548 | - id: '1145.1' 549 | setup: 550 | watchers: 551 | - ./bike-shop.sh 552 | - id: '1150' 553 | steps: 554 | - id: '1150.1' 555 | setup: 556 | watchers: 557 | - ../.bash_history 558 | - id: '1160' 559 | steps: 560 | - id: '1160.1' 561 | setup: 562 | watchers: 563 | - ./bike-shop.sh 564 | - id: '1162' 565 | steps: 566 | - id: '1162.1' 567 | setup: 568 | watchers: 569 | - ./bike-shop.sh 570 | - id: '1164' 571 | steps: 572 | - id: '1164.1' 573 | setup: 574 | watchers: 575 | - ../.bash_history 576 | - id: '1165' 577 | steps: 578 | - id: '1165.1' 579 | setup: 580 | watchers: 581 | - ../.bash_history 582 | - id: '1166' 583 | steps: 584 | - id: '1166.1' 585 | setup: 586 | watchers: 587 | - ../.bash_history 588 | - id: '1167' 589 | steps: 590 | - id: '1167.1' 591 | setup: 592 | watchers: 593 | - ../.bash_history 594 | - id: '1168' 595 | steps: 596 | - id: '1168.1' 597 | setup: 598 | watchers: 599 | - ../.bash_history 600 | - id: '1169' 601 | steps: 602 | - id: '1169.1' 603 | setup: 604 | watchers: 605 | - ../.bash_history 606 | - id: '1170' 607 | steps: 608 | - id: '1170.1' 609 | setup: 610 | watchers: 611 | - ../.bash_history 612 | - id: '1176' 613 | steps: 614 | - id: '1176.1' 615 | setup: 616 | watchers: 617 | - ./bike-shop.sh 618 | - id: '1177' 619 | steps: 620 | - id: '1177.1' 621 | setup: 622 | watchers: 623 | - ./bike-shop.sh 624 | - id: '1178' 625 | steps: 626 | - id: '1178.1' 627 | setup: 628 | watchers: 629 | - ../.bash_history 630 | - id: '1179' 631 | steps: 632 | - id: '1179.1' 633 | setup: 634 | watchers: 635 | - ./bike-shop.sh 636 | - id: '1180' 637 | steps: 638 | - id: '1180.1' 639 | setup: 640 | watchers: 641 | - ./bike-shop.sh 642 | - id: '1190' 643 | steps: 644 | - id: '1190.1' 645 | setup: 646 | watchers: 647 | - ./bike-shop.sh 648 | - id: '1200' 649 | steps: 650 | - id: '1200.1' 651 | setup: 652 | watchers: 653 | - ../.bash_history 654 | - id: '1210' 655 | steps: 656 | - id: '1210.1' 657 | setup: 658 | watchers: 659 | - ./bike-shop.sh 660 | - id: '1215' 661 | steps: 662 | - id: '1215.1' 663 | setup: 664 | watchers: 665 | - ./bike-shop.sh 666 | - id: '1220' 667 | steps: 668 | - id: '1220.1' 669 | setup: 670 | watchers: 671 | - ./bike-shop.sh 672 | - id: '1230' 673 | steps: 674 | - id: '1230.1' 675 | setup: 676 | watchers: 677 | - ../.bash_history 678 | - id: '1233' 679 | steps: 680 | - id: '1233.1' 681 | setup: 682 | watchers: 683 | - ../queryResults.log 684 | - id: '1236' 685 | steps: 686 | - id: '1236.1' 687 | setup: 688 | watchers: 689 | - ./bike-shop.sh 690 | - id: '1240' 691 | steps: 692 | - id: '1240.1' 693 | setup: 694 | watchers: 695 | - ./bike-shop.sh 696 | - id: '1250' 697 | steps: 698 | - id: '1250.1' 699 | setup: 700 | watchers: 701 | - ./bike-shop.sh 702 | - id: '1260' 703 | steps: 704 | - id: '1260.1' 705 | setup: 706 | watchers: 707 | - ./bike-shop.sh 708 | - id: '1265' 709 | steps: 710 | - id: '1265.1' 711 | setup: 712 | watchers: 713 | - ./bike-shop.sh 714 | - id: '1270' 715 | steps: 716 | - id: '1270.1' 717 | setup: 718 | watchers: 719 | - ./bike-shop.sh 720 | - id: '1280' 721 | steps: 722 | - id: '1280.1' 723 | setup: 724 | watchers: 725 | - ./bike-shop.sh 726 | - id: '1290' 727 | steps: 728 | - id: '1290.1' 729 | setup: 730 | watchers: 731 | - ./bike-shop.sh 732 | - id: '1300' 733 | steps: 734 | - id: '1300.1' 735 | setup: 736 | watchers: 737 | - ../.bash_history 738 | - id: '1310' 739 | steps: 740 | - id: '1310.1' 741 | setup: 742 | watchers: 743 | - ../queryResults.log 744 | - id: '1311' 745 | steps: 746 | - id: '1311.1' 747 | setup: 748 | watchers: 749 | - ../queryResults.log 750 | - id: '1312' 751 | steps: 752 | - id: '1312.1' 753 | setup: 754 | watchers: 755 | - ../queryResults.log 756 | - id: '1315' 757 | steps: 758 | - id: '1315.1' 759 | setup: 760 | watchers: 761 | - ./bike-shop.sh 762 | - id: '1320' 763 | steps: 764 | - id: '1320.1' 765 | setup: 766 | watchers: 767 | - ./bike-shop.sh 768 | - id: '1330' 769 | steps: 770 | - id: '1330.1' 771 | setup: 772 | watchers: 773 | - ./bike-shop.sh 774 | - id: '1370' 775 | steps: 776 | - id: '1370.1' 777 | setup: 778 | watchers: 779 | - ./bike-shop.sh 780 | - id: '1380' 781 | steps: 782 | - id: '1380.1' 783 | setup: 784 | watchers: 785 | - ../.bash_history 786 | - id: '1390' 787 | steps: 788 | - id: '1390.1' 789 | setup: 790 | watchers: 791 | - ../queryResults.log 792 | - id: '1400' 793 | steps: 794 | - id: '1400.1' 795 | setup: 796 | watchers: 797 | - ../queryResults.log 798 | - id: '1401' 799 | steps: 800 | - id: '1401.1' 801 | setup: 802 | watchers: 803 | - ./bike-shop.sh 804 | - id: '1402' 805 | steps: 806 | - id: '1402.1' 807 | setup: 808 | watchers: 809 | - ./bike-shop.sh 810 | - id: '1403' 811 | steps: 812 | - id: '1403.1' 813 | setup: 814 | watchers: 815 | - ../.bash_history 816 | - id: '1404' 817 | steps: 818 | - id: '1404.1' 819 | setup: 820 | watchers: 821 | - ../.bash_history 822 | - id: '1405' 823 | steps: 824 | - id: '1405.1' 825 | setup: 826 | watchers: 827 | - ../.bash_history 828 | - id: '1407' 829 | steps: 830 | - id: '1407.1' 831 | setup: 832 | watchers: 833 | - ../.bash_history 834 | - id: '1408' 835 | steps: 836 | - id: '1408.1' 837 | setup: 838 | watchers: 839 | - ../.bash_history 840 | - id: '1410' 841 | steps: 842 | - id: '1410.1' 843 | setup: 844 | watchers: 845 | - ../.bash_history 846 | - id: '1411' 847 | steps: 848 | - id: '1411.1' 849 | setup: 850 | watchers: 851 | - ./bike-shop.sh 852 | - id: '1413' 853 | steps: 854 | - id: '1413.1' 855 | setup: 856 | watchers: 857 | - ../.bash_history 858 | - id: '1415' 859 | steps: 860 | - id: '1415.1' 861 | setup: 862 | watchers: 863 | - ./bike-shop.sh 864 | - id: '1417' 865 | steps: 866 | - id: '1417.1' 867 | setup: 868 | watchers: 869 | - ./bike-shop.sh 870 | - id: '1418' 871 | steps: 872 | - id: '1418.1' 873 | setup: 874 | watchers: 875 | - ../.bash_history 876 | - id: '1420' 877 | steps: 878 | - id: '1420.1' 879 | setup: 880 | watchers: 881 | - ../.bash_history 882 | - id: '1422' 883 | steps: 884 | - id: '1422.1' 885 | setup: 886 | watchers: 887 | - ../.bash_history 888 | - id: '1424' 889 | steps: 890 | - id: '1424.1' 891 | setup: 892 | watchers: 893 | - ../.bash_history 894 | - id: '1425' 895 | steps: 896 | - id: '1425.1' 897 | setup: 898 | watchers: 899 | - ../.bash_history 900 | - id: '1427' 901 | steps: 902 | - id: '1427.1' 903 | setup: 904 | watchers: 905 | - ../.bash_history 906 | - id: '1428' 907 | steps: 908 | - id: '1428.1' 909 | setup: 910 | watchers: 911 | - ../.bash_history 912 | - id: '1430' 913 | steps: 914 | - id: '1430.1' 915 | setup: 916 | watchers: 917 | - ../.bash_history 918 | - id: '1432' 919 | steps: 920 | - id: '1432.1' 921 | setup: 922 | watchers: 923 | - ../.bash_history 924 | - id: '1433' 925 | steps: 926 | - id: '1433.1' 927 | setup: 928 | watchers: 929 | - ../.bash_history 930 | - id: '1435' 931 | steps: 932 | - id: '1435.1' 933 | setup: 934 | watchers: 935 | - ../.bash_history 936 | - id: '1436' 937 | steps: 938 | - id: '1436.1' 939 | setup: 940 | watchers: 941 | - ../.bash_history 942 | - id: '1437' 943 | steps: 944 | - id: '1437.1' 945 | setup: 946 | watchers: 947 | - ../.bash_history 948 | - id: '1438' 949 | steps: 950 | - id: '1438.1' 951 | setup: 952 | watchers: 953 | - ../.bash_history 954 | - id: '1440' 955 | steps: 956 | - id: '1440.1' 957 | setup: 958 | watchers: 959 | - ./bike-shop.sh 960 | - id: '1442' 961 | steps: 962 | - id: '1442.1' 963 | setup: 964 | watchers: 965 | - ../.bash_history 966 | - id: '1444' 967 | steps: 968 | - id: '1444.1' 969 | setup: 970 | watchers: 971 | - ../.bash_history 972 | - id: '1446' 973 | steps: 974 | - id: '1446.1' 975 | setup: 976 | watchers: 977 | - ../.bash_history 978 | - id: '1448' 979 | steps: 980 | - id: '1448.1' 981 | setup: 982 | watchers: 983 | - ../queryResults.log 984 | - id: '1449' 985 | steps: 986 | - id: '1449.1' 987 | setup: 988 | watchers: 989 | - ../queryResults.log 990 | - id: '1450' 991 | steps: 992 | - id: '1450.1' 993 | setup: 994 | watchers: 995 | - ../queryResults.log 996 | - id: '1453' 997 | steps: 998 | - id: '1453.1' 999 | setup: 1000 | watchers: 1001 | - ./bike-shop.sh 1002 | - id: '1457' 1003 | steps: 1004 | - id: '1457.1' 1005 | setup: 1006 | watchers: 1007 | - ./bike-shop.sh 1008 | - id: '1460' 1009 | steps: 1010 | - id: '1460.1' 1011 | setup: 1012 | watchers: 1013 | - ./bike-shop.sh 1014 | - id: '1470' 1015 | steps: 1016 | - id: '1470.1' 1017 | setup: 1018 | watchers: 1019 | - ./bike-shop.sh 1020 | - id: '1472' 1021 | steps: 1022 | - id: '1472.1' 1023 | setup: 1024 | watchers: 1025 | - ./bike-shop.sh 1026 | - id: '1474' 1027 | steps: 1028 | - id: '1474.1' 1029 | setup: 1030 | watchers: 1031 | - ./bike-shop.sh 1032 | - id: '1475' 1033 | steps: 1034 | - id: '1475.1' 1035 | setup: 1036 | watchers: 1037 | - ./bike-shop.sh 1038 | - id: '1476' 1039 | steps: 1040 | - id: '1476.1' 1041 | setup: 1042 | watchers: 1043 | - ../.bash_history 1044 | - id: '1478' 1045 | steps: 1046 | - id: '1478.1' 1047 | setup: 1048 | watchers: 1049 | - ./bike-shop.sh 1050 | - id: '1480' 1051 | steps: 1052 | - id: '1480.1' 1053 | setup: 1054 | watchers: 1055 | - ../queryResults.log 1056 | - id: '1485' 1057 | steps: 1058 | - id: '1485.1' 1059 | setup: 1060 | watchers: 1061 | - ../queryResults.log 1062 | - id: '1490' 1063 | steps: 1064 | - id: '1490.1' 1065 | setup: 1066 | watchers: 1067 | - ../queryResults.log 1068 | - id: '1500' 1069 | steps: 1070 | - id: '1500.1' 1071 | setup: 1072 | watchers: 1073 | - ../queryResults.log 1074 | - id: '1510' 1075 | steps: 1076 | - id: '1510.1' 1077 | setup: 1078 | watchers: 1079 | - ../queryResults.log 1080 | - id: '1520' 1081 | steps: 1082 | - id: '1520.1' 1083 | setup: 1084 | watchers: 1085 | - ../queryResults.log 1086 | - id: '1525' 1087 | steps: 1088 | - id: '1525.1' 1089 | setup: 1090 | watchers: 1091 | - ../queryResults.log 1092 | - id: '1530' 1093 | steps: 1094 | - id: '1530.1' 1095 | setup: 1096 | watchers: 1097 | - ./bike-shop.sh 1098 | - id: '1540' 1099 | steps: 1100 | - id: '1540.1' 1101 | setup: 1102 | watchers: 1103 | - ./bike-shop.sh 1104 | - id: '1550' 1105 | steps: 1106 | - id: '1550.1' 1107 | setup: 1108 | watchers: 1109 | - ../.bash_history 1110 | - id: '1560' 1111 | steps: 1112 | - id: '1560.1' 1113 | setup: 1114 | watchers: 1115 | - ./bike-shop.sh 1116 | - id: '1563' 1117 | steps: 1118 | - id: '1563.1' 1119 | setup: 1120 | watchers: 1121 | - ./bike-shop.sh 1122 | - id: '1570' 1123 | steps: 1124 | - id: '1570.1' 1125 | setup: 1126 | watchers: 1127 | - ./bike-shop.sh 1128 | - id: '1572' 1129 | steps: 1130 | - id: '1572.1' 1131 | setup: 1132 | watchers: 1133 | - ./bike-shop.sh 1134 | - id: '1575' 1135 | steps: 1136 | - id: '1575.1' 1137 | setup: 1138 | watchers: 1139 | - ./bike-shop.sh 1140 | - id: '1578' 1141 | steps: 1142 | - id: '1578.1' 1143 | setup: 1144 | watchers: 1145 | - ../.bash_history 1146 | - id: '1580' 1147 | steps: 1148 | - id: '1580.1' 1149 | setup: 1150 | watchers: 1151 | - ./bike-shop.sh 1152 | - id: '1585' 1153 | steps: 1154 | - id: '1585.1' 1155 | setup: 1156 | watchers: 1157 | - ../.bash_history 1158 | - id: '1590' 1159 | steps: 1160 | - id: '1590.1' 1161 | setup: 1162 | watchers: 1163 | - ./bike-shop.sh 1164 | - id: '1600' 1165 | steps: 1166 | - id: '1600.1' 1167 | setup: 1168 | watchers: 1169 | - ./bike-shop.sh 1170 | - id: '1602' 1171 | steps: 1172 | - id: '1602.1' 1173 | setup: 1174 | watchers: 1175 | - ./bike-shop.sh 1176 | - id: '1605' 1177 | steps: 1178 | - id: '1605.1' 1179 | setup: 1180 | watchers: 1181 | - ./bike-shop.sh 1182 | - id: '1607' 1183 | steps: 1184 | - id: '1607.1' 1185 | setup: 1186 | watchers: 1187 | - ./bike-shop.sh 1188 | - id: '1610' 1189 | steps: 1190 | - id: '1610.1' 1191 | setup: 1192 | watchers: 1193 | - ../queryResults.log 1194 | - id: '1620' 1195 | steps: 1196 | - id: '1620.1' 1197 | setup: 1198 | watchers: 1199 | - ../queryResults.log 1200 | - id: '1625' 1201 | steps: 1202 | - id: '1625.1' 1203 | setup: 1204 | watchers: 1205 | - ../queryResults.log 1206 | - id: '1630' 1207 | steps: 1208 | - id: '1630.1' 1209 | setup: 1210 | watchers: 1211 | - ./bike-shop.sh 1212 | - id: '1640' 1213 | steps: 1214 | - id: '1640.1' 1215 | setup: 1216 | watchers: 1217 | - ./bike-shop.sh 1218 | - id: '1645' 1219 | steps: 1220 | - id: '1645.1' 1221 | setup: 1222 | watchers: 1223 | - ./bike-shop.sh 1224 | - id: '1648' 1225 | steps: 1226 | - id: '1648.1' 1227 | setup: 1228 | watchers: 1229 | - ./bike-shop.sh 1230 | - id: '1650' 1231 | steps: 1232 | - id: '1650.1' 1233 | setup: 1234 | watchers: 1235 | - ../.bash_history 1236 | - id: '1660' 1237 | steps: 1238 | - id: '1660.1' 1239 | setup: 1240 | watchers: 1241 | - ./bike-shop.sh 1242 | - id: '1680' 1243 | steps: 1244 | - id: '1680.1' 1245 | setup: 1246 | watchers: 1247 | - ./bike-shop.sh 1248 | - id: '1690' 1249 | steps: 1250 | - id: '1690.1' 1251 | setup: 1252 | watchers: 1253 | - ./bike-shop.sh 1254 | - id: '1710' 1255 | steps: 1256 | - id: '1710.1' 1257 | setup: 1258 | watchers: 1259 | - ./bike-shop.sh 1260 | - id: '1730' 1261 | steps: 1262 | - id: '1730.1' 1263 | setup: 1264 | watchers: 1265 | - ./bike-shop.sh 1266 | - id: '1740' 1267 | steps: 1268 | - id: '1740.1' 1269 | setup: 1270 | watchers: 1271 | - ../.bash_history 1272 | - id: '1750' 1273 | steps: 1274 | - id: '1750.1' 1275 | setup: 1276 | watchers: 1277 | - ../queryResults.log 1278 | - id: '1760' 1279 | steps: 1280 | - id: '1760.1' 1281 | setup: 1282 | watchers: 1283 | - ../queryResults.log 1284 | - id: '1770' 1285 | steps: 1286 | - id: '1770.1' 1287 | setup: 1288 | watchers: 1289 | - ../.bash_history 1290 | --------------------------------------------------------------------------------