diff --git a/docs/g5k/getting-started-g5k.md b/docs/g5k/getting-started-g5k.md index 97372ba6..8f7e70b6 100644 --- a/docs/g5k/getting-started-g5k.md +++ b/docs/g5k/getting-started-g5k.md @@ -1,3 +1,5 @@ +[:fontawesome-solid-download: Presentation slides [pdf]](slides.pdf){: .md-button .md-button--link } + # Introduction Grid'5000 is a large-scale and flexible testbed for experiment-driven research in all areas of computer science, with a focus on parallel and distributed computing, cloud, HPC, Big Data and AI. @@ -738,7 +740,7 @@ While specifying a command of their own with their reservation, users can execut Here is a small bash script that will deploy an environment and run a stress command: ```bash -#! /bin/bash +#!/bin/bash # bash strict mode configuration set -euo pipefail diff --git a/docs/g5k/slides.pdf b/docs/g5k/slides.pdf new file mode 100644 index 00000000..13ccd631 Binary files /dev/null and b/docs/g5k/slides.pdf differ diff --git a/docs/g5k/slides/main.typ b/docs/g5k/slides/main.typ new file mode 100644 index 00000000..d8b64803 --- /dev/null +++ b/docs/g5k/slides/main.typ @@ -0,0 +1,469 @@ +#import "template.typ": * + +#let unilu-colormap = ( +rgb("#e9edee"), +rgb("#e9edee"), +rgb("#4D4E4F"), +rgb("#AB3502"), +rgb("#E69426"), +rgb("#9CD7F3"), +) + + +#set text(lang: "en") +#show: sns-polylux-template.with( + aspect-ratio : "16-9", + title : [Getting Started on Grid’5000], + subtitle : [Practical Tutorial Session], + event : [University of Luxembourg\ 08/09/2025], + short-title : [], + short-event : [], + logo-1 : image("pics/UNI-Logo-en-rgb.png"), + logo-2 : image("pics/UNI-Logo-en-rgb.png"), + side_image : "pics/logo.png", + colormap : unilu-colormap, + authors : ( + ) +) +#set page(footer: none) + +#title-slide() + +#toc-slide( title: [Table of Contents] ) + +#slide(title: [Grid'5000 Getting Started Tutorial])[ + Follow along with the tutorial at: + + #link("https://hpc-docs.uni.lu/g5k/getting-started-g5k/")[https://hpc-docs.uni.lu/g5k/getting-started-g5k/] + + #v(1em) + _A hands-on guide to using Grid'5000 for research_ +] + +#new-section-slide([Introduction]) + +#slide(title: [What is Grid'5000?])[ + Grid'5000 is a large-scale testbed for experiment-driven research in computer science + + *Key Features:* + - 11 sites in France, Belgium and Luxembourg + - \~25,000 cores, 800 compute nodes, 550+ GPUs + - Highly configurable and controllable hardware (bare-metal) + - Advanced monitoring and measurement features + - Reproducible research support + + *Focus Areas:* Parallel/distributed computing, cloud, HPC, Big Data, AI +] + +#slide(title: [Before we start])[ + Make sure you have: + - A Grid'5000 account + - A Standard SSH client (OpenSSH on Mac OS, Linux or WSL) + - Your SSH key configured + + #block( + fill: yellow.lighten(80%), + stroke: orange + 1pt, + inset: 10pt, + radius: 4pt, + width: 100% + )[ + ⚠️ Request your account here (select the group *luxembourg-misc*) + + *#link("https://www.grid5000.fr/w/Special:G5KRequestAccountUMS")* + ] + +] + +#slide(title: [Key Concepts])[ + + *Hierarchical Resource Organization:* + + #align(center)[ + #table( + columns: (1fr, 2fr), + [*Resource*], [*Description*], + [*Cluster*], [Named group of homogeneous nodes], + [*Node*], [Bare-metal server/machine], + [*Core*], [Smallest reservable unit (CPU core)] + ) + ] + + *Examples:* + - Cluster: `larochette`, `clervaux`, `petitprince` + - Node: `larochette-1`, `clervaux-11` + - Luxembourg clusters: `clervaux` (48 nodes), `larochette` (7 nodes), `vianden` (1 node), `petitprince` (11 nodes) +] + +#slide(title: [Important resources])[ + + *Grid'5000 Wiki:* *#link("https://www.grid5000.fr")* + - Hardware specs: *#link("https://www.grid5000.fr/w/Hardware")* + - Status and monitoring: *#link("https://www.grid5000.fr/w/Status")* + + *Resource Availability:* + - Check Drawgantt charts for real-time availability + - Plan reservations during off-peak hours + - Monitor maintenance schedules +] + + +#new-section-slide([First connection]) + +#slide(title: [SSH keys setup])[ + *Before first login, generate your SSH keys:* + + ```bash + user@pc: ssh-keygen -t ed25519 + user@pc: cat .ssh/id_ed25519.pub + # Copy the output + ``` + + *Add your public key to Grid'5000:* + 1. Visit: https://api.grid5000.fr/stable/users/ + 2. Paste public key in "SSH Keys" tab + 3. Save changes + + ⚠️ *Required before any Grid'5000 access* +] + +#slide(title: [First connection])[ + #place(right, dy: 20pt, image("pics/Grid5000_SSH_access.png", width: 50%)) + + *Manual connection:* + ```bash + user@pc:~$ ssh access.grid5000.fr + user@access-north:~$ ssh luxembourg + user@fluxembourg:~$ + ``` + + *You should see the welcome message.* +] + +#slide(title: [SSH config (recommended)])[ + + *Edit `~/.ssh/config` on your local machine:* + + #set par(leading: 0.1em) + ```bash + Host g5k + User + Hostname access.grid5000.fr + ForwardAgent no + + Host *.g5k + User + ProxyCommand ssh g5k -W "$(basename %h .g5k):%p" + ForwardAgent no + ``` + + *Now you can connect directly:* + ```bash + user@pc:~$ ssh luxembourg.g5k + ``` +] + +#new-section-slide([First resource reservation]) + +#slide(title: [Reserving resources])[ + + *Basic reservation with OAR:* + ```bash + [user@fluxembourg|~]$ oarsub -r now -q testing + # Filtering out exotic resources (vianden). + # Set walltime to default (3600 s). + OAR_JOB_ID=256908 + # Advance reservation request: waiting for validation... + # Reservation valid --> OK + ``` + + *Check reservation status:* + ```bash + [user@fluxembourg|~]$ oarstat -u + ``` + + *Job States:* W (waiting), L (launching), R (running), E (error), F (finished) +] + +#slide(title: [Connecting to the reservation])[ + + *Get detailed job information:* + ```bash + user@fluxembourg:~$ oarstat -f -j + ``` + + *Connect to allocated node:* + ```bash + # Method 1: Direct SSH + [user@fluxembourg|~]$ ssh clervaux-11 + + # Method 2: OAR shortcut (single reservation only) + [user@fluxembourg|~]$ oarsub -C + ``` + + *Verify you're on the compute node* - prompt should change! +] + + +#slide(title: [Working on the node])[ + + *Storage locations:* + - `~/` - Home directory (25GB, NFS-mounted, persistent) + - `/tmp/` - Local disk (fast I/O, non-persistent) + - Storage groups - Large shared volumes + + *Best practice:* Work in `/tmp/` for performance, copy results to `~/` + + *Example workflow:* + ```bash + user@clervaux-11:~$ cd /tmp/ + # Download, compile, run experiments + # Copy important results back to ~/ + ``` +] + +#slide(title: [Practical example])[ + + *Download and run NAS Parallel Benchmarks:* + ```bash + user@clervaux-11:~$ cd /tmp/ + user@clervaux-11:~$ wget 'https://www.nas.nasa.gov/assets/npb/NPB3.4.3.tar.gz' + user@clervaux-11:~$ tar -xzvf NPB3.4.3.tar.gz + user@clervaux-11:~$ cd NPB3.4.3/NPB3.4-OMP + user@clervaux-11:/tmp/NPB3.4.3/NPB3.4-OMP$ cp config/suite.def.template config/suite.def + user@clervaux-11:/tmp/NPB3.4.3/NPB3.4-OMP$ cp config/make.def.template config/make.def + user@clervaux-11:/tmp/NPB3.4.3/NPB3.4-OMP$ make -j$(nproc) suite + ``` +] +#slide(title: [Practical Example])[ + + *Run benchmarks and save results:* + ```bash + user@clervaux-11:/tmp/NPB3.4.3/NPB3.4-OMP$ mkdir /tmp/benchs + user@clervaux-11:/tmp/NPB3.4.3/NPB3.4-OMP$ for bench in $(ls bin); do ./bin/$bench | tee /tmp/benchs/$bench.txt; done + user@clervaux-11:/tmp/NPB3.4.3/NPB3.4-OMP$ cp -R /tmp/benchs ~/benchs-$OAR_JOBID + ``` +] + +#slide(title: [Root Access with sudo-g5k])[ + + *Gain administrator privileges:* + ```bash + user@clervaux-11:~$ sudo-g5k + user@clervaux-11:~$ sudo -iu root + root@clervaux-11:~# + ``` + + *Now you can:* + - Install system packages: `apt update && apt install ...` + - Modify system configuration + - Install drivers, kernels, file systems, etc. + + ⚠️ *Warning:* Using `sudo-g5k` triggers full node redeployment after job ends +] + +#new-section-slide([Advanced resource management]) + +#slide(title: [Advanced resource selection])[ + + *Reserve specific cluster:* + ```bash + user@fluxembourg:~$ oarsub -r now -p clervaux + ``` + + *Reserve by hardware properties:* + ```bash + user@fluxembourg:~$ oarsub -r now -p "core_count > 8" + user@fluxembourg:~$ oarsub -r now -p "cputype LIKE 'Intel Xeon%'" + ``` + + *Reserve exotic resources:* + ```bash + user@fluxembourg:~$ oarsub -r now -p vianden -t exotic + ``` + + *Reserve multiple nodes for longer time:* + ```bash + user@fluxembourg:~$ oarsub -r now -l nodes=2,walltime=4:00 + ``` +] + +#slide(title: [Advanced reservations])[ + + *Schedule future reservations:* + ```bash + user@fluxembourg:~$ oarsub -r "2025-06-10 10:00, 2025-06-10 12:00" + ``` + + *Extend running reservation:* + ```bash + user@fluxembourg:~$ oarwalltime +1:00 + ``` + + *Always clean up when done:* + ```bash + user@clervaux-11:~$ logout + [user@fluxembourg|~]$ oardel + ``` + + 💡 *Good practice:* Delete unused reservations to free resources for others +] + +#new-section-slide([System deployment]) + +#slide(title: [System deployment])[ +// TODO: Add a note concerning kaenv3 + *Reserve node for deployment:* + ```bash + user@fluxembourg:~$ oarsub -r now -t deploy -q testing + ``` + + *Deploy custom environment:* + ```bash + user@fluxembourg:~$ kadeploy3 -e debian12-min -m clervaux-3.luxembourg.grid5000.fr + # or with job ID: + user@fluxembourg:~$ oarsub -C + user@fluxembourg:~$ kadeploy3 -e debian12-min + ``` +] +#slide(title: [System deployment])[ + + *Available environments:* + - `debian11-min`, `debian12-min` - Minimal Debian + - `debian11-nfs`, `debian12-nfs` - With NFS home mounting + - `ubuntu2404-min`, `ubuntu2404-nfs` - Ubuntu variants + + *List all environments:* + ```bash + user@fluxembourg:~$ kaenv3 + ``` +] + +#slide(title: [Serial console access])[ + + *Access node console (useful for debugging):* + ```bash + user@fluxembourg:~$ kaconsole3 -m clervaux-3 + ``` + + *Reboot deployed node:* + ```bash + user@fluxembourg:~$ kareboot3 simple -m clervaux-3 + ``` + + *Exit console:* Type `&.` or press `ESC` 4 times + + *Use case:* Recover from network misconfigurations, debug boot issues +] + +#new-section-slide([Experiment automation]) + +#slide(title: [Commands])[ + + *Submit command with reservation:* + ```bash + user@fluxembourg:~$ oarsub -r now "lscpu > lscpu.txt" + ``` + + *Script-based experiments:* + ```bash + user@fluxembourg:~$ chmod +x experiment.sh + user@fluxembourg:~$ oarsub -t deploy -r now "./experiment.sh" -q testing + ``` + + *Monitor job output:* + ```bash + user@fluxembourg:~$ multitail -i OAR..stdout -i OAR..stderr + ``` + + #set par(leading: 0.2em) + *Day vs Night usage:* + - Day: Interactive work, shorter reservations + - Night/Weekends: Automated, longer experiments +] + +#slide(title: [REST API Usage])[ + + *Programmatic resource discovery:* + - Sites: *#link("https://api.grid5000.fr/stable/sites/")* + - Luxembourg clusters: *#link("https://api.grid5000.fr/stable/sites/luxembourg/clusters/")* + - Node details: *#link("https://api.grid5000.fr/stable/sites/luxembourg/clusters/vianden/nodes/vianden-1")* + +] + +#slide(title: [REST API Usage])[ + *Automated job submission:* + #set par(leading: 0.2em) + ```python + import requests + + payload = { + 'resources': 'nodes=1', + 'types': ['deploy'], + 'command': './experiment.sh', + 'properties': f"cluster='{cluster}'" + } + job = requests.post(api_job_url, data=payload).json() + ``` +] + +#new-section-slide([Summary and Wrap-up]) + +#slide(title: [Summary: Key Commands])[ + + #table( + columns: (1fr, 2fr), + [*Command*], [*Purpose*], + [`oarsub -r now`], [Reserve resource immediately], + [`oarstat -u`], [Check your reservations], + [`oarsub -C`], [Connect to reserved node], + [`oardel `], [Delete reservation], + [`sudo-g5k`], [Gain root access], + [`kadeploy3 -e `], [Deploy OS environment], + [`kaconsole3 -m `], [Access serial console], + [`oarwalltime +1:00`], [Extend reservation] + ) +] + +#slide(title: [Best Practices])[ + + *Resource Management:* + - Always delete unused reservations + - Use `/tmp/` for intensive I/O operations + - Copy important results to home directory + - Plan reservations during off-peak hours + + *Experimentation:* + - Test interactively first, then automate + - Use version control for experiment scripts + - Document your environment and dependencies + - Monitor resource usage and platform status + + *Troubleshooting:* + - Check Grid'5000 status page for issues + - Use `kaconsole3` for network problems + - Monitor job output files for errors +] + +#slide(title: [Next Steps & Resources])[ + + *Advanced Topics:* + - Network reconfiguration (KaVLAN) + // - Energy monitoring + - Multi-site experiments + - Custom environment creation + + *Key Documentation:* + - Tutorial: *#link("https://hpc-docs.uni.lu/g5k/getting-started-g5k/")* + - Main wiki: *#link("https://www.grid5000.fr/w/Home")* + // - API documentation: https://www.grid5000.fr/w/API + // - Experiment scripting: https://www.grid5000.fr/w/Experiment_scripting_tutorial + + *Support:* + - Support page: *#link("https://www.grid5000.fr/w/Support")* + - User mailing list and forums +] + +#empty-slide()[ + *Questions?* +] diff --git a/docs/g5k/slides/pics/Grid5000_SSH_access.png b/docs/g5k/slides/pics/Grid5000_SSH_access.png new file mode 100644 index 00000000..015e5f4a Binary files /dev/null and b/docs/g5k/slides/pics/Grid5000_SSH_access.png differ diff --git a/docs/g5k/slides/pics/UNI-Logo-en-rgb.png b/docs/g5k/slides/pics/UNI-Logo-en-rgb.png new file mode 100644 index 00000000..b8ee5fa0 Binary files /dev/null and b/docs/g5k/slides/pics/UNI-Logo-en-rgb.png differ diff --git a/docs/g5k/slides/pics/logo.png b/docs/g5k/slides/pics/logo.png new file mode 100644 index 00000000..ecec73e8 Binary files /dev/null and b/docs/g5k/slides/pics/logo.png differ diff --git a/docs/g5k/slides/template.typ b/docs/g5k/slides/template.typ new file mode 100644 index 00000000..0c5d5cd4 --- /dev/null +++ b/docs/g5k/slides/template.typ @@ -0,0 +1,580 @@ +/*************************************************************** +* A polylux theme by martino barbieri (https://mbarbieri.it) * + ***************************************************************/ + + #import "@preview/polylux:0.4.0" as pl: * + +/* PER TEMPLATE SNS */ +// Background and decorations +#let sns-polylux-template_sns-colormap = ( + rgb("#00728D"), +rgb("#183F56"), +rgb("#4D4E4F"), +rgb("#AB3502"), +rgb("#E69426"), +rgb("#9CD7F3"), +) + +/* PER TEMPLATE UNIPI */ +#let sns-polylux-template_unipi-colormap = ( + cmyk(100%,57%,0%,9%), +cmyk(100%,57%,0%,38%), +rgb("#444444"), +rgb("#AB3502"), +rgb("#E69426"), +cmyk(25%,7%,0%,0%), +) + +#let sns-polylux-template_colormap = state("colormap", none) + +// Text and Fonts +#let sns-polylux-template_text-font = state("txt-font", none) +#let sns-polylux-template_title-font = state("title-font", none) +#let sns-polylux-template_background-color = state("bkg_color1", none) +#let sns-polylux-template_main-text-color = state("txt_color1", none) +#let sns-polylux-template_second-text-color = state("txt_color2", none) +#let sns-polylux-template_title-text-color = state("title_color", none)//#000000 +#let sns-polylux-template_size = state("size", none) + +// Data +#let sns-polylux-template_title = state("title", none) +#let sns-polylux-template_short-title = state("short-title", none) +#let sns-polylux-template_subtitle = state("subtitle", none) +#let sns-polylux-template_event = state("event", none) +#let sns-polylux-template_short-event = state("short-event", none) +#let sns-polylux-template_authors = state("authors", none) + +#let sns-polylux-template_logo-1 = state("logo-1", none) +#let sns-polylux-template_logo-2 = state("logo-2", none) +#let sns-polylux-template_side_image = state("side_image", none) + +// Init +#let sns-polylux-template( + // General parameters + aspect-ratio : "16-9", + + txt-font : ("Roboto", "Fira Sans", "DejaVu Sans"), + // title-font : ("PT Sans", "DejaVu Sans"), + title-font : ("Raleway", "PT Sans", "DejaVu Sans"), + txt-color1 : black, + txt-color2 : rgb("#222222"), + title-color : rgb("#444444"), + size : 20pt, + bkgnd-color : white, + + colormap : sns-polylux-template_sns-colormap, + + // Data + title : none, + subtitle : none, + short-title : none, + event : none, + short-event : none, + logo-2 : none, + logo-1 : none, + side_image : none, + authors : none, + // Stuff + body +) = { + sns-polylux-template_text-font.update(txt-font) + sns-polylux-template_title-font.update(title-font) + sns-polylux-template_background-color.update(bkgnd-color) + sns-polylux-template_main-text-color.update(txt-color1) + sns-polylux-template_second-text-color.update(txt-color2) + sns-polylux-template_title-text-color.update(title-color) + sns-polylux-template_size.update(size) + + sns-polylux-template_colormap.update(colormap) + + set page( + paper : "presentation-" + aspect-ratio, + fill : bkgnd-color, + margin : 0pt, + header : none, + footer : none, + header-ascent : 0pt, + footer-descent : 0pt, + ) + set text( + fill : txt-color1, + size : size, + font : txt-font, + ) + sns-polylux-template_title.update(title) + sns-polylux-template_subtitle.update(subtitle) + if short-title != none { sns-polylux-template_short-title.update(short-title) } + else { sns-polylux-template_short-title.update(title) } + sns-polylux-template_event.update(event) + if short-event != none { sns-polylux-template_short-event.update(short-event) } + else { sns-polylux-template_short-event.update(event) } + sns-polylux-template_logo-2.update(logo-2) + sns-polylux-template_logo-1.update(logo-1) + sns-polylux-template_side_image.update(side_image) + sns-polylux-template_authors.update(authors) + + body +} + +#let title-slide( + body : none, +logo : none, +side_image : none, +) = context( { + let content = align(top + center, context( { + let title = sns-polylux-template_title.at(here()) + let subtitle = sns-polylux-template_subtitle.at(here()) + let event = sns-polylux-template_event.at(here()) + let authors = sns-polylux-template_authors.at(here()) + let logo = { + if logo == none { sns-polylux-template_logo-1.at(here()) } + else { logo } + } + let side_image = { + if side_image == none { sns-polylux-template_side_image.at(here()) } + else { side_image } + } + + // Left column + grid( + columns: (25%, 75%), + + // Left column + + // Use box.inset to fix the blank border issue + box(image(side_image, width: 100%, height: 100%, fit: "cover"), clip: true, inset: -1pt), + + + // Right column - multiple place statements for title slide elements + block(width: 100%, height: 100%, { + + place( + bottom + right, + polygon( + fill : sns-polylux-template_colormap.at(here()).at(0), + stroke : none, + (0%, 0%),(0%, 30%),(100%, 30%),(100%, 0%), + ), + ) + place( + top + left, + polygon( + fill : sns-polylux-template_colormap.at(here()).at(0), + stroke : none, + (0%, 0%),(0%, 15%),(100%, 15%),(100%, 0%), + ), + ) + place( + bottom + center, + dy: -1cm, + text(fill: sns-polylux-template_main-text-color.at(here()), size: 22pt, event) + ) + if logo != none { + place( + bottom + right, + dx: -0.5cm, + dy: -0.3cm, + scale(page.height/measure(logo).height*22%, reflow: true, logo) + ) + } + // Contents + set align(center + horizon) + v(-25%) + text( + font : sns-polylux-template_title-font.at(here()), + size : 64pt, + fill: sns-polylux-template_title-text-color.at(here()), + weight: "bold", + title + ) + linebreak() + v(0em) + text( + font : sns-polylux-template_title-font.at(here()), + size : 22pt, + fill: sns-polylux-template_title-text-color.at(here()), + subtitle + ) + v(-0.9em) + // line(length: 90%, stroke: (paint: sns-polylux-template_colormap.at(here()).at(5), thickness: 4pt)) + v(0.5em) + set text( + size: 24pt, + top-edge: 0pt, + bottom-edge: 0pt, + fill: sns-polylux-template_main-text-color.at(here()) + ) + for i in range(authors.len()) { + move(dx: 2% * ( i - ( authors.len() - 1 ) / 2 ), authors.at(i)) + } + body + + } ) + + ) + + } +)) + + pl.slide({ content }) + + // counter("logical-slide").update( n => n - 1 ) + } ) + + +#let small-sections(show-sec-name: true) = context( { + set text(bottom-edge: "descender") + if show-sec-name {pl.toolbox.current-section;" "} + + pl.toolbox.all-sections( + (sections, current) => { + let over_current = false + for i in sections { + if current == i {$ast.circle$; over_current = true} + else if (over_current or current not in sections) { + $circle.dotted$ + } else {$circle.filled$} + } + } + ) +} ) + +#let big-sections = context( { + set align(horizon + right) + grid( + box(height: 40%, inset: 0.8cm)[#small-sections(show-sec-name: false)], + box(height: 60%, inset: 0.8cm)[ + #pl.toolbox.current-section + ]) +} ) + +#let slide( + title : none, + subtitle : none, + new-sec : false, + page-number : true, + hide-section : false, + body +) = context( { + // HEADER + let header = align(top, context( { + let logo = sns-polylux-template_logo-2.at(here()) + + // If new-sec is false, do nothing + // If new-sec is true, new section's name is the slide title + // Else the new-sec name is new-sec + if type(new-sec)==bool {if new-sec { + pl.toolbox.register-section(title) + }} + else {pl.toolbox.register-section(new-sec)} + + place( + top + left, + grid( + columns: (auto,auto), + gutter: 0pt, + // if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) }, + align(horizon+right, + if title != none { + grid(rect( + width: 100%, height: 40%, + inset: 0.8cm, outset: 0pt, + fill: sns-polylux-template_colormap.at(here()).at(0), + align(horizon,text(fill: sns-polylux-template_second-text-color.at(here()), { + if hide-section { + hide( + small-sections(show-sec-name: new-sec != true) + ) } + else { + small-sections(show-sec-name: new-sec != true) + } + } + )) + ), + rect( + width: 100%, height: 60%, + inset: 0.8cm, outset: 0pt, + fill: sns-polylux-template_colormap.at(here()).at(0), + align(horizon + center, + { + text( + fill: sns-polylux-template_second-text-color.at(here()), + font: sns-polylux-template_title-font.at(here()), + size: 32pt, + weight: "bold", + title + ) + if subtitle != none { + smallcaps(text( + fill: sns-polylux-template_second-text-color.at(here()), + font: sns-polylux-template_title-font.at(here()), + size: 24pt, + " — " + subtitle + )) + } + } + ) + ))} else { + rect( + width: 100%, height: 100%, + inset: 0cm, outset: 0pt, + fill: sns-polylux-template_colormap.at(here()).at(1), + align(horizon + right,text(fill: sns-polylux-template_second-text-color.at(here()), + if hide-section { + hide( big-sections ) + } else { + big-sections + } + ))) + } + ) + ) + ) + + place( + top + left, + box( + height: 2.3cm, + if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) } + ) + ) + } )) + + // FOOTER + let footer = align(top + center, context( { + let short-title = sns-polylux-template_short-title.at(here()) + let short-event = sns-polylux-template_short-event.at(here()) + + // place(top + center, line(length: 100%-2cm, stroke: (paint: sns-polylux-template_colormap.at(here()).at(1), thickness: 2pt))) + + set text(bottom-edge: "descender") + + block( + height: 100%, + width: 100%, + inset: (x: 0.8cm), + align(horizon,text(fill: sns-polylux-template_colormap.at(here()).at(2), size: 16pt, + grid( + gutter: 0.8cm, + columns: (0.7fr, 1fr, 0.7fr), + align(left, short-title), + align(center, smallcaps(short-event)), + align(right, if page-number [#toolbox.slide-number/#toolbox.last-slide-number]), + )) + )) + } )) + + set page( + margin: (top: 2.5cm, bottom: 1cm), + header: header, + footer: footer, + ) + + pl.slide({ + set align(horizon) + set text(size: sns-polylux-template_size.at(here()), top-edge: 20pt, bottom-edge: 0pt) + show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%) + body + }) + + if not page-number { counter("logical-slide").update( n => n - 1 ) } +} ) + +#let focus-slide( + new-sec : none, + page-number : true, + hide-section : false, + body +) = context( { + // HEADER + let header = align(top, context( { + let logo = sns-polylux-template_logo-1.at(here()) + set text(size: sns-polylux-template_size.at(here())) + + // If new-sec is none, do nothing + // Else the new-sec name is new-sec + if new-sec!=none {pl.toolbox.register-section(new-sec)} + + place( + top + left, + grid( + columns: (auto,auto), + gutter: 0pt, + if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) }, + align(top+right,grid( + box( + width: 100%, height: 100%, + inset: (top: 4pt, x: 0pt, bottom: 0pt), outset: 0pt, + align(horizon,text(fill: sns-polylux-template_second-text-color.at(here()), + if hide-section { + hide( + big-sections + ) } + else { + big-sections + } + )) + ), + ) + )) + ) + } )) + + set page( + margin: (top: 2.5cm, bottom: 0cm), + header: header, + footer: none, + fill: sns-polylux-template_colormap.at(here()).at(1), + ) + + pl.slide({ + set align(horizon + center) + set text( + size: sns-polylux-template_size.at(here())*1.5, + fill: sns-polylux-template_second-text-color.at(here()), + style: "italic" + ) + show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%) + body + }) + + // if not page-number { counter("logical-slide").update( n => n - 1 ) } +} ) + +#let empty-slide( + body +) = context( { + // HEADER + let header = align(top, context( { + let logo = sns-polylux-template_logo-1.at(here()) + + place( + top + left, + box( + height: 2.5cm, + if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) } + ) + ) + } )) + + set page( + margin: (top: 0cm, bottom: 0cm), + foreground: header, + footer: none, + fill: sns-polylux-template_colormap.at(here()).at(1), + ) + + pl.slide({ + set align(horizon + center) + set text( + size: sns-polylux-template_size.at(here())*1.5, + fill: sns-polylux-template_second-text-color.at(here()), + ) + show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%) + body + }) + + // counter("logical-slide").update( n => n - 1 ) +} ) + +#let new-section-slide(name) = context( { + // HEADER + let header = align(top, context( { + let logo = sns-polylux-template_logo-1.at(here()) + + place( + top + left, + box( + height: 2.5cm, + if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) } + ) + ) + } )) + + set page( + margin: (top: 0cm, bottom: 0cm), + foreground: header, + footer: none, + fill: sns-polylux-template_colormap.at(here()).at(1), + ) + + // TOC + let content = context( { + pl.toolbox.all-sections( (sections, current) => { + set text(weight: "regular") + let over_current = false + for i in sections { + if (current == i) {[ + + #text(weight: "black", i) + ]; over_current = true} + else if (over_current) [ + + #text(weight: "thin", i) + ] + else [ + + #text(i) + ] + } + } ) + } ) + + pl.slide({ + set align(horizon + center) + set text( + size: sns-polylux-template_size.at(here())*1.5, + fill: sns-polylux-template_second-text-color.at(here()), + ) + pl.toolbox.register-section(name) + + show: box.with() + set align(left) + content + }) + + // counter("logical-slide").update( n => n - 1 ) +} ) + +#let toc-slide(title: none) = context( { + // HEADER + let header = align(top, { + let logo = sns-polylux-template_logo-1.at(here()) + + place( + top + left, + box( + height: 2.5cm, + if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) } + ) + ) + } ) + + set page( + margin: (top: 0cm, bottom: 0cm), + foreground: header, + footer: none, + fill: sns-polylux-template_colormap.at(here()).at(1), + ) + + // TOC + let content = { + if title != none { align(center,text(weight: "bold", title)); v(-0.2em) } + pl.toolbox.all-sections( (sections, current) => { + for i in sections [ + + #text(i) + ] + } ) + } + + pl.slide({ + set align(horizon + center) + set text( + size: sns-polylux-template_size.at(here())*1.5, + fill: sns-polylux-template_second-text-color.at(here()), + ) + + show: box.with() + set align(left) + content + }) + + // counter("logical-slide").update( n => n - 1 ) +} ) diff --git a/docs/jobs/arrays.md b/docs/jobs/arrays.md new file mode 100644 index 00000000..2da44e7d --- /dev/null +++ b/docs/jobs/arrays.md @@ -0,0 +1 @@ +# Job Arrays \ No newline at end of file