From e3ece3363394f20e47980533a9e048b07ca31619 Mon Sep 17 00:00:00 2001 From: Kirill Voronin Date: Wed, 26 Aug 2026 03:19:38 +0300 Subject: [PATCH 01/24] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=B0=D0=BB=20=D0=BA=D1=83=D1=80=D1=81=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20Positron=20=D0=B8=20Quarto?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 01-01-about.Rmd | 61 +- 01-02-install.Rmd | 62 +- 01-03-shell.Rmd | 40 +- 02-01-init.Rmd | 75 +- 02-02-commit.Rmd | 55 +- 02-03-practice.Rmd | 148 +- 02-04-log-n-diff.Rmd | 44 +- 03-01-branches.Rmd | 76 +- 03-02-checkout.Rmd | 38 +- 03-03-merge.Rmd | 99 +- 03-04-conclusion.Rmd | 65 +- 04-01-github.Rmd | 40 +- 04-02-remote.Rmd | 53 +- 04-03-push-pull.Rmd | 77 +- 04-04-pull-request.Rmd | 60 +- 04-05-clone.Rmd | 41 +- 04-06-conclusion.Rmd | 23 +- 05-01-faq.Rmd | 60 +- 05-02-references.Rmd | 26 +- 05-03-webhooks.Rmd | 32 +- Makefile | 9 + README.md | 2 + _bookdown.yml | 22 + bin/check_course.py | 94 + bin/create_course_project.py | 477 +++ course-project/README.md | 9 + course-project/build_outputs.R | 19 + .../outputs/penguins-boxplot-by-sex.png | Bin 0 -> 15709 bytes .../outputs/penguins-boxplot-labelled.png | Bin 0 -> 12467 bytes course-project/outputs/penguins-boxplot.png | Bin 0 -> 11010 bytes course-project/outputs/penguins-hist.png | Bin 0 -> 16034 bytes course-project/starter-manifest.json | 66 + course-project/starter/.gitignore | 7 + course-project/starter/analysis.qmd | 47 + course-project/starter/base.R | 10 + course-project/starter/coffee.R | 4 + course-project/starter/data/data.rds | Bin 0 -> 5183 bytes course-project/starter/data/data_csv.csv | 101 + course-project/starter/data/data_csv2.csv | 101 + course-project/starter/data/data_excel.xlsx | Bin 0 -> 19971 bytes course-project/starter/data/data_rds.rds | Bin 0 -> 11661 bytes course-project/starter/data/data_tsv.tsv | 101 + course-project/starter/data/penguins.csv | 345 +++ course-project/starter/out/hist.png | Bin 0 -> 24180 bytes course-project/starter/penguins.R | 9 + course-project/starter/report.html | 2652 ++++++++++++++++ course-project/starter/report.qmd | 23 + course-project/starter/tables.qmd | 35 + docs/01-01-about.md | 49 +- docs/01-02-install.md | 62 +- docs/01-03-shell.md | 40 +- docs/02-01-init.md | 75 +- docs/02-02-commit.md | 53 +- docs/02-03-practice.md | 136 +- docs/02-04-log-n-diff.md | 39 +- docs/03-01-branches.md | 72 +- docs/03-02-checkout.md | 38 +- docs/03-03-merge.md | 93 +- docs/03-04-conclusion.md | 65 +- docs/04-01-github.md | 40 +- docs/04-02-remote.md | 48 +- docs/04-03-push-pull.md | 72 +- docs/04-04-pull-request.md | 59 +- docs/04-05-clone.md | 41 +- docs/04-06-conclusion.md | 23 +- docs/05-01-faq.md | 60 +- docs/05-02-references.md | 26 +- docs/05-03-webhooks.md | 32 +- docs/404.html | 144 +- docs/about-git.html | 142 + docs/about.html | 137 - docs/branch.html | 133 - docs/branches-conclusion.html | 134 + docs/branches.html | 134 + docs/clone-repository.html | 129 + docs/commit-workflow.html | 166 + docs/faq.html | 151 +- docs/first-commit.html | 152 + docs/git-branch.html | 144 - docs/git-checkout.html | 138 - docs/git-clone.html | 150 - docs/git-commit.html | 147 - docs/git-commit2.html | 215 -- docs/git-identity.html | 126 + docs/git-init.html | 180 -- docs/git-log.html | 143 - docs/git-merge.html | 178 -- docs/git-push-pull.html | 161 - docs/git-remote.html | 146 - docs/github-conclusion.html | 128 + docs/github-part.html | 134 + docs/github.html | 150 - docs/history-diff.html | 159 + docs/index.html | 112 +- docs/index.md | 58 +- docs/install-git.html | 147 + docs/install.html | 164 - docs/libs/bootstrap-4.6.0/bootstrap.min.css | 2 +- docs/libs/bs3compat-0.11.0/bs3compat.js | 48 + docs/libs/bs3compat-0.11.0/tabs.js | 157 + docs/libs/bs3compat-0.11.0/transition.js | 59 + docs/merge-conflict.html | 149 + docs/open-project.html | 140 + docs/pr.html | 147 - docs/publish-github.html | 132 + docs/pull-request.html | 167 + docs/reference-keys.txt | 87 +- docs/references.html | 123 +- docs/search.json | 2 +- docs/setup.html | 140 - docs/switch-branches.html | 137 + docs/sync-remote.html | 162 + docs/webhooks.html | 99 +- ...07\320\265\320\275\320\270\320\265-1.html" | 129 - ...\207\320\265\320\275\320\270\320\265.html" | 176 -- index.Rmd | 68 +- penguins.R | 5 - penguins.csv | 125 - renv.lock | 2714 +++++++++++++++-- tests/test_course_project.py | 163 + 121 files changed, 10479 insertions(+), 5286 deletions(-) create mode 100644 bin/check_course.py create mode 100644 bin/create_course_project.py create mode 100644 course-project/README.md create mode 100644 course-project/build_outputs.R create mode 100644 course-project/outputs/penguins-boxplot-by-sex.png create mode 100644 course-project/outputs/penguins-boxplot-labelled.png create mode 100644 course-project/outputs/penguins-boxplot.png create mode 100644 course-project/outputs/penguins-hist.png create mode 100644 course-project/starter-manifest.json create mode 100644 course-project/starter/.gitignore create mode 100644 course-project/starter/analysis.qmd create mode 100644 course-project/starter/base.R create mode 100644 course-project/starter/coffee.R create mode 100644 course-project/starter/data/data.rds create mode 100644 course-project/starter/data/data_csv.csv create mode 100644 course-project/starter/data/data_csv2.csv create mode 100644 course-project/starter/data/data_excel.xlsx create mode 100644 course-project/starter/data/data_rds.rds create mode 100644 course-project/starter/data/data_tsv.tsv create mode 100644 course-project/starter/data/penguins.csv create mode 100644 course-project/starter/out/hist.png create mode 100644 course-project/starter/penguins.R create mode 100644 course-project/starter/report.html create mode 100644 course-project/starter/report.qmd create mode 100644 course-project/starter/tables.qmd create mode 100644 docs/about-git.html delete mode 100644 docs/about.html delete mode 100644 docs/branch.html create mode 100644 docs/branches-conclusion.html create mode 100644 docs/branches.html create mode 100644 docs/clone-repository.html create mode 100644 docs/commit-workflow.html create mode 100644 docs/first-commit.html delete mode 100644 docs/git-branch.html delete mode 100644 docs/git-checkout.html delete mode 100644 docs/git-clone.html delete mode 100644 docs/git-commit.html delete mode 100644 docs/git-commit2.html create mode 100644 docs/git-identity.html delete mode 100644 docs/git-init.html delete mode 100644 docs/git-log.html delete mode 100644 docs/git-merge.html delete mode 100644 docs/git-push-pull.html delete mode 100644 docs/git-remote.html create mode 100644 docs/github-conclusion.html create mode 100644 docs/github-part.html delete mode 100644 docs/github.html create mode 100644 docs/history-diff.html create mode 100644 docs/install-git.html delete mode 100644 docs/install.html create mode 100644 docs/libs/bs3compat-0.11.0/bs3compat.js create mode 100644 docs/libs/bs3compat-0.11.0/tabs.js create mode 100644 docs/libs/bs3compat-0.11.0/transition.js create mode 100644 docs/merge-conflict.html create mode 100644 docs/open-project.html delete mode 100644 docs/pr.html create mode 100644 docs/publish-github.html create mode 100644 docs/pull-request.html delete mode 100644 docs/setup.html create mode 100644 docs/switch-branches.html create mode 100644 docs/sync-remote.html delete mode 100644 "docs/\320\267\320\260\320\272\320\273\321\216\321\207\320\265\320\275\320\270\320\265-1.html" delete mode 100644 "docs/\320\267\320\260\320\272\320\273\321\216\321\207\320\265\320\275\320\270\320\265.html" delete mode 100644 penguins.R delete mode 100644 penguins.csv create mode 100644 tests/test_course_project.py diff --git a/.gitignore b/.gitignore index 5b6a065..94a8c85 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .Rhistory .RData .Ruserdata +__pycache__/ diff --git a/01-01-about.Rmd b/01-01-about.Rmd index d76277f..f62ddb2 100644 --- a/01-01-about.Rmd +++ b/01-01-about.Rmd @@ -1,57 +1,28 @@ -# (PART) Введение {-} +# (PART) Подготовка {-} -# Что такое Git {#about} +# Зачем проекту Git {#about-git} -**Git** --- это программа, выполняющая функции **Системы Контроля Версий (VCS, Version Control System)**. -Многие применяют простую систему контроля версий, вручную копируя файлы и добавляя дату в названия. -Git автоматически отслеживает изменения во время редактирования файлов, позволяет фиксировать состояние файлов в версии, хранить и переключаться между ними. -Вы сможете оценить, какие изменения внесли, а также посмотреть историю изменений --- когда, кем и с какой целью они были сделаны. +В проекте анализа данных меняются код, текст отчёта и графики. Копии с названиями `final`, `final-2` и `really-final` сохраняют файлы, но не объясняют, кто и зачем их менял. -```{r, include=FALSE} -# Очевидно ли, зачем оценивать какие изменения внесли или нужно расписать, -# что работать надо над конкретной задачей, а не хаотично редактировать код. -``` +Git хранит **коммиты** — снимки выбранных изменений с коротким пояснением. Из них складывается история проекта. По ней можно: -::: {.text-center} -![](./img/notFinal.gif){width=400px style="border: 1px solid #ddd"} -::: +- сравнить текущую работу с предыдущей версией; +- вернуть исправный вариант; +- вести несколько вариантов анализа в ветках; +- объединять изменения разных участников. -Важная особенность Git в том, что участники могут работать и создавать версии независимо друг от друга на своих компьютерах. Каждый может работать над своей задачей, не мешая другим, даже если все редактируют один и тот же файл. Git поможет объединить изменения в одну общую версию. +Git работает локально. Для коммитов не нужны интернет и аккаунт. GitHub понадобится позже как удалённое место для общей истории и обсуждения изменений. -```{r, include=FALSE} -# Особенность звучит так себе, но ветки это реально основная фича Git. -# Должно быть согласовано с этим же тезисом в предыдущей главе. -``` +## Что уже есть в проекте -Проект Git можно загрузить на сервер для надежного хранения и передачи файлов, совместной работы и публикации. -Самым популярным сервисом для этого является GitHub. -Он похож на облачные хранилища, такие как Google Drive или Dropbox, но с более продвинутым отслеживанием и объединением изменений, а также другими полезными функциями. -Вместо GitHub можно использовать другой сервер, например корпоративный во внутренней сети организации или использовать Git оффлайн --- только на своем компьютере. +Откройте папку `r-course`, созданную в предыдущем курсе. Не создавайте новый учебный проект и не переносите файлы. -```{r, include=FALSE} -# Расписать "другими полезными функциями". -``` +В проекте могут оставаться `.R`-скрипты, `report.qmd`, `analysis.qmd`, другие документы, папки `data` и `out`. Это ожидаемое состояние. Git умеет отслеживать любые файлы; расширение не нужно менять ради Git. -Если это всё ещё не убедило вас начать использовать Git, вот несколько примеров, когда он будет полезен: +Новый код этого курса будем писать в `paper.qmd`. Так текст, команды R и результат останутся в одном воспроизводимом документе Quarto. -```{r, include=FALSE} -# Два раза "использовать Git". -``` +## Репозиторий +**Репозиторий** — папка проекта вместе со скрытой служебной папкой `.git`. В `.git` находится история, ветки и настройки связи с удалённым репозиторием. -- Возможно, вы оказывались в следующей ситуации. Вы вносите изменения в работающую программу или файл. Оцениваете результат и решаете отменить изменения. Вот только у вас нет копии оригинального файла, а вернуть прежнее состояние почему-то не получается --- программа никак не работает или работает иначе. С Git это делается одной командой, а экспериментальную версию можно сохранить и вернуться к ней позже. - -- Если вам понадобилась помощь, вы можете одной командой загрузить сделанные изменения на GitHub. Другой участник увидит, что вы пытаетесь сделать, и может загрузить решение проблемы, а вы так же одной командой получите исправленную версию. - -Благодаря последовательному внесению и отслеживанию изменений Git помогает организовать процесс анализа данных, обеспечивает воспроизводимость и упрощает совместную работу над проектом. - -```{r, include=FALSE} -# Как-будто из текста выше этого все еще не следует. -``` - -::: {.callout .callout-info} - -Существуют другие системы контроля версий, например Mercurial и Subversion и вероятно, в будущем появятся новые. -Но благодаря простоте, эффективности и приобретенной популярности в основном используется Git. - -::: +Шаблон R Project в Positron создаёт `.git` и `.gitignore` автоматически. Поэтому проект из R-курса уже должен быть репозиторием, хотя в нём пока нет коммитов. В главе \@ref(open-project) мы это проверим. diff --git a/01-02-install.Rmd b/01-02-install.Rmd index 9c4f972..6ca85eb 100644 --- a/01-02-install.Rmd +++ b/01-02-install.Rmd @@ -1,59 +1,27 @@ -# Установка {#install} +# Установка Git {#install-git} -## Проверьте наличие Git {#terminal} +Positron предоставляет интерфейс Source Control, но использует Git, установленный в операционной системе. Если Git не найден, Source Control покажет предложение его установить. Такое поведение описано в официальной главе [Git Version Control](https://positron.posit.co/git.html). -В комплекте с дистрибутивом Git устанавливается программа для терминала. -Чтобы её запустить, откройте Rstudio и в верхнем меню выберите **Tools → Terminal → New Terminal**. -В появившемся окне терминала введите команду `git` и нажмите клавишу Enter. +## Проверка -Если вы видите результат как на скриншоте ниже, то Git установлен. -Иначе нужно его установить --- см. инструкцию для вашей операционной системы ниже. -После установки перезапустите RStudio и повторите проверку. - -![](./img/git.png){width="100%"} - -## Windows - -Загрузите инсталлятор по ссылке [git-scm.com/downloads/win](https://git-scm.com/downloads/win) -(используйте **Standalone**, а не **Portable** версию, если в этом нет необходимости), запустите и следуйте инструкциям на экране, можете везде оставить опции, выбранные по умолчанию. - -## Mac OS - -**Вариант 1.** Git входит в инструменты разработчика от Apple, которые предоставляются бесплатно. Для установки введите в терминал следующую команду: +Откройте встроенный терминал командой **Terminal: Create New Terminal** из палитры команд и выполните: ```sh -xcode-select --install +git --version ``` -В появившемся окне нажмите кнопку **Install**. +Если команда вывела строку вида `git version 2.45.2`, установка готова. Конкретный номер может отличаться. -**Вариант 2.** Последнюю версию Git можно установить используя сторонний менеджер программ [Homebrew](https://brew.sh). Если он у вас установлен, введите в терминал следующую команду: +![Терминал Positron после проверки версии Git: видна строка с установленной версией]() -```sh -brew install git -``` - -## Linux +## Если Git не установлен -Используйте в терминале одну из следующих команд, в зависимости от вашего дистрибутива Linux. +- **Windows:** установите [Git for Windows](https://git-scm.com/download/win), оставив параметры установщика по умолчанию. +- **macOS:** установите [Xcode Command Line Tools](https://developer.apple.com/xcode/resources/) по предложению системы после команды `git --version` или установите Git с [официальной страницы](https://git-scm.com/download/mac). +- **Linux:** используйте менеджер пакетов своего дистрибутива; команды приведены в [официальной инструкции Git](https://git-scm.com/download/linux). -**Ubuntu или Debian** - -```sh -sudo apt-get update -sudo apt-get install git -``` - -**Fedora** - -```sh -sudo dnf install git -``` - -**Arch Linux** - -```sh -sudo pacman -S git -``` +После установки полностью перезапустите Positron и снова выполните `git --version`. -Для других дистрибутивов см. [git-scm.com/downloads/linux](https://git-scm.com/downloads/linux). Не забудьте, что команды нужно запускать с правами администратора, т.е. начав с `sudo`, как в примере выше. +::: {.callout .callout-warning} +Не скачивайте отдельные графические клиенты Git для прохождения курса. Они могут пригодиться позже, но названия действий и расположение элементов будут отличаться от Positron. +::: diff --git a/01-03-shell.Rmd b/01-03-shell.Rmd index 5bd75b6..8bc0e63 100644 --- a/01-03-shell.Rmd +++ b/01-03-shell.Rmd @@ -1,41 +1,21 @@ -# Настройка {#setup} +# Имя автора {#git-identity} -Основной способ работы с Git --- это команда `git`, которую мы выполнили в предыдущей главе. -Команды для терминала вы встретите в документации и в интернете, ими легко поделиться и использовать в скриптах. -Кроме терминала есть много других способов и их даже можно использовать одновременно. +Каждый коммит хранит имя и электронную почту автора. При первом коммите Positron может попросить их настроить. Укажите имя, по которому коллеги вас узнают, и почту, связанную с GitHub. -Графические интерфейсы --- все они имеют ограничения и реализуют только часть возможностей Git, но достаточны для решения большинства задач. Это может быть интерфейс, встроенный в другие программы (например [RStudio](https://docs.posit.co/ide/user/ide/guide/tools/version-control.html), [Pycharm](https://www.jetbrains.com/help/pycharm/using-git-integration.html), [VS Code](https://code.visualstudio.com/docs/sourcecontrol/overview)) или самостоятельная программа (например [GitHub Desktop](https://github.com/apps/desktop), [GitKraken](https://www.gitkraken.com) [и многие другие](https://git-scm.com/downloads/guis)); - -Веб-интерфейсы --- прямо на сайте GitHub можно редактировать отдельные файлы, а также выполнять некоторые команды. - -В этом курсе мы будем работать с Git одновременно в интерфейсе RStudio и в терминале, как это делает большинство пользователей R каждый день, а также через GitHub. -Поэтому запомните, как запустить терминал в RStudio --- -в верхнем меню выберите **Tools → Terminal → New Terminal** ([см. скриншот в предыдущей главе](#terminal)). - -Перед началом работы необходимо сделать несколько настроек. -Укажите свое имя и адрес электронной почты, чтобы Git верно записывал информацию об авторе изменений. -В терминале выполните следующие команды, заменив **Your Name** на свое имя и **your@email.com** на свой email, не стирая кавычки. - -```sh -git config --global user.name "Your Name" -git config --global user.email "your@email.com" -``` - -Если вы уже использовали Git, то чтобы вывести в терминале текущее значение настроек выполните эти же команды, но не указывая новых значений. +Если интерфейс показал ошибку `Please tell me who you are`, откройте терминал и выполните две команды, заменив значения своими: ```sh -git config --global user.name -git config --global user.email +git config --global user.name "Ivan Ivanov" +git config --global user.email "ivan@example.org" ``` -Также заранее настроим способ объединения изменений, чтобы не возвращаться к этому позже. +Проверьте результат: ```sh -git config --global pull.rebase false +git config --global --get user.name +git config --global --get user.email ``` -Опция `--global` означает, что эти настройки будут использованы для всех проектов на компьютере и их достаточно сделать один раз. -Чтобы изменить настройки для отдельного проекта, выполните в нем эти же команды без опции `--global`. Например, иногда требуется указать корпоративный email для рабочего проекта на персональном компьютере. +Настройка `--global` применяется ко всем будущим проектам этого пользователя. Если рабочий проект требует другую почту, откройте его папку и повторите команды без `--global`: значение сохранится только в этом репозитории. -Это все настройки, которые понадобятся для курса. -Всего через команду `git config` их доступно более 800. +Пароль GitHub здесь не нужен. Вход в GitHub выполним в браузере в части \@ref(github-part). diff --git a/02-01-init.Rmd b/02-01-init.Rmd index 436f077..108ea5b 100644 --- a/02-01-init.Rmd +++ b/02-01-init.Rmd @@ -1,72 +1,25 @@ -# (PART) Основы {-} +# (PART) Коммиты {-} -# Создание репозитория {#git-init} +# Открытие проекта {#open-project} -Git может отслеживать изменения в любой папке на вашем компьютере. -Для этого нужно инициализировать в ней Git репозиторий. -**Репозиторий** --- это скрытая подпапка `.git`, в которой хранятся версии проекта и информация об изменениях. -Всё необходимое для работы Git содержится непосредственно в ней. +На экране Welcome в Positron выберите **Open Folder** и откройте папку `r-course`. Убедитесь, что в Explorer видны накопленные файлы R-курса, в том числе папка `data`. -Самый простой способ создать репозиторий --- вместе с проектом RStudio. -В верхнем меню выберите [File → New Project]{.figtext}. -В появившемся окне выберите [New directory]{.figtext}, а затем [New Project]{.figtext}. -На последнем шаге в поле [Directory name]{.figtext} введите название папки для проекта: [penguins]{.figtext}. -Она будет создана на вашем компьютере по адресу, указанному в поле [Create project as subdirectory of]{.figtext}. -‼️ Не забудьте поставить галочку напротив опции [ Create a git repository]{.figtext}, иначе проект будет создан без Git репозитория. -После нажатия кнопки [Create Project]{.figtext} окно RStudio перезагрузится с открытым проектом. +Откройте **Source Control** на панели активности слева. У изменённых файлов стоят обозначения состояния: `U` у ещё не отслеживаемых и `M` у изменённых. - - - - - - - - - -
![](./img/02-01-01-new-project.png){width="320px"}![](./img/02-01-02-new-project.png){width="320px"}
![](./img/02-01-03-new-project.png){width="320px"}![](./img/02-01-04-new-project.png){width="320px"}
+![Окно Positron с открытым проектом r-course: в Explorer видны накопленные файлы, а в Source Control перечислены незафиксированные изменения]() -При следующем запуске RStudio откроет последний проект. -Если этого не произойдет, чтобы открыть проект в верхнем меню выберите [File → Open Project]{.figtext} или [File → Recent Projects]{.figtext}. +Если Source Control уже показывает файлы, репозиторий готов. Не нажимайте **Initialize Repository** повторно и не удаляйте `.git`. -Убедитесь в том, что проект загружен, для этого обратите внимание на следующие элементы интерфейса: -В правом верхнем углу указано название проекта [(A)]{.figref}. -На панели файлов (по умолчанию она в нижнем правом углу) открыта папка с файлами проекта [(B)]{.figref}. +## Если репозитория нет -![](./img/02-01-05-window.png){width="680px"} +В старой версии R-курса проект мог быть создан без Git. Тогда Source Control покажет кнопку **Initialize Repository**. Нажмите её один раз. Positron создаст `.git` и начнёт показывать изменения. -Когда в RStudio открыт проект, R и Git ищут файлы в папке проекта --- это так называемая **рабочая папка или рабочая область**. +Официальная документация Positron описывает те же шаги: открыть папку, перейти в Source Control и выбрать **Initialize Repository**. -
Подробнее про поиск и адреса файлов. -На разных компьютерах, например у разных участников, проект может находиться в разных местах. -У пользователя с именем `mjordan` это может быть `/Users/mjordan/penguins`, -а у пользователя `scruz` допустим -`C:\Users\scruz\penguins`. +## Что сейчас видит Git -Если в скрипте использовать полный адрес файла, например: +Все накопленные файлы ещё не входят ни в один коммит. Это не ошибка и не повод чистить проект. В следующей главе сделаем один исходный коммит, который станет точкой отсчёта для новой работы. -```r -read_csv("/Users/mjordan/penguins/data/sample.csv") -``` - -то он будет работать только у пользователя `mjordan`. -У других полный адрес будет отличаться, и код «сломается». -Чтобы он работал у всех, нужно указывать адрес файла относительно рабочей папки. - -```r -read_csv("data/sample.csv") -``` -
- -Рассмотрим созданные RStudio файлы: - -- `hello-git.Rproj` --- содержит настройки проекта -- `.gitignore` --- содержит список файлов, которые Git не будет отслеживать; о том, зачем это нужно и как настроить [смотри в отдельном разделе](#gitignore) -- `.git` --- репозиторий; это скрытая папка, чтобы ее увидеть, в меню на панели файлов выберите [More → Show Hidden Files]{.figtext} - -Если файл `.gitignore` отсутствует, значит, вы не отметили галочку [ Create a git repository]{.figtext} при создании проекта или не установили Git. -[Проверьте наличие Git](#install) и создайте проект заново. - -Итак, у нас есть проект RStudio --- папка, в которой мы будем работать, и -внутри нее Git репозиторий --- скрытая папка, в которой будут храниться версии проекта. -Приступим к созданию первой версии. +::: {.callout .callout-warning} +Не переводите старые `.R`-файлы в `.qmd`, не удаляйте дополнительные данные и не заменяйте результаты. Исходный коммит должен быть точной фиксацией конца R-курса. +::: diff --git a/02-02-commit.Rmd b/02-02-commit.Rmd index 44a2a77..ecef4c4 100644 --- a/02-02-commit.Rmd +++ b/02-02-commit.Rmd @@ -1,50 +1,35 @@ -# Отслеживание изменений {#git-commit} +# Первый коммит {#first-commit} -Git отслеживает изменения в файлах, находящихся в рабочей папке. -Но не все подряд, как это делают Блокнот или Word при помощи команд «Отменить» и «Повторить», -а при помощи версий --- или, в терминах Git, **коммитов (commit)**. -Коммиты нужно создавать вручную, выбирая, какие файлы вы хотите зафиксировать, добавив в версию. +Коммит состоит из снимка выбранных файлов, автора, времени и сообщения. Сначала файлы попадают в **индекс** (staging area), затем Git записывает из индекса коммит. -Откройте в RStudio панель с названием [Git]{.figtext} (по умолчанию она в верхнем правом углу). -В отличие от списка файлов, на ней выводятся только те файлы, которые были изменены по сравнению с последней версией (коммитом). -Так как мы еще не создали ни одной версии, то в списке выводятся оба файла, созданных с проектом: `.gitignore` и `penguins.Rproj` +## Проверка изменений +В Source Control выберите любой текстовый файл. Откроется редактор различий (diff). Для нового файла одна сторона сравнения пуста, а весь текст отмечен как добавленный. -![](./img/02-02-01-window.png){width=680px} +Бинарные файлы, например `.png`, `.xlsx` и `.rds`, Git сохранит, но не покажет построчное сравнение. Перед коммитом откройте их обычным способом и убедитесь, что это нужные файлы. -
Нет панели Git? -Значит, вы не отметили галочку [Create a git repository]{.figtext} при создании проекта или не установили Git. -[Проверьте наличие Git](#install) и [создайте проект заново](#git-init). -
+![Редактор различий Positron для нового текстового файла из проекта r-course и список Changes в Source Control]() -Чтобы создать коммит (версию), отметьте файлы галочкой в столбце [Staged]{.figtext}. -Галочка напротив файла означает, что он добавлен в **индекс (staging)** --- -промежуточную область для выбора файлов, которые будут зафиксированы. -Неотмеченные файлы останутся в рабочей папке, но в коммит не попадут. -Вы можете добавить их в следующую версию позже или отменить изменения. -Нажмите кнопку [Commit]{.figtext}. +## Добавление в индекс -![](./img/02-02-02-staging.png){width=400px} +Наведите указатель на заголовок **Changes** и нажмите `+` (**Stage All Changes**). Файлы переместятся в раздел **Staged Changes**. -В открывшемся окне можно подробнее посмотреть, что изменилось в файлах. -Просмотрите изменения и введите краткое описание в поле [Commit message]{.figtext}. -В нашем примере был создан проект, это и будет подходящим описанием. -Нажмите кнопку [Commit]{.figtext} под текстовым полем. +Проверьте список ещё раз. В первый коммит должны войти все накопленные файлы проекта, кроме уже скрытых правилами `.gitignore`. -![](./img/02-02-03-commit.png){width=600px} +## Запись коммита -В открывшемся окне не должно быть ошибок, но должно быть сообщение как на изображении ниже. +Введите сообщение: -![](./img/02-02-04-message.png){width=600px} +```text +Зафиксировал результат курса R +``` -Закройте окно с сообщением и окно создания коммита, вернитесь к RStudio. -Обратите внимание, теперь панель [Git]{.figtext} со списком измененных файлов пуста --- -это значит, что изменений по сравнению с последней версией, которую мы только что создали, нет. +Нажмите **Commit**. Если Positron попросит настроить автора, вернитесь к главе \@ref(git-identity). -![](./img/02-02-05-git-pane.png){width=400px} +![Source Control сразу после исходного коммита: разделы Changes и Staged Changes пусты, в Graph виден один коммит]() -Теперь у нас есть версия проекта, к которой можно вернуться в любой момент и начать работу с этого места. +Пустой список изменений означает, что рабочая папка совпадает с последним коммитом. Старые файлы никуда не переместились: Git только записал их состояние. -```{r, include=FALSE} -# Заменить название главы на «Создание коммита» -``` +::: {.callout .callout-info} +Сообщение коммита отвечает на вопрос «что сделал этот шаг?». Короткая форма с глаголом помогает читать историю: «Добавил импорт данных», «Исправил подпись оси». +::: diff --git a/02-03-practice.Rmd b/02-03-practice.Rmd index a30a426..8e34b76 100644 --- a/02-03-practice.Rmd +++ b/02-03-practice.Rmd @@ -1,137 +1,57 @@ -# Рабочий процесс {#git-commit2} +# Рабочий цикл {#commit-workflow} -В предыдущей главе мы научились создавать коммиты (версии). -Работая с Git, это нужно делать регулярно --- -обычно после выполнения задачи или её части, -после внесения исправлений или просто чтобы зафиксировать изменения. -Коммит сохраняет «стабильную» версию проекта, к которой можно вернуться или сравнить с ней сделанные изменения. +Теперь начнём отдельный анализ для Git-курса. Каждая небольшая законченная задача станет коммитом: -Рассмотрим процесс работы над проектом подробнее: +1. изменить и сохранить файл; +2. открыть diff и проверить изменение; +3. добавить нужные файлы в индекс; +4. записать коммит; +5. убедиться, что Source Control снова пуст. -1. Мы создали коммит, и с тех пор в рабочей папке не было изменений. -2. Выполняем задачу и добавляем нужные для ее решения изменения в индекс, а лишние, например код для отладки или временные файлы, удаляем. -3. Перед созданием коммита обязательно проверяем изменения, которые в него попадут. - Начинающие пользователи часто либо добавляют ненужный код, не относящийся к задаче, либо забывают добавить код, без которого не будет работать остальная часть проекта. -4. Создаём коммит и получаем чистую рабочую папку --- без изменений относительно нового коммита. - Можно переходить к следующей задаче. +## Документ Quarto -![](./img/02-02-06-workflow.png){width=540px} +Создайте в корне проекта файл `paper.qmd`. Накопленные `.R`-скрипты остаются без изменений, но весь новый код пишем в Quarto. -Такой процесс помогает упорядочить внесение изменений и сделать результат воспроизводимым. -Он хорошо подходит для анализа данных, потому что его легко разделить на задачи, из которых получатся коммиты. -Попробуем сделать это на практике и проанализируем длину клюва антарктических пингвинов. -Каждая подглава этой главы соответствует одной задаче и завершается одним коммитом. +Добавьте настройки и первый блок R: -## Импорт данных - -Загрузите файл с данными [penguins.csv](https://github.com/yoursdearboy/git-101/releases/download/penguins/penguins.csv) в папку проекта. -Если нужно открыть папку в файловом менеджере операционной системы, в меню на панели [Files]{.figtext} выберите [More → Show Folder in New Window]{.figtext}. -Вернитесь в RStudio и убедитесь, что файл `penguins.csv` появился на панели [Git]{.figtext}. - -![](./img/02-03-01-show-folder.png){width=400px} - -Создайте скрипт для анализа. В меню на панели [Files]{.figtext} выберите [New File → R Script]{.figtext} и введите название файла `penguins.R` - -![](./img/02-03-02-new-file.png){width=400px} - -Скопируйте следующий код для импорта данных и сохраните его в созданном файле. -Выделите обе строки и запустите, нажав кнопку [Run]{.figtext} в правом верхнем углу редактора RStudio. -Если импорт данных работает, в консоли появится вектор из чисел. - -```r -data <- read.csv("penguins.csv") -data$bill_length_mm +```yaml +--- +title: "Длина клюва пингвинов" +format: html +--- ``` -Убедитесь, что файл скрипта также появился на панели [Git]{.figtext}. -Добавьте оба файла в индекс, отметив галочкой в столбце [Staged]{.figtext}, и создайте коммит. -В окне коммита обязательно проверьте содержимое скрипта `penguins.R`, -так как часто пользователи забывают сохранить файл перед добавлением в индекс. - -![](./img/02-03-03-git-pane.png){width=690px} - -После создания коммита список измененных файлов на панели [Git]{.figtext} должен быть пуст. - -## Визуализация - -Анализ новых данных полезно начинать с исследования распределения. -Для этого присвоим данные с длиной клюва переменной `x` и построим несколько вариантов гистограммы с разной шириной столбца. -Сохраните приведённый ниже код в тот же файл, запустите и посмотрите графики. - -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm - -hist(x, breaks = seq(40, 60, 4)) -hist(x, breaks = seq(40, 60, 2)) -hist(x, breaks = seq(40, 60, 1)) +```{r, eval=FALSE} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() +x ``` -После сохранения файл `penguins.R` снова появился в списке изменений на панели [Git]{.figtext}. -Добавьте его в индекс и проверьте изменения в окне коммита. +Путь начинается от корня проекта. Данные уже находятся в `data`, поэтому ничего скачивать и перекладывать не нужно. В новом коде используем базовую трубу `|>`. -Вы уже могли заметить, что новые строки выделяются зеленым цветом. -Красным цветом выделяются удаленные строки, а неизмененные остаются белыми. -Такой формат записи изменений называется **«дифф» (diff)**. -Обратите внимание, что по умолчанию Git анализирует строки, а не отдельные слова или символы. -Поэтому получился следующий дифф: старая вторая строка была удалена, новая вторая строка добавлена (см. номера строк слева), хотя мы всего лишь добавили присвоение `x <- ` в начало строки. +Выполните блок в текущей R-сессии. Positron передаст код из документа Quarto в Console. Убедитесь, что вектор `x` создан без ошибки. -![](./img/02-03-04-git-pane.png){width=690px} +![Открытый paper.qmd после выполнения блока: в Console виден результат импорта data/penguins.csv]() -Убедитесь, что сделанные изменения соответствуют диффу на скриншоте выше, и создайте новый коммит с описанием «Добавили гистограммы для длины клюва». +Сохраните файл, проверьте diff и создайте коммит `Добавил импорт данных в paper.qmd`. -## Экспорт +## Гистограмма -Гистограмма с шириной столбца 2 выглядит наиболее информативно. -Такой график можно и опубликовать. -Чтобы экспортировать изображение, сохраните следующий код в файл скрипта и запустите его. +Замените блок кода на следующий: -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm +```{r, eval=FALSE} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -png("penguins-hist.png") -hist(x, breaks = seq(40, 60, 2)) +png("out/penguins-hist.png") +hist(x, breaks = seq(30, 60, 2)) dev.off() ``` -После этого в списке изменений на панели [Git]{.figtext}, кроме файла `penguins.R`, появился файл с изображением `penguins-hist.png`. -Его мы тоже добавим в коммит. -Во-первых, так другие участники, загрузив проект, сразу увидят результат без необходимости запускать скрипт. -Во-вторых, если вы измените ширину столбца или другие настройки графика, будет удобно сравнить старую и новую версии. +Выполните блок. В папке `out` появится `penguins-hist.png`. -Добавьте оба файла в индекс, проверьте изменения, изучив дифф, и создайте коммит с описанием «Сохранили гистограмму длины клюва». +В Source Control выберите `paper.qmd` и проверьте добавленные строки. Затем добавьте в индекс `paper.qmd` и `out/penguins-hist.png`, но не остальные случайные изменения. Создайте коммит `Сохранил гистограмму длины клюва`. -На этом остановимся и посмотрим историю версий в журнале Git. +![Source Control перед коммитом гистограммы: в Staged Changes находятся только paper.qmd и out/penguins-hist.png]() -::: {.callout .callout-info} -Делайте коммиты часто и не придавайте слишком большое значение планированию. -Коммит это не концептуально новая версия проекта, а просто шаг или изменения, которые вы хотите зафиксировать. - -```{r, include=FALSE} -# При необходимости можно объединить несколько коммитов в один -# ([см. в разделе с решением частых задач](#faq)). -``` -::: - -::: {.callout .callout-info} -Не обязательно добавлять в коммит все изменения сразу или их отменять --- они могут оставаться в рабочей папке сколько угодно. -Тем не менее старайтесь не копить изменения, потому что тогда версия в репозитории будет отличаться от версии, с которой вы работаете, а значит, теряется смысл системы контроля версий и возникают ошибки. - -```{r, include=FALSE} -# Сказать, что можно отменить. -# Сказать про ветки. -``` -::: - -```{r, include=FALSE} -# Показать как отменить изменения. -``` - -```{r, include=FALSE} -# Как писать сообщение коммита. -``` - -```{r, include=FALSE} -# Заменить название главы на «Практика» или «Отслеживание изменений» -``` +Теперь у проекта есть исходная версия, импорт данных и готовый график в трёх отдельных коммитах. diff --git a/02-04-log-n-diff.Rmd b/02-04-log-n-diff.Rmd index bb88292..8dd7692 100644 --- a/02-04-log-n-diff.Rmd +++ b/02-04-log-n-diff.Rmd @@ -1,37 +1,25 @@ -# Просмотр истории {#git-log} +# История и различия {#history-diff} -До этого мы просматривали изменения только по сравнению с последней версией в момент создания коммита. Предыдущие коммиты можно посмотреть в **журнале (log)**. +Разверните **Source Control Graph** в Source Control. В нём видны коммиты текущей ветки `main`. -Журнал позволяет изучить изменения от других участников или вспомнить свои собственные, и зачем они сделаны. -Поэтому так важно писать ясные и содержательные описания коммитов. -Используя журнал, можно найти, когда сделаны изменения, приведшие к ошибке, и вернуть проект к предыдущему состоянию. -В конце концов, его можно использовать для отчетности и бизнесс-аналитики по проекту. +Выберите коммит `Сохранил гистограмму длины клюва`. Под ним появится список изменённых файлов. Выберите `paper.qmd`, чтобы открыть diff именно для этого коммита. -Чтобы открыть журнал, нажмите кнопку [History]{.figtext} на панели [Git]{.figtext}. -В открывшемся окне выводится список коммитов в обратном порядке --- последние коммиты находятся вверху. -В списке выводится краткая информация о коммите, а под списком подробная информация по выделенному коммиту. +![Source Control Graph с тремя учебными коммитами и открытым diff файла paper.qmd для коммита с гистограммой]() -![](./img/02-04-02-history.png){width=690px} +В diff удалённые строки отмечены красным, добавленные — зелёным. Git сравнивает строки, поэтому даже изменение одного символа может выглядеть как удаление старой строки и добавление новой. -- SHA --- так называемый хэш коммита, который является его уникальным идентификатором в репозитории -- Author --- автор коммита \, [которые были указаны в настройках](#setup) -- Date --- дата и время создания коммита -- Subject --- описание коммита -- Parent --- хэш (идентификатор) предыдущего коммита +Для истории одного файла откройте `paper.qmd`, затем разверните **Timeline** в Explorer. Там можно выбрать прежний коммит и посмотреть, как менялся только этот файл. -Еще ниже показан дифф --- изменения, сделанные в этом коммите по сравнению с предыдущим. -Для больших файлов выводятся только те строки, которые поменялись, а также несколько строк выше и ниже, чтобы был понятен контекст. -Если нажать кнопку [View file]{.figtext} справа от названия файла, можно увидеть его полное содержимое, каким оно было зафиксировано создания коммита. +## Рабочая папка, индекс и коммит -Даже если вы работаете в одиночку, полезно иметь под рукой историю изменений. -Но по настоящему эта функция полезна, -когда приходится работать с несколькими версиями одновременно, -например при работе в команде. -[Об этом далее](#git-branch). +Эти три состояния полезно различать: -```{r, include=F} -# Название главы что-то типа «Журнал (log)»? +| Состояние | Что содержит | +|---|---| +| Рабочая папка | Сохранённые на диске файлы, включая незаконченные изменения | +| Индекс | Только изменения, выбранные для следующего коммита | +| Последний коммит | Уже записанный снимок проекта | -# примеры? код ревью, просто посмотреть кто, когда и зачем. -# рассказать почему в списке выводится только первые 8 символов sha? -``` +Кнопка `+` переносит изменение из рабочей папки в индекс. Кнопка `−` у **Staged Changes** убирает его из индекса, но не удаляет из файла. **Commit** записывает содержимое индекса в историю. + +Официальное руководство [Staging and committing changes](https://code.visualstudio.com/docs/sourcecontrol/staging-commits) использует эту же модель. diff --git a/03-01-branches.Rmd b/03-01-branches.Rmd index 6ac3805..54eb928 100644 --- a/03-01-branches.Rmd +++ b/03-01-branches.Rmd @@ -1,78 +1,30 @@ # (PART) Ветки {-} -```{r, include=FALSE} -# Ветка отражает состояние проекта во времени. -# Ветки можно делать от веток. -``` - -# Введение {#branch} - -До этого мы создавали версии только последовательно, -чтобы записывать историю изменений. -Git позволяет создавать параллельные версии. -Это могут быть как версии различных участников (collaborators) с различных устройств, -так и несколько альтернативных версий на одном и том же компьютере. -Таким образом участники могут создавать и обмениваться различными вариантами изменений. -Git позволяет эффективно объединять эти изменения, делая совместную работу комфортной, -чего, к слову, не умеют облачные сервисы вроде Google Drive. - -Для этого используются так называемые ветки (branch). -Почему ветки? Потому что начиная с выбранного коммита история изменений разветвляется. - -По умолчанию, мы работаем в ветке `main` -(ранее ветка по умолчанию называлась `master`, будьте готовы встретить и такое название). -Ее можно сравнить со стволом дерева --- вот он слева на изображении. -В нашем проекте с пингвинами в ветке `main` 4 коммита, последний из которых содержит гистограмму для публикации. - -![](./img/03-01-00-history.png){width=600px} +# Альтернативный график {#branches} -Представим ситуацию --- из журнала приходит ответ Рецензента 2, в котором он просит заменить гистограмму на ящик с усами. -С одной стороны, можно податься в журнал, где знают, что такое гистограмма, -с другой, можно хотя бы попробовать удовлетворить пожелания рецензента и, -если нам не понравится новая диаграмма, просто удалить изменения. +Ветка — указатель на последовательность коммитов. Она позволяет экспериментировать, не меняя основную линию `main`. -# Создание ветки {#git-branch} +Представим, что рецензент попросил заменить гистограмму на ящик с усами. Сделаем вариант в отдельной ветке. -Чтобы спокойно поэкспериментировать создадим новую ветку. -Так будет проще удалить изменения и они не будут мешать, если мы захотим поправить что-то действительно важное в основной ветке `main`. +Убедитесь, что Source Control пуст. Нажмите название `main` в строке состояния и выберите **Create new branch…**. То же действие доступно из палитры команд как **Git: Create Branch**. -В RStudio нажмите кнопку [New Branch]{.figtext} [(A)]{.figref} +Введите название `boxplot` и выберите `main` как исходную ветку. Positron сразу переключится на новую ветку; её имя появится в строке состояния. -![](./img/03-01-01-new-branch.png){width=400px} +![Positron после создания ветки boxplot: имя ветки видно в строке состояния, Source Control пуст]() -В появившемся окне введите название, например `boxplot` и нажмите кнопку [Create]{.figtext}. -Откроется окно с сообщением, что мы переключились на ветку `boxplot`, -можете закрыть его кнопкой [Close]{.figtext}. +Замените код графика в `paper.qmd`: -![](./img/03-01-02-new-branch.png){width=200px} +```{r, eval=FALSE} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -![](./img/03-01-03-new-branch.png){width=400px} - -Обратите внимание, что название ветки на панели [Git]{.figtext}, рядом с кнопкой создания ветки [(A)]{.figref}, поменялось с `main` на `boxplot`. - -Вернемся к пингвинам. -Замените содержимое скрипта `penguins.R` на следующее: - -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm - -png("penguins-boxplot.png") +png("out/penguins-boxplot.png") boxplot(x) dev.off() ``` -Сохраните файл и выполните скрипт. -Обратите внмание, что мы поменяли название файла. -Старый файл `penguins-hist.png` в этой версии нам не нужен и его необходимо удалить. -Не переживайте, благодаря Git, в основной ветке `main` он останется. -На панели [Files]{.figtext} отметьте галочкой файл `penguins-hist.png` [(A)]{.figref} и нажмите кнопку [Delete]{.figtext} [(B)]{.figref}. - -![](./img/03-01-04-delete-files.png){width=400px} - -Отметьте все изменения для фиксации и создайте коммит. -Обратите внимание, что удаление файла это тоже изменение, которое надо отметить. +Выполните код. Удалите `out/penguins-hist.png`: в этой версии проекта он больше не нужен. Добавьте в индекс изменение `paper.qmd`, удаление гистограммы и новый `out/penguins-boxplot.png`. -![](./img/03-01-05-commit.png){width=400px} +Создайте коммит `Заменил гистограмму на ящик с усами`. -Теперь отложим эксперименты и вернемся к прежней версии. +![Source Control Graph после коммита в boxplot: main указывает на гистограмму, boxplot — на новый коммит с ящиком с усами]() diff --git a/03-02-checkout.Rmd b/03-02-checkout.Rmd index 9bfc862..729bc33 100644 --- a/03-02-checkout.Rmd +++ b/03-02-checkout.Rmd @@ -1,35 +1,25 @@ -# Переключение веток {#git-checkout} +# Переключение веток {#switch-branches} -Для переключения ветки нажмите на название текущей ветки [(A)]{.figref} на панели [Git]{.figtext}. -В выпадающем списке выберите ветку на которую хотите переключиться (`main`). +Нажмите `boxplot` в строке состояния и выберите `main`. Эта операция называется переключением, а в терминах Git — checkout или switch. -![](./img/03-02-01-branch.png){width=400px} +Откройте `paper.qmd` и папку `out`. В `main` снова должна быть гистограмма и не должно быть нового боксплота. Git привёл рабочую папку к коммиту выбранной ветки. -Убедитесь, что код скрипта вернулся к прежнему состоянию и строит гистограмму, -а в списке файлов находится файл с гистограммой `penguins-hist.png` и нету файла `penguins-boxplot.png`. +![Ветка main после переключения: paper.qmd содержит hist(), в out виден penguins-hist.png]() -![](./img/03-02-02-files.png){width=400px} +## Защита незаписанной работы -Это было просто. -Но есть один случай, когда -Git откажется переключать ветку --- если это приведет к потере данных. - -Например, замените содержимое скрипта `penguins.R` на следующее (добавилась подпись оси X): +В `paper.qmd` добавьте подпись оси: ```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm - -png("penguins-hist.png") -hist(x, breaks = seq(40, 60, 2), xlab = "Bill length, mm") -dev.off() +hist(x, breaks = seq(30, 60, 2), xlab = "Bill length, mm") ``` -Сохраните файл и попробуйте переключиться на ветку `boxplot`. -Вы получите сообщение как на скриншоте ниже. -Если бы Git переключил ветку, ему бы пришлось перезаписать файл `penguins.R`, в который мы внесли изменения, но не зафиксировали. -Поэтому, чтобы не потерять изменения при переключении, сначала необходимо их зафиксировать создав коммит. +Сохраните файл, но пока не создавайте коммит. Попробуйте переключиться на `boxplot`. + +Если переключение перезапишет изменённые строки, Git остановит операцию и предложит сначала сохранить работу. Это защитное поведение: незакоммиченные изменения не потеряны, вы по-прежнему на `main`. + +![Уведомление Positron об отказе переключить ветку из-за незакоммиченных изменений в paper.qmd]() -![](./img/03-02-03-error.png){width=690px} +Вернитесь в Source Control, проверьте diff и создайте коммит `Добавил подпись оси гистограммы`. После этого переключитесь на `boxplot` и обратно на `main`, чтобы проверить обе версии. -Создайте коммит и попробуйте переключиться на ветку `boxplot` и обратно на ветку `main`. +Если нужно временно убрать незаконченные изменения без коммита, используйте **Git: Stash (Include Untracked)**. Для основного упражнения stash не нужен. diff --git a/03-03-merge.Rmd b/03-03-merge.Rmd index ae3cbd4..372762b 100644 --- a/03-03-merge.Rmd +++ b/03-03-merge.Rmd @@ -1,100 +1,35 @@ -# Слияние веток {#git-merge} +# Слияние и конфликт {#merge-conflict} -[Откройте окно истории](#git-log) и выберите в фильтре сверху показывать все ветки [(all branches)]{.figtext} и все коммиты [(all commits)]{.figtext}. -На диграмме наглядно видно почему это называется веткой. +Сейчас `main` и `boxplot` по-разному изменили одну строку `paper.qmd`. Объединим ветки и разрешим конфликт осознанно. -![](./img/03-03-01-log.png){width=690px} +Переключитесь на `main`. Откройте палитру команд, выполните **Git: Merge Branch** и выберите `boxplot`. -Если мы или другой участник проекта, решим принять эти изменения в основную ветку `main`, -нам нужно выполнить операцию «слияния» (merge). -В RStudio нет встроенной возможности слияния веток, это необходимо делать в терминале. -К счастью, команда совсем не сложная. +Git автоматически объединит независимые изменения, но остановится на `paper.qmd`: обе ветки изменили код графика, и программа не знает, какой вариант нужен. -Для начала переключитесь на ветку, в которую будут вливаться изменения --- -в нашем случае это `main` ([см. переключение веток](#git-checkout)). -Откройте терминал ^[В меню RStudio выберите Tools → Terminal → New Terminal] и введите команду для слияния с веткой `boxplot`. +В Source Control файл появится в разделе **Merge Changes** с предупреждением. Это незавершённое слияние, а не повреждение проекта. -```sh -git merge boxplot +![Source Control после Git: Merge Branch: paper.qmd находится в Merge Changes, слияние ожидает решения]() -``` - -Git попытается автоматически объединить изменения из обеих веток и создать новый коммит. -В большинстве случаев этого достаточно, -но любая совместная работа может приводить к конфликтам --- -когда в обеих ветках была изменена одна и та же строка, но разным образом. -Какую версию предпочтет Git? -Git предпочтет выдать ошибку и попросит вас разрешить конфликт. - -В списке изменений мы видим, -что Git автоматически выбрал изменения связанные с новым и старым файлом для графика -`penguins-hist.png` и `penguins-boxplot.png`, -но лишь частично для скрипта `penguins.R`. - -![](./img/03-03-02-git-pane.png){width=400px} +## Редактор слияний -Причина в том, что мы вносили изменения в код графика в ветке `main` после того как изменили его в ветке `boxplot`. -Откройте файл `penguins.R`. -Git любезно оставил для нас обе версии кода разделив специальными символами. -После строки `<<< HEAD` идет версия из текущей ветки, -строка `===` отделяет две версии друг от друга, -а строка `>>> boxplot` завершает версию из ветки `boxplot`. +Нажмите `paper.qmd` правой кнопкой и выберите **Open in Merge Editor**. Редактор показывает три области: -![](./img/03-03-03-merge-conflict.png){width=690px} +- **Incoming** — изменение из `boxplot`; +- **Current** — изменение из `main`; +- **Result** — итог, который будет записан. -Наша задача переписать выделенный участок (строки 4-12) в одну версию и убрать спецсимволы. -Важно понимать, что Git просто вставил в скрипт кусок текста, -но это все еще обычный R скрипт и мы должны привести его в рабочее состояние. - -Нам нужна версия из ветки `boxplot`, но мы хотим добавить в нее подпись оси, как это было сделано в ветке `main`. -Для этого оставим нижнюю версию (строки 9-11) и удалим лишние строки (4-8 и 12) -и добавим подпись, только для ящика с усами это должна быть подпись оси Y. -В итоге должен получиться следующий код. +В Result оставьте боксплот из Incoming и добавьте к нему подпись из Current: ```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm - -png("penguins-boxplot.png") +png("out/penguins-boxplot.png") boxplot(x, ylab = "Bill length, mm") dev.off() ``` -Сохраните файл и выполните скрипт. -Создайте коммит и -не забудьте отметить галочкой внесенные изменения, -в том числе обновившийся файл `penguins-boxplot.png`, который теперь содержит подпись оси. -Обычно сообщение коммита о слиянии веток содержит следующий текст «Merge branch название-ветки», но можете придумать свое. - -![](./img/03-03-04-git-pane.png){width=400px} +Нажмите **Complete Merge**. Убедитесь, что в Result нет строк `<<<<<<<`, `=======` и `>>>>>>>`, а `paper.qmd` находится в **Staged Changes**. -Итак, мы успешно слили изменения из ветки `boxplot` в основную ветку `main`. -Теперь можно продолжить работу в основной ветке. -Еще лучше будет создать очередную ветку для новых изменений, выполнить работу в ней и точно так же слить в основную. +![Редактор слияний Positron: Incoming содержит boxplot, Current — hist с подписью, Result — boxplot с ylab]() -![](./img/03-03-05-log.png){width=690px} +Обновите `out/penguins-boxplot.png`, добавьте его в индекс и создайте коммит `Слил ветку boxplot`. -
Как удалить ветку? -Слитую ветку можно удалить. -В RStudio для этого нет встроенных средств, поэтому придется использовать терминал. -Выполните команду: - -```sh -git branch -d boxplot -``` - -Если ветка не была слита, Git откажется ее удалять, ведь могут быть потеряны сделанные в ней изменения. -Если вы действительно уверены, что они вам не нужны и вы хотите удалить не слитую ветку, выполните команду: - -```sh -git branch -D boxplot -``` -
- -```{r, include=FALSE} -# Советуем немного попрактиковаться и создать пару веток, -# переключиться между ними, от них создать еще и слить их, -# пока не освоитесь. -# -# Да не, ту мач и репозиторий выйдет из под контроля. -``` +Если нужно отказаться от всего слияния, выполните **Git: Abort Merge** из палитры команд. Git вернёт проект к состоянию до попытки merge. diff --git a/03-04-conclusion.Rmd b/03-04-conclusion.Rmd index 7afd073..e8d027e 100644 --- a/03-04-conclusion.Rmd +++ b/03-04-conclusion.Rmd @@ -1,58 +1,21 @@ -# Заключение +# Итог работы с ветками {#branches-conclusion} -Теперь вы умеете создавать и объединять ветки --- -это одни из ключевых функций Git, особенно при совместной работе. -Благодаря простоте работы с ветками, рекомендуется создавать их чаще. -Чем меньше в ветке изменений, тем проще ее слить, и тем ниже вероятность конфликтов из-за одновременных правок одной и той же части проекта. Это отражает известную идею, что при работе в команде лучше синхронизироваться чаще. +Разверните Source Control Graph. От общего коммита расходятся `main` и `boxplot`, а коммит слияния снова соединяет линии. -Рассмотрим продвинутые способы использования веток, а также для чего их использовать не стоит. +![Source Control Graph после слияния: видны расхождение main и boxplot и merge-коммит в main]() -Для начала уточним, что можно создать ветку от любой другой, а не только от основной ветки `main`. Уровень вложенности и количество веток не ограничены. -После слияния ветки она не прекращает свое существование --- в ней можно продолжить работу, а после слить еще раз. -На практике вам вряд ли понадобится больше 3-х уровней вложенности, а ветки лучше периодически удалять, чтобы не запутаться. +Теперь вы умеете: -## Тематические ветки (feature branch) +- создавать ветку командой **Git: Create Branch**; +- переключаться через индикатор ветки или **Git: Checkout to**; +- объединять ветки командой **Git: Merge Branch**; +- разрешать конфликт в трёхстороннем редакторе; +- отменять незавершённое слияние командой **Git: Abort Merge**. -Тематическая ветка содержит изменения, связанные с конкретной задачей или направлением работы. -Это может быть новый этап анализа или изменения в уже сделанные этапы, например: +После проверки слитую локальную ветку можно удалить: переключитесь на `main`, выполните **Git: Delete Branch** и выберите `boxplot`. -- ветка в которой мы визуализировали данные при помощи графиков, может называться `visualize` или `plot`; -- ветка в которой добавляются модели, может называться `model` или, если это более специфическая модель, например нелинейная, то `model-nle`; -- ветка в которой обновлены данные для уже выполненного анализа `update-data`; -- в нашем репозитории, когда мы заменили график на ящик с усами, ветка называлась `boxplot`. +::: {.callout .callout-warning} +Не удаляйте ветку, пока её изменения не слиты и не стали ненужными. Удаление несохранённой линии истории сложнее отменить, чем обычное редактирование файла. +::: -Если в проекте используется трекер задач или ошибок, -то зачастую работа выполняется в отдельной ветке с названием соответствующим номеру из трекера, -например `issue42` или `ticket58`. - -Это самый частый способ использования веток, применяемый независимо от размеров проекта и количества участников. - -## Долгоживущие ветки (long-running branches) - -Этот подход часто применяется для крупных проектов, когда нужно обеспечить высокую стабильность продукта, как правило при разработке программного обеспечения. - -Ветка `main` содержит стабильную версию. -От нее создается ветка `develop` в которой ведется разработка. -Тематические ветки создаются от ветки `develop` и вливаются в нее. -Когда разработка очередной версии завершилась, -изменения из ветки `develop` стабилизируются --- проходят тестирование и ревью, -после чего вливаются в стабильную ветку `main`. - -Далее цикл повторяется --- разработка следующей версии продолжается в ветке `develop` с использованием тематических веток, после чего она снова сливается с веткой `main`. - -## Когда не стоит использовать ветки - -Выше описаны лишь некоторые наиболее часто используемые процессы работы построенные вокруг веток. -Существует и можно придумать много других, подходящих для вас или вашей команды. - -Но у всех применений веток есть общая черта --- это способ организации внесения изменений в проект и рано или поздно эти изменения должны быть слиты или удалены. - -Ветки это не способ структурирования самого анализа или программы. -Например, если у вас есть несколько моделей и вы собираетесь поддерживать их все, то вероятно они должны быть в одной ветке, а не в отдельных. -Иначе потребуется следить за тем, чтобы изменения вносились в каждую ветку --- это утомительно и чревато ошибками. -Для работы с несколькими моделями одновременно придется переключаться и работать с несколькими ветками, что противоречит большинству способов их использования, например описанных выше. - -Другая частая ошибка --- участники создают ветки с собственным именем (`ivan`, `masha-work`) и используют их как личные папки для хранения своих файлов не связанных с файлами других участников. -Ветки предназначены для внесения изменений в один общий проект. Следует либо интегрировать эти файлы в проект, возможно отдельной веткой, либо хранить в другом месте. - -В следующей части мы посмотрим как организовать совместную работу при помощи «удаленных» (remote) веток и сервиса GitHub. +В следующей части вынесем репозиторий на GitHub и повторим этот процесс как предложение изменений для коллег. diff --git a/04-01-github.Rmd b/04-01-github.Rmd index 928b329..3622ec6 100644 --- a/04-01-github.Rmd +++ b/04-01-github.Rmd @@ -1,39 +1,23 @@ # (PART) GitHub {-} -# Настройка {#github} +# Аккаунт и вход {#github-part} -GitHub --- это веб-сервис для хранения Git репозиториев и совместной работы. -Ваши файлы размещаются на удаленном сервере и доступны публично или приватно для загрузки другими пользователями. В некотором смысле это аналог Dropbox или Google Drive для Git. -Помимо хранения репозиториев, GitHub предоставляет другие инструменты: отслеживание задач, обсуждение изменений, запуск тестов и сборок и многое другое. +Git хранит историю на вашем компьютере. GitHub хранит копию репозитория на сервере, поэтому проект можно открыть с другого устройства, показать преподавателю и обсудить изменения с коллегами. -Для работы с GitHub вам понадобится зарегистрировать учетную запись и создать токен --- отдельный пароль для Git на вашем компьютере. +Создайте аккаунт на [github.com](https://github.com/signup), если его ещё нет. Имя пользователя станет частью адресов репозиториев, поэтому лучше использовать короткое имя латиницей. -## Регистрация на GitHub +Positron включает расширения **GitHub** и **GitHub Pull Requests and Issues**. При первой публикации или отправке изменений редактор предложит войти. Выберите **Sign in with GitHub**, подтвердите открытие браузера и разрешите доступ. -Перейдите на сайт github.com и зарегистрируйте учетную запись нажав на кнопку [Sign up]{.figtext} в верхнем правом углу или войдите в существующую учетную запись нажав [Sign in]{.figtext}. +![Positron показывает запрос Sign in with GitHub перед первой публикацией репозитория]() -E-mail при регистрации не обязательно должен совпадать с указанным при настройке Git в [Главе 1](#setup). Дополнительные e-mail адреса можно добавить после регистрации [на странице настроек](https://github.com/settings/emails). -Это рекоммендуется сделать, чтобы GitHub мог ассоциировать сделанные на компьютере коммиты с вашей учетной записью онлайн. +После подтверждения вернитесь в Positron. Не создавайте classic personal access token для этого упражнения: обычный путь входа проходит через браузер. -## Создание токена +::: {.callout .callout-warning} +Никому не отправляйте пароли, токены, приватные ключи и секреты webhook. Не добавляйте их в `.qmd`, `.R`, `.env` или другие файлы репозитория. +::: -В целях безопасности, GitHub не позволяет использовать пароль от веб-сайта при работе с Git, -а требует создать так называемый **Personal Access Token** --- отдельный пароль специально для Git на вашем компьютере. -[Во всех случаях, когда Git запрашивает пароль от GitHub, необходимо вводить токен, а не пароль от веб-сайта.]{} +## Git и GitHub — разные системы -Для этого перейдите по ссылке github.com/settings/tokens, -авторизуйтесь и нажмите **Generate new token**, в выпадающем списке выберите **classic**. -На новой странице введите название токена, например Work. -Отметьте следующие права `repo`, `workflow`, `user` -и нажмите зеленую кнопку **Generate token** в конце страницы. +Коммит, ветка и слияние работают в Git без GitHub. GitHub добавляет удалённый репозиторий, права доступа, pull request, обсуждения и автоматические проверки. -![](img/github-1.png){width=100%} -![](img/github-2.png){width=100%} - -Не забудьте скопировать и сохранить ваш токен - он выглядит как строка вида `ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`. -После того как вы закроете страницу посмотреть созданный токен невозможно. -Храните его в надежном месте как пароль. - -![](img/github-3.png){width=100%} - -Теперь мы готовы опубликовать наш репозиторий на GitHub. +Если сайт GitHub недоступен, локальные коммиты продолжают работать. Когда связь восстановится, их можно отправить на сервер. diff --git a/04-02-remote.Rmd b/04-02-remote.Rmd index bb49e2b..ce54fac 100644 --- a/04-02-remote.Rmd +++ b/04-02-remote.Rmd @@ -1,48 +1,25 @@ -# Удаленный репозиторий {#git-remote} +# Публикация репозитория {#publish-github} -```{r, include=FALSE} -# Рассказать про видимость репозиториев -``` +Убедитесь, что выбрана ветка `main`, Source Control пуст и последний коммит — `Слил ветку boxplot`. -Для загрузки репозитория с вашего компьютера (он называется локальный репозиторий) на Github необходимо создать удаленный репозиторий на сайте. -На верхней панели в правом углу нажмите кнопку [+]{.figtext} и выберите пункт [New repository]{.figtext}. +В Source Control нажмите **Publish to GitHub**. Если кнопка не видна, откройте палитру команд и найдите **Publish to GitHub**. -![](./img/04-02-01-new-repository.png){width=400px} +Выберите имя репозитория, например `r-course`, и доступ **Private repository**. Для учебного проекта приватный режим безопаснее: открыть репозиторий позже можно в настройках GitHub. -В открывшейся форме достаточно заполнить только название репозитория в поле **Repository name**, например `penguins`. -Остальные поля оставьте по умолчанию, мы только разберем за что они отвечают. +Если Positron предложит выбрать файлы, оставьте все уже отслеживаемые файлы. В проекте не должно быть секретов. -- Description --- краткое описание -- Public / Private --- настройка доступа - - Public --- кто угодно сможет просматривать ваши файлы, но только отдельно добавленные пользователи смогут их изменять - - Private --- только отдельно добавленные пользователи смогут просматривать и изменять файлы -- Initialize this repository with --- этот раздел позволяет добавить в создаваемый репозиторий несколько типовых файлов `README` `.gitignore` и `LICENSE`; не отмечайте ни один из них, потому что в нашем репозитории на компьютере уже есть файлы и они будут конфликтовать с этими. +![Диалог Publish to GitHub с именем r-course и выбранным вариантом Private repository]() -Внизу страницы нажмите [Create repository]{.figtext}. +Positron выполнит три связанных действия: -
Пример заполненной формы -![](./img/04-02-02-new-repository.png){width=600px} -
+1. создаст репозиторий на GitHub; +2. добавит его как удалённый репозиторий `origin`; +3. отправит коммиты ветки `main`. -*Удалить это? Там и так на форме все написано, только что на англ. Оставить только предупреждение, чтобы не жали Initialize this repository with.* +После публикации откройте созданный репозиторий на GitHub и сравните список файлов с Explorer. Убедитесь, что на сайте есть `paper.qmd`, папка `data` и история коммитов. -*Со скрином формы репозитория тоже ту мач?* +**Удалённый репозиторий** (remote) — адрес другой копии проекта. Имя `origin` условное, но Git назначает его основной удалённой копии при публикации и клонировании. -Для созданного репозитория GitHub сгенерировал набор команд быстрой настройки, воспользуемся ими. -Сначала необходимо убедиться, что напротив адреса репозитория выбрана опция доступа через [HTTPS]{.figtext} [(A)]{.figref}. -Далее скопируйте все три команды из раздела для существующего репозитория (**... or push an existing repository from the command line**, [B]{.figref}) и выполните в терминале ^[В меню RStudio выберите Tools → Terminal → New Terminal]. -На запрос пароля скопируйте и вставьте сгенерированный в предыдущей главе токен. - -![](./img/04-02-03-git-push.png){width=100%} - -```{r, include=FALSE} -#
В чем разница между HTTPS и SSH? -#
-``` - -Мы связали наш локальный репозиторий с удаленным при помощи команды **remote add** --- это необходимо было сделать один раз. -И выполнили команду **push** --- отправить сделанные фиксации в удаленный репозиторий, это необходимо делать регулярно и для этого в интерфейсе RStudio есть кнопка на панели [Git]{.figtext}. -Если команды выполнились успешно, файлы были загружены на GitHub. -Обновите страницу репозитория и проверьте содержимое файлов. - -![](./img/04-02-04-github.png){width=100%} +::: {.callout .callout-info} +GitHub не выполняет код Quarto при обычной отправке. Файлы и история появятся на сервере, но готовый сайт требует отдельной настройки публикации. +::: diff --git a/04-03-push-pull.Rmd b/04-03-push-pull.Rmd index 1e4b7f4..67379ee 100644 --- a/04-03-push-pull.Rmd +++ b/04-03-push-pull.Rmd @@ -1,72 +1,27 @@ -# Загрузка изменений {#git-push-pull} +# Push, pull и синхронизация {#sync-remote} -```{r, include=FALSE} -# Рассмотреть пример ситуации - push с конфликтом (надо сначала сделать pull). -# Для этого надо создать изменения на GitHub, -# потом в репозитории, сделать push и только потом pull. -# Это не последовательно и запутает, оставить для практики. -``` +Локальная и удалённая копии меняются независимо. Три операции поддерживают их в согласованном состоянии. -На предыдущем шаге мы загрузили изменения из нашего локального репозитория в удаленный репозиторий на GitHub при помощи команды `push` в терминале. +| Действие | Результат | +|---|---| +| **Push** | Отправляет локальные коммиты на GitHub | +| **Pull** | Загружает удалённые коммиты и объединяет их с текущей веткой | +| **Sync Changes** | Сначала выполняет pull, затем push | -Git не синхронизирует изменения автоматически, это необходимо делать вручную, используя команду push ил кнопку [Push]{.figtext} в интерфейсе RStudio на панели [Git]{.figtext}. +Эти определения соответствуют официальной документации [Working with repositories and remotes](https://code.visualstudio.com/docs/sourcecontrol/repos-remotes). -Создадим и загрузим еще один коммит. Например, добавим небольшой комментарий к коду, чтобы человеку открывшему его впервые было легче разобраться. +## Небольшая проверка -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm +Добавьте после заголовка `paper.qmd` одно предложение о цели анализа. Сохраните файл, проверьте diff и создайте коммит `Уточнил цель анализа`. -# Ящик с усами для длины клюва +В строке состояния появится исходящий коммит `↑1`. Нажмите **Sync Changes**. После синхронизации счётчик исчезнет, а коммит появится на GitHub. -png("penguins-boxplot.png") -boxplot(x, ylab = "Bill length, mm") -dev.off() -``` +![Source Control перед Sync Changes: локальная main опережает origin/main на один коммит, в строке состояния показано ↑1]() -Сохраните и закомитьте файл `penguins.R`. -После чего нажмите кнопку [Push]{.figtext} в верхнем правом углу. +## Перед началом работы -![](./img/04-03-01-git-push.png){width=100%} +В совместном проекте начинайте с **Pull**, а заканчивайте **Push**. Так вы раньше увидите чужие изменения и реже столкнётесь с конфликтом. -Перейдите на страницу репозитория на GitHub и убедитесь, что коммит был загружен. -Это можно понять по тексту сообщения над списком файлов и по тексту и времени изменения напротив файла `penguins.R`. +**Sync Changes** удобно, когда вы понимаете обе половины операции. Если нужно отдельно проверить входящие коммиты, выполните **Fetch**, посмотрите их в Source Control Graph и только затем нажмите **Pull**. -![](./img/04-03-02-github.png){width=100%} - -GitHub позволяет вносить изменения в репозиторий из веб-интерфейса. -Эта функция используется редко, потому что код необходимо запускать и проверять на компьютере, но она полезна для небольших правок или загрузки файлов. -Создадим при помощи нее новый файл. -Файл README --- это файл, который отображается на главной странице репозитория для краткого описания проекта. Обычно он включает описание данных и скриптов, как начать работу с проектом и тому подобное. - -Нажмите кнопку [Add a README]{.figtext}. В открывшемся файле введите текст в формате Markdown^[это как RMarkdown, только без возможности выполнения кода на R] (используйте или измените текст ниже) -и нажмите кнопку [Commit changes]{.figtext} в верхнем правом углу. -Откроется окно создания коммита, оставьте текст по умолчанию и подтвердите создание коммита нажатием кнопки [Commit changes]{.figtext} - -![](./img/04-03-03-add-readme.png){width=100%} - -```md -# Пингвины «Палмер» 🐧 - -Этот репозиторий был создан в рамках курса от [Института биоинформатики](bioinf.me/education/stat), -чтобы познакомиться с основами Git — фиксацией изменений, ветвлением и работой с GitHub. - -В качестве примера использованы данные о длине клюва пингвинов, -собранные доктором Кристен Горман на станции «Палмер» в Антарктиде. - -Содержимое репозитория: - -- penguins-boxplot.png — диаграмма ящик с усами, показывающая распределение длины клюва -- penguins.R — скрипт для построения диаграммы -- penguins.csv — данные -``` - -Чтобы загрузить изменения из удаленного репозитория на компьютер используется команда **pull**. - -Вернитесь в RStudio и на панели [Git]{.figtext} нажмите кнопку [Pull]{.figtext}. -Если команда выполнилась успешно, в списке файлов появится файл `README.md`, -а в журнале --- коммит созданный через GitHub. - -Как и в случае с переключением веток, Git откажется загружать изменения и выдаст ошибку, если в рабочей папке имеются незафиксированные изменения, которые конфликтуют с загружаемыми. - -Теперь вы умеете загружать изменения в удалённый репозиторий и из него. Рекомендуем делать это регулярно, чтобы синхронизироваться с другими участниками проекта, по крайней мере, в конце рабочего дня или рабочей сессии. +Если push отклонён, обычно удалённая ветка содержит новые коммиты. Не применяйте force push. Сначала выполните Pull, разрешите возможный конфликт и повторите Push. diff --git a/04-04-pull-request.Rmd b/04-04-pull-request.Rmd index 71ab9a6..5fbfb19 100644 --- a/04-04-pull-request.Rmd +++ b/04-04-pull-request.Rmd @@ -1,54 +1,48 @@ -# Pull Request {#pr} +# Pull request {#pull-request} -Pull Request --- это механизм GitHub для слияния веток загруженных в удаленный репозиторий, позволяющий просмотреть, обсудить и проверить предлагаемые изменения перед слиянием. Похожий механизм существует и на других платформах. +Pull request — предложение объединить одну ветку с другой на GitHub. Перед слиянием коллеги могут посмотреть diff, обсудить решение и запустить проверки. -Орнитолог проходящий мимо нашего репозитория обратит внимание, что длину клюва пингвина лучше рассматривать в зависимости от пола. Он даже может предложить необходимые изменения при помощи Pull Request. +## Изменение в ветке -Создайте ветку с названием `adjust-by-sex` при помощи кнопки [New branch]{.figtext} на панели [Git]{.figtext} в RStudio. Убедитесь, что справа от кнопки вместо названия ветки по умолчанию `main` выводится название созданной ветки `adjust-by-sex`. +Создайте от актуальной `main` ветку `adjust-by-sex`. В `paper.qmd` замените блок кода: -![](./img/04-04-01-add-branch.png){width=200} - -Отредактируйте скрипт `penguins.R`, добавив пол в код для построения ящика с усами. Код приведен ниже, не забывайте, что вы можете сравнить изменения по сравнению с оригиналом при помощи кнопки [Diff]{.figtext} на панели [Git]{.figtext}. - -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm +```{r, eval=FALSE} +data <- read.csv("data/penguins.csv") +x <- data$bill_len g <- data$sex -png("penguins-boxplot.png") +png("out/penguins-boxplot.png") boxplot(x ~ g, xlab = "Sex", ylab = "Bill length, mm") dev.off() ``` -Сохраните и выполните скрипт `penguins.R`. -Создайте коммит включив в него скрипт и обновленную диаграмму `penguins-boxplot.png`. +Соберите документ, проверьте обновлённый график и создайте коммит `Сгруппировал пингвинов по полу`. + +Нажмите **Publish Branch**. Это создаст `adjust-by-sex` в `origin` и свяжет локальную ветку с удалённой. + +![Ветка adjust-by-sex после Publish Branch: Source Control Graph показывает локальную и удалённую ветки на одном коммите]() -![](./img/04-04-02-git-commit.png){width=100%} +## Создание предложения -После создания коммита нажмите кнопку [Push]{.figtext} в верхнем правом углу или на панели [Git]{.figtext}. Так как у вас полные права на редактирование репозитория, то новая ветка будет загружена на GitHub. Прохожему орнитологу пришлось бы создать свою копию репозитория или просить дать доступ средствами GitHub. +Откройте представление **Pull Requests** на панели активности. Нажмите **Create Pull Request** или выполните команду **GitHub Pull Requests: Create Pull Request**. -Перейдите на страницу репозитория в GitHub и убедитесь, что ветка была загружена и содержит сделанные измнения, для этого выберите ее в выпадающем меню появляющемся при нажатии кнопки с названием ветки [main]{.figtext}. +Выберите: -![](img/04-04-03-github-branch.png){width=100%} +- базовый репозиторий — ваш `r-course`; +- базовую ветку — `main`; +- ветку с изменением — `adjust-by-sex`; +- заголовок — `Сгруппировал пингвинов по полу`. -При просмотре ветки отличной от основной, GitHub предложит создать из нее **Pull Request** --- предложение автору репозитория слить изменения из этой ветки. Нажмите кнопку [Contribute]{.figtext} и в выпадающем меню выберите [Open pull request]{.figtext}. +В описании объясните причину: распределение длины клюва теперь показано отдельно для каждого пола. Перед созданием откройте список файлов и проверьте diff. -![](img/04-04-04-github-pr.png){width=100%} +![Форма Create Pull Request в Positron: base main, compare adjust-by-sex, заполнены заголовок и описание]() -GitHub предложит ввести заголовок и описание предлагаемых изменений, правило хорошего тона кратко описать причину изменений и суть предлагаемого решения. А также, прокрутите страницу создания Pull Request и проверьте изменения, которые вы предлагаете, после чего нажмите кнопку [Create pull Request]{.figtext} под полем с описанием. +Нажмите **Create**. Откроется режим просмотра pull request. Здесь можно оставить комментарий к строке, запросить проверку и увидеть обсуждение. -![](img/04-04-05-github-pr.png){width=100%} +## Слияние -На странице Pull Request владельцу репозитория доступна опция слить предложенные изменения. -Нажмите кнопку [Merge pull request]{.figtext} внизу страницы. -В открывшемся окне GitHub предложить ввести текст коммита, как если бы мы делали слияние ветки в терминале. Оставьте или измените текст и нажмите кнопку [Confirm merge]{.figtext} -После успешного слияния ветку можно удалить. +Нажмите **Merge** только после проверки файлов. Выберите обычное создание merge-коммита, затем подтвердите операцию. После успешного слияния удалите ветку, когда Positron предложит это сделать. -![](img/04-04-06-merge-pr.png){width=100%} -![](img/04-04-07-merge-pr.png){width=100%} -![](img/04-04-08-merge-pr.png){width=100%} +Переключитесь на локальную `main` и выполните **Pull**. Убедитесь, что `paper.qmd` содержит группировку по полу, а Source Control Graph — коммит слияния с GitHub. -Вернемся к нашему проекту в RStudio. -Слияние было выполнено онлайн на GitHub, а значит необходимо загрузить изменения в наш локальный репозиторий, т.е. сделать pull. -Переключитесь на ветку `main` при помощи панели [Git]{.figtext} и нажмите кнопку [Pull]{.figtext}. -Убедитесь, что теперь ветка `main` содержит актуальные изменения в файлах `penguins.R` и `penguins-boxplot.png`. +![Локальная main после Pull: в paper.qmd код boxplot по sex, в Graph виден слитый pull request]() diff --git a/04-05-clone.Rmd b/04-05-clone.Rmd index f22c4ab..ed665d5 100644 --- a/04-05-clone.Rmd +++ b/04-05-clone.Rmd @@ -1,34 +1,19 @@ -# Клонирование репозитория {#git-clone} +# Клонирование {#clone-repository} -Сейчас репозиторий доступен публично и -чтобы поделиться проектом достаточно скопировать ссылку из адресной строки браузера. -Отличная идея приложить ее к тексту публикации, если репозиторий содержит данные и код для воспроизведения результатов. -Используйте GitHub чтобы делиться примерами кода. Например, если просите помощи, так другим будет легче понять проблему и предложить решение. +**Клонирование** создаёт новую локальную папку из удалённого репозитория. Вместе с файлами загружаются коммиты и ветки, а Git автоматически добавляет remote `origin`. -Чтобы загрузить удаленный репозиторий на компьютер выполните команду **клонирования (clone)**. -Для этого понадобится адрес репозитория. -Нажмите кнопку [Code]{.figtext} на странице репозитория, -убедитесь что выбрана опция **HTTPS** и скопируйте адрес. +Не клонируйте репозиторий внутрь уже открытого `r-course`. Для проверки используйте другую родительскую папку. -![](./img/04-03-05-new-project.png){width="600px"} +1. Откройте новое окно Positron без проекта. +2. Выполните **Workspaces: New Folder from Git…** из палитры команд. +3. Выберите **Clone from GitHub** и свой репозиторий `r-course`. +4. Укажите родительскую папку, например `projects-copy`. +5. После загрузки нажмите **Open**. -Создадим проект RStudio. -В верхнем меню выберите [File → New Project]{.figtext}. -В появившемся окне выберите [Version Control]{.figtext} и далее [Git]{.figtext}. -В поле [Repository URL]{.figtext} вставьте адрес репозитория. -В поле [Project directory name]{.figtext} укажите название папки для проекта --- -т.к. папка `penguins` уже существует, используем название `penguins2`. -Откроется окно проекта, RStudio готова к работе. +![Окно Workspaces: New Folder from Git со списком репозиториев GitHub и выбранным r-course]() - - - - - - - - - -
![](./img/04-03-01-new-project.png){width="320px"}![](./img/04-03-02-new-project.png){width="320px"}
![](./img/04-03-03-new-project.png){width="320px"}![](./img/04-03-04-new-project.png){width="320px"}
+Откройте Source Control Graph и `paper.qmd`. История и код должны совпадать с первым проектом. -Мы склонировали удаленный репозиторий на компьютер и теперь можем работать с ним как с оригинальным проектом --- делать коммиты, загружать изменения в удаленный репозиторий (push) и из него (pull). +Не редактируйте обе копии одновременно без необходимости. Это два независимых рабочих каталога: изменения попадут друг к другу только через Push и Pull. + +Если Positron спрашивает, доверяете ли вы содержимому, подтверждайте доверие только для своего репозитория или известного источника. Открытие чужого проекта ещё не запускает код, но дальнейшее выполнение файлов может это сделать. diff --git a/04-06-conclusion.Rmd b/04-06-conclusion.Rmd index bf1b66e..5b0ed71 100644 --- a/04-06-conclusion.Rmd +++ b/04-06-conclusion.Rmd @@ -1,17 +1,14 @@ -# Заключение +# Итог работы с GitHub {#github-conclusion} -Теперь у вас есть аккаунт на GitHub и вы умеете синхронизировать изменения с удаленным репозиторием, -пользоваться веб-интерфейсом и создавать Pull Request. -Этого достаточно для командной работы на курсе и в большинстве проектов. +Теперь вы умеете: -Диаграмма ниже поможет запомнить как соотносятся действия, которые мы изучили: -[1) создание коммитов](#git-commit), [2) работа с ветками](#branch) и [3) синхронизация с удаленным репозиторием](#git-push-pull). +- публиковать локальный репозиторий через **Publish to GitHub**; +- входить в GitHub через браузер; +- различать Push, Pull, Fetch и Sync Changes; +- публиковать отдельную ветку; +- создавать, проверять и сливать pull request; +- клонировать проект командой **Workspaces: New Folder from Git…**. -![](./img/04-06-sequence.png){width=100%} +Для обычной работы достаточно короткого цикла: Pull → новая ветка → небольшие коммиты → Push → pull request → проверка → merge. -Рекомендуем использовать Git в своих проектах и не бояться экспериментировать с ветками. -Это помогает структурировать рабочий процесс, делает анализ данных воспроизводимым и облегчает командную работу. -Даже если вы работаете в одиночку, история изменений, возможность вернуться к предыдущим версиям и ветвление значительно упрощают развитие проекта. -А со временем вы сможете применять более продвинутые возможности, такие как автоматизация, интеграция с другими сервисами и управление проектами. - -Удачи в прохождении курса! +GitHub — не резервная копия незакоммиченных файлов. Пока изменение не вошло в коммит и не отправлено, оно существует только в вашей рабочей папке. diff --git a/05-01-faq.Rmd b/05-01-faq.Rmd index 128bc53..0bf9008 100644 --- a/05-01-faq.Rmd +++ b/05-01-faq.Rmd @@ -1,57 +1,41 @@ -# (PART) Дополнительные материалы {-} +# (PART) Дополнительно {-} -# Best practices {#faq} +# Частые ситуации {#faq} -## .gitignore {#gitignore} +## Source Control не показывает проект -## Feature бранчи {#feature-branch} +Убедитесь, что в Positron открыта именно папка `r-course`, а не отдельный файл. Затем выполните **Developer: Reload Window**. Если репозитория действительно нет, появится **Initialize Repository**. -Хорошая практика каждое изменение делать в свой ветке. +Для диагностики откройте **Git: Show Git Output**. Последняя строка обычно содержит команду и причину ошибки. Перед отправкой лога удалите из него токены и приватные адреса. -Не всегда это удобно, особенно когда работаешь один. -Чтобы перенести уже сделанные коммиты в отдельную ветку воспользуйтесь [этим рецептом](#commits-to-branch). +## Коммит не содержит файл -## Комитьте и пушьте чаще +Коммит получает только **Staged Changes**. Найдите файл в **Changes**, нажмите `+`, проверьте diff и создайте новый коммит. Не нужно удалять предыдущий коммит ради пропущенного файла. -Так меньше проблем при слиянии +## В коммит попал лишний файл -## Принудительный push {#force-push} +Если коммит ещё не отправлен и вы работаете один, откройте в Source Control меню **More Actions (…) → Commit → Undo Last Commit**. Изменения останутся в **Staged Changes**. Исправьте индекс и создайте коммит снова. -Это может привести к потери изменений загруженных на сервер ранее, например вашим коллегой. -Никогда не делайте так в команде, не уточнив у других. +Если коммит уже отправлен или его могли скачать коллеги, не переписывайте историю. Сделайте новый коммит, который удаляет или исправляет лишнее. -## Как перенести коммиты в ветку {#commits-to-branch} +## Нужно временно переключиться -Идея рецепта в том, -что мы создаем новую ветку из текущего набора коммитов, -переключаемся на оригинальную и в ней ненужные коммиты отменяем. +Сохраните законченную часть коммитом. Для незаконченной используйте **Git: Stash (Include Untracked)**, затем переключитесь. Вернуть выбранный stash можно командой **Git: Pop Stash...**. -::: {.alert .alert-warning} -Этот подход не сработает если вы загрузили коммиты на сервер, -потому что отмена коммитов переписывает историю. -Это потребует выполнения команды `git push --force`. -[Почему это плохо?](#force-push) -::: +## Конфликт возник при Pull -Создайте новую ветку - она будет содержать набор коммитов, который вы имеете сейчас, -при помощи RStudio или командой ниже. +Это то же слияние, что в главе \@ref(merge-conflict). Откройте файлы из **Merge Changes**, соберите осмысленный Result, нажмите **Complete Merge** и создайте коммит. После этого повторите Push. -```sh -git branch some -``` +## Опасные операции -Важно! Убедитесь в том, что создали ветку. Для этого посмотрите журнал или команду `git log` и найдите напротив текущего коммита надпись с названием созданной ветки. +Команды force push, hard reset, удаление неслитой ветки и переписывание опубликованной истории могут стереть доступ к чужим коммитам. -Вернитесь на оригинальную ветку, как правило это `main`, при помощи RStudio или команды ниже. +::: {.callout .callout-warning} +Не используйте **Force Push**, `git reset --hard` и удаление неслитых веток в командном проекте без явного согласования. Сначала создайте резервную ветку или попросите преподавателя помочь. +::: -```sh -git checkout main -``` +## Данные и секреты -Отмените нужное количество комитов, скажем `3`. -Опция `--hard` удалит все изменения. -Ничего страшного, ведь они остались в ветке, созданной на предыдущем шаге. +Git хорошо подходит для кода и небольших учебных данных. Большие файлы быстро раздувают историю, а удалённый из последнего коммита секрет может сохраниться в старых версиях. -```sh -git reset --hard HEAD~3 -``` +Перед первым коммитом добавляйте в `.gitignore` временные файлы, локальные настройки и секреты. Если секрет уже отправлен, сначала отзовите его у провайдера; одного удаления файла недостаточно. diff --git a/05-02-references.Rmd b/05-02-references.Rmd index b1460ee..4e63d99 100644 --- a/05-02-references.Rmd +++ b/05-02-references.Rmd @@ -1,5 +1,25 @@ # Ссылки {#references} -- [Pro Git](https://git-scm.com/book/en/v2) --- небольшая книга рекомендованная разработчиками Git. Из нее вы узнаете о внутреннем устройстве Git и научитесь работать с командой `git` в терминале. Пригодятся главы 1-3 и глава 6. -- [Happy Git and GitHub for the useR](https://happygitwithr.com/) --- материалы практического курса по Git с конференции Posit. -- [Git Cheatsheet](https://ndpsoftware.com/git-cheatsheet.html#loc=local_repo;) - интерактивная шпаргалка. +## Positron + +- [Welcome to Positron](https://positron.posit.co/welcome.html) — исходная точка официальной документации. +- [Git Version Control](https://positron.posit.co/git.html) — Git, Source Control, ветки и конфликты в Positron. +- [Command Palette](https://positron.posit.co/command-palette.html) — поиск и запуск команд. +- [Quarto](https://positron.posit.co/quarto.html) — выполнение и предпросмотр `.qmd`. +- [Folder Templates](https://positron.posit.co/folder-templates.html) — состав проекта, включая `.git` и `.gitignore`. + +## Git и Source Control + +- [Source Control overview](https://code.visualstudio.com/docs/sourcecontrol/overview). +- [Staging and committing changes](https://code.visualstudio.com/docs/sourcecontrol/staging-commits). +- [Source Control history](https://code.visualstudio.com/docs/sourcecontrol/history). +- [Branches and worktrees](https://code.visualstudio.com/docs/sourcecontrol/branches-worktrees). +- [Merge conflicts](https://code.visualstudio.com/docs/sourcecontrol/merge-conflicts). +- [Repositories and remotes](https://code.visualstudio.com/docs/sourcecontrol/repos-remotes). +- [GitHub in Source Control](https://code.visualstudio.com/docs/sourcecontrol/github). +- [Pro Git](https://git-scm.com/book/ru/v2) — подробная бесплатная книга. + +## Практика + +- [Learn Git Branching](https://learngitbranching.js.org/?locale=ru_RU) — интерактивные упражнения с ветками. +- [Happy Git and GitHub for the useR](https://happygitwithr.com/) — Git для проектов анализа данных. diff --git a/05-03-webhooks.Rmd b/05-03-webhooks.Rmd index eae5442..09ee9cd 100644 --- a/05-03-webhooks.Rmd +++ b/05-03-webhooks.Rmd @@ -1,25 +1,23 @@ # Webhooks {#webhooks} -Webhooks — это механизм GitHub для реагирования на события в репозитории. -Когда что-то происходит (например, кто-то сделал push или создал Pull Request), -GitHub отправит информацию о событии на указанный в настройках адрес. +Webhook позволяет GitHub отправить HTTP-запрос внешнему сервису после события: push, создания pull request или слияния. Так запускают уведомления и автоматические проверки. -Для обработки событий по указанному адресу должна работать программа (веб-сервер). -Многие сервисы, например Slack или Microsoft Teams, поддерживают таким образом отправку уведомлений в рабочий чат. -Для Telegram можно воспользоваться ботом [@octo8bot](https://t.me/octo8bot). +Для настройки нужен готовый HTTPS-адрес сервиса. Не указывайте случайный сайт: содержимое запроса может включать имена репозитория, веток и участников. -Добавьте бота в чат и скопируйте присланный им адрес. +1. Откройте репозиторий на GitHub. +2. Перейдите **Settings → Webhooks → Add webhook**. +3. Вставьте адрес в **Payload URL**. +4. Выберите `application/json`. +5. Добавьте отдельный случайный **Secret**, если принимающий сервис умеет проверять подпись. +6. Выберите **Let me select individual events** и оставьте **Pull requests**. +7. Нажмите **Add webhook**. -![](./img/05-03-add-bot.png){width=400px} +![Страница GitHub Add webhook: заполнен Payload URL, content type application/json, выбран Pull requests, секрет скрыт]() -Откройте репозиторий на Github и выберите **Settings → Webhooks → Add webhook**. -Вставьте адрес в поле **Payload URL** и заполните форму как на скриншоте ниже. -Нажмите **Add webhook**. +В разделе **Recent Deliveries** откройте тестовую доставку. Код `2xx` означает, что сервис принял запрос. Код `4xx` обычно указывает на неверный адрес или авторизацию, `5xx` — на ошибку принимающего сервиса. -![](./img/05-03-github.png){width=100%} +::: {.callout .callout-warning} +Webhook может запускать действия во внешней системе. Проверяйте адрес и минимально необходимый набор событий. Не записывайте secret в репозиторий и не показывайте его на скриншоте. +::: -Если webhook настроен правильно, в чат придет сообщение с текстом «Successfully installed». - -Когда создаётся новый Pull Request, в него вносятся изменения или он сливается (merge), бот пришлет уведомление с ссылкой на этот Pull Request. - -![](./img/05-03-notifications.png){width=400px} +Для преподавателя генератор проекта умеет создать такой webhook через `gh` в состоянии `github-webhook`; студенту достаточно один раз пройти настройку в интерфейсе и проверить доставку. diff --git a/Makefile b/Makefile index da11b6d..84dac92 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,14 @@ +.PHONY: all test practice build dev + all: build +test: + python3 -m unittest discover -s tests -v + python3 bin/check_course.py + +practice: + quarto render practice/workshop_notebook.qmd --execute-dir practice/assets + build: R -e 'bookdown::render_book(output_dir="docs")' diff --git a/README.md b/README.md index fd507de..34a5705 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Практикум по Git и тулам для ИБ 2024 +Курс «Основы Git в Positron» продолжает учебный проект `r-course`: студенты сохраняют накопленные файлы в Git и продолжают анализ пингвинов в Quarto. + Слайды [slides.pptx](./slides.pptx) или [slides.pdf](./slides.pdf). Использованные источники ниже. diff --git a/_bookdown.yml b/_bookdown.yml index 532ba7b..8106e6d 100644 --- a/_bookdown.yml +++ b/_bookdown.yml @@ -2,6 +2,28 @@ book_filename: "git-101" new_session: true before_chapter_script: _common.R delete_merged_file: true +rmd_files: + - index.Rmd + - 01-01-about.Rmd + - 01-02-install.Rmd + - 01-03-shell.Rmd + - 02-01-init.Rmd + - 02-02-commit.Rmd + - 02-03-practice.Rmd + - 02-04-log-n-diff.Rmd + - 03-01-branches.Rmd + - 03-02-checkout.Rmd + - 03-03-merge.Rmd + - 03-04-conclusion.Rmd + - 04-01-github.Rmd + - 04-02-remote.Rmd + - 04-03-push-pull.Rmd + - 04-04-pull-request.Rmd + - 04-05-clone.Rmd + - 04-06-conclusion.Rmd + - 05-01-faq.Rmd + - 05-03-webhooks.Rmd + - 05-02-references.Rmd language: ui: chapter_name: "Глава " diff --git a/bin/check_course.py b/bin/check_course.py new file mode 100644 index 0000000..8ec0125 --- /dev/null +++ b/bin/check_course.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +"""Static checks for the reader-facing course sources.""" + +from __future__ import annotations + +from html.parser import HTMLParser +from pathlib import Path +import re +import sys +from urllib.parse import unquote, urlsplit + + +ROOT = Path(__file__).resolve().parents[1] +SOURCES = sorted(ROOT.glob("*.Rmd")) +PRACTICE_SOURCES = sorted((ROOT / "practice").rglob("*.qmd")) + sorted( + (ROOT / "practice").glob("*.patch") +) + + +class LinkParser(HTMLParser): + def __init__(self) -> None: + super().__init__() + self.links: list[str] = [] + + def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: + if tag != "a": + return + href = dict(attrs).get("href") + if href: + self.links.append(href) + + +def fail(message: str, failures: list[str]) -> None: + failures.append(message) + + +def main() -> int: + failures: list[str] = [] + for source in SOURCES: + text = source.read_text(encoding="utf-8") + if "%>%" in text: + fail(f"{source.name}: используется %>%", failures) + if "RStudio" in text or "Rstudio" in text: + fail(f"{source.name}: осталось упоминание RStudio", failures) + if "R Markdown" in text or "RMarkdown" in text: + fail(f"{source.name}: осталось упоминание R Markdown", failures) + for match in re.finditer(r"!\[([^\]]*)\]\(([^)]*)\)", text): + alt, target = match.groups() + if not alt.strip(): + fail(f"{source.name}: у изображения нет описания", failures) + if target.strip(): + fail(f"{source.name}: скриншот должен иметь пустой адрес: {target}", failures) + + for source in PRACTICE_SOURCES: + text = source.read_text(encoding="utf-8") + relative = source.relative_to(ROOT) + if "%>%" in text: + fail(f"{relative}: используется %>%", failures) + if "RStudio" in text or "Rstudio" in text: + fail(f"{relative}: осталось упоминание RStudio", failures) + if "R Markdown" in text or "RMarkdown" in text: + fail(f"{relative}: осталось упоминание R Markdown", failures) + if ".Rmd" in text: + fail(f"{relative}: активный файл ссылается на .Rmd", failures) + + generator = (ROOT / "bin" / "create_course_project.py").read_text(encoding="utf-8") + if "%>%" in generator: + fail("create_course_project.py: используется %>%", failures) + if 'read.csv("data/penguins.csv")' not in generator: + fail("create_course_project.py: paper.qmd читает данные не из data/penguins.csv", failures) + if "|>" not in generator: + fail("create_course_project.py: в новом R-коде нет базовой трубы |>", failures) + + docs = ROOT / "docs" + for page in sorted(docs.glob("*.html")): + parser = LinkParser() + parser.feed(page.read_text(encoding="utf-8")) + for href in parser.links: + parsed = urlsplit(href) + if parsed.scheme or parsed.netloc or not parsed.path: + continue + target = (page.parent / unquote(parsed.path)).resolve() + if not target.exists(): + fail(f"{page.relative_to(ROOT)}: не найдена ссылка {href}", failures) + + if failures: + print("\n".join(failures), file=sys.stderr) + return 1 + print(f"Проверено файлов курса и практики: {len(SOURCES) + len(PRACTICE_SOURCES)}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/bin/create_course_project.py b/bin/create_course_project.py new file mode 100644 index 0000000..872e6e0 --- /dev/null +++ b/bin/create_course_project.py @@ -0,0 +1,477 @@ +#!/usr/bin/env python3 +"""Create reproducible checkpoints for the Positron Git course.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import os +from pathlib import Path +import shutil +import subprocess +import sys + + +ROOT = Path(__file__).resolve().parents[1] +STARTER = ROOT / "course-project" / "starter" +OUTPUTS = ROOT / "course-project" / "outputs" +MANIFEST = ROOT / "course-project" / "starter-manifest.json" + +LOCAL_STATES = ( + "starter", + "baseline", + "paper", + "histogram", + "boxplot-branch", + "dirty-main", + "conflict", + "merged", +) +GITHUB_STATES = ( + "github-published", + "github-pr", + "github-merged", + "github-webhook", +) +STATES = LOCAL_STATES + GITHUB_STATES + +GIT_ENV = { + "GIT_AUTHOR_NAME": "Участник курса", + "GIT_AUTHOR_EMAIL": "student@example.org", + "GIT_COMMITTER_NAME": "Участник курса", + "GIT_COMMITTER_EMAIL": "student@example.org", +} + + +class CourseProjectError(RuntimeError): + """An expected error that can be shown without a traceback.""" + + +def run( + args: list[str], + *, + cwd: Path | None = None, + env: dict[str, str] | None = None, + check: bool = True, + capture: bool = False, +) -> subprocess.CompletedProcess[str]: + command_env = os.environ.copy() + if env: + command_env.update(env) + result = subprocess.run( + args, + cwd=cwd, + env=command_env, + check=False, + text=True, + stdout=subprocess.PIPE if capture else None, + stderr=subprocess.PIPE if capture else None, + ) + if check and result.returncode != 0: + detail = (result.stderr or result.stdout or "").strip() + if detail: + raise CourseProjectError(f"Команда завершилась с ошибкой: {' '.join(args)}\n{detail}") + raise CourseProjectError(f"Команда завершилась с ошибкой: {' '.join(args)}") + return result + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as source: + for block in iter(lambda: source.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def validate_starter(path: Path) -> None: + expected = json.loads(MANIFEST.read_text(encoding="utf-8")) + actual_paths = sorted( + item.relative_to(path).as_posix() + for item in path.rglob("*") + if item.is_file() and ".git" not in item.relative_to(path).parts + ) + expected_paths = sorted(expected) + if actual_paths != expected_paths: + raise CourseProjectError("Состав стартового проекта не совпадает с манифестом") + for relative, metadata in expected.items(): + item = path / relative + if item.stat().st_size != metadata["size"] or sha256(item) != metadata["sha256"]: + raise CourseProjectError(f"Стартовый файл повреждён: {relative}") + + +def initialize_repository(target: Path) -> None: + initialized = run(["git", "init", "-b", "main"], cwd=target, check=False, capture=True) + if initialized.returncode != 0: + run(["git", "init"], cwd=target) + run(["git", "branch", "-m", "main"], cwd=target) + run(["git", "config", "user.name", GIT_ENV["GIT_AUTHOR_NAME"]], cwd=target) + run(["git", "config", "user.email", GIT_ENV["GIT_AUTHOR_EMAIL"]], cwd=target) + + +def copy_starter(target: Path) -> None: + if target.exists(): + raise CourseProjectError(f"Путь уже существует: {target}") + target.parent.mkdir(parents=True, exist_ok=True) + shutil.copytree(STARTER, target, copy_function=shutil.copy2) + try: + validate_starter(target) + initialize_repository(target) + except Exception: + shutil.rmtree(target) + raise + + +def commit(target: Path, message: str, day: int) -> None: + run(["git", "add", "-A"], cwd=target, capture=True) + stamp = f"2026-09-{day:02d}T09:00:00+03:00" + run( + ["git", "commit", "-m", message], + cwd=target, + env={**GIT_ENV, "GIT_AUTHOR_DATE": stamp, "GIT_COMMITTER_DATE": stamp}, + capture=True, + ) + + +def write_paper(target: Path, version: str) -> None: + bodies = { + "paper": '''--- +title: "Длина клюва пингвинов" +format: html +--- + +```{r} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() +x +``` +''', + "histogram": '''--- +title: "Длина клюва пингвинов" +format: html +--- + +```{r} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() + +png("out/penguins-hist.png") +hist(x, breaks = seq(30, 60, 2)) +dev.off() +``` +''', + "histogram-labelled": '''--- +title: "Длина клюва пингвинов" +format: html +--- + +```{r} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() + +png("out/penguins-hist.png") +hist(x, breaks = seq(30, 60, 2), xlab = "Bill length, mm") +dev.off() +``` +''', + "boxplot": '''--- +title: "Длина клюва пингвинов" +format: html +--- + +```{r} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() + +png("out/penguins-boxplot.png") +boxplot(x) +dev.off() +``` +''', + "boxplot-labelled": '''--- +title: "Длина клюва пингвинов" +format: html +--- + +```{r} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() + +png("out/penguins-boxplot.png") +boxplot(x, ylab = "Bill length, mm") +dev.off() +``` +''', + "by-sex": '''--- +title: "Длина клюва пингвинов" +format: html +--- + +```{r} +data <- read.csv("data/penguins.csv") +x <- data$bill_len +g <- data$sex + +png("out/penguins-boxplot.png") +boxplot(x ~ g, xlab = "Sex", ylab = "Bill length, mm") +dev.off() +``` +''', + } + (target / "paper.qmd").write_text(bodies[version], encoding="utf-8") + + +def copy_output(target: Path, source: str, destination: str) -> None: + output = target / "out" / destination + output.parent.mkdir(exist_ok=True) + shutil.copy2(OUTPUTS / source, output) + + +def make_baseline(target: Path) -> None: + commit(target, "Зафиксировал результат курса R", 1) + + +def make_paper(target: Path) -> None: + make_baseline(target) + write_paper(target, "paper") + commit(target, "Добавил импорт данных в paper.qmd", 2) + + +def make_histogram(target: Path) -> None: + make_paper(target) + write_paper(target, "histogram") + copy_output(target, "penguins-hist.png", "penguins-hist.png") + commit(target, "Сохранил гистограмму длины клюва", 3) + + +def make_boxplot_branch(target: Path) -> None: + make_histogram(target) + run(["git", "switch", "-c", "boxplot"], cwd=target, capture=True) + write_paper(target, "boxplot") + (target / "out" / "penguins-hist.png").unlink() + copy_output(target, "penguins-boxplot.png", "penguins-boxplot.png") + commit(target, "Заменил гистограмму на ящик с усами", 4) + + +def make_dirty_main(target: Path) -> None: + make_boxplot_branch(target) + run(["git", "switch", "main"], cwd=target, capture=True) + write_paper(target, "histogram-labelled") + + +def make_conflict(target: Path) -> None: + make_dirty_main(target) + commit(target, "Добавил подпись оси гистограммы", 5) + merged = run(["git", "merge", "boxplot"], cwd=target, check=False, capture=True) + if merged.returncode == 0: + raise CourseProjectError("Не удалось создать учебный конфликт слияния") + + +def make_merged(target: Path) -> None: + make_conflict(target) + write_paper(target, "boxplot-labelled") + copy_output(target, "penguins-boxplot-labelled.png", "penguins-boxplot.png") + commit(target, "Слил ветку boxplot", 6) + + +def make_adjust_by_sex(target: Path) -> None: + make_merged(target) + run(["git", "switch", "-c", "adjust-by-sex"], cwd=target, capture=True) + write_paper(target, "by-sex") + copy_output(target, "penguins-boxplot-by-sex.png", "penguins-boxplot.png") + commit(target, "Сгруппировал пингвинов по полу", 7) + + +def build_local_state(target: Path, state: str) -> None: + builders = { + "starter": lambda path: None, + "baseline": make_baseline, + "paper": make_paper, + "histogram": make_histogram, + "boxplot-branch": make_boxplot_branch, + "dirty-main": make_dirty_main, + "conflict": make_conflict, + "merged": make_merged, + } + builders[state](target) + + +def ensure_gh_auth() -> None: + if shutil.which("gh") is None: + raise CourseProjectError("Не найден GitHub CLI (gh). Установите его и повторите запуск") + status = run(["gh", "auth", "status", "-h", "github.com"], check=False) + if status.returncode != 0: + print("Откроется браузер для входа в GitHub.") + run(["gh", "auth", "login", "--web", "-h", "github.com", "-p", "https"]) + run(["gh", "auth", "status", "-h", "github.com"]) + + +def ensure_remote_absent(repository: str) -> None: + existing = run( + ["gh", "repo", "view", repository, "--json", "nameWithOwner"], + check=False, + capture=True, + ) + if existing.returncode == 0: + raise CourseProjectError(f"Репозиторий GitHub уже существует: {repository}") + detail = (existing.stderr or existing.stdout or "").strip() + missing_markers = ("Could not resolve to a Repository", "HTTP 404", "Not Found") + if detail and not any(marker in detail for marker in missing_markers): + raise CourseProjectError(f"Не удалось проверить репозиторий GitHub:\n{detail}") + + +def publish_repository(target: Path, repository: str, visibility: str) -> None: + current_branch = run( + ["git", "branch", "--show-current"], cwd=target, capture=True + ).stdout.strip() + if current_branch != "main": + run(["git", "switch", "main"], cwd=target, capture=True) + run( + [ + "gh", + "repo", + "create", + repository, + "--source=.", + "--remote=origin", + "--push", + f"--{visibility}", + ], + cwd=target, + ) + run(["git", "push", "--all", "origin"], cwd=target) + if current_branch != "main": + run(["git", "switch", current_branch], cwd=target, capture=True) + + +def create_pull_request(target: Path, repository: str) -> str: + run(["git", "push", "-u", "origin", "adjust-by-sex"], cwd=target) + created = run( + [ + "gh", + "pr", + "create", + "--repo", + repository, + "--base", + "main", + "--head", + "adjust-by-sex", + "--title", + "Сгруппировал пингвинов по полу", + "--body", + "Ящик с усами теперь показывает распределение длины клюва отдельно для каждого пола.", + ], + cwd=target, + capture=True, + ) + return created.stdout.strip() + + +def add_webhook(repository: str, url: str, secret: str | None) -> None: + args = [ + "gh", + "api", + "--method", + "POST", + f"repos/{repository}/hooks", + "-f", + "name=web", + "-F", + "active=true", + "-f", + f"config[url]={url}", + "-f", + "config[content_type]=json", + "-f", + "events[]=pull_request", + ] + if secret: + args.extend(["-f", f"config[secret]={secret}"]) + run(args) + + +def build_github_state( + target: Path, + state: str, + repository: str, + visibility: str, + webhook_url: str | None, + webhook_secret: str | None, +) -> None: + if state == "github-published": + make_merged(target) + publish_repository(target, repository, visibility) + return + + make_adjust_by_sex(target) + publish_repository(target, repository, visibility) + + if state == "github-webhook": + if not webhook_url: + raise CourseProjectError("Для github-webhook нужен параметр --webhook-url") + add_webhook(repository, webhook_url, webhook_secret) + + pull_request = create_pull_request(target, repository) + print(f"Pull request: {pull_request}") + + if state == "github-merged": + run( + ["gh", "pr", "merge", pull_request, "--repo", repository, "--merge", "--delete-branch"], + cwd=target, + ) + run(["git", "switch", "main"], cwd=target) + run(["git", "pull", "--ff-only", "origin", "main"], cwd=target) + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Создать проект для выбранной контрольной точки курса Git", + ) + parser.add_argument("target", type=Path, help="новая папка проекта") + parser.add_argument("--state", choices=STATES, default="starter") + parser.add_argument("--repo", help="репозиторий GitHub в формате OWNER/NAME") + parser.add_argument("--visibility", choices=("private", "public"), default="private") + parser.add_argument("--webhook-url") + parser.add_argument("--webhook-secret") + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(argv) + target = args.target.expanduser().resolve() + + try: + if target.exists(): + raise CourseProjectError(f"Путь уже существует: {target}") + + if args.state in GITHUB_STATES: + if not args.repo or args.repo.count("/") != 1: + raise CourseProjectError("Для GitHub-состояния укажите --repo OWNER/NAME") + if args.state == "github-webhook" and not args.webhook_url: + raise CourseProjectError("Для github-webhook нужен параметр --webhook-url") + ensure_gh_auth() + ensure_remote_absent(args.repo) + + copy_starter(target) + if args.state in LOCAL_STATES: + build_local_state(target, args.state) + else: + build_github_state( + target, + args.state, + args.repo, + args.visibility, + args.webhook_url, + args.webhook_secret, + ) + except CourseProjectError as error: + print(f"Ошибка: {error}", file=sys.stderr) + return 1 + + print(f"Создано состояние {args.state}: {target}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/course-project/README.md b/course-project/README.md new file mode 100644 index 0000000..aeb56ab --- /dev/null +++ b/course-project/README.md @@ -0,0 +1,9 @@ +# Эталон проекта студента + +`starter/` — состояние проекта сразу после последнего задания R-курса. Это не очищенный шаблон: старые `.R`, документы Quarto, данные и созданные результаты сохранены. + +Генератор сначала копирует дерево как есть, сверяет `starter-manifest.json`, затем создаёт локальную `.git`. В `starter` история пуста, а все накопленные файлы ожидают первого коммита. Следующие состояния добавляют только работу Git-курса. + +Файл `build_outputs.R` пересоздаёт эталонные PNG для контрольных состояний. Он не меняет стартовый `out/hist.png`, полученный по заданию R-курса. + +Если задания R-курса изменились, обновите `starter/`, пересоздайте результаты, затем осознанно обновите размеры и SHA-256 в манифесте. Не преобразовывайте содержимое в «более удобный» формат. diff --git a/course-project/build_outputs.R b/course-project/build_outputs.R new file mode 100644 index 0000000..271d5ad --- /dev/null +++ b/course-project/build_outputs.R @@ -0,0 +1,19 @@ +data <- read.csv("course-project/starter/data/penguins.csv") +x <- data$bill_len +g <- data$sex + +png("course-project/outputs/penguins-hist.png") +hist(x, breaks = seq(30, 60, 2)) +dev.off() + +png("course-project/outputs/penguins-boxplot.png") +boxplot(x) +dev.off() + +png("course-project/outputs/penguins-boxplot-labelled.png") +boxplot(x, ylab = "Bill length, mm") +dev.off() + +png("course-project/outputs/penguins-boxplot-by-sex.png") +boxplot(x ~ g, xlab = "Sex", ylab = "Bill length, mm") +dev.off() diff --git a/course-project/outputs/penguins-boxplot-by-sex.png b/course-project/outputs/penguins-boxplot-by-sex.png new file mode 100644 index 0000000000000000000000000000000000000000..f76518b6be21155d825afc68af6be9bcfeec4c3e GIT binary patch literal 15709 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 Z&C)%DJBM7v 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 literal 0 HcmV?d00001 diff --git a/course-project/outputs/penguins-hist.png b/course-project/outputs/penguins-hist.png new file mode 100644 index 0000000000000000000000000000000000000000..e5016d78f3ac2a21c3aaf995a0eab8b163c6bb67 GIT binary patch literal 16034 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 literal 0 HcmV?d00001 diff --git a/course-project/starter-manifest.json b/course-project/starter-manifest.json new file mode 100644 index 0000000..bc2f871 --- /dev/null +++ b/course-project/starter-manifest.json @@ -0,0 +1,66 @@ +{ + ".gitignore": { + "sha256": "a57247db5f9eae084a417e62d6977d54de690ef16026a773dc2771410d9b90dd", + "size": 62 + }, + "analysis.qmd": { + "sha256": "47a6a626f3ba7943b65c45c36c0cbe26319f74f0415df6d6df6183fd4bf813f2", + "size": 1460 + }, + "base.R": { + "sha256": "ea8717357591f98abf37f4ca76902af4e4dc0b3050dc9ed8b6fe2e61aaa21b50", + "size": 202 + }, + "coffee.R": { + "sha256": "cddb0a7bb8ac3692dc660f715841075e23bf564b318d9ef059e65f9fe35b94b2", + "size": 55 + }, + "data/data.rds": { + "sha256": "96e2953c8c11282cb984551dd5bebc0efbd75ed767ed845598731343677d4d28", + "size": 5183 + }, + "data/data_csv.csv": { + "sha256": "2bc1d926890c6364d0708198e738b3915976a8784aa26d297460cdbc710610b8", + "size": 10909 + }, + "data/data_csv2.csv": { + "sha256": "de4b324352f8ca173cd0a486eba481a1f9fcc2f4762d22dfaf205e141ee37c26", + "size": 12973 + }, + "data/data_excel.xlsx": { + "sha256": "e4a6280d6e9038f18f8b922be81587e27f944e9ec0e686e3080a20adbd0815dc", + "size": 19971 + }, + "data/data_rds.rds": { + "sha256": "ed3d699fd0415427dacb4c3bc23dd49775b51043d86af9e4aaa2278c87e826c1", + "size": 11661 + }, + "data/data_tsv.tsv": { + "sha256": "ad6c18f0977516f7c5ddee689dc6a8df31f46cc083fcbb49128f410ae75d3153", + "size": 10314 + }, + "data/penguins.csv": { + "sha256": "310b5783fe528ad4b7635bad2973b31ed0aafa02619492978bc14bab5c3d7f64", + "size": 17242 + }, + "out/hist.png": { + "sha256": "17adbf4165d1300c52fd228d328b28fcf23c1430c209aaec677b720a603a85c6", + "size": 24180 + }, + "penguins.R": { + "sha256": "50b476daf079ea372edf3e79e8338ad0b5f697e20009af9eeb6e2ac9a9370763", + "size": 206 + }, + "report.html": { + "sha256": "2267e9e1a963017b2f64aae888c0eb6ea444c1f84b100f806cb7c087fb037f92", + "size": 1200715 + }, + "report.qmd": { + "sha256": "f7b86181ea166cbed3e67dcc7cb4317b798592424435330ea80ed8fca2af43f4", + "size": 467 + }, + "tables.qmd": { + "sha256": "fbc78bd8d0c204944c3abd3fa5ecfc3b44e90d74edb5a277f699a4008afec5f9", + "size": 937 + } +} diff --git a/course-project/starter/.gitignore b/course-project/starter/.gitignore new file mode 100644 index 0000000..d7f8b0b --- /dev/null +++ b/course-project/starter/.gitignore @@ -0,0 +1,7 @@ +.Rhistory +.RData +.Ruserdata +.DS_Store +report_files/ +*_cache/ + diff --git a/course-project/starter/analysis.qmd b/course-project/starter/analysis.qmd new file mode 100644 index 0000000..6c97394 --- /dev/null +++ b/course-project/starter/analysis.qmd @@ -0,0 +1,47 @@ +--- +title: "Анализ медицинских данных" +format: html +--- + +```{r} +library(tidyverse) +``` + +```{r} +data <- read_tsv("data/data_tsv.tsv", show_col_types = FALSE) +data$Группа <- factor(data$Группа) +data$Пол <- factor(data$Пол) +data$`Группа крови` <- factor( + data$`Группа крови`, + levels = c("O (I)", "A (II)", "B (III)", "AB (IV)") +) +``` + +```{r} +statistics <- list( + `Количество субъектов` = ~ length(.x), + `Количество (есть данные)` = ~ sum(!is.na(.x)), + `Нет данных` = ~ sum(is.na(.x)), + `Ср. знач.` = ~ mean(.x, na.rm = TRUE), + `Станд. отклон.` = ~ sd(.x, na.rm = TRUE), + `мин.` = ~ min(.x, na.rm = TRUE), + `макс.` = ~ max(.x, na.rm = TRUE), + `Медиана` = ~ median(.x, na.rm = TRUE), + `Q1` = ~ quantile(.x, 0.25, na.rm = TRUE), + `Q3` = ~ quantile(.x, 0.75, na.rm = TRUE) +) + +table <- data |> + select(`Группа`, where(is.numeric)) |> + group_by(`Группа`) |> + summarise(across(where(is.numeric), statistics, .names = "{.col}__{.fn}")) |> + mutate(across(-`Группа`, function(x) round(x, 2))) |> + mutate(across(-`Группа`, as.character)) |> + mutate(across(-`Группа`, function(x) replace_na(x, "Н/П*"))) |> + pivot_longer(!`Группа`) |> + separate(name, into = c("Переменная", "Статистика"), sep = "__") |> + rename(`Значение` = value) + +table +``` + diff --git a/course-project/starter/base.R b/course-project/starter/base.R new file mode 100644 index 0000000..b493bc1 --- /dev/null +++ b/course-project/starter/base.R @@ -0,0 +1,10 @@ +my_var1 <- 42 +my_var2 <- 35.25 +my_var3 <- my_var1^2 + my_var2^2 +my_new_var <- my_var1 == my_var2 + +numbers <- c(20, 68, 45, 76, 41, 36, 13, 52, 77, 53, 70, 73) +mean(numbers) +median(numbers) +sd(numbers) + diff --git a/course-project/starter/coffee.R b/course-project/starter/coffee.R new file mode 100644 index 0000000..d0d50e5 --- /dev/null +++ b/course-project/starter/coffee.R @@ -0,0 +1,4 @@ +1.5 * 100 / 2 +1.5 * 100 / 2 / 2 +1.5 * 100 / 2 / 2 / 2 + diff --git a/course-project/starter/data/data.rds b/course-project/starter/data/data.rds new file mode 100644 index 0000000000000000000000000000000000000000..a21bb8a78b5910082ce16953b5695a0c75c767b0 GIT binary patch literal 5183 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 literal 0 HcmV?d00001 diff --git a/course-project/starter/data/data_csv.csv b/course-project/starter/data/data_csv.csv new file mode 100644 index 0000000..9986520 --- /dev/null +++ b/course-project/starter/data/data_csv.csv @@ -0,0 +1,101 @@ +"Группа","Возраст","Пол","Рост","Группа крови","Базофилы_E1","Эозинофилы_E1","Гемоглобин_E1","Эритроциты_E1","Базофилы_E2","Эозинофилы_E2","Гемоглобин_E2","Эритроциты_E2" +"Группа 1",31,"Женский",174,"A (II)",0.4222,0.6465,10.6842,4.2573,0.8264,1.6613,11.4051,6.5728 +"Группа 1",28,"Женский",157,"A (II)",0.327,4.9742,9.6169,3.8813,0.7312,5.989,10.3378,6.1968 +"Группа 1",33,"Женский",166,NA,0.7994,3.3875,10.1628,5.0607,1.2036,4.4023,10.8837,7.3762 +"Группа 1",26,"Женский",168,"O (I)",0.0237,4.5403,10.6391,3.8083,0.4279,5.5551,11.36,6.1238 +"Группа 1",33,"Женский",170,"A (II)",0.6636,3.3159,12.259,3.0321,1.0678,4.3307,12.9799,5.3476 +"Группа 1",28,"Мужской",172,"B (III)",0.481,2.7863,12.3529,4.7917,0.8852,3.8011,13.0738,7.1072 +"Группа 1",27,"Мужской",157,"A (II)",0.8899,2.3432,11.2656,3.3619,1.2941,3.358,11.9865,5.6774 +"Группа 1",31,"Мужской",174,NA,0.8576,3.9788,14.8948,4.4598,1.2618,4.9936,15.6157,6.7753 +"Группа 1",23,"Женский",175,"A (II)",0.3832,3.3896,15.6802,4.4339,0.7874,4.4044,16.4011,6.7494 +"Группа 1",29,"Женский",172,"A (II)",0.2812,7.9352,12.9084,4.3275,0.6854,8.95,13.6293,6.643 +"Группа 1",32,"Женский",165,"A (II)",0.8032,2.4649,10.1162,3.4207,1.2074,3.4797,10.8371,5.7362 +"Группа 1",33,"Мужской",171,"B (III)",0.7606,2.8023,11.0011,4.3114,1.1648,3.8171,11.722,6.6269 +"Группа 1",30,"Женский",176,NA,-0.2188,1.2468,12.0861,3.6621,0.1854,2.2616,12.807,5.9776 +"Группа 1",28,"Женский",165,"O (I)",0.517,8.1285,11.4946,2.8699,0.9212,9.1433,12.2155,5.1854 +"Группа 1",25,"Женский",170,"B (III)",0.9893,0.5132,14.4936,4.3594,1.3935,1.528,15.2145,6.6749 +"Группа 1",38,"Женский",167,NA,0.899,2.6541,10.6878,4.9044,1.3032,3.6689,11.4087,7.2199 +"Группа 1",32,"Мужской",177,"B (III)",0.3413,0.8715,16.0903,4.1925,0.7455,1.8863,16.8112,6.508 +"Группа 1",27,"Женский",167,"B (III)",0.4083,3.7789,13.2827,4.5453,0.8125,4.7937,14.0036,6.8608 +"Группа 1",28,"Женский",169,"O (I)",0.3009,2.3743,11.5597,3.1849,0.7051,3.3891,12.2806,5.5004 +"Группа 1",27,"Мужской",158,"B (III)",0.416,3.798,13.4759,5.0699,0.8202,4.8128,14.1968,7.3854 +"Группа 1",28,"Женский",162,"O (I)",0.834,2.5866,12.353,3.7413,1.2382,3.6014,13.0739,6.0568 +"Группа 1",31,"Женский",164,"A (II)",0.8936,4.3898,12.152,3.73,1.2978,5.4046,12.8729,6.0455 +"Группа 1",26,"Мужской",171,NA,0.8364,5.0805,8.6038,4.6658,1.2406,6.0953,9.3247,6.9813 +"Группа 1",34,"Женский",173,NA,0.8969,4.5769,14.0891,3.7455,1.3011,5.5917,14.81,6.061 +"Группа 1",27,"Мужской",169,"O (I)",0.5617,5.6353,11.1436,3.8355,0.9659,6.6501,11.8645,6.151 +"Группа 1",31,"Женский",173,"B (III)",0.8466,5.8133,16.2315,4.5226,1.2508,6.8281,16.9524,6.8381 +"Группа 1",21,"Мужской",156,"A (II)",0.7375,3.6625,10.9569,3.5251,1.1417,4.6773,11.6778,5.8406 +"Группа 1",28,"Мужской",164,NA,0.8984,0.2688,13.7583,3.9492,1.3026,1.2836,14.4792,6.2647 +"Группа 1",27,"Женский",168,"A (II)",-0.0391,1.67,10.4017,3.6078,0.3651,2.6848,11.1226,5.9233 +"Группа 1",33,"Мужской",170,"O (I)",-0.2002,2.1515,9.8202,5.7281,0.204,3.1663,10.5411,8.0436 +"Группа 1",35,"Мужской",155,"A (II)",0.3337,3.4448,12.1903,4.4991,0.7379,4.4596,12.9112,6.8146 +"Группа 1",25,"Мужской",175,NA,0.2541,3.8754,15.2743,4.7965,0.6583,4.8902,15.9952,7.112 +"Группа 1",36,"Женский",169,"O (I)",0.6489,2.2938,9.1329,4.8499,1.0531,3.3086,9.8538,7.1654 +"Группа 1",23,"Женский",166,"O (I)",0.4381,2.5826,11.1547,4.4297,0.8423,3.5974,11.8756,6.7452 +"Группа 1",32,"Женский",162,"B (III)",1.3054,2.9359,13.2145,3.786,1.7096,3.9507,13.9354,6.1015 +"Группа 1",28,"Мужской",165,"O (I)",0.5758,3.1627,10.9963,4.1499,0.98,4.1775,11.7172,6.4654 +"Группа 1",32,"Женский",170,"B (III)",0.2684,1.8568,11.2402,3.3907,0.6726,2.8716,11.9611,5.7062 +"Группа 1",31,"Женский",171,"A (II)",0.4208,4.4054,5.3523,4.011,0.825,5.4202,6.0732,6.3265 +"Группа 1",31,"Женский",181,"B (III)",0.1761,3.0373,9.505,4.7135,0.5803,4.0521,10.2259,7.029 +"Группа 1",25,"Женский",179,"AB (IV)",0.318,1.8673,11.4646,2.8206,0.7222,2.8821,12.1855,5.1361 +"Группа 1",30,"Мужской",156,"AB (IV)",0.0509,0.3804,13.3238,3.7554,0.4551,1.3952,14.0447,6.0709 +"Группа 1",26,"Женский",172,"AB (IV)",0.4853,3.3438,10.5516,4.4054,0.8895,4.3586,11.2725,6.7209 +"Группа 1",33,"Женский",164,"A (II)",1.5915,5.0897,9.7669,4.1358,1.9957,6.1045,10.4878,6.4513 +"Группа 1",34,"Женский",164,"A (II)",0.3361,4.2492,12.4213,4.2117000000000004,0.7403,5.264,13.1422,6.5272 +"Группа 1",24,"Женский",163,NA,0.2666,2.336,15.1213,4.7835,0.6708,3.3508,15.8422,7.099 +"Группа 1",25,"Женский",171,"B (III)",1.454,3.4946,11.9013,4.6613,1.8582,4.5094,12.6222,6.9768 +"Группа 1",23,"Мужской",162,"AB (IV)",0.7981,2.1393,14.1017,2.8917,1.2023,3.1541,14.8226,5.2072 +"Группа 1",35,"Женский",171,"A (II)",0.3588,5.0382,10.6129,4.4047,0.763,6.053,11.3338,6.7202 +"Группа 1",29,"Мужской",175,"O (I)",0.8537,-0.3005,13.205,5.2975,1.2579,0.7143,13.9259,7.613 +"Группа 1",30,"Мужской",171,"A (II)",0.665,1.594,12.6169,5.4316,1.0692,2.6088,13.3378,7.7471 +"Группа 2",37,"Мужской",165,"AB (IV)",0.8954,5.1303,13.5317,2.926,1.2996,6.1451,14.2526,5.2415 +"Группа 2",25,"Женский",168,"O (I)",1.3261,6.8981,13.2712,4.0185,1.7303,7.9129,13.9921,6.334 +"Группа 2",32,"Женский",159,"A (II)",-0.0283,4.0341,8.8472,3.5037,0.3759,5.0489,9.5681,5.8192 +"Группа 2",35,"Мужской",164,"AB (IV)",0.8283,7.0987,10.1555,3.9505,1.2325,8.1135,10.8764,6.266 +"Группа 2",29,"Мужской",170,"O (I)",0.412,6.0201,9.6631,4.0911,0.8162,7.0349,10.384,6.4066 +"Группа 2",34,"Мужской",169,"B (III)",0.3367,3.6771,11.9647,5.2631,0.7409,4.6919,12.6856,7.5786 +"Группа 2",34,"Мужской",161,"A (II)",0.7744,4.405,11.9282,3.2528,1.1786,5.4198,12.6491,5.5683 +"Группа 2",27,"Женский",167,NA,0.1906,3.8312,11.27,5.0763,0.5948,4.846,11.9909,7.3918 +"Группа 2",34,"Женский",175,"AB (IV)",0.4139,-1.048,10.5656,3.9456,0.8181,-0.0332,11.2865,6.2611 +"Группа 2",30,"Мужской",167,"A (II)",0.8407,1.3026,15.1292,3.7485,1.2449,2.3174,15.8501,6.064 +"Группа 2",33,"Женский",162,"A (II)",1.0976,6.3401,10.9379,4.3332,1.5018,7.3549,11.6588,6.6487 +"Группа 2",26,"Мужской",164,"O (I)",0.8849,1.469,12.1955,4.9171,1.2891,2.4838,12.9164,7.2326 +"Группа 2",28,"Мужской",165,"A (II)",1.7186,5.9387,11.2181,4.2957,2.1228,6.9535,11.939,6.6112 +"Группа 2",35,"Мужской",172,"O (I)",1.2805,7.0429,12.3226,4.0218,1.6847,8.0577,13.0435,6.3373 +"Группа 2",22,"Женский",161,NA,0.9704,6.2395,10.6715,4.2513,1.3746,7.2543,11.3924,6.5668 +"Группа 2",34,"Мужской",171,"A (II)",1.1937,2.0692,11.7092,3.3324,1.5979,3.084,12.4301,5.6479 +"Группа 2",27,"Мужской",176,"A (II)",0.6806,3.4455,10.4657,4.775,1.0848,4.4603,11.1866,7.0905 +"Группа 2",32,"Женский",159,"O (I)",0.5602,1.6435,13.3411,4.1875,0.9644,2.6583,14.062,6.503 +"Группа 2",31,"Женский",168,"A (II)",0.7827,3.9147,13.1647,4.7969,1.1869,4.9295,13.8856,7.1124 +"Группа 2",31,"Мужской",168,"B (III)",0.92490000000000006,4.7131,11.0108,3.2465,1.3291,5.7279,11.7317,5.562 +"Группа 2",33,"Мужской",170,"B (III)",1.4613,7.2709,11.7787,4.0559,1.8655,8.2857,12.4996,6.3714 +"Группа 2",30,"Женский",165,"A (II)",0.2669,6.4108,14.4411,4.2103,0.6711,7.4256,15.162,6.5258 +"Группа 2",28,"Мужской",174,"A (II)",0.795,2.6174,10.9779,3.5962,1.1992,3.6322,11.6988,5.9117 +"Группа 2",29,"Мужской",171,"A (II)",0.482,4.9124,10.089,3.2071,0.8862,5.9272,10.8099,5.5226 +"Группа 2",29,"Женский",166,"O (I)",0.6358,4.7582,11.3264,3.5469,1.04,5.773,12.0473,5.8624 +"Группа 2",21,"Мужской",167,"O (I)",0.4371,2.5971,14.2052,4.3911,0.8413,3.6119,14.9261,6.7066 +"Группа 2",29,"Мужской",164,"O (I)",0.6036,6.0198,13.354,4.8232,1.0078,7.0346,14.0749,7.1387 +"Группа 2",33,"Женский",159,"O (I)",0.6529,4.3756,12.875,4.7547,1.0571,5.3904,13.5959,7.0702 +"Группа 2",42,"Женский",161,NA,0.8271,4.902,10.9604,4.7991,1.2313,5.9168,11.6813,7.1146 +"Группа 2",37,"Мужской",160,"A (II)",0.3053,4.7937,10.9401,3.2195,0.7095,5.8085,11.661,5.535 +"Группа 2",38,"Мужской",177,"O (I)",0.2841,4.5635,10.3758,5.1561,0.6883,5.5783,11.0967,7.4716 +"Группа 2",32,"Мужской",160,"A (II)",0.6112,-0.6534,11.9738,3.4066,1.0154,0.3614,12.6947,5.7221 +"Группа 2",28,"Мужской",166,"A (II)",0.6741,3.8194,9.8513,3.0476,1.0783,4.8342,10.5722,5.3631 +"Группа 2",34,"Мужской",163,NA,0.7178,6.2474,12.2265,4.0731,1.122,7.2622,12.9474,6.3886 +"Группа 2",35,"Женский",177,"A (II)",0.7161,6.1906,9.9169,2.8447,1.1203,7.2054,10.6378,5.1602 +"Группа 2",29,"Женский",176,"O (I)",1.1057,1.4231,13.8564,4.1773,1.5099,2.4379,14.5773,6.4928 +"Группа 2",33,"Мужской",170,"A (II)",0.4425,5.8075,10.7608,5.2198,0.8467,6.8223,11.4817,7.5353 +"Группа 2",32,"Мужской",174,NA,0.9519,7.4574,11.4253,3.6331,1.3561,8.4722,12.1462,5.9486 +"Группа 2",33,"Женский",161,"B (III)",1.0887,3.5337,10.8088,3.5177,1.4929,4.5485,11.5297,5.8332 +"Группа 2",32,"Женский",171,"O (I)",0.5839,2.5204,13.1545,4.0298,0.9881,3.5352,13.8754,6.3453 +"Группа 2",28,"Мужской",164,NA,1.0915,0.139,11.7136,4.578,1.4957,1.1538,12.4345,6.8935 +"Группа 2",25,"Мужской",176,"A (II)",0.4885,1.376,13.0178,4.039,0.8927,2.3908,13.7387,6.3545 +"Группа 2",30,"Женский",173,"O (I)",0.1545,4.3131,12.9821,5.1128,0.5587,5.3279,13.703,7.4283 +"Группа 2",32,"Женский",176,"B (III)",0.8272,-1.2272,10.2154,5.0766,1.2314,-0.2124,10.9363,7.3921 +"Группа 2",35,"Женский",169,"A (II)",1.3627,5.9156,11.9732,3.5125,1.7669,6.9304,12.6941,5.828 +"Группа 2",33,"Мужской",159,"AB (IV)",0.6324,5.7865,10.2755,3.6352,1.0366,6.8013,10.9964,5.9507 +"Группа 2",33,"Мужской",167,"O (I)",0.5179,7.4466,13.291,3.8014,0.9221,8.4614,14.0119,6.1169 +"Группа 2",30,"Мужской",164,NA,0.424,8.4344,10.829,3.8113,0.8282,9.4492,11.5499,6.1268 +"Группа 2",34,"Женский",168,"O (I)",0.9505,0.8028,13.4033,3.5868,1.3547,1.8176,14.1242,5.9023 +"Группа 2",30,"Женский",169,NA,0.7031,5.3706,12.2419,3.2039,1.1073,6.3854,12.9628,5.5194 diff --git a/course-project/starter/data/data_csv2.csv b/course-project/starter/data/data_csv2.csv new file mode 100644 index 0000000..025ce36 --- /dev/null +++ b/course-project/starter/data/data_csv2.csv @@ -0,0 +1,101 @@ +"Группа";"Возраст";"Пол";"Рост";"Группа крови";"Базофилы_E1";"Эозинофилы_E1";"Гемоглобин_E1";"Эритроциты_E1";"Базофилы_E2";"Эозинофилы_E2";"Гемоглобин_E2";"Эритроциты_E2" +"Группа 1";"31";"Женский";"174";"A (II)";"0,4222";"0,6465";"10,6842";"4,2573";"0,8264";"1,6613";"11,4051";"6,5728" +"Группа 1";"28";"Женский";"157";"A (II)";"0,3270";"4,9742";"9,6169";"3,8813";"0,7312";"5,9890";"10,3378";"6,1968" +"Группа 1";"33";"Женский";"166";NA;"0,7994";"3,3875";"10,1628";"5,0607";"1,2036";"4,4023";"10,8837";"7,3762" +"Группа 1";"26";"Женский";"168";"O (I)";"0,0237";"4,5403";"10,6391";"3,8083";"0,4279";"5,5551";"11,3600";"6,1238" +"Группа 1";"33";"Женский";"170";"A (II)";"0,6636";"3,3159";"12,2590";"3,0321";"1,0678";"4,3307";"12,9799";"5,3476" +"Группа 1";"28";"Мужской";"172";"B (III)";"0,4810";"2,7863";"12,3529";"4,7917";"0,8852";"3,8011";"13,0738";"7,1072" +"Группа 1";"27";"Мужской";"157";"A (II)";"0,8899";"2,3432";"11,2656";"3,3619";"1,2941";"3,3580";"11,9865";"5,6774" +"Группа 1";"31";"Мужской";"174";NA;"0,8576";"3,9788";"14,8948";"4,4598";"1,2618";"4,9936";"15,6157";"6,7753" +"Группа 1";"23";"Женский";"175";"A (II)";"0,3832";"3,3896";"15,6802";"4,4339";"0,7874";"4,4044";"16,4011";"6,7494" +"Группа 1";"29";"Женский";"172";"A (II)";"0,2812";"7,9352";"12,9084";"4,3275";"0,6854";"8,9500";"13,6293";"6,6430" +"Группа 1";"32";"Женский";"165";"A (II)";"0,8032";"2,4649";"10,1162";"3,4207";"1,2074";"3,4797";"10,8371";"5,7362" +"Группа 1";"33";"Мужской";"171";"B (III)";"0,7606";"2,8023";"11,0011";"4,3114";"1,1648";"3,8171";"11,7220";"6,6269" +"Группа 1";"30";"Женский";"176";NA;"-0,2188";"1,2468";"12,0861";"3,6621";"0,1854";"2,2616";"12,8070";"5,9776" +"Группа 1";"28";"Женский";"165";"O (I)";"0,5170";"8,1285";"11,4946";"2,8699";"0,9212";"9,1433";"12,2155";"5,1854" +"Группа 1";"25";"Женский";"170";"B (III)";"0,9893";"0,5132";"14,4936";"4,3594";"1,3935";"1,5280";"15,2145";"6,6749" +"Группа 1";"38";"Женский";"167";NA;"0,8990";"2,6541";"10,6878";"4,9044";"1,3032";"3,6689";"11,4087";"7,2199" +"Группа 1";"32";"Мужской";"177";"B (III)";"0,3413";"0,8715";"16,0903";"4,1925";"0,7455";"1,8863";"16,8112";"6,5080" +"Группа 1";"27";"Женский";"167";"B (III)";"0,4083";"3,7789";"13,2827";"4,5453";"0,8125";"4,7937";"14,0036";"6,8608" +"Группа 1";"28";"Женский";"169";"O (I)";"0,3009";"2,3743";"11,5597";"3,1849";"0,7051";"3,3891";"12,2806";"5,5004" +"Группа 1";"27";"Мужской";"158";"B (III)";"0,4160";"3,7980";"13,4759";"5,0699";"0,8202";"4,8128";"14,1968";"7,3854" +"Группа 1";"28";"Женский";"162";"O (I)";"0,8340";"2,5866";"12,3530";"3,7413";"1,2382";"3,6014";"13,0739";"6,0568" +"Группа 1";"31";"Женский";"164";"A (II)";"0,8936";"4,3898";"12,1520";"3,7300";"1,2978";"5,4046";"12,8729";"6,0455" +"Группа 1";"26";"Мужской";"171";NA;"0,8364";"5,0805";"8,6038";"4,6658";"1,2406";"6,0953";"9,3247";"6,9813" +"Группа 1";"34";"Женский";"173";NA;"0,8969";"4,5769";"14,0891";"3,7455";"1,3011";"5,5917";"14,8100";"6,0610" +"Группа 1";"27";"Мужской";"169";"O (I)";"0,5617";"5,6353";"11,1436";"3,8355";"0,9659";"6,6501";"11,8645";"6,1510" +"Группа 1";"31";"Женский";"173";"B (III)";"0,8466";"5,8133";"16,2315";"4,5226";"1,2508";"6,8281";"16,9524";"6,8381" +"Группа 1";"21";"Мужской";"156";"A (II)";"0,7375";"3,6625";"10,9569";"3,5251";"1,1417";"4,6773";"11,6778";"5,8406" +"Группа 1";"28";"Мужской";"164";NA;"0,8984";"0,2688";"13,7583";"3,9492";"1,3026";"1,2836";"14,4792";"6,2647" +"Группа 1";"27";"Женский";"168";"A (II)";"-0,0391";"1,6700";"10,4017";"3,6078";"0,3651";"2,6848";"11,1226";"5,9233" +"Группа 1";"33";"Мужской";"170";"O (I)";"-0,2002";"2,1515";"9,8202";"5,7281";"0,2040";"3,1663";"10,5411";"8,0436" +"Группа 1";"35";"Мужской";"155";"A (II)";"0,3337";"3,4448";"12,1903";"4,4991";"0,7379";"4,4596";"12,9112";"6,8146" +"Группа 1";"25";"Мужской";"175";NA;"0,2541";"3,8754";"15,2743";"4,7965";"0,6583";"4,8902";"15,9952";"7,1120" +"Группа 1";"36";"Женский";"169";"O (I)";"0,6489";"2,2938";"9,1329";"4,8499";"1,0531";"3,3086";"9,8538";"7,1654" +"Группа 1";"23";"Женский";"166";"O (I)";"0,4381";"2,5826";"11,1547";"4,4297";"0,8423";"3,5974";"11,8756";"6,7452" +"Группа 1";"32";"Женский";"162";"B (III)";"1,3054";"2,9359";"13,2145";"3,7860";"1,7096";"3,9507";"13,9354";"6,1015" +"Группа 1";"28";"Мужской";"165";"O (I)";"0,5758";"3,1627";"10,9963";"4,1499";"0,9800";"4,1775";"11,7172";"6,4654" +"Группа 1";"32";"Женский";"170";"B (III)";"0,2684";"1,8568";"11,2402";"3,3907";"0,6726";"2,8716";"11,9611";"5,7062" +"Группа 1";"31";"Женский";"171";"A (II)";"0,4208";"4,4054";"5,3523";"4,0110";"0,8250";"5,4202";"6,0732";"6,3265" +"Группа 1";"31";"Женский";"181";"B (III)";"0,1761";"3,0373";"9,5050";"4,7135";"0,5803";"4,0521";"10,2259";"7,0290" +"Группа 1";"25";"Женский";"179";"AB (IV)";"0,3180";"1,8673";"11,4646";"2,8206";"0,7222";"2,8821";"12,1855";"5,1361" +"Группа 1";"30";"Мужской";"156";"AB (IV)";"0,0509";"0,3804";"13,3238";"3,7554";"0,4551";"1,3952";"14,0447";"6,0709" +"Группа 1";"26";"Женский";"172";"AB (IV)";"0,4853";"3,3438";"10,5516";"4,4054";"0,8895";"4,3586";"11,2725";"6,7209" +"Группа 1";"33";"Женский";"164";"A (II)";"1,5915";"5,0897";"9,7669";"4,1358";"1,9957";"6,1045";"10,4878";"6,4513" +"Группа 1";"34";"Женский";"164";"A (II)";"0,3361";"4,2492";"12,4213";"4,2117";"0,7403";"5,2640";"13,1422";"6,5272" +"Группа 1";"24";"Женский";"163";NA;"0,2666";"2,3360";"15,1213";"4,7835";"0,6708";"3,3508";"15,8422";"7,0990" +"Группа 1";"25";"Женский";"171";"B (III)";"1,4540";"3,4946";"11,9013";"4,6613";"1,8582";"4,5094";"12,6222";"6,9768" +"Группа 1";"23";"Мужской";"162";"AB (IV)";"0,7981";"2,1393";"14,1017";"2,8917";"1,2023";"3,1541";"14,8226";"5,2072" +"Группа 1";"35";"Женский";"171";"A (II)";"0,3588";"5,0382";"10,6129";"4,4047";"0,7630";"6,0530";"11,3338";"6,7202" +"Группа 1";"29";"Мужской";"175";"O (I)";"0,8537";"-0,3005";"13,2050";"5,2975";"1,2579";"0,7143";"13,9259";"7,6130" +"Группа 1";"30";"Мужской";"171";"A (II)";"0,6650";"1,5940";"12,6169";"5,4316";"1,0692";"2,6088";"13,3378";"7,7471" +"Группа 2";"37";"Мужской";"165";"AB (IV)";"0,8954";"5,1303";"13,5317";"2,9260";"1,2996";"6,1451";"14,2526";"5,2415" +"Группа 2";"25";"Женский";"168";"O (I)";"1,3261";"6,8981";"13,2712";"4,0185";"1,7303";"7,9129";"13,9921";"6,3340" +"Группа 2";"32";"Женский";"159";"A (II)";"-0,0283";"4,0341";"8,8472";"3,5037";"0,3759";"5,0489";"9,5681";"5,8192" +"Группа 2";"35";"Мужской";"164";"AB (IV)";"0,8283";"7,0987";"10,1555";"3,9505";"1,2325";"8,1135";"10,8764";"6,2660" +"Группа 2";"29";"Мужской";"170";"O (I)";"0,4120";"6,0201";"9,6631";"4,0911";"0,8162";"7,0349";"10,3840";"6,4066" +"Группа 2";"34";"Мужской";"169";"B (III)";"0,3367";"3,6771";"11,9647";"5,2631";"0,7409";"4,6919";"12,6856";"7,5786" +"Группа 2";"34";"Мужской";"161";"A (II)";"0,7744";"4,4050";"11,9282";"3,2528";"1,1786";"5,4198";"12,6491";"5,5683" +"Группа 2";"27";"Женский";"167";NA;"0,1906";"3,8312";"11,2700";"5,0763";"0,5948";"4,8460";"11,9909";"7,3918" +"Группа 2";"34";"Женский";"175";"AB (IV)";"0,4139";"-1,0480";"10,5656";"3,9456";"0,8181";"-0,0332";"11,2865";"6,2611" +"Группа 2";"30";"Мужской";"167";"A (II)";"0,8407";"1,3026";"15,1292";"3,7485";"1,2449";"2,3174";"15,8501";"6,0640" +"Группа 2";"33";"Женский";"162";"A (II)";"1,0976";"6,3401";"10,9379";"4,3332";"1,5018";"7,3549";"11,6588";"6,6487" +"Группа 2";"26";"Мужской";"164";"O (I)";"0,8849";"1,4690";"12,1955";"4,9171";"1,2891";"2,4838";"12,9164";"7,2326" +"Группа 2";"28";"Мужской";"165";"A (II)";"1,7186";"5,9387";"11,2181";"4,2957";"2,1228";"6,9535";"11,9390";"6,6112" +"Группа 2";"35";"Мужской";"172";"O (I)";"1,2805";"7,0429";"12,3226";"4,0218";"1,6847";"8,0577";"13,0435";"6,3373" +"Группа 2";"22";"Женский";"161";NA;"0,9704";"6,2395";"10,6715";"4,2513";"1,3746";"7,2543";"11,3924";"6,5668" +"Группа 2";"34";"Мужской";"171";"A (II)";"1,1937";"2,0692";"11,7092";"3,3324";"1,5979";"3,0840";"12,4301";"5,6479" +"Группа 2";"27";"Мужской";"176";"A (II)";"0,6806";"3,4455";"10,4657";"4,7750";"1,0848";"4,4603";"11,1866";"7,0905" +"Группа 2";"32";"Женский";"159";"O (I)";"0,5602";"1,6435";"13,3411";"4,1875";"0,9644";"2,6583";"14,0620";"6,5030" +"Группа 2";"31";"Женский";"168";"A (II)";"0,7827";"3,9147";"13,1647";"4,7969";"1,1869";"4,9295";"13,8856";"7,1124" +"Группа 2";"31";"Мужской";"168";"B (III)";"0,9249";"4,7131";"11,0108";"3,2465";"1,3291";"5,7279";"11,7317";"5,5620" +"Группа 2";"33";"Мужской";"170";"B (III)";"1,4613";"7,2709";"11,7787";"4,0559";"1,8655";"8,2857";"12,4996";"6,3714" +"Группа 2";"30";"Женский";"165";"A (II)";"0,2669";"6,4108";"14,4411";"4,2103";"0,6711";"7,4256";"15,1620";"6,5258" +"Группа 2";"28";"Мужской";"174";"A (II)";"0,7950";"2,6174";"10,9779";"3,5962";"1,1992";"3,6322";"11,6988";"5,9117" +"Группа 2";"29";"Мужской";"171";"A (II)";"0,4820";"4,9124";"10,0890";"3,2071";"0,8862";"5,9272";"10,8099";"5,5226" +"Группа 2";"29";"Женский";"166";"O (I)";"0,6358";"4,7582";"11,3264";"3,5469";"1,0400";"5,7730";"12,0473";"5,8624" +"Группа 2";"21";"Мужской";"167";"O (I)";"0,4371";"2,5971";"14,2052";"4,3911";"0,8413";"3,6119";"14,9261";"6,7066" +"Группа 2";"29";"Мужской";"164";"O (I)";"0,6036";"6,0198";"13,3540";"4,8232";"1,0078";"7,0346";"14,0749";"7,1387" +"Группа 2";"33";"Женский";"159";"O (I)";"0,6529";"4,3756";"12,8750";"4,7547";"1,0571";"5,3904";"13,5959";"7,0702" +"Группа 2";"42";"Женский";"161";NA;"0,8271";"4,9020";"10,9604";"4,7991";"1,2313";"5,9168";"11,6813";"7,1146" +"Группа 2";"37";"Мужской";"160";"A (II)";"0,3053";"4,7937";"10,9401";"3,2195";"0,7095";"5,8085";"11,6610";"5,5350" +"Группа 2";"38";"Мужской";"177";"O (I)";"0,2841";"4,5635";"10,3758";"5,1561";"0,6883";"5,5783";"11,0967";"7,4716" +"Группа 2";"32";"Мужской";"160";"A (II)";"0,6112";"-0,6534";"11,9738";"3,4066";"1,0154";"0,3614";"12,6947";"5,7221" +"Группа 2";"28";"Мужской";"166";"A (II)";"0,6741";"3,8194";"9,8513";"3,0476";"1,0783";"4,8342";"10,5722";"5,3631" +"Группа 2";"34";"Мужской";"163";NA;"0,7178";"6,2474";"12,2265";"4,0731";"1,1220";"7,2622";"12,9474";"6,3886" +"Группа 2";"35";"Женский";"177";"A (II)";"0,7161";"6,1906";"9,9169";"2,8447";"1,1203";"7,2054";"10,6378";"5,1602" +"Группа 2";"29";"Женский";"176";"O (I)";"1,1057";"1,4231";"13,8564";"4,1773";"1,5099";"2,4379";"14,5773";"6,4928" +"Группа 2";"33";"Мужской";"170";"A (II)";"0,4425";"5,8075";"10,7608";"5,2198";"0,8467";"6,8223";"11,4817";"7,5353" +"Группа 2";"32";"Мужской";"174";NA;"0,9519";"7,4574";"11,4253";"3,6331";"1,3561";"8,4722";"12,1462";"5,9486" +"Группа 2";"33";"Женский";"161";"B (III)";"1,0887";"3,5337";"10,8088";"3,5177";"1,4929";"4,5485";"11,5297";"5,8332" +"Группа 2";"32";"Женский";"171";"O (I)";"0,5839";"2,5204";"13,1545";"4,0298";"0,9881";"3,5352";"13,8754";"6,3453" +"Группа 2";"28";"Мужской";"164";NA;"1,0915";"0,1390";"11,7136";"4,5780";"1,4957";"1,1538";"12,4345";"6,8935" +"Группа 2";"25";"Мужской";"176";"A (II)";"0,4885";"1,3760";"13,0178";"4,0390";"0,8927";"2,3908";"13,7387";"6,3545" +"Группа 2";"30";"Женский";"173";"O (I)";"0,1545";"4,3131";"12,9821";"5,1128";"0,5587";"5,3279";"13,7030";"7,4283" +"Группа 2";"32";"Женский";"176";"B (III)";"0,8272";"-1,2272";"10,2154";"5,0766";"1,2314";"-0,2124";"10,9363";"7,3921" +"Группа 2";"35";"Женский";"169";"A (II)";"1,3627";"5,9156";"11,9732";"3,5125";"1,7669";"6,9304";"12,6941";"5,8280" +"Группа 2";"33";"Мужской";"159";"AB (IV)";"0,6324";"5,7865";"10,2755";"3,6352";"1,0366";"6,8013";"10,9964";"5,9507" +"Группа 2";"33";"Мужской";"167";"O (I)";"0,5179";"7,4466";"13,2910";"3,8014";"0,9221";"8,4614";"14,0119";"6,1169" +"Группа 2";"30";"Мужской";"164";NA;"0,4240";"8,4344";"10,8290";"3,8113";"0,8282";"9,4492";"11,5499";"6,1268" +"Группа 2";"34";"Женский";"168";"O (I)";"0,9505";"0,8028";"13,4033";"3,5868";"1,3547";"1,8176";"14,1242";"5,9023" +"Группа 2";"30";"Женский";"169";NA;"0,7031";"5,3706";"12,2419";"3,2039";"1,1073";"6,3854";"12,9628";"5,5194" diff --git a/course-project/starter/data/data_excel.xlsx b/course-project/starter/data/data_excel.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..9b828eca8dfed30501c429626b6f0ccb5e3851c2 GIT binary patch literal 19971 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 p8v_GI&5EuawfsZYzR?3oJG3+m@MZ5H^#=`&r literal 0 HcmV?d00001 diff --git a/course-project/starter/data/data_rds.rds b/course-project/starter/data/data_rds.rds new file mode 100644 index 0000000000000000000000000000000000000000..92bbacb4caee30e40ea654cd2b54efac13b2562d GIT binary patch literal 11661 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 literal 0 HcmV?d00001 diff --git a/course-project/starter/data/data_tsv.tsv b/course-project/starter/data/data_tsv.tsv new file mode 100644 index 0000000..cdc3217 --- /dev/null +++ b/course-project/starter/data/data_tsv.tsv @@ -0,0 +1,101 @@ +Группа Возраст Пол Рост Группа крови Базофилы_E1 Эозинофилы_E1 Гемоглобин_E1 Эритроциты_E1 Базофилы_E2 Эозинофилы_E2 Гемоглобин_E2 Эритроциты_E2 +Группа 1 31 Женский 174 A (II) 0.4222 0.6465 10.6842 4.2573 0.8264 1.6613 11.4051 6.5728 +Группа 1 28 Женский 157 A (II) 0.327 4.9742 9.6169 3.8813 0.7312 5.989 10.3378 6.1968 +Группа 1 33 Женский 166 NA 0.7994 3.3875 10.1628 5.0607 1.2036 4.4023 10.8837 7.3762 +Группа 1 26 Женский 168 O (I) 0.0237 4.5403 10.6391 3.8083 0.4279 5.5551 11.36 6.1238 +Группа 1 33 Женский 170 A (II) 0.6636 3.3159 12.259 3.0321 1.0678 4.3307 12.9799 5.3476 +Группа 1 28 Мужской 172 B (III) 0.481 2.7863 12.3529 4.7917 0.8852 3.8011 13.0738 7.1072 +Группа 1 27 Мужской 157 A (II) 0.8899 2.3432 11.2656 3.3619 1.2941 3.358 11.9865 5.6774 +Группа 1 31 Мужской 174 NA 0.8576 3.9788 14.8948 4.4598 1.2618 4.9936 15.6157 6.7753 +Группа 1 23 Женский 175 A (II) 0.3832 3.3896 15.6802 4.4339 0.7874 4.4044 16.4011 6.7494 +Группа 1 29 Женский 172 A (II) 0.2812 7.9352 12.9084 4.3275 0.6854 8.95 13.6293 6.643 +Группа 1 32 Женский 165 A (II) 0.8032 2.4649 10.1162 3.4207 1.2074 3.4797 10.8371 5.7362 +Группа 1 33 Мужской 171 B (III) 0.7606 2.8023 11.0011 4.3114 1.1648 3.8171 11.722 6.6269 +Группа 1 30 Женский 176 NA -0.2188 1.2468 12.0861 3.6621 0.1854 2.2616 12.807 5.9776 +Группа 1 28 Женский 165 O (I) 0.517 8.1285 11.4946 2.8699 0.9212 9.1433 12.2155 5.1854 +Группа 1 25 Женский 170 B (III) 0.9893 0.5132 14.4936 4.3594 1.3935 1.528 15.2145 6.6749 +Группа 1 38 Женский 167 NA 0.899 2.6541 10.6878 4.9044 1.3032 3.6689 11.4087 7.2199 +Группа 1 32 Мужской 177 B (III) 0.3413 0.8715 16.0903 4.1925 0.7455 1.8863 16.8112 6.508 +Группа 1 27 Женский 167 B (III) 0.4083 3.7789 13.2827 4.5453 0.8125 4.7937 14.0036 6.8608 +Группа 1 28 Женский 169 O (I) 0.3009 2.3743 11.5597 3.1849 0.7051 3.3891 12.2806 5.5004 +Группа 1 27 Мужской 158 B (III) 0.416 3.798 13.4759 5.0699 0.8202 4.8128 14.1968 7.3854 +Группа 1 28 Женский 162 O (I) 0.834 2.5866 12.353 3.7413 1.2382 3.6014 13.0739 6.0568 +Группа 1 31 Женский 164 A (II) 0.8936 4.3898 12.152 3.73 1.2978 5.4046 12.8729 6.0455 +Группа 1 26 Мужской 171 NA 0.8364 5.0805 8.6038 4.6658 1.2406 6.0953 9.3247 6.9813 +Группа 1 34 Женский 173 NA 0.8969 4.5769 14.0891 3.7455 1.3011 5.5917 14.81 6.061 +Группа 1 27 Мужской 169 O (I) 0.5617 5.6353 11.1436 3.8355 0.9659 6.6501 11.8645 6.151 +Группа 1 31 Женский 173 B (III) 0.8466 5.8133 16.2315 4.5226 1.2508 6.8281 16.9524 6.8381 +Группа 1 21 Мужской 156 A (II) 0.7375 3.6625 10.9569 3.5251 1.1417 4.6773 11.6778 5.8406 +Группа 1 28 Мужской 164 NA 0.8984 0.2688 13.7583 3.9492 1.3026 1.2836 14.4792 6.2647 +Группа 1 27 Женский 168 A (II) -0.0391 1.67 10.4017 3.6078 0.3651 2.6848 11.1226 5.9233 +Группа 1 33 Мужской 170 O (I) -0.2002 2.1515 9.8202 5.7281 0.204 3.1663 10.5411 8.0436 +Группа 1 35 Мужской 155 A (II) 0.3337 3.4448 12.1903 4.4991 0.7379 4.4596 12.9112 6.8146 +Группа 1 25 Мужской 175 NA 0.2541 3.8754 15.2743 4.7965 0.6583 4.8902 15.9952 7.112 +Группа 1 36 Женский 169 O (I) 0.6489 2.2938 9.1329 4.8499 1.0531 3.3086 9.8538 7.1654 +Группа 1 23 Женский 166 O (I) 0.4381 2.5826 11.1547 4.4297 0.8423 3.5974 11.8756 6.7452 +Группа 1 32 Женский 162 B (III) 1.3054 2.9359 13.2145 3.786 1.7096 3.9507 13.9354 6.1015 +Группа 1 28 Мужской 165 O (I) 0.5758 3.1627 10.9963 4.1499 0.98 4.1775 11.7172 6.4654 +Группа 1 32 Женский 170 B (III) 0.2684 1.8568 11.2402 3.3907 0.6726 2.8716 11.9611 5.7062 +Группа 1 31 Женский 171 A (II) 0.4208 4.4054 5.3523 4.011 0.825 5.4202 6.0732 6.3265 +Группа 1 31 Женский 181 B (III) 0.1761 3.0373 9.505 4.7135 0.5803 4.0521 10.2259 7.029 +Группа 1 25 Женский 179 AB (IV) 0.318 1.8673 11.4646 2.8206 0.7222 2.8821 12.1855 5.1361 +Группа 1 30 Мужской 156 AB (IV) 0.0509 0.3804 13.3238 3.7554 0.4551 1.3952 14.0447 6.0709 +Группа 1 26 Женский 172 AB (IV) 0.4853 3.3438 10.5516 4.4054 0.8895 4.3586 11.2725 6.7209 +Группа 1 33 Женский 164 A (II) 1.5915 5.0897 9.7669 4.1358 1.9957 6.1045 10.4878 6.4513 +Группа 1 34 Женский 164 A (II) 0.3361 4.2492 12.4213 4.2117000000000004 0.7403 5.264 13.1422 6.5272 +Группа 1 24 Женский 163 NA 0.2666 2.336 15.1213 4.7835 0.6708 3.3508 15.8422 7.099 +Группа 1 25 Женский 171 B (III) 1.454 3.4946 11.9013 4.6613 1.8582 4.5094 12.6222 6.9768 +Группа 1 23 Мужской 162 AB (IV) 0.7981 2.1393 14.1017 2.8917 1.2023 3.1541 14.8226 5.2072 +Группа 1 35 Женский 171 A (II) 0.3588 5.0382 10.6129 4.4047 0.763 6.053 11.3338 6.7202 +Группа 1 29 Мужской 175 O (I) 0.8537 -0.3005 13.205 5.2975 1.2579 0.7143 13.9259 7.613 +Группа 1 30 Мужской 171 A (II) 0.665 1.594 12.6169 5.4316 1.0692 2.6088 13.3378 7.7471 +Группа 2 37 Мужской 165 AB (IV) 0.8954 5.1303 13.5317 2.926 1.2996 6.1451 14.2526 5.2415 +Группа 2 25 Женский 168 O (I) 1.3261 6.8981 13.2712 4.0185 1.7303 7.9129 13.9921 6.334 +Группа 2 32 Женский 159 A (II) -0.0283 4.0341 8.8472 3.5037 0.3759 5.0489 9.5681 5.8192 +Группа 2 35 Мужской 164 AB (IV) 0.8283 7.0987 10.1555 3.9505 1.2325 8.1135 10.8764 6.266 +Группа 2 29 Мужской 170 O (I) 0.412 6.0201 9.6631 4.0911 0.8162 7.0349 10.384 6.4066 +Группа 2 34 Мужской 169 B (III) 0.3367 3.6771 11.9647 5.2631 0.7409 4.6919 12.6856 7.5786 +Группа 2 34 Мужской 161 A (II) 0.7744 4.405 11.9282 3.2528 1.1786 5.4198 12.6491 5.5683 +Группа 2 27 Женский 167 NA 0.1906 3.8312 11.27 5.0763 0.5948 4.846 11.9909 7.3918 +Группа 2 34 Женский 175 AB (IV) 0.4139 -1.048 10.5656 3.9456 0.8181 -0.0332 11.2865 6.2611 +Группа 2 30 Мужской 167 A (II) 0.8407 1.3026 15.1292 3.7485 1.2449 2.3174 15.8501 6.064 +Группа 2 33 Женский 162 A (II) 1.0976 6.3401 10.9379 4.3332 1.5018 7.3549 11.6588 6.6487 +Группа 2 26 Мужской 164 O (I) 0.8849 1.469 12.1955 4.9171 1.2891 2.4838 12.9164 7.2326 +Группа 2 28 Мужской 165 A (II) 1.7186 5.9387 11.2181 4.2957 2.1228 6.9535 11.939 6.6112 +Группа 2 35 Мужской 172 O (I) 1.2805 7.0429 12.3226 4.0218 1.6847 8.0577 13.0435 6.3373 +Группа 2 22 Женский 161 NA 0.9704 6.2395 10.6715 4.2513 1.3746 7.2543 11.3924 6.5668 +Группа 2 34 Мужской 171 A (II) 1.1937 2.0692 11.7092 3.3324 1.5979 3.084 12.4301 5.6479 +Группа 2 27 Мужской 176 A (II) 0.6806 3.4455 10.4657 4.775 1.0848 4.4603 11.1866 7.0905 +Группа 2 32 Женский 159 O (I) 0.5602 1.6435 13.3411 4.1875 0.9644 2.6583 14.062 6.503 +Группа 2 31 Женский 168 A (II) 0.7827 3.9147 13.1647 4.7969 1.1869 4.9295 13.8856 7.1124 +Группа 2 31 Мужской 168 B (III) 0.92490000000000006 4.7131 11.0108 3.2465 1.3291 5.7279 11.7317 5.562 +Группа 2 33 Мужской 170 B (III) 1.4613 7.2709 11.7787 4.0559 1.8655 8.2857 12.4996 6.3714 +Группа 2 30 Женский 165 A (II) 0.2669 6.4108 14.4411 4.2103 0.6711 7.4256 15.162 6.5258 +Группа 2 28 Мужской 174 A (II) 0.795 2.6174 10.9779 3.5962 1.1992 3.6322 11.6988 5.9117 +Группа 2 29 Мужской 171 A (II) 0.482 4.9124 10.089 3.2071 0.8862 5.9272 10.8099 5.5226 +Группа 2 29 Женский 166 O (I) 0.6358 4.7582 11.3264 3.5469 1.04 5.773 12.0473 5.8624 +Группа 2 21 Мужской 167 O (I) 0.4371 2.5971 14.2052 4.3911 0.8413 3.6119 14.9261 6.7066 +Группа 2 29 Мужской 164 O (I) 0.6036 6.0198 13.354 4.8232 1.0078 7.0346 14.0749 7.1387 +Группа 2 33 Женский 159 O (I) 0.6529 4.3756 12.875 4.7547 1.0571 5.3904 13.5959 7.0702 +Группа 2 42 Женский 161 NA 0.8271 4.902 10.9604 4.7991 1.2313 5.9168 11.6813 7.1146 +Группа 2 37 Мужской 160 A (II) 0.3053 4.7937 10.9401 3.2195 0.7095 5.8085 11.661 5.535 +Группа 2 38 Мужской 177 O (I) 0.2841 4.5635 10.3758 5.1561 0.6883 5.5783 11.0967 7.4716 +Группа 2 32 Мужской 160 A (II) 0.6112 -0.6534 11.9738 3.4066 1.0154 0.3614 12.6947 5.7221 +Группа 2 28 Мужской 166 A (II) 0.6741 3.8194 9.8513 3.0476 1.0783 4.8342 10.5722 5.3631 +Группа 2 34 Мужской 163 NA 0.7178 6.2474 12.2265 4.0731 1.122 7.2622 12.9474 6.3886 +Группа 2 35 Женский 177 A (II) 0.7161 6.1906 9.9169 2.8447 1.1203 7.2054 10.6378 5.1602 +Группа 2 29 Женский 176 O (I) 1.1057 1.4231 13.8564 4.1773 1.5099 2.4379 14.5773 6.4928 +Группа 2 33 Мужской 170 A (II) 0.4425 5.8075 10.7608 5.2198 0.8467 6.8223 11.4817 7.5353 +Группа 2 32 Мужской 174 NA 0.9519 7.4574 11.4253 3.6331 1.3561 8.4722 12.1462 5.9486 +Группа 2 33 Женский 161 B (III) 1.0887 3.5337 10.8088 3.5177 1.4929 4.5485 11.5297 5.8332 +Группа 2 32 Женский 171 O (I) 0.5839 2.5204 13.1545 4.0298 0.9881 3.5352 13.8754 6.3453 +Группа 2 28 Мужской 164 NA 1.0915 0.139 11.7136 4.578 1.4957 1.1538 12.4345 6.8935 +Группа 2 25 Мужской 176 A (II) 0.4885 1.376 13.0178 4.039 0.8927 2.3908 13.7387 6.3545 +Группа 2 30 Женский 173 O (I) 0.1545 4.3131 12.9821 5.1128 0.5587 5.3279 13.703 7.4283 +Группа 2 32 Женский 176 B (III) 0.8272 -1.2272 10.2154 5.0766 1.2314 -0.2124 10.9363 7.3921 +Группа 2 35 Женский 169 A (II) 1.3627 5.9156 11.9732 3.5125 1.7669 6.9304 12.6941 5.828 +Группа 2 33 Мужской 159 AB (IV) 0.6324 5.7865 10.2755 3.6352 1.0366 6.8013 10.9964 5.9507 +Группа 2 33 Мужской 167 O (I) 0.5179 7.4466 13.291 3.8014 0.9221 8.4614 14.0119 6.1169 +Группа 2 30 Мужской 164 NA 0.424 8.4344 10.829 3.8113 0.8282 9.4492 11.5499 6.1268 +Группа 2 34 Женский 168 O (I) 0.9505 0.8028 13.4033 3.5868 1.3547 1.8176 14.1242 5.9023 +Группа 2 30 Женский 169 NA 0.7031 5.3706 12.2419 3.2039 1.1073 6.3854 12.9628 5.5194 diff --git a/course-project/starter/data/penguins.csv b/course-project/starter/data/penguins.csv new file mode 100644 index 0000000..3a39afa --- /dev/null +++ b/course-project/starter/data/penguins.csv @@ -0,0 +1,345 @@ +"species","island","bill_len","bill_dep","flipper_len","body_mass","sex","year" +"Adelie","Torgersen",39.1,18.7,181,3750,"male",2007 +"Adelie","Torgersen",39.5,17.4,186,3800,"female",2007 +"Adelie","Torgersen",40.3,18,195,3250,"female",2007 +"Adelie","Torgersen",,,,,,2007 +"Adelie","Torgersen",36.7,19.3,193,3450,"female",2007 +"Adelie","Torgersen",39.3,20.6,190,3650,"male",2007 +"Adelie","Torgersen",38.9,17.8,181,3625,"female",2007 +"Adelie","Torgersen",39.2,19.6,195,4675,"male",2007 +"Adelie","Torgersen",34.1,18.1,193,3475,,2007 +"Adelie","Torgersen",42,20.2,190,4250,,2007 +"Adelie","Torgersen",37.8,17.1,186,3300,,2007 +"Adelie","Torgersen",37.8,17.3,180,3700,,2007 +"Adelie","Torgersen",41.1,17.6,182,3200,"female",2007 +"Adelie","Torgersen",38.6,21.2,191,3800,"male",2007 +"Adelie","Torgersen",34.6,21.1,198,4400,"male",2007 +"Adelie","Torgersen",36.6,17.8,185,3700,"female",2007 +"Adelie","Torgersen",38.7,19,195,3450,"female",2007 +"Adelie","Torgersen",42.5,20.7,197,4500,"male",2007 +"Adelie","Torgersen",34.4,18.4,184,3325,"female",2007 +"Adelie","Torgersen",46,21.5,194,4200,"male",2007 +"Adelie","Biscoe",37.8,18.3,174,3400,"female",2007 +"Adelie","Biscoe",37.7,18.7,180,3600,"male",2007 +"Adelie","Biscoe",35.9,19.2,189,3800,"female",2007 +"Adelie","Biscoe",38.2,18.1,185,3950,"male",2007 +"Adelie","Biscoe",38.8,17.2,180,3800,"male",2007 +"Adelie","Biscoe",35.3,18.9,187,3800,"female",2007 +"Adelie","Biscoe",40.6,18.6,183,3550,"male",2007 +"Adelie","Biscoe",40.5,17.9,187,3200,"female",2007 +"Adelie","Biscoe",37.9,18.6,172,3150,"female",2007 +"Adelie","Biscoe",40.5,18.9,180,3950,"male",2007 +"Adelie","Dream",39.5,16.7,178,3250,"female",2007 +"Adelie","Dream",37.2,18.1,178,3900,"male",2007 +"Adelie","Dream",39.5,17.8,188,3300,"female",2007 +"Adelie","Dream",40.9,18.9,184,3900,"male",2007 +"Adelie","Dream",36.4,17,195,3325,"female",2007 +"Adelie","Dream",39.2,21.1,196,4150,"male",2007 +"Adelie","Dream",38.8,20,190,3950,"male",2007 +"Adelie","Dream",42.2,18.5,180,3550,"female",2007 +"Adelie","Dream",37.6,19.3,181,3300,"female",2007 +"Adelie","Dream",39.8,19.1,184,4650,"male",2007 +"Adelie","Dream",36.5,18,182,3150,"female",2007 +"Adelie","Dream",40.8,18.4,195,3900,"male",2007 +"Adelie","Dream",36,18.5,186,3100,"female",2007 +"Adelie","Dream",44.1,19.7,196,4400,"male",2007 +"Adelie","Dream",37,16.9,185,3000,"female",2007 +"Adelie","Dream",39.6,18.8,190,4600,"male",2007 +"Adelie","Dream",41.1,19,182,3425,"male",2007 +"Adelie","Dream",37.5,18.9,179,2975,,2007 +"Adelie","Dream",36,17.9,190,3450,"female",2007 +"Adelie","Dream",42.3,21.2,191,4150,"male",2007 +"Adelie","Biscoe",39.6,17.7,186,3500,"female",2008 +"Adelie","Biscoe",40.1,18.9,188,4300,"male",2008 +"Adelie","Biscoe",35,17.9,190,3450,"female",2008 +"Adelie","Biscoe",42,19.5,200,4050,"male",2008 +"Adelie","Biscoe",34.5,18.1,187,2900,"female",2008 +"Adelie","Biscoe",41.4,18.6,191,3700,"male",2008 +"Adelie","Biscoe",39,17.5,186,3550,"female",2008 +"Adelie","Biscoe",40.6,18.8,193,3800,"male",2008 +"Adelie","Biscoe",36.5,16.6,181,2850,"female",2008 +"Adelie","Biscoe",37.6,19.1,194,3750,"male",2008 +"Adelie","Biscoe",35.7,16.9,185,3150,"female",2008 +"Adelie","Biscoe",41.3,21.1,195,4400,"male",2008 +"Adelie","Biscoe",37.6,17,185,3600,"female",2008 +"Adelie","Biscoe",41.1,18.2,192,4050,"male",2008 +"Adelie","Biscoe",36.4,17.1,184,2850,"female",2008 +"Adelie","Biscoe",41.6,18,192,3950,"male",2008 +"Adelie","Biscoe",35.5,16.2,195,3350,"female",2008 +"Adelie","Biscoe",41.1,19.1,188,4100,"male",2008 +"Adelie","Torgersen",35.9,16.6,190,3050,"female",2008 +"Adelie","Torgersen",41.8,19.4,198,4450,"male",2008 +"Adelie","Torgersen",33.5,19,190,3600,"female",2008 +"Adelie","Torgersen",39.7,18.4,190,3900,"male",2008 +"Adelie","Torgersen",39.6,17.2,196,3550,"female",2008 +"Adelie","Torgersen",45.8,18.9,197,4150,"male",2008 +"Adelie","Torgersen",35.5,17.5,190,3700,"female",2008 +"Adelie","Torgersen",42.8,18.5,195,4250,"male",2008 +"Adelie","Torgersen",40.9,16.8,191,3700,"female",2008 +"Adelie","Torgersen",37.2,19.4,184,3900,"male",2008 +"Adelie","Torgersen",36.2,16.1,187,3550,"female",2008 +"Adelie","Torgersen",42.1,19.1,195,4000,"male",2008 +"Adelie","Torgersen",34.6,17.2,189,3200,"female",2008 +"Adelie","Torgersen",42.9,17.6,196,4700,"male",2008 +"Adelie","Torgersen",36.7,18.8,187,3800,"female",2008 +"Adelie","Torgersen",35.1,19.4,193,4200,"male",2008 +"Adelie","Dream",37.3,17.8,191,3350,"female",2008 +"Adelie","Dream",41.3,20.3,194,3550,"male",2008 +"Adelie","Dream",36.3,19.5,190,3800,"male",2008 +"Adelie","Dream",36.9,18.6,189,3500,"female",2008 +"Adelie","Dream",38.3,19.2,189,3950,"male",2008 +"Adelie","Dream",38.9,18.8,190,3600,"female",2008 +"Adelie","Dream",35.7,18,202,3550,"female",2008 +"Adelie","Dream",41.1,18.1,205,4300,"male",2008 +"Adelie","Dream",34,17.1,185,3400,"female",2008 +"Adelie","Dream",39.6,18.1,186,4450,"male",2008 +"Adelie","Dream",36.2,17.3,187,3300,"female",2008 +"Adelie","Dream",40.8,18.9,208,4300,"male",2008 +"Adelie","Dream",38.1,18.6,190,3700,"female",2008 +"Adelie","Dream",40.3,18.5,196,4350,"male",2008 +"Adelie","Dream",33.1,16.1,178,2900,"female",2008 +"Adelie","Dream",43.2,18.5,192,4100,"male",2008 +"Adelie","Biscoe",35,17.9,192,3725,"female",2009 +"Adelie","Biscoe",41,20,203,4725,"male",2009 +"Adelie","Biscoe",37.7,16,183,3075,"female",2009 +"Adelie","Biscoe",37.8,20,190,4250,"male",2009 +"Adelie","Biscoe",37.9,18.6,193,2925,"female",2009 +"Adelie","Biscoe",39.7,18.9,184,3550,"male",2009 +"Adelie","Biscoe",38.6,17.2,199,3750,"female",2009 +"Adelie","Biscoe",38.2,20,190,3900,"male",2009 +"Adelie","Biscoe",38.1,17,181,3175,"female",2009 +"Adelie","Biscoe",43.2,19,197,4775,"male",2009 +"Adelie","Biscoe",38.1,16.5,198,3825,"female",2009 +"Adelie","Biscoe",45.6,20.3,191,4600,"male",2009 +"Adelie","Biscoe",39.7,17.7,193,3200,"female",2009 +"Adelie","Biscoe",42.2,19.5,197,4275,"male",2009 +"Adelie","Biscoe",39.6,20.7,191,3900,"female",2009 +"Adelie","Biscoe",42.7,18.3,196,4075,"male",2009 +"Adelie","Torgersen",38.6,17,188,2900,"female",2009 +"Adelie","Torgersen",37.3,20.5,199,3775,"male",2009 +"Adelie","Torgersen",35.7,17,189,3350,"female",2009 +"Adelie","Torgersen",41.1,18.6,189,3325,"male",2009 +"Adelie","Torgersen",36.2,17.2,187,3150,"female",2009 +"Adelie","Torgersen",37.7,19.8,198,3500,"male",2009 +"Adelie","Torgersen",40.2,17,176,3450,"female",2009 +"Adelie","Torgersen",41.4,18.5,202,3875,"male",2009 +"Adelie","Torgersen",35.2,15.9,186,3050,"female",2009 +"Adelie","Torgersen",40.6,19,199,4000,"male",2009 +"Adelie","Torgersen",38.8,17.6,191,3275,"female",2009 +"Adelie","Torgersen",41.5,18.3,195,4300,"male",2009 +"Adelie","Torgersen",39,17.1,191,3050,"female",2009 +"Adelie","Torgersen",44.1,18,210,4000,"male",2009 +"Adelie","Torgersen",38.5,17.9,190,3325,"female",2009 +"Adelie","Torgersen",43.1,19.2,197,3500,"male",2009 +"Adelie","Dream",36.8,18.5,193,3500,"female",2009 +"Adelie","Dream",37.5,18.5,199,4475,"male",2009 +"Adelie","Dream",38.1,17.6,187,3425,"female",2009 +"Adelie","Dream",41.1,17.5,190,3900,"male",2009 +"Adelie","Dream",35.6,17.5,191,3175,"female",2009 +"Adelie","Dream",40.2,20.1,200,3975,"male",2009 +"Adelie","Dream",37,16.5,185,3400,"female",2009 +"Adelie","Dream",39.7,17.9,193,4250,"male",2009 +"Adelie","Dream",40.2,17.1,193,3400,"female",2009 +"Adelie","Dream",40.6,17.2,187,3475,"male",2009 +"Adelie","Dream",32.1,15.5,188,3050,"female",2009 +"Adelie","Dream",40.7,17,190,3725,"male",2009 +"Adelie","Dream",37.3,16.8,192,3000,"female",2009 +"Adelie","Dream",39,18.7,185,3650,"male",2009 +"Adelie","Dream",39.2,18.6,190,4250,"male",2009 +"Adelie","Dream",36.6,18.4,184,3475,"female",2009 +"Adelie","Dream",36,17.8,195,3450,"female",2009 +"Adelie","Dream",37.8,18.1,193,3750,"male",2009 +"Adelie","Dream",36,17.1,187,3700,"female",2009 +"Adelie","Dream",41.5,18.5,201,4000,"male",2009 +"Gentoo","Biscoe",46.1,13.2,211,4500,"female",2007 +"Gentoo","Biscoe",50,16.3,230,5700,"male",2007 +"Gentoo","Biscoe",48.7,14.1,210,4450,"female",2007 +"Gentoo","Biscoe",50,15.2,218,5700,"male",2007 +"Gentoo","Biscoe",47.6,14.5,215,5400,"male",2007 +"Gentoo","Biscoe",46.5,13.5,210,4550,"female",2007 +"Gentoo","Biscoe",45.4,14.6,211,4800,"female",2007 +"Gentoo","Biscoe",46.7,15.3,219,5200,"male",2007 +"Gentoo","Biscoe",43.3,13.4,209,4400,"female",2007 +"Gentoo","Biscoe",46.8,15.4,215,5150,"male",2007 +"Gentoo","Biscoe",40.9,13.7,214,4650,"female",2007 +"Gentoo","Biscoe",49,16.1,216,5550,"male",2007 +"Gentoo","Biscoe",45.5,13.7,214,4650,"female",2007 +"Gentoo","Biscoe",48.4,14.6,213,5850,"male",2007 +"Gentoo","Biscoe",45.8,14.6,210,4200,"female",2007 +"Gentoo","Biscoe",49.3,15.7,217,5850,"male",2007 +"Gentoo","Biscoe",42,13.5,210,4150,"female",2007 +"Gentoo","Biscoe",49.2,15.2,221,6300,"male",2007 +"Gentoo","Biscoe",46.2,14.5,209,4800,"female",2007 +"Gentoo","Biscoe",48.7,15.1,222,5350,"male",2007 +"Gentoo","Biscoe",50.2,14.3,218,5700,"male",2007 +"Gentoo","Biscoe",45.1,14.5,215,5000,"female",2007 +"Gentoo","Biscoe",46.5,14.5,213,4400,"female",2007 +"Gentoo","Biscoe",46.3,15.8,215,5050,"male",2007 +"Gentoo","Biscoe",42.9,13.1,215,5000,"female",2007 +"Gentoo","Biscoe",46.1,15.1,215,5100,"male",2007 +"Gentoo","Biscoe",44.5,14.3,216,4100,,2007 +"Gentoo","Biscoe",47.8,15,215,5650,"male",2007 +"Gentoo","Biscoe",48.2,14.3,210,4600,"female",2007 +"Gentoo","Biscoe",50,15.3,220,5550,"male",2007 +"Gentoo","Biscoe",47.3,15.3,222,5250,"male",2007 +"Gentoo","Biscoe",42.8,14.2,209,4700,"female",2007 +"Gentoo","Biscoe",45.1,14.5,207,5050,"female",2007 +"Gentoo","Biscoe",59.6,17,230,6050,"male",2007 +"Gentoo","Biscoe",49.1,14.8,220,5150,"female",2008 +"Gentoo","Biscoe",48.4,16.3,220,5400,"male",2008 +"Gentoo","Biscoe",42.6,13.7,213,4950,"female",2008 +"Gentoo","Biscoe",44.4,17.3,219,5250,"male",2008 +"Gentoo","Biscoe",44,13.6,208,4350,"female",2008 +"Gentoo","Biscoe",48.7,15.7,208,5350,"male",2008 +"Gentoo","Biscoe",42.7,13.7,208,3950,"female",2008 +"Gentoo","Biscoe",49.6,16,225,5700,"male",2008 +"Gentoo","Biscoe",45.3,13.7,210,4300,"female",2008 +"Gentoo","Biscoe",49.6,15,216,4750,"male",2008 +"Gentoo","Biscoe",50.5,15.9,222,5550,"male",2008 +"Gentoo","Biscoe",43.6,13.9,217,4900,"female",2008 +"Gentoo","Biscoe",45.5,13.9,210,4200,"female",2008 +"Gentoo","Biscoe",50.5,15.9,225,5400,"male",2008 +"Gentoo","Biscoe",44.9,13.3,213,5100,"female",2008 +"Gentoo","Biscoe",45.2,15.8,215,5300,"male",2008 +"Gentoo","Biscoe",46.6,14.2,210,4850,"female",2008 +"Gentoo","Biscoe",48.5,14.1,220,5300,"male",2008 +"Gentoo","Biscoe",45.1,14.4,210,4400,"female",2008 +"Gentoo","Biscoe",50.1,15,225,5000,"male",2008 +"Gentoo","Biscoe",46.5,14.4,217,4900,"female",2008 +"Gentoo","Biscoe",45,15.4,220,5050,"male",2008 +"Gentoo","Biscoe",43.8,13.9,208,4300,"female",2008 +"Gentoo","Biscoe",45.5,15,220,5000,"male",2008 +"Gentoo","Biscoe",43.2,14.5,208,4450,"female",2008 +"Gentoo","Biscoe",50.4,15.3,224,5550,"male",2008 +"Gentoo","Biscoe",45.3,13.8,208,4200,"female",2008 +"Gentoo","Biscoe",46.2,14.9,221,5300,"male",2008 +"Gentoo","Biscoe",45.7,13.9,214,4400,"female",2008 +"Gentoo","Biscoe",54.3,15.7,231,5650,"male",2008 +"Gentoo","Biscoe",45.8,14.2,219,4700,"female",2008 +"Gentoo","Biscoe",49.8,16.8,230,5700,"male",2008 +"Gentoo","Biscoe",46.2,14.4,214,4650,,2008 +"Gentoo","Biscoe",49.5,16.2,229,5800,"male",2008 +"Gentoo","Biscoe",43.5,14.2,220,4700,"female",2008 +"Gentoo","Biscoe",50.7,15,223,5550,"male",2008 +"Gentoo","Biscoe",47.7,15,216,4750,"female",2008 +"Gentoo","Biscoe",46.4,15.6,221,5000,"male",2008 +"Gentoo","Biscoe",48.2,15.6,221,5100,"male",2008 +"Gentoo","Biscoe",46.5,14.8,217,5200,"female",2008 +"Gentoo","Biscoe",46.4,15,216,4700,"female",2008 +"Gentoo","Biscoe",48.6,16,230,5800,"male",2008 +"Gentoo","Biscoe",47.5,14.2,209,4600,"female",2008 +"Gentoo","Biscoe",51.1,16.3,220,6000,"male",2008 +"Gentoo","Biscoe",45.2,13.8,215,4750,"female",2008 +"Gentoo","Biscoe",45.2,16.4,223,5950,"male",2008 +"Gentoo","Biscoe",49.1,14.5,212,4625,"female",2009 +"Gentoo","Biscoe",52.5,15.6,221,5450,"male",2009 +"Gentoo","Biscoe",47.4,14.6,212,4725,"female",2009 +"Gentoo","Biscoe",50,15.9,224,5350,"male",2009 +"Gentoo","Biscoe",44.9,13.8,212,4750,"female",2009 +"Gentoo","Biscoe",50.8,17.3,228,5600,"male",2009 +"Gentoo","Biscoe",43.4,14.4,218,4600,"female",2009 +"Gentoo","Biscoe",51.3,14.2,218,5300,"male",2009 +"Gentoo","Biscoe",47.5,14,212,4875,"female",2009 +"Gentoo","Biscoe",52.1,17,230,5550,"male",2009 +"Gentoo","Biscoe",47.5,15,218,4950,"female",2009 +"Gentoo","Biscoe",52.2,17.1,228,5400,"male",2009 +"Gentoo","Biscoe",45.5,14.5,212,4750,"female",2009 +"Gentoo","Biscoe",49.5,16.1,224,5650,"male",2009 +"Gentoo","Biscoe",44.5,14.7,214,4850,"female",2009 +"Gentoo","Biscoe",50.8,15.7,226,5200,"male",2009 +"Gentoo","Biscoe",49.4,15.8,216,4925,"male",2009 +"Gentoo","Biscoe",46.9,14.6,222,4875,"female",2009 +"Gentoo","Biscoe",48.4,14.4,203,4625,"female",2009 +"Gentoo","Biscoe",51.1,16.5,225,5250,"male",2009 +"Gentoo","Biscoe",48.5,15,219,4850,"female",2009 +"Gentoo","Biscoe",55.9,17,228,5600,"male",2009 +"Gentoo","Biscoe",47.2,15.5,215,4975,"female",2009 +"Gentoo","Biscoe",49.1,15,228,5500,"male",2009 +"Gentoo","Biscoe",47.3,13.8,216,4725,,2009 +"Gentoo","Biscoe",46.8,16.1,215,5500,"male",2009 +"Gentoo","Biscoe",41.7,14.7,210,4700,"female",2009 +"Gentoo","Biscoe",53.4,15.8,219,5500,"male",2009 +"Gentoo","Biscoe",43.3,14,208,4575,"female",2009 +"Gentoo","Biscoe",48.1,15.1,209,5500,"male",2009 +"Gentoo","Biscoe",50.5,15.2,216,5000,"female",2009 +"Gentoo","Biscoe",49.8,15.9,229,5950,"male",2009 +"Gentoo","Biscoe",43.5,15.2,213,4650,"female",2009 +"Gentoo","Biscoe",51.5,16.3,230,5500,"male",2009 +"Gentoo","Biscoe",46.2,14.1,217,4375,"female",2009 +"Gentoo","Biscoe",55.1,16,230,5850,"male",2009 +"Gentoo","Biscoe",44.5,15.7,217,4875,,2009 +"Gentoo","Biscoe",48.8,16.2,222,6000,"male",2009 +"Gentoo","Biscoe",47.2,13.7,214,4925,"female",2009 +"Gentoo","Biscoe",,,,,,2009 +"Gentoo","Biscoe",46.8,14.3,215,4850,"female",2009 +"Gentoo","Biscoe",50.4,15.7,222,5750,"male",2009 +"Gentoo","Biscoe",45.2,14.8,212,5200,"female",2009 +"Gentoo","Biscoe",49.9,16.1,213,5400,"male",2009 +"Chinstrap","Dream",46.5,17.9,192,3500,"female",2007 +"Chinstrap","Dream",50,19.5,196,3900,"male",2007 +"Chinstrap","Dream",51.3,19.2,193,3650,"male",2007 +"Chinstrap","Dream",45.4,18.7,188,3525,"female",2007 +"Chinstrap","Dream",52.7,19.8,197,3725,"male",2007 +"Chinstrap","Dream",45.2,17.8,198,3950,"female",2007 +"Chinstrap","Dream",46.1,18.2,178,3250,"female",2007 +"Chinstrap","Dream",51.3,18.2,197,3750,"male",2007 +"Chinstrap","Dream",46,18.9,195,4150,"female",2007 +"Chinstrap","Dream",51.3,19.9,198,3700,"male",2007 +"Chinstrap","Dream",46.6,17.8,193,3800,"female",2007 +"Chinstrap","Dream",51.7,20.3,194,3775,"male",2007 +"Chinstrap","Dream",47,17.3,185,3700,"female",2007 +"Chinstrap","Dream",52,18.1,201,4050,"male",2007 +"Chinstrap","Dream",45.9,17.1,190,3575,"female",2007 +"Chinstrap","Dream",50.5,19.6,201,4050,"male",2007 +"Chinstrap","Dream",50.3,20,197,3300,"male",2007 +"Chinstrap","Dream",58,17.8,181,3700,"female",2007 +"Chinstrap","Dream",46.4,18.6,190,3450,"female",2007 +"Chinstrap","Dream",49.2,18.2,195,4400,"male",2007 +"Chinstrap","Dream",42.4,17.3,181,3600,"female",2007 +"Chinstrap","Dream",48.5,17.5,191,3400,"male",2007 +"Chinstrap","Dream",43.2,16.6,187,2900,"female",2007 +"Chinstrap","Dream",50.6,19.4,193,3800,"male",2007 +"Chinstrap","Dream",46.7,17.9,195,3300,"female",2007 +"Chinstrap","Dream",52,19,197,4150,"male",2007 +"Chinstrap","Dream",50.5,18.4,200,3400,"female",2008 +"Chinstrap","Dream",49.5,19,200,3800,"male",2008 +"Chinstrap","Dream",46.4,17.8,191,3700,"female",2008 +"Chinstrap","Dream",52.8,20,205,4550,"male",2008 +"Chinstrap","Dream",40.9,16.6,187,3200,"female",2008 +"Chinstrap","Dream",54.2,20.8,201,4300,"male",2008 +"Chinstrap","Dream",42.5,16.7,187,3350,"female",2008 +"Chinstrap","Dream",51,18.8,203,4100,"male",2008 +"Chinstrap","Dream",49.7,18.6,195,3600,"male",2008 +"Chinstrap","Dream",47.5,16.8,199,3900,"female",2008 +"Chinstrap","Dream",47.6,18.3,195,3850,"female",2008 +"Chinstrap","Dream",52,20.7,210,4800,"male",2008 +"Chinstrap","Dream",46.9,16.6,192,2700,"female",2008 +"Chinstrap","Dream",53.5,19.9,205,4500,"male",2008 +"Chinstrap","Dream",49,19.5,210,3950,"male",2008 +"Chinstrap","Dream",46.2,17.5,187,3650,"female",2008 +"Chinstrap","Dream",50.9,19.1,196,3550,"male",2008 +"Chinstrap","Dream",45.5,17,196,3500,"female",2008 +"Chinstrap","Dream",50.9,17.9,196,3675,"female",2009 +"Chinstrap","Dream",50.8,18.5,201,4450,"male",2009 +"Chinstrap","Dream",50.1,17.9,190,3400,"female",2009 +"Chinstrap","Dream",49,19.6,212,4300,"male",2009 +"Chinstrap","Dream",51.5,18.7,187,3250,"male",2009 +"Chinstrap","Dream",49.8,17.3,198,3675,"female",2009 +"Chinstrap","Dream",48.1,16.4,199,3325,"female",2009 +"Chinstrap","Dream",51.4,19,201,3950,"male",2009 +"Chinstrap","Dream",45.7,17.3,193,3600,"female",2009 +"Chinstrap","Dream",50.7,19.7,203,4050,"male",2009 +"Chinstrap","Dream",42.5,17.3,187,3350,"female",2009 +"Chinstrap","Dream",52.2,18.8,197,3450,"male",2009 +"Chinstrap","Dream",45.2,16.6,191,3250,"female",2009 +"Chinstrap","Dream",49.3,19.9,203,4050,"male",2009 +"Chinstrap","Dream",50.2,18.8,202,3800,"male",2009 +"Chinstrap","Dream",45.6,19.4,194,3525,"female",2009 +"Chinstrap","Dream",51.9,19.5,206,3950,"male",2009 +"Chinstrap","Dream",46.8,16.5,189,3650,"female",2009 +"Chinstrap","Dream",45.7,17,195,3650,"female",2009 +"Chinstrap","Dream",55.8,19.8,207,4000,"male",2009 +"Chinstrap","Dream",43.5,18.1,202,3400,"female",2009 +"Chinstrap","Dream",49.6,18.2,193,3775,"male",2009 +"Chinstrap","Dream",50.8,19,210,4100,"male",2009 +"Chinstrap","Dream",50.2,18.7,198,3775,"female",2009 diff --git a/course-project/starter/out/hist.png b/course-project/starter/out/hist.png new file mode 100644 index 0000000000000000000000000000000000000000..9653909ffe4d1f3449e34588ba44e47883237fb3 GIT binary patch literal 24180 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 XTddUQ{aR!s@aKY(>e=)&H}Cy7#0 + + + + + + + + +Пингвины с острова Dream + + + + + + + + + + + + + + + + + + + + + +

+ +
+ +
+
+

Пингвины с острова Dream

+
+ + + +
+ + + + +
+ + + +
+ + +

Данные собраны на трёх островах архипелага Палмера. Возьмём пингвинов с острова Dream.

+
+
penguins <- read.csv("data/penguins.csv")
+dream <- subset(penguins, island == "Dream")
+nrow(dream)
+
+
[1] 124
+
+
+

Самый длинный плавник:

+
+
gigapeng <- max(dream$flipper_len)
+gigapeng
+
+
[1] 212
+
+
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/course-project/starter/report.qmd b/course-project/starter/report.qmd new file mode 100644 index 0000000..e3063b1 --- /dev/null +++ b/course-project/starter/report.qmd @@ -0,0 +1,23 @@ +--- +title: "Пингвины с острова Dream" +format: + html: + embed-resources: true +--- + +Данные собраны на трёх островах архипелага Палмера. +Возьмём пингвинов с острова Dream. + +```{r} +penguins <- read.csv("data/penguins.csv") +dream <- subset(penguins, island == "Dream") +nrow(dream) +``` + +Самый длинный плавник: + +```{r} +gigapeng <- max(dream$flipper_len) +gigapeng +``` + diff --git a/course-project/starter/tables.qmd b/course-project/starter/tables.qmd new file mode 100644 index 0000000..723ff22 --- /dev/null +++ b/course-project/starter/tables.qmd @@ -0,0 +1,35 @@ +--- +title: "Статистическая таблица" +format: html +--- + +```{r} +library(tidyverse) +library(flextable) +``` + +```{r} +data <- read_tsv("data/data_tsv.tsv", show_col_types = FALSE) +data$Группа <- factor(data$Группа) + +statistics <- list( + `Количество субъектов` = ~ length(.x), + `Ср. знач.` = ~ mean(.x, na.rm = TRUE), + `Станд. отклон.` = ~ sd(.x, na.rm = TRUE), + `Медиана` = ~ median(.x, na.rm = TRUE) +) + +table <- data |> + select(`Группа`, where(is.numeric)) |> + group_by(`Группа`) |> + summarise(across(where(is.numeric), statistics, .names = "{.col}__{.fn}")) |> + mutate(across(-`Группа`, function(x) round(x, 2))) |> + pivot_longer(!`Группа`) |> + separate(name, into = c("Переменная", "Статистика"), sep = "__") + +table |> + flextable() |> + theme_box() |> + merge_v(c("Группа", "Переменная")) +``` + diff --git a/docs/01-01-about.md b/docs/01-01-about.md index 556109d..f62ddb2 100644 --- a/docs/01-01-about.md +++ b/docs/01-01-about.md @@ -1,45 +1,28 @@ -# (PART) Введение {-} +# (PART) Подготовка {-} -# Что такое Git {#about} +# Зачем проекту Git {#about-git} -**Git** --- это программа, выполняющая функции **Системы Контроля Версий (VCS, Version Control System)**. -Многие применяют простую систему контроля версий, вручную копируя файлы и добавляя дату в названия. -Git автоматически отслеживает изменения во время редактирования файлов, позволяет фиксировать состояние файлов в версии, хранить и переключаться между ними. -Вы сможете оценить, какие изменения внесли, а также посмотреть историю изменений --- когда, кем и с какой целью они были сделаны. +В проекте анализа данных меняются код, текст отчёта и графики. Копии с названиями `final`, `final-2` и `really-final` сохраняют файлы, но не объясняют, кто и зачем их менял. +Git хранит **коммиты** — снимки выбранных изменений с коротким пояснением. Из них складывается история проекта. По ней можно: +- сравнить текущую работу с предыдущей версией; +- вернуть исправный вариант; +- вести несколько вариантов анализа в ветках; +- объединять изменения разных участников. -::: {.text-center} -![](./img/notFinal.gif){width=400px style="border: 1px solid #ddd"} -::: +Git работает локально. Для коммитов не нужны интернет и аккаунт. GitHub понадобится позже как удалённое место для общей истории и обсуждения изменений. -Важная особенность Git в том, что участники могут работать и создавать версии независимо друг от друга на своих компьютерах. Каждый может работать над своей задачей, не мешая другим, даже если все редактируют один и тот же файл. Git поможет объединить изменения в одну общую версию. +## Что уже есть в проекте +Откройте папку `r-course`, созданную в предыдущем курсе. Не создавайте новый учебный проект и не переносите файлы. +В проекте могут оставаться `.R`-скрипты, `report.qmd`, `analysis.qmd`, другие документы, папки `data` и `out`. Это ожидаемое состояние. Git умеет отслеживать любые файлы; расширение не нужно менять ради Git. -Проект Git можно загрузить на сервер для надежного хранения и передачи файлов, совместной работы и публикации. -Самым популярным сервисом для этого является GitHub. -Он похож на облачные хранилища, такие как Google Drive или Dropbox, но с более продвинутым отслеживанием и объединением изменений, а также другими полезными функциями. -Вместо GitHub можно использовать другой сервер, например корпоративный во внутренней сети организации или использовать Git оффлайн --- только на своем компьютере. +Новый код этого курса будем писать в `paper.qmd`. Так текст, команды R и результат останутся в одном воспроизводимом документе Quarto. +## Репозиторий +**Репозиторий** — папка проекта вместе со скрытой служебной папкой `.git`. В `.git` находится история, ветки и настройки связи с удалённым репозиторием. -Если это всё ещё не убедило вас начать использовать Git, вот несколько примеров, когда он будет полезен: - - - - -- Возможно, вы оказывались в следующей ситуации. Вы вносите изменения в работающую программу или файл. Оцениваете результат и решаете отменить изменения. Вот только у вас нет копии оригинального файла, а вернуть прежнее состояние почему-то не получается --- программа никак не работает или работает иначе. С Git это делается одной командой, а экспериментальную версию можно сохранить и вернуться к ней позже. - -- Если вам понадобилась помощь, вы можете одной командой загрузить сделанные изменения на GitHub. Другой участник увидит, что вы пытаетесь сделать, и может загрузить решение проблемы, а вы так же одной командой получите исправленную версию. - -Благодаря последовательному внесению и отслеживанию изменений Git помогает организовать процесс анализа данных, обеспечивает воспроизводимость и упрощает совместную работу над проектом. - - - -::: {.callout .callout-info} - -Существуют другие системы контроля версий, например Mercurial и Subversion и вероятно, в будущем появятся новые. -Но благодаря простоте, эффективности и приобретенной популярности в основном используется Git. - -::: +Шаблон R Project в Positron создаёт `.git` и `.gitignore` автоматически. Поэтому проект из R-курса уже должен быть репозиторием, хотя в нём пока нет коммитов. В главе \@ref(open-project) мы это проверим. diff --git a/docs/01-02-install.md b/docs/01-02-install.md index 9c4f972..6ca85eb 100644 --- a/docs/01-02-install.md +++ b/docs/01-02-install.md @@ -1,59 +1,27 @@ -# Установка {#install} +# Установка Git {#install-git} -## Проверьте наличие Git {#terminal} +Positron предоставляет интерфейс Source Control, но использует Git, установленный в операционной системе. Если Git не найден, Source Control покажет предложение его установить. Такое поведение описано в официальной главе [Git Version Control](https://positron.posit.co/git.html). -В комплекте с дистрибутивом Git устанавливается программа для терминала. -Чтобы её запустить, откройте Rstudio и в верхнем меню выберите **Tools → Terminal → New Terminal**. -В появившемся окне терминала введите команду `git` и нажмите клавишу Enter. +## Проверка -Если вы видите результат как на скриншоте ниже, то Git установлен. -Иначе нужно его установить --- см. инструкцию для вашей операционной системы ниже. -После установки перезапустите RStudio и повторите проверку. - -![](./img/git.png){width="100%"} - -## Windows - -Загрузите инсталлятор по ссылке [git-scm.com/downloads/win](https://git-scm.com/downloads/win) -(используйте **Standalone**, а не **Portable** версию, если в этом нет необходимости), запустите и следуйте инструкциям на экране, можете везде оставить опции, выбранные по умолчанию. - -## Mac OS - -**Вариант 1.** Git входит в инструменты разработчика от Apple, которые предоставляются бесплатно. Для установки введите в терминал следующую команду: +Откройте встроенный терминал командой **Terminal: Create New Terminal** из палитры команд и выполните: ```sh -xcode-select --install +git --version ``` -В появившемся окне нажмите кнопку **Install**. +Если команда вывела строку вида `git version 2.45.2`, установка готова. Конкретный номер может отличаться. -**Вариант 2.** Последнюю версию Git можно установить используя сторонний менеджер программ [Homebrew](https://brew.sh). Если он у вас установлен, введите в терминал следующую команду: +![Терминал Positron после проверки версии Git: видна строка с установленной версией]() -```sh -brew install git -``` - -## Linux +## Если Git не установлен -Используйте в терминале одну из следующих команд, в зависимости от вашего дистрибутива Linux. +- **Windows:** установите [Git for Windows](https://git-scm.com/download/win), оставив параметры установщика по умолчанию. +- **macOS:** установите [Xcode Command Line Tools](https://developer.apple.com/xcode/resources/) по предложению системы после команды `git --version` или установите Git с [официальной страницы](https://git-scm.com/download/mac). +- **Linux:** используйте менеджер пакетов своего дистрибутива; команды приведены в [официальной инструкции Git](https://git-scm.com/download/linux). -**Ubuntu или Debian** - -```sh -sudo apt-get update -sudo apt-get install git -``` - -**Fedora** - -```sh -sudo dnf install git -``` - -**Arch Linux** - -```sh -sudo pacman -S git -``` +После установки полностью перезапустите Positron и снова выполните `git --version`. -Для других дистрибутивов см. [git-scm.com/downloads/linux](https://git-scm.com/downloads/linux). Не забудьте, что команды нужно запускать с правами администратора, т.е. начав с `sudo`, как в примере выше. +::: {.callout .callout-warning} +Не скачивайте отдельные графические клиенты Git для прохождения курса. Они могут пригодиться позже, но названия действий и расположение элементов будут отличаться от Positron. +::: diff --git a/docs/01-03-shell.md b/docs/01-03-shell.md index 5bd75b6..8bc0e63 100644 --- a/docs/01-03-shell.md +++ b/docs/01-03-shell.md @@ -1,41 +1,21 @@ -# Настройка {#setup} +# Имя автора {#git-identity} -Основной способ работы с Git --- это команда `git`, которую мы выполнили в предыдущей главе. -Команды для терминала вы встретите в документации и в интернете, ими легко поделиться и использовать в скриптах. -Кроме терминала есть много других способов и их даже можно использовать одновременно. +Каждый коммит хранит имя и электронную почту автора. При первом коммите Positron может попросить их настроить. Укажите имя, по которому коллеги вас узнают, и почту, связанную с GitHub. -Графические интерфейсы --- все они имеют ограничения и реализуют только часть возможностей Git, но достаточны для решения большинства задач. Это может быть интерфейс, встроенный в другие программы (например [RStudio](https://docs.posit.co/ide/user/ide/guide/tools/version-control.html), [Pycharm](https://www.jetbrains.com/help/pycharm/using-git-integration.html), [VS Code](https://code.visualstudio.com/docs/sourcecontrol/overview)) или самостоятельная программа (например [GitHub Desktop](https://github.com/apps/desktop), [GitKraken](https://www.gitkraken.com) [и многие другие](https://git-scm.com/downloads/guis)); - -Веб-интерфейсы --- прямо на сайте GitHub можно редактировать отдельные файлы, а также выполнять некоторые команды. - -В этом курсе мы будем работать с Git одновременно в интерфейсе RStudio и в терминале, как это делает большинство пользователей R каждый день, а также через GitHub. -Поэтому запомните, как запустить терминал в RStudio --- -в верхнем меню выберите **Tools → Terminal → New Terminal** ([см. скриншот в предыдущей главе](#terminal)). - -Перед началом работы необходимо сделать несколько настроек. -Укажите свое имя и адрес электронной почты, чтобы Git верно записывал информацию об авторе изменений. -В терминале выполните следующие команды, заменив **Your Name** на свое имя и **your@email.com** на свой email, не стирая кавычки. - -```sh -git config --global user.name "Your Name" -git config --global user.email "your@email.com" -``` - -Если вы уже использовали Git, то чтобы вывести в терминале текущее значение настроек выполните эти же команды, но не указывая новых значений. +Если интерфейс показал ошибку `Please tell me who you are`, откройте терминал и выполните две команды, заменив значения своими: ```sh -git config --global user.name -git config --global user.email +git config --global user.name "Ivan Ivanov" +git config --global user.email "ivan@example.org" ``` -Также заранее настроим способ объединения изменений, чтобы не возвращаться к этому позже. +Проверьте результат: ```sh -git config --global pull.rebase false +git config --global --get user.name +git config --global --get user.email ``` -Опция `--global` означает, что эти настройки будут использованы для всех проектов на компьютере и их достаточно сделать один раз. -Чтобы изменить настройки для отдельного проекта, выполните в нем эти же команды без опции `--global`. Например, иногда требуется указать корпоративный email для рабочего проекта на персональном компьютере. +Настройка `--global` применяется ко всем будущим проектам этого пользователя. Если рабочий проект требует другую почту, откройте его папку и повторите команды без `--global`: значение сохранится только в этом репозитории. -Это все настройки, которые понадобятся для курса. -Всего через команду `git config` их доступно более 800. +Пароль GitHub здесь не нужен. Вход в GitHub выполним в браузере в части \@ref(github-part). diff --git a/docs/02-01-init.md b/docs/02-01-init.md index 436f077..108ea5b 100644 --- a/docs/02-01-init.md +++ b/docs/02-01-init.md @@ -1,72 +1,25 @@ -# (PART) Основы {-} +# (PART) Коммиты {-} -# Создание репозитория {#git-init} +# Открытие проекта {#open-project} -Git может отслеживать изменения в любой папке на вашем компьютере. -Для этого нужно инициализировать в ней Git репозиторий. -**Репозиторий** --- это скрытая подпапка `.git`, в которой хранятся версии проекта и информация об изменениях. -Всё необходимое для работы Git содержится непосредственно в ней. +На экране Welcome в Positron выберите **Open Folder** и откройте папку `r-course`. Убедитесь, что в Explorer видны накопленные файлы R-курса, в том числе папка `data`. -Самый простой способ создать репозиторий --- вместе с проектом RStudio. -В верхнем меню выберите [File → New Project]{.figtext}. -В появившемся окне выберите [New directory]{.figtext}, а затем [New Project]{.figtext}. -На последнем шаге в поле [Directory name]{.figtext} введите название папки для проекта: [penguins]{.figtext}. -Она будет создана на вашем компьютере по адресу, указанному в поле [Create project as subdirectory of]{.figtext}. -‼️ Не забудьте поставить галочку напротив опции [ Create a git repository]{.figtext}, иначе проект будет создан без Git репозитория. -После нажатия кнопки [Create Project]{.figtext} окно RStudio перезагрузится с открытым проектом. +Откройте **Source Control** на панели активности слева. У изменённых файлов стоят обозначения состояния: `U` у ещё не отслеживаемых и `M` у изменённых. - - - - - - - - - -
![](./img/02-01-01-new-project.png){width="320px"}![](./img/02-01-02-new-project.png){width="320px"}
![](./img/02-01-03-new-project.png){width="320px"}![](./img/02-01-04-new-project.png){width="320px"}
+![Окно Positron с открытым проектом r-course: в Explorer видны накопленные файлы, а в Source Control перечислены незафиксированные изменения]() -При следующем запуске RStudio откроет последний проект. -Если этого не произойдет, чтобы открыть проект в верхнем меню выберите [File → Open Project]{.figtext} или [File → Recent Projects]{.figtext}. +Если Source Control уже показывает файлы, репозиторий готов. Не нажимайте **Initialize Repository** повторно и не удаляйте `.git`. -Убедитесь в том, что проект загружен, для этого обратите внимание на следующие элементы интерфейса: -В правом верхнем углу указано название проекта [(A)]{.figref}. -На панели файлов (по умолчанию она в нижнем правом углу) открыта папка с файлами проекта [(B)]{.figref}. +## Если репозитория нет -![](./img/02-01-05-window.png){width="680px"} +В старой версии R-курса проект мог быть создан без Git. Тогда Source Control покажет кнопку **Initialize Repository**. Нажмите её один раз. Positron создаст `.git` и начнёт показывать изменения. -Когда в RStudio открыт проект, R и Git ищут файлы в папке проекта --- это так называемая **рабочая папка или рабочая область**. +Официальная документация Positron описывает те же шаги: открыть папку, перейти в Source Control и выбрать **Initialize Repository**. -
Подробнее про поиск и адреса файлов. -На разных компьютерах, например у разных участников, проект может находиться в разных местах. -У пользователя с именем `mjordan` это может быть `/Users/mjordan/penguins`, -а у пользователя `scruz` допустим -`C:\Users\scruz\penguins`. +## Что сейчас видит Git -Если в скрипте использовать полный адрес файла, например: +Все накопленные файлы ещё не входят ни в один коммит. Это не ошибка и не повод чистить проект. В следующей главе сделаем один исходный коммит, который станет точкой отсчёта для новой работы. -```r -read_csv("/Users/mjordan/penguins/data/sample.csv") -``` - -то он будет работать только у пользователя `mjordan`. -У других полный адрес будет отличаться, и код «сломается». -Чтобы он работал у всех, нужно указывать адрес файла относительно рабочей папки. - -```r -read_csv("data/sample.csv") -``` -
- -Рассмотрим созданные RStudio файлы: - -- `hello-git.Rproj` --- содержит настройки проекта -- `.gitignore` --- содержит список файлов, которые Git не будет отслеживать; о том, зачем это нужно и как настроить [смотри в отдельном разделе](#gitignore) -- `.git` --- репозиторий; это скрытая папка, чтобы ее увидеть, в меню на панели файлов выберите [More → Show Hidden Files]{.figtext} - -Если файл `.gitignore` отсутствует, значит, вы не отметили галочку [ Create a git repository]{.figtext} при создании проекта или не установили Git. -[Проверьте наличие Git](#install) и создайте проект заново. - -Итак, у нас есть проект RStudio --- папка, в которой мы будем работать, и -внутри нее Git репозиторий --- скрытая папка, в которой будут храниться версии проекта. -Приступим к созданию первой версии. +::: {.callout .callout-warning} +Не переводите старые `.R`-файлы в `.qmd`, не удаляйте дополнительные данные и не заменяйте результаты. Исходный коммит должен быть точной фиксацией конца R-курса. +::: diff --git a/docs/02-02-commit.md b/docs/02-02-commit.md index 5cd252d..ecef4c4 100644 --- a/docs/02-02-commit.md +++ b/docs/02-02-commit.md @@ -1,48 +1,35 @@ -# Отслеживание изменений {#git-commit} +# Первый коммит {#first-commit} -Git отслеживает изменения в файлах, находящихся в рабочей папке. -Но не все подряд, как это делают Блокнот или Word при помощи команд «Отменить» и «Повторить», -а при помощи версий --- или, в терминах Git, **коммитов (commit)**. -Коммиты нужно создавать вручную, выбирая, какие файлы вы хотите зафиксировать, добавив в версию. +Коммит состоит из снимка выбранных файлов, автора, времени и сообщения. Сначала файлы попадают в **индекс** (staging area), затем Git записывает из индекса коммит. -Откройте в RStudio панель с названием [Git]{.figtext} (по умолчанию она в верхнем правом углу). -В отличие от списка файлов, на ней выводятся только те файлы, которые были изменены по сравнению с последней версией (коммитом). -Так как мы еще не создали ни одной версии, то в списке выводятся оба файла, созданных с проектом: `.gitignore` и `penguins.Rproj` +## Проверка изменений +В Source Control выберите любой текстовый файл. Откроется редактор различий (diff). Для нового файла одна сторона сравнения пуста, а весь текст отмечен как добавленный. -![](./img/02-02-01-window.png){width=680px} +Бинарные файлы, например `.png`, `.xlsx` и `.rds`, Git сохранит, но не покажет построчное сравнение. Перед коммитом откройте их обычным способом и убедитесь, что это нужные файлы. -
Нет панели Git? -Значит, вы не отметили галочку [Create a git repository]{.figtext} при создании проекта или не установили Git. -[Проверьте наличие Git](#install) и [создайте проект заново](#git-init). -
+![Редактор различий Positron для нового текстового файла из проекта r-course и список Changes в Source Control]() -Чтобы создать коммит (версию), отметьте файлы галочкой в столбце [Staged]{.figtext}. -Галочка напротив файла означает, что он добавлен в **индекс (staging)** --- -промежуточную область для выбора файлов, которые будут зафиксированы. -Неотмеченные файлы останутся в рабочей папке, но в коммит не попадут. -Вы можете добавить их в следующую версию позже или отменить изменения. -Нажмите кнопку [Commit]{.figtext}. +## Добавление в индекс -![](./img/02-02-02-staging.png){width=400px} +Наведите указатель на заголовок **Changes** и нажмите `+` (**Stage All Changes**). Файлы переместятся в раздел **Staged Changes**. -В открывшемся окне можно подробнее посмотреть, что изменилось в файлах. -Просмотрите изменения и введите краткое описание в поле [Commit message]{.figtext}. -В нашем примере был создан проект, это и будет подходящим описанием. -Нажмите кнопку [Commit]{.figtext} под текстовым полем. +Проверьте список ещё раз. В первый коммит должны войти все накопленные файлы проекта, кроме уже скрытых правилами `.gitignore`. -![](./img/02-02-03-commit.png){width=600px} +## Запись коммита -В открывшемся окне не должно быть ошибок, но должно быть сообщение как на изображении ниже. +Введите сообщение: -![](./img/02-02-04-message.png){width=600px} +```text +Зафиксировал результат курса R +``` -Закройте окно с сообщением и окно создания коммита, вернитесь к RStudio. -Обратите внимание, теперь панель [Git]{.figtext} со списком измененных файлов пуста --- -это значит, что изменений по сравнению с последней версией, которую мы только что создали, нет. +Нажмите **Commit**. Если Positron попросит настроить автора, вернитесь к главе \@ref(git-identity). -![](./img/02-02-05-git-pane.png){width=400px} - -Теперь у нас есть версия проекта, к которой можно вернуться в любой момент и начать работу с этого места. +![Source Control сразу после исходного коммита: разделы Changes и Staged Changes пусты, в Graph виден один коммит]() +Пустой список изменений означает, что рабочая папка совпадает с последним коммитом. Старые файлы никуда не переместились: Git только записал их состояние. +::: {.callout .callout-info} +Сообщение коммита отвечает на вопрос «что сделал этот шаг?». Короткая форма с глаголом помогает читать историю: «Добавил импорт данных», «Исправил подпись оси». +::: diff --git a/docs/02-03-practice.md b/docs/02-03-practice.md index 09043a9..9799a07 100644 --- a/docs/02-03-practice.md +++ b/docs/02-03-practice.md @@ -1,125 +1,59 @@ -# Рабочий процесс {#git-commit2} +# Рабочий цикл {#commit-workflow} -В предыдущей главе мы научились создавать коммиты (версии). -Работая с Git, это нужно делать регулярно --- -обычно после выполнения задачи или её части, -после внесения исправлений или просто чтобы зафиксировать изменения. -Коммит сохраняет «стабильную» версию проекта, к которой можно вернуться или сравнить с ней сделанные изменения. +Теперь начнём отдельный анализ для Git-курса. Каждая небольшая законченная задача станет коммитом: -Рассмотрим процесс работы над проектом подробнее: +1. изменить и сохранить файл; +2. открыть diff и проверить изменение; +3. добавить нужные файлы в индекс; +4. записать коммит; +5. убедиться, что Source Control снова пуст. -1. Мы создали коммит, и с тех пор в рабочей папке не было изменений. -2. Выполняем задачу и добавляем нужные для ее решения изменения в индекс, а лишние, например код для отладки или временные файлы, удаляем. -3. Перед созданием коммита обязательно проверяем изменения, которые в него попадут. - Начинающие пользователи часто либо добавляют ненужный код, не относящийся к задаче, либо забывают добавить код, без которого не будет работать остальная часть проекта. -4. Создаём коммит и получаем чистую рабочую папку --- без изменений относительно нового коммита. - Можно переходить к следующей задаче. +## Документ Quarto -![](./img/02-02-06-workflow.png){width=540px} +Создайте в корне проекта файл `paper.qmd`. Накопленные `.R`-скрипты остаются без изменений, но весь новый код пишем в Quarto. -Такой процесс помогает упорядочить внесение изменений и сделать результат воспроизводимым. -Он хорошо подходит для анализа данных, потому что его легко разделить на задачи, из которых получатся коммиты. -Попробуем сделать это на практике и проанализируем длину клюва антарктических пингвинов. -Каждая подглава этой главы соответствует одной задаче и завершается одним коммитом. +Добавьте настройки и первый блок R: -## Импорт данных - -Загрузите файл с данными [penguins.csv](https://github.com/yoursdearboy/git-101/releases/download/penguins/penguins.csv) в папку проекта. -Если нужно открыть папку в файловом менеджере операционной системы, в меню на панели [Files]{.figtext} выберите [More → Show Folder in New Window]{.figtext}. -Вернитесь в RStudio и убедитесь, что файл `penguins.csv` появился на панели [Git]{.figtext}. - -![](./img/02-03-01-show-folder.png){width=400px} - -Создайте скрипт для анализа. В меню на панели [Files]{.figtext} выберите [New File → R Script]{.figtext} и введите название файла `penguins.R` - -![](./img/02-03-02-new-file.png){width=400px} - -Скопируйте следующий код для импорта данных и сохраните его в созданном файле. -Выделите обе строки и запустите, нажав кнопку [Run]{.figtext} в правом верхнем углу редактора RStudio. -Если импорт данных работает, в консоли появится вектор из чисел. - -```r -data <- read.csv("penguins.csv") -data$bill_length_mm +```yaml +--- +title: "Длина клюва пингвинов" +format: html +--- ``` -Убедитесь, что файл скрипта также появился на панели [Git]{.figtext}. -Добавьте оба файла в индекс, отметив галочкой в столбце [Staged]{.figtext}, и создайте коммит. -В окне коммита обязательно проверьте содержимое скрипта `penguins.R`, -так как часто пользователи забывают сохранить файл перед добавлением в индекс. -![](./img/02-03-03-git-pane.png){width=690px} - -После создания коммита список измененных файлов на панели [Git]{.figtext} должен быть пуст. - -## Визуализация - -Анализ новых данных полезно начинать с исследования распределения. -Для этого присвоим данные с длиной клюва переменной `x` и построим несколько вариантов гистограммы с разной шириной столбца. -Сохраните приведённый ниже код в тот же файл, запустите и посмотрите графики. - -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm - -hist(x, breaks = seq(40, 60, 4)) -hist(x, breaks = seq(40, 60, 2)) -hist(x, breaks = seq(40, 60, 1)) +``` r +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() +x ``` -После сохранения файл `penguins.R` снова появился в списке изменений на панели [Git]{.figtext}. -Добавьте его в индекс и проверьте изменения в окне коммита. +Путь начинается от корня проекта. Данные уже находятся в `data`, поэтому ничего скачивать и перекладывать не нужно. В новом коде используем базовую трубу `|>`. + +Выполните блок в текущей R-сессии. Positron передаст код из документа Quarto в Console. Убедитесь, что вектор `x` создан без ошибки. -Вы уже могли заметить, что новые строки выделяются зеленым цветом. -Красным цветом выделяются удаленные строки, а неизмененные остаются белыми. -Такой формат записи изменений называется **«дифф» (diff)**. -Обратите внимание, что по умолчанию Git анализирует строки, а не отдельные слова или символы. -Поэтому получился следующий дифф: старая вторая строка была удалена, новая вторая строка добавлена (см. номера строк слева), хотя мы всего лишь добавили присвоение `x <- ` в начало строки. +![Открытый paper.qmd после выполнения блока: в Console виден результат импорта data/penguins.csv]() -![](./img/02-03-04-git-pane.png){width=690px} +Сохраните файл, проверьте diff и создайте коммит `Добавил импорт данных в paper.qmd`. -Убедитесь, что сделанные изменения соответствуют диффу на скриншоте выше, и создайте новый коммит с описанием «Добавили гистограммы для длины клюва». +## Гистограмма -## Экспорт +Замените блок кода на следующий: -Гистограмма с шириной столбца 2 выглядит наиболее информативно. -Такой график можно и опубликовать. -Чтобы экспортировать изображение, сохраните следующий код в файл скрипта и запустите его. -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm +``` r +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -png("penguins-hist.png") -hist(x, breaks = seq(40, 60, 2)) +png("out/penguins-hist.png") +hist(x, breaks = seq(30, 60, 2)) dev.off() ``` -После этого в списке изменений на панели [Git]{.figtext}, кроме файла `penguins.R`, появился файл с изображением `penguins-hist.png`. -Его мы тоже добавим в коммит. -Во-первых, так другие участники, загрузив проект, сразу увидят результат без необходимости запускать скрипт. -Во-вторых, если вы измените ширину столбца или другие настройки графика, будет удобно сравнить старую и новую версии. - -Добавьте оба файла в индекс, проверьте изменения, изучив дифф, и создайте коммит с описанием «Сохранили гистограмму длины клюва». - -На этом остановимся и посмотрим историю версий в журнале Git. - -::: {.callout .callout-info} -Делайте коммиты часто и не придавайте слишком большое значение планированию. -Коммит это не концептуально новая версия проекта, а просто шаг или изменения, которые вы хотите зафиксировать. - - -::: - -::: {.callout .callout-info} -Не обязательно добавлять в коммит все изменения сразу или их отменять --- они могут оставаться в рабочей папке сколько угодно. -Тем не менее старайтесь не копить изменения, потому что тогда версия в репозитории будет отличаться от версии, с которой вы работаете, а значит, теряется смысл системы контроля версий и возникают ошибки. - - -::: - - - +Выполните блок. В папке `out` появится `penguins-hist.png`. +В Source Control выберите `paper.qmd` и проверьте добавленные строки. Затем добавьте в индекс `paper.qmd` и `out/penguins-hist.png`, но не остальные случайные изменения. Создайте коммит `Сохранил гистограмму длины клюва`. +![Source Control перед коммитом гистограммы: в Staged Changes находятся только paper.qmd и out/penguins-hist.png]() +Теперь у проекта есть исходная версия, импорт данных и готовый график в трёх отдельных коммитах. diff --git a/docs/02-04-log-n-diff.md b/docs/02-04-log-n-diff.md index a531118..8dd7692 100644 --- a/docs/02-04-log-n-diff.md +++ b/docs/02-04-log-n-diff.md @@ -1,32 +1,25 @@ -# Просмотр истории {#git-log} +# История и различия {#history-diff} -До этого мы просматривали изменения только по сравнению с последней версией в момент создания коммита. Предыдущие коммиты можно посмотреть в **журнале (log)**. +Разверните **Source Control Graph** в Source Control. В нём видны коммиты текущей ветки `main`. -Журнал позволяет изучить изменения от других участников или вспомнить свои собственные, и зачем они сделаны. -Поэтому так важно писать ясные и содержательные описания коммитов. -Используя журнал, можно найти, когда сделаны изменения, приведшие к ошибке, и вернуть проект к предыдущему состоянию. -В конце концов, его можно использовать для отчетности и бизнесс-аналитики по проекту. +Выберите коммит `Сохранил гистограмму длины клюва`. Под ним появится список изменённых файлов. Выберите `paper.qmd`, чтобы открыть diff именно для этого коммита. -Чтобы открыть журнал, нажмите кнопку [History]{.figtext} на панели [Git]{.figtext}. -В открывшемся окне выводится список коммитов в обратном порядке --- последние коммиты находятся вверху. -В списке выводится краткая информация о коммите, а под списком подробная информация по выделенному коммиту. +![Source Control Graph с тремя учебными коммитами и открытым diff файла paper.qmd для коммита с гистограммой]() -![](./img/02-04-02-history.png){width=690px} +В diff удалённые строки отмечены красным, добавленные — зелёным. Git сравнивает строки, поэтому даже изменение одного символа может выглядеть как удаление старой строки и добавление новой. -- SHA --- так называемый хэш коммита, который является его уникальным идентификатором в репозитории -- Author --- автор коммита \, [которые были указаны в настройках](#setup) -- Date --- дата и время создания коммита -- Subject --- описание коммита -- Parent --- хэш (идентификатор) предыдущего коммита +Для истории одного файла откройте `paper.qmd`, затем разверните **Timeline** в Explorer. Там можно выбрать прежний коммит и посмотреть, как менялся только этот файл. -Еще ниже показан дифф --- изменения, сделанные в этом коммите по сравнению с предыдущим. -Для больших файлов выводятся только те строки, которые поменялись, а также несколько строк выше и ниже, чтобы был понятен контекст. -Если нажать кнопку [View file]{.figtext} справа от названия файла, можно увидеть его полное содержимое, каким оно было зафиксировано создания коммита. +## Рабочая папка, индекс и коммит -Даже если вы работаете в одиночку, полезно иметь под рукой историю изменений. -Но по настоящему эта функция полезна, -когда приходится работать с несколькими версиями одновременно, -например при работе в команде. -[Об этом далее](#git-branch). +Эти три состояния полезно различать: +| Состояние | Что содержит | +|---|---| +| Рабочая папка | Сохранённые на диске файлы, включая незаконченные изменения | +| Индекс | Только изменения, выбранные для следующего коммита | +| Последний коммит | Уже записанный снимок проекта | +Кнопка `+` переносит изменение из рабочей папки в индекс. Кнопка `−` у **Staged Changes** убирает его из индекса, но не удаляет из файла. **Commit** записывает содержимое индекса в историю. + +Официальное руководство [Staging and committing changes](https://code.visualstudio.com/docs/sourcecontrol/staging-commits) использует эту же модель. diff --git a/docs/03-01-branches.md b/docs/03-01-branches.md index 83ea721..e0832dc 100644 --- a/docs/03-01-branches.md +++ b/docs/03-01-branches.md @@ -1,75 +1,31 @@ # (PART) Ветки {-} +# Альтернативный график {#branches} +Ветка — указатель на последовательность коммитов. Она позволяет экспериментировать, не меняя основную линию `main`. -# Введение {#branch} +Представим, что рецензент попросил заменить гистограмму на ящик с усами. Сделаем вариант в отдельной ветке. -До этого мы создавали версии только последовательно, -чтобы записывать историю изменений. -Git позволяет создавать параллельные версии. -Это могут быть как версии различных участников (collaborators) с различных устройств, -так и несколько альтернативных версий на одном и том же компьютере. -Таким образом участники могут создавать и обмениваться различными вариантами изменений. -Git позволяет эффективно объединять эти изменения, делая совместную работу комфортной, -чего, к слову, не умеют облачные сервисы вроде Google Drive. +Убедитесь, что Source Control пуст. Нажмите название `main` в строке состояния и выберите **Create new branch…**. То же действие доступно из палитры команд как **Git: Create Branch**. -Для этого используются так называемые ветки (branch). -Почему ветки? Потому что начиная с выбранного коммита история изменений разветвляется. +Введите название `boxplot` и выберите `main` как исходную ветку. Positron сразу переключится на новую ветку; её имя появится в строке состояния. -По умолчанию, мы работаем в ветке `main` -(ранее ветка по умолчанию называлась `master`, будьте готовы встретить и такое название). -Ее можно сравнить со стволом дерева --- вот он слева на изображении. -В нашем проекте с пингвинами в ветке `main` 4 коммита, последний из которых содержит гистограмму для публикации. +![Positron после создания ветки boxplot: имя ветки видно в строке состояния, Source Control пуст]() -![](./img/03-01-00-history.png){width=600px} +Замените код графика в `paper.qmd`: -Представим ситуацию --- из журнала приходит ответ Рецензента 2, в котором он просит заменить гистограмму на ящик с усами. -С одной стороны, можно податься в журнал, где знают, что такое гистограмма, -с другой, можно хотя бы попробовать удовлетворить пожелания рецензента и, -если нам не понравится новая диаграмма, просто удалить изменения. -# Создание ветки {#git-branch} +``` r +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -Чтобы спокойно поэкспериментировать создадим новую ветку. -Так будет проще удалить изменения и они не будут мешать, если мы захотим поправить что-то действительно важное в основной ветке `main`. - -В RStudio нажмите кнопку [New Branch]{.figtext} [(A)]{.figref} - -![](./img/03-01-01-new-branch.png){width=400px} - -В появившемся окне введите название, например `boxplot` и нажмите кнопку [Create]{.figtext}. -Откроется окно с сообщением, что мы переключились на ветку `boxplot`, -можете закрыть его кнопкой [Close]{.figtext}. - -![](./img/03-01-02-new-branch.png){width=200px} - -![](./img/03-01-03-new-branch.png){width=400px} - -Обратите внимание, что название ветки на панели [Git]{.figtext}, рядом с кнопкой создания ветки [(A)]{.figref}, поменялось с `main` на `boxplot`. - -Вернемся к пингвинам. -Замените содержимое скрипта `penguins.R` на следующее: - -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm - -png("penguins-boxplot.png") +png("out/penguins-boxplot.png") boxplot(x) dev.off() ``` -Сохраните файл и выполните скрипт. -Обратите внмание, что мы поменяли название файла. -Старый файл `penguins-hist.png` в этой версии нам не нужен и его необходимо удалить. -Не переживайте, благодаря Git, в основной ветке `main` он останется. -На панели [Files]{.figtext} отметьте галочкой файл `penguins-hist.png` [(A)]{.figref} и нажмите кнопку [Delete]{.figtext} [(B)]{.figref}. - -![](./img/03-01-04-delete-files.png){width=400px} - -Отметьте все изменения для фиксации и создайте коммит. -Обратите внимание, что удаление файла это тоже изменение, которое надо отметить. +Выполните код. Удалите `out/penguins-hist.png`: в этой версии проекта он больше не нужен. Добавьте в индекс изменение `paper.qmd`, удаление гистограммы и новый `out/penguins-boxplot.png`. -![](./img/03-01-05-commit.png){width=400px} +Создайте коммит `Заменил гистограмму на ящик с усами`. -Теперь отложим эксперименты и вернемся к прежней версии. +![Source Control Graph после коммита в boxplot: main указывает на гистограмму, boxplot — на новый коммит с ящиком с усами]() diff --git a/docs/03-02-checkout.md b/docs/03-02-checkout.md index 9bfc862..729bc33 100644 --- a/docs/03-02-checkout.md +++ b/docs/03-02-checkout.md @@ -1,35 +1,25 @@ -# Переключение веток {#git-checkout} +# Переключение веток {#switch-branches} -Для переключения ветки нажмите на название текущей ветки [(A)]{.figref} на панели [Git]{.figtext}. -В выпадающем списке выберите ветку на которую хотите переключиться (`main`). +Нажмите `boxplot` в строке состояния и выберите `main`. Эта операция называется переключением, а в терминах Git — checkout или switch. -![](./img/03-02-01-branch.png){width=400px} +Откройте `paper.qmd` и папку `out`. В `main` снова должна быть гистограмма и не должно быть нового боксплота. Git привёл рабочую папку к коммиту выбранной ветки. -Убедитесь, что код скрипта вернулся к прежнему состоянию и строит гистограмму, -а в списке файлов находится файл с гистограммой `penguins-hist.png` и нету файла `penguins-boxplot.png`. +![Ветка main после переключения: paper.qmd содержит hist(), в out виден penguins-hist.png]() -![](./img/03-02-02-files.png){width=400px} +## Защита незаписанной работы -Это было просто. -Но есть один случай, когда -Git откажется переключать ветку --- если это приведет к потере данных. - -Например, замените содержимое скрипта `penguins.R` на следующее (добавилась подпись оси X): +В `paper.qmd` добавьте подпись оси: ```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm - -png("penguins-hist.png") -hist(x, breaks = seq(40, 60, 2), xlab = "Bill length, mm") -dev.off() +hist(x, breaks = seq(30, 60, 2), xlab = "Bill length, mm") ``` -Сохраните файл и попробуйте переключиться на ветку `boxplot`. -Вы получите сообщение как на скриншоте ниже. -Если бы Git переключил ветку, ему бы пришлось перезаписать файл `penguins.R`, в который мы внесли изменения, но не зафиксировали. -Поэтому, чтобы не потерять изменения при переключении, сначала необходимо их зафиксировать создав коммит. +Сохраните файл, но пока не создавайте коммит. Попробуйте переключиться на `boxplot`. + +Если переключение перезапишет изменённые строки, Git остановит операцию и предложит сначала сохранить работу. Это защитное поведение: незакоммиченные изменения не потеряны, вы по-прежнему на `main`. + +![Уведомление Positron об отказе переключить ветку из-за незакоммиченных изменений в paper.qmd]() -![](./img/03-02-03-error.png){width=690px} +Вернитесь в Source Control, проверьте diff и создайте коммит `Добавил подпись оси гистограммы`. После этого переключитесь на `boxplot` и обратно на `main`, чтобы проверить обе версии. -Создайте коммит и попробуйте переключиться на ветку `boxplot` и обратно на ветку `main`. +Если нужно временно убрать незаконченные изменения без коммита, используйте **Git: Stash (Include Untracked)**. Для основного упражнения stash не нужен. diff --git a/docs/03-03-merge.md b/docs/03-03-merge.md index a73aef7..372762b 100644 --- a/docs/03-03-merge.md +++ b/docs/03-03-merge.md @@ -1,94 +1,35 @@ -# Слияние веток {#git-merge} +# Слияние и конфликт {#merge-conflict} -[Откройте окно истории](#git-log) и выберите в фильтре сверху показывать все ветки [(all branches)]{.figtext} и все коммиты [(all commits)]{.figtext}. -На диграмме наглядно видно почему это называется веткой. +Сейчас `main` и `boxplot` по-разному изменили одну строку `paper.qmd`. Объединим ветки и разрешим конфликт осознанно. -![](./img/03-03-01-log.png){width=690px} +Переключитесь на `main`. Откройте палитру команд, выполните **Git: Merge Branch** и выберите `boxplot`. -Если мы или другой участник проекта, решим принять эти изменения в основную ветку `main`, -нам нужно выполнить операцию «слияния» (merge). -В RStudio нет встроенной возможности слияния веток, это необходимо делать в терминале. -К счастью, команда совсем не сложная. +Git автоматически объединит независимые изменения, но остановится на `paper.qmd`: обе ветки изменили код графика, и программа не знает, какой вариант нужен. -Для начала переключитесь на ветку, в которую будут вливаться изменения --- -в нашем случае это `main` ([см. переключение веток](#git-checkout)). -Откройте терминал ^[В меню RStudio выберите Tools → Terminal → New Terminal] и введите команду для слияния с веткой `boxplot`. +В Source Control файл появится в разделе **Merge Changes** с предупреждением. Это незавершённое слияние, а не повреждение проекта. -```sh -git merge boxplot +![Source Control после Git: Merge Branch: paper.qmd находится в Merge Changes, слияние ожидает решения]() -``` - -Git попытается автоматически объединить изменения из обеих веток и создать новый коммит. -В большинстве случаев этого достаточно, -но любая совместная работа может приводить к конфликтам --- -когда в обеих ветках была изменена одна и та же строка, но разным образом. -Какую версию предпочтет Git? -Git предпочтет выдать ошибку и попросит вас разрешить конфликт. - -В списке изменений мы видим, -что Git автоматически выбрал изменения связанные с новым и старым файлом для графика -`penguins-hist.png` и `penguins-boxplot.png`, -но лишь частично для скрипта `penguins.R`. - -![](./img/03-03-02-git-pane.png){width=400px} +## Редактор слияний -Причина в том, что мы вносили изменения в код графика в ветке `main` после того как изменили его в ветке `boxplot`. -Откройте файл `penguins.R`. -Git любезно оставил для нас обе версии кода разделив специальными символами. -После строки `<<< HEAD` идет версия из текущей ветки, -строка `===` отделяет две версии друг от друга, -а строка `>>> boxplot` завершает версию из ветки `boxplot`. +Нажмите `paper.qmd` правой кнопкой и выберите **Open in Merge Editor**. Редактор показывает три области: -![](./img/03-03-03-merge-conflict.png){width=690px} +- **Incoming** — изменение из `boxplot`; +- **Current** — изменение из `main`; +- **Result** — итог, который будет записан. -Наша задача переписать выделенный участок (строки 4-12) в одну версию и убрать спецсимволы. -Важно понимать, что Git просто вставил в скрипт кусок текста, -но это все еще обычный R скрипт и мы должны привести его в рабочее состояние. - -Нам нужна версия из ветки `boxplot`, но мы хотим добавить в нее подпись оси, как это было сделано в ветке `main`. -Для этого оставим нижнюю версию (строки 9-11) и удалим лишние строки (4-8 и 12) -и добавим подпись, только для ящика с усами это должна быть подпись оси Y. -В итоге должен получиться следующий код. +В Result оставьте боксплот из Incoming и добавьте к нему подпись из Current: ```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm - -png("penguins-boxplot.png") +png("out/penguins-boxplot.png") boxplot(x, ylab = "Bill length, mm") dev.off() ``` -Сохраните файл и выполните скрипт. -Создайте коммит и -не забудьте отметить галочкой внесенные изменения, -в том числе обновившийся файл `penguins-boxplot.png`, который теперь содержит подпись оси. -Обычно сообщение коммита о слиянии веток содержит следующий текст «Merge branch название-ветки», но можете придумать свое. - -![](./img/03-03-04-git-pane.png){width=400px} - -Итак, мы успешно слили изменения из ветки `boxplot` в основную ветку `main`. -Теперь можно продолжить работу в основной ветке. -Еще лучше будет создать очередную ветку для новых изменений, выполнить работу в ней и точно так же слить в основную. - -![](./img/03-03-05-log.png){width=690px} - -
Как удалить ветку? -Слитую ветку можно удалить. -В RStudio для этого нет встроенных средств, поэтому придется использовать терминал. -Выполните команду: - -```sh -git branch -d boxplot -``` - -Если ветка не была слита, Git откажется ее удалять, ведь могут быть потеряны сделанные в ней изменения. -Если вы действительно уверены, что они вам не нужны и вы хотите удалить не слитую ветку, выполните команду: +Нажмите **Complete Merge**. Убедитесь, что в Result нет строк `<<<<<<<`, `=======` и `>>>>>>>`, а `paper.qmd` находится в **Staged Changes**. -```sh -git branch -D boxplot -``` -
+![Редактор слияний Positron: Incoming содержит boxplot, Current — hist с подписью, Result — boxplot с ylab]() +Обновите `out/penguins-boxplot.png`, добавьте его в индекс и создайте коммит `Слил ветку boxplot`. +Если нужно отказаться от всего слияния, выполните **Git: Abort Merge** из палитры команд. Git вернёт проект к состоянию до попытки merge. diff --git a/docs/03-04-conclusion.md b/docs/03-04-conclusion.md index 7afd073..e8d027e 100644 --- a/docs/03-04-conclusion.md +++ b/docs/03-04-conclusion.md @@ -1,58 +1,21 @@ -# Заключение +# Итог работы с ветками {#branches-conclusion} -Теперь вы умеете создавать и объединять ветки --- -это одни из ключевых функций Git, особенно при совместной работе. -Благодаря простоте работы с ветками, рекомендуется создавать их чаще. -Чем меньше в ветке изменений, тем проще ее слить, и тем ниже вероятность конфликтов из-за одновременных правок одной и той же части проекта. Это отражает известную идею, что при работе в команде лучше синхронизироваться чаще. +Разверните Source Control Graph. От общего коммита расходятся `main` и `boxplot`, а коммит слияния снова соединяет линии. -Рассмотрим продвинутые способы использования веток, а также для чего их использовать не стоит. +![Source Control Graph после слияния: видны расхождение main и boxplot и merge-коммит в main]() -Для начала уточним, что можно создать ветку от любой другой, а не только от основной ветки `main`. Уровень вложенности и количество веток не ограничены. -После слияния ветки она не прекращает свое существование --- в ней можно продолжить работу, а после слить еще раз. -На практике вам вряд ли понадобится больше 3-х уровней вложенности, а ветки лучше периодически удалять, чтобы не запутаться. +Теперь вы умеете: -## Тематические ветки (feature branch) +- создавать ветку командой **Git: Create Branch**; +- переключаться через индикатор ветки или **Git: Checkout to**; +- объединять ветки командой **Git: Merge Branch**; +- разрешать конфликт в трёхстороннем редакторе; +- отменять незавершённое слияние командой **Git: Abort Merge**. -Тематическая ветка содержит изменения, связанные с конкретной задачей или направлением работы. -Это может быть новый этап анализа или изменения в уже сделанные этапы, например: +После проверки слитую локальную ветку можно удалить: переключитесь на `main`, выполните **Git: Delete Branch** и выберите `boxplot`. -- ветка в которой мы визуализировали данные при помощи графиков, может называться `visualize` или `plot`; -- ветка в которой добавляются модели, может называться `model` или, если это более специфическая модель, например нелинейная, то `model-nle`; -- ветка в которой обновлены данные для уже выполненного анализа `update-data`; -- в нашем репозитории, когда мы заменили график на ящик с усами, ветка называлась `boxplot`. +::: {.callout .callout-warning} +Не удаляйте ветку, пока её изменения не слиты и не стали ненужными. Удаление несохранённой линии истории сложнее отменить, чем обычное редактирование файла. +::: -Если в проекте используется трекер задач или ошибок, -то зачастую работа выполняется в отдельной ветке с названием соответствующим номеру из трекера, -например `issue42` или `ticket58`. - -Это самый частый способ использования веток, применяемый независимо от размеров проекта и количества участников. - -## Долгоживущие ветки (long-running branches) - -Этот подход часто применяется для крупных проектов, когда нужно обеспечить высокую стабильность продукта, как правило при разработке программного обеспечения. - -Ветка `main` содержит стабильную версию. -От нее создается ветка `develop` в которой ведется разработка. -Тематические ветки создаются от ветки `develop` и вливаются в нее. -Когда разработка очередной версии завершилась, -изменения из ветки `develop` стабилизируются --- проходят тестирование и ревью, -после чего вливаются в стабильную ветку `main`. - -Далее цикл повторяется --- разработка следующей версии продолжается в ветке `develop` с использованием тематических веток, после чего она снова сливается с веткой `main`. - -## Когда не стоит использовать ветки - -Выше описаны лишь некоторые наиболее часто используемые процессы работы построенные вокруг веток. -Существует и можно придумать много других, подходящих для вас или вашей команды. - -Но у всех применений веток есть общая черта --- это способ организации внесения изменений в проект и рано или поздно эти изменения должны быть слиты или удалены. - -Ветки это не способ структурирования самого анализа или программы. -Например, если у вас есть несколько моделей и вы собираетесь поддерживать их все, то вероятно они должны быть в одной ветке, а не в отдельных. -Иначе потребуется следить за тем, чтобы изменения вносились в каждую ветку --- это утомительно и чревато ошибками. -Для работы с несколькими моделями одновременно придется переключаться и работать с несколькими ветками, что противоречит большинству способов их использования, например описанных выше. - -Другая частая ошибка --- участники создают ветки с собственным именем (`ivan`, `masha-work`) и используют их как личные папки для хранения своих файлов не связанных с файлами других участников. -Ветки предназначены для внесения изменений в один общий проект. Следует либо интегрировать эти файлы в проект, возможно отдельной веткой, либо хранить в другом месте. - -В следующей части мы посмотрим как организовать совместную работу при помощи «удаленных» (remote) веток и сервиса GitHub. +В следующей части вынесем репозиторий на GitHub и повторим этот процесс как предложение изменений для коллег. diff --git a/docs/04-01-github.md b/docs/04-01-github.md index 928b329..3622ec6 100644 --- a/docs/04-01-github.md +++ b/docs/04-01-github.md @@ -1,39 +1,23 @@ # (PART) GitHub {-} -# Настройка {#github} +# Аккаунт и вход {#github-part} -GitHub --- это веб-сервис для хранения Git репозиториев и совместной работы. -Ваши файлы размещаются на удаленном сервере и доступны публично или приватно для загрузки другими пользователями. В некотором смысле это аналог Dropbox или Google Drive для Git. -Помимо хранения репозиториев, GitHub предоставляет другие инструменты: отслеживание задач, обсуждение изменений, запуск тестов и сборок и многое другое. +Git хранит историю на вашем компьютере. GitHub хранит копию репозитория на сервере, поэтому проект можно открыть с другого устройства, показать преподавателю и обсудить изменения с коллегами. -Для работы с GitHub вам понадобится зарегистрировать учетную запись и создать токен --- отдельный пароль для Git на вашем компьютере. +Создайте аккаунт на [github.com](https://github.com/signup), если его ещё нет. Имя пользователя станет частью адресов репозиториев, поэтому лучше использовать короткое имя латиницей. -## Регистрация на GitHub +Positron включает расширения **GitHub** и **GitHub Pull Requests and Issues**. При первой публикации или отправке изменений редактор предложит войти. Выберите **Sign in with GitHub**, подтвердите открытие браузера и разрешите доступ. -Перейдите на сайт github.com и зарегистрируйте учетную запись нажав на кнопку [Sign up]{.figtext} в верхнем правом углу или войдите в существующую учетную запись нажав [Sign in]{.figtext}. +![Positron показывает запрос Sign in with GitHub перед первой публикацией репозитория]() -E-mail при регистрации не обязательно должен совпадать с указанным при настройке Git в [Главе 1](#setup). Дополнительные e-mail адреса можно добавить после регистрации [на странице настроек](https://github.com/settings/emails). -Это рекоммендуется сделать, чтобы GitHub мог ассоциировать сделанные на компьютере коммиты с вашей учетной записью онлайн. +После подтверждения вернитесь в Positron. Не создавайте classic personal access token для этого упражнения: обычный путь входа проходит через браузер. -## Создание токена +::: {.callout .callout-warning} +Никому не отправляйте пароли, токены, приватные ключи и секреты webhook. Не добавляйте их в `.qmd`, `.R`, `.env` или другие файлы репозитория. +::: -В целях безопасности, GitHub не позволяет использовать пароль от веб-сайта при работе с Git, -а требует создать так называемый **Personal Access Token** --- отдельный пароль специально для Git на вашем компьютере. -[Во всех случаях, когда Git запрашивает пароль от GitHub, необходимо вводить токен, а не пароль от веб-сайта.]{} +## Git и GitHub — разные системы -Для этого перейдите по ссылке github.com/settings/tokens, -авторизуйтесь и нажмите **Generate new token**, в выпадающем списке выберите **classic**. -На новой странице введите название токена, например Work. -Отметьте следующие права `repo`, `workflow`, `user` -и нажмите зеленую кнопку **Generate token** в конце страницы. +Коммит, ветка и слияние работают в Git без GitHub. GitHub добавляет удалённый репозиторий, права доступа, pull request, обсуждения и автоматические проверки. -![](img/github-1.png){width=100%} -![](img/github-2.png){width=100%} - -Не забудьте скопировать и сохранить ваш токен - он выглядит как строка вида `ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`. -После того как вы закроете страницу посмотреть созданный токен невозможно. -Храните его в надежном месте как пароль. - -![](img/github-3.png){width=100%} - -Теперь мы готовы опубликовать наш репозиторий на GitHub. +Если сайт GitHub недоступен, локальные коммиты продолжают работать. Когда связь восстановится, их можно отправить на сервер. diff --git a/docs/04-02-remote.md b/docs/04-02-remote.md index 5db3803..ce54fac 100644 --- a/docs/04-02-remote.md +++ b/docs/04-02-remote.md @@ -1,43 +1,25 @@ -# Удаленный репозиторий {#git-remote} +# Публикация репозитория {#publish-github} +Убедитесь, что выбрана ветка `main`, Source Control пуст и последний коммит — `Слил ветку boxplot`. +В Source Control нажмите **Publish to GitHub**. Если кнопка не видна, откройте палитру команд и найдите **Publish to GitHub**. -Для загрузки репозитория с вашего компьютера (он называется локальный репозиторий) на Github необходимо создать удаленный репозиторий на сайте. -На верхней панели в правом углу нажмите кнопку [+]{.figtext} и выберите пункт [New repository]{.figtext}. +Выберите имя репозитория, например `r-course`, и доступ **Private repository**. Для учебного проекта приватный режим безопаснее: открыть репозиторий позже можно в настройках GitHub. -![](./img/04-02-01-new-repository.png){width=400px} +Если Positron предложит выбрать файлы, оставьте все уже отслеживаемые файлы. В проекте не должно быть секретов. -В открывшейся форме достаточно заполнить только название репозитория в поле **Repository name**, например `penguins`. -Остальные поля оставьте по умолчанию, мы только разберем за что они отвечают. +![Диалог Publish to GitHub с именем r-course и выбранным вариантом Private repository]() -- Description --- краткое описание -- Public / Private --- настройка доступа - - Public --- кто угодно сможет просматривать ваши файлы, но только отдельно добавленные пользователи смогут их изменять - - Private --- только отдельно добавленные пользователи смогут просматривать и изменять файлы -- Initialize this repository with --- этот раздел позволяет добавить в создаваемый репозиторий несколько типовых файлов `README` `.gitignore` и `LICENSE`; не отмечайте ни один из них, потому что в нашем репозитории на компьютере уже есть файлы и они будут конфликтовать с этими. +Positron выполнит три связанных действия: -Внизу страницы нажмите [Create repository]{.figtext}. +1. создаст репозиторий на GitHub; +2. добавит его как удалённый репозиторий `origin`; +3. отправит коммиты ветки `main`. -
Пример заполненной формы -![](./img/04-02-02-new-repository.png){width=600px} -
+После публикации откройте созданный репозиторий на GitHub и сравните список файлов с Explorer. Убедитесь, что на сайте есть `paper.qmd`, папка `data` и история коммитов. -*Удалить это? Там и так на форме все написано, только что на англ. Оставить только предупреждение, чтобы не жали Initialize this repository with.* +**Удалённый репозиторий** (remote) — адрес другой копии проекта. Имя `origin` условное, но Git назначает его основной удалённой копии при публикации и клонировании. -*Со скрином формы репозитория тоже ту мач?* - -Для созданного репозитория GitHub сгенерировал набор команд быстрой настройки, воспользуемся ими. -Сначала необходимо убедиться, что напротив адреса репозитория выбрана опция доступа через [HTTPS]{.figtext} [(A)]{.figref}. -Далее скопируйте все три команды из раздела для существующего репозитория (**... or push an existing repository from the command line**, [B]{.figref}) и выполните в терминале ^[В меню RStudio выберите Tools → Terminal → New Terminal]. -На запрос пароля скопируйте и вставьте сгенерированный в предыдущей главе токен. - -![](./img/04-02-03-git-push.png){width=100%} - - - -Мы связали наш локальный репозиторий с удаленным при помощи команды **remote add** --- это необходимо было сделать один раз. -И выполнили команду **push** --- отправить сделанные фиксации в удаленный репозиторий, это необходимо делать регулярно и для этого в интерфейсе RStudio есть кнопка на панели [Git]{.figtext}. -Если команды выполнились успешно, файлы были загружены на GitHub. -Обновите страницу репозитория и проверьте содержимое файлов. - -![](./img/04-02-04-github.png){width=100%} +::: {.callout .callout-info} +GitHub не выполняет код Quarto при обычной отправке. Файлы и история появятся на сервере, но готовый сайт требует отдельной настройки публикации. +::: diff --git a/docs/04-03-push-pull.md b/docs/04-03-push-pull.md index 978d26b..67379ee 100644 --- a/docs/04-03-push-pull.md +++ b/docs/04-03-push-pull.md @@ -1,67 +1,27 @@ -# Загрузка изменений {#git-push-pull} +# Push, pull и синхронизация {#sync-remote} +Локальная и удалённая копии меняются независимо. Три операции поддерживают их в согласованном состоянии. +| Действие | Результат | +|---|---| +| **Push** | Отправляет локальные коммиты на GitHub | +| **Pull** | Загружает удалённые коммиты и объединяет их с текущей веткой | +| **Sync Changes** | Сначала выполняет pull, затем push | -На предыдущем шаге мы загрузили изменения из нашего локального репозитория в удаленный репозиторий на GitHub при помощи команды `push` в терминале. +Эти определения соответствуют официальной документации [Working with repositories and remotes](https://code.visualstudio.com/docs/sourcecontrol/repos-remotes). -Git не синхронизирует изменения автоматически, это необходимо делать вручную, используя команду push ил кнопку [Push]{.figtext} в интерфейсе RStudio на панели [Git]{.figtext}. +## Небольшая проверка -Создадим и загрузим еще один коммит. Например, добавим небольшой комментарий к коду, чтобы человеку открывшему его впервые было легче разобраться. +Добавьте после заголовка `paper.qmd` одно предложение о цели анализа. Сохраните файл, проверьте diff и создайте коммит `Уточнил цель анализа`. -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm +В строке состояния появится исходящий коммит `↑1`. Нажмите **Sync Changes**. После синхронизации счётчик исчезнет, а коммит появится на GitHub. -# Ящик с усами для длины клюва +![Source Control перед Sync Changes: локальная main опережает origin/main на один коммит, в строке состояния показано ↑1]() -png("penguins-boxplot.png") -boxplot(x, ylab = "Bill length, mm") -dev.off() -``` +## Перед началом работы -Сохраните и закомитьте файл `penguins.R`. -После чего нажмите кнопку [Push]{.figtext} в верхнем правом углу. +В совместном проекте начинайте с **Pull**, а заканчивайте **Push**. Так вы раньше увидите чужие изменения и реже столкнётесь с конфликтом. -![](./img/04-03-01-git-push.png){width=100%} +**Sync Changes** удобно, когда вы понимаете обе половины операции. Если нужно отдельно проверить входящие коммиты, выполните **Fetch**, посмотрите их в Source Control Graph и только затем нажмите **Pull**. -Перейдите на страницу репозитория на GitHub и убедитесь, что коммит был загружен. -Это можно понять по тексту сообщения над списком файлов и по тексту и времени изменения напротив файла `penguins.R`. - -![](./img/04-03-02-github.png){width=100%} - -GitHub позволяет вносить изменения в репозиторий из веб-интерфейса. -Эта функция используется редко, потому что код необходимо запускать и проверять на компьютере, но она полезна для небольших правок или загрузки файлов. -Создадим при помощи нее новый файл. -Файл README --- это файл, который отображается на главной странице репозитория для краткого описания проекта. Обычно он включает описание данных и скриптов, как начать работу с проектом и тому подобное. - -Нажмите кнопку [Add a README]{.figtext}. В открывшемся файле введите текст в формате Markdown^[это как RMarkdown, только без возможности выполнения кода на R] (используйте или измените текст ниже) -и нажмите кнопку [Commit changes]{.figtext} в верхнем правом углу. -Откроется окно создания коммита, оставьте текст по умолчанию и подтвердите создание коммита нажатием кнопки [Commit changes]{.figtext} - -![](./img/04-03-03-add-readme.png){width=100%} - -```md -# Пингвины «Палмер» 🐧 - -Этот репозиторий был создан в рамках курса от [Института биоинформатики](bioinf.me/education/stat), -чтобы познакомиться с основами Git — фиксацией изменений, ветвлением и работой с GitHub. - -В качестве примера использованы данные о длине клюва пингвинов, -собранные доктором Кристен Горман на станции «Палмер» в Антарктиде. - -Содержимое репозитория: - -- penguins-boxplot.png — диаграмма ящик с усами, показывающая распределение длины клюва -- penguins.R — скрипт для построения диаграммы -- penguins.csv — данные -``` - -Чтобы загрузить изменения из удаленного репозитория на компьютер используется команда **pull**. - -Вернитесь в RStudio и на панели [Git]{.figtext} нажмите кнопку [Pull]{.figtext}. -Если команда выполнилась успешно, в списке файлов появится файл `README.md`, -а в журнале --- коммит созданный через GitHub. - -Как и в случае с переключением веток, Git откажется загружать изменения и выдаст ошибку, если в рабочей папке имеются незафиксированные изменения, которые конфликтуют с загружаемыми. - -Теперь вы умеете загружать изменения в удалённый репозиторий и из него. Рекомендуем делать это регулярно, чтобы синхронизироваться с другими участниками проекта, по крайней мере, в конце рабочего дня или рабочей сессии. +Если push отклонён, обычно удалённая ветка содержит новые коммиты. Не применяйте force push. Сначала выполните Pull, разрешите возможный конфликт и повторите Push. diff --git a/docs/04-04-pull-request.md b/docs/04-04-pull-request.md index 71ab9a6..a5bc728 100644 --- a/docs/04-04-pull-request.md +++ b/docs/04-04-pull-request.md @@ -1,54 +1,49 @@ -# Pull Request {#pr} +# Pull request {#pull-request} -Pull Request --- это механизм GitHub для слияния веток загруженных в удаленный репозиторий, позволяющий просмотреть, обсудить и проверить предлагаемые изменения перед слиянием. Похожий механизм существует и на других платформах. +Pull request — предложение объединить одну ветку с другой на GitHub. Перед слиянием коллеги могут посмотреть diff, обсудить решение и запустить проверки. -Орнитолог проходящий мимо нашего репозитория обратит внимание, что длину клюва пингвина лучше рассматривать в зависимости от пола. Он даже может предложить необходимые изменения при помощи Pull Request. +## Изменение в ветке -Создайте ветку с названием `adjust-by-sex` при помощи кнопки [New branch]{.figtext} на панели [Git]{.figtext} в RStudio. Убедитесь, что справа от кнопки вместо названия ветки по умолчанию `main` выводится название созданной ветки `adjust-by-sex`. +Создайте от актуальной `main` ветку `adjust-by-sex`. В `paper.qmd` замените блок кода: -![](./img/04-04-01-add-branch.png){width=200} -Отредактируйте скрипт `penguins.R`, добавив пол в код для построения ящика с усами. Код приведен ниже, не забывайте, что вы можете сравнить изменения по сравнению с оригиналом при помощи кнопки [Diff]{.figtext} на панели [Git]{.figtext}. - -```r -data <- read.csv("penguins.csv") -x <- data$bill_length_mm +``` r +data <- read.csv("data/penguins.csv") +x <- data$bill_len g <- data$sex -png("penguins-boxplot.png") +png("out/penguins-boxplot.png") boxplot(x ~ g, xlab = "Sex", ylab = "Bill length, mm") dev.off() ``` -Сохраните и выполните скрипт `penguins.R`. -Создайте коммит включив в него скрипт и обновленную диаграмму `penguins-boxplot.png`. +Соберите документ, проверьте обновлённый график и создайте коммит `Сгруппировал пингвинов по полу`. + +Нажмите **Publish Branch**. Это создаст `adjust-by-sex` в `origin` и свяжет локальную ветку с удалённой. + +![Ветка adjust-by-sex после Publish Branch: Source Control Graph показывает локальную и удалённую ветки на одном коммите]() -![](./img/04-04-02-git-commit.png){width=100%} +## Создание предложения -После создания коммита нажмите кнопку [Push]{.figtext} в верхнем правом углу или на панели [Git]{.figtext}. Так как у вас полные права на редактирование репозитория, то новая ветка будет загружена на GitHub. Прохожему орнитологу пришлось бы создать свою копию репозитория или просить дать доступ средствами GitHub. +Откройте представление **Pull Requests** на панели активности. Нажмите **Create Pull Request** или выполните команду **GitHub Pull Requests: Create Pull Request**. -Перейдите на страницу репозитория в GitHub и убедитесь, что ветка была загружена и содержит сделанные измнения, для этого выберите ее в выпадающем меню появляющемся при нажатии кнопки с названием ветки [main]{.figtext}. +Выберите: -![](img/04-04-03-github-branch.png){width=100%} +- базовый репозиторий — ваш `r-course`; +- базовую ветку — `main`; +- ветку с изменением — `adjust-by-sex`; +- заголовок — `Сгруппировал пингвинов по полу`. -При просмотре ветки отличной от основной, GitHub предложит создать из нее **Pull Request** --- предложение автору репозитория слить изменения из этой ветки. Нажмите кнопку [Contribute]{.figtext} и в выпадающем меню выберите [Open pull request]{.figtext}. +В описании объясните причину: распределение длины клюва теперь показано отдельно для каждого пола. Перед созданием откройте список файлов и проверьте diff. -![](img/04-04-04-github-pr.png){width=100%} +![Форма Create Pull Request в Positron: base main, compare adjust-by-sex, заполнены заголовок и описание]() -GitHub предложит ввести заголовок и описание предлагаемых изменений, правило хорошего тона кратко описать причину изменений и суть предлагаемого решения. А также, прокрутите страницу создания Pull Request и проверьте изменения, которые вы предлагаете, после чего нажмите кнопку [Create pull Request]{.figtext} под полем с описанием. +Нажмите **Create**. Откроется режим просмотра pull request. Здесь можно оставить комментарий к строке, запросить проверку и увидеть обсуждение. -![](img/04-04-05-github-pr.png){width=100%} +## Слияние -На странице Pull Request владельцу репозитория доступна опция слить предложенные изменения. -Нажмите кнопку [Merge pull request]{.figtext} внизу страницы. -В открывшемся окне GitHub предложить ввести текст коммита, как если бы мы делали слияние ветки в терминале. Оставьте или измените текст и нажмите кнопку [Confirm merge]{.figtext} -После успешного слияния ветку можно удалить. +Нажмите **Merge** только после проверки файлов. Выберите обычное создание merge-коммита, затем подтвердите операцию. После успешного слияния удалите ветку, когда Positron предложит это сделать. -![](img/04-04-06-merge-pr.png){width=100%} -![](img/04-04-07-merge-pr.png){width=100%} -![](img/04-04-08-merge-pr.png){width=100%} +Переключитесь на локальную `main` и выполните **Pull**. Убедитесь, что `paper.qmd` содержит группировку по полу, а Source Control Graph — коммит слияния с GitHub. -Вернемся к нашему проекту в RStudio. -Слияние было выполнено онлайн на GitHub, а значит необходимо загрузить изменения в наш локальный репозиторий, т.е. сделать pull. -Переключитесь на ветку `main` при помощи панели [Git]{.figtext} и нажмите кнопку [Pull]{.figtext}. -Убедитесь, что теперь ветка `main` содержит актуальные изменения в файлах `penguins.R` и `penguins-boxplot.png`. +![Локальная main после Pull: в paper.qmd код boxplot по sex, в Graph виден слитый pull request]() diff --git a/docs/04-05-clone.md b/docs/04-05-clone.md index f22c4ab..ed665d5 100644 --- a/docs/04-05-clone.md +++ b/docs/04-05-clone.md @@ -1,34 +1,19 @@ -# Клонирование репозитория {#git-clone} +# Клонирование {#clone-repository} -Сейчас репозиторий доступен публично и -чтобы поделиться проектом достаточно скопировать ссылку из адресной строки браузера. -Отличная идея приложить ее к тексту публикации, если репозиторий содержит данные и код для воспроизведения результатов. -Используйте GitHub чтобы делиться примерами кода. Например, если просите помощи, так другим будет легче понять проблему и предложить решение. +**Клонирование** создаёт новую локальную папку из удалённого репозитория. Вместе с файлами загружаются коммиты и ветки, а Git автоматически добавляет remote `origin`. -Чтобы загрузить удаленный репозиторий на компьютер выполните команду **клонирования (clone)**. -Для этого понадобится адрес репозитория. -Нажмите кнопку [Code]{.figtext} на странице репозитория, -убедитесь что выбрана опция **HTTPS** и скопируйте адрес. +Не клонируйте репозиторий внутрь уже открытого `r-course`. Для проверки используйте другую родительскую папку. -![](./img/04-03-05-new-project.png){width="600px"} +1. Откройте новое окно Positron без проекта. +2. Выполните **Workspaces: New Folder from Git…** из палитры команд. +3. Выберите **Clone from GitHub** и свой репозиторий `r-course`. +4. Укажите родительскую папку, например `projects-copy`. +5. После загрузки нажмите **Open**. -Создадим проект RStudio. -В верхнем меню выберите [File → New Project]{.figtext}. -В появившемся окне выберите [Version Control]{.figtext} и далее [Git]{.figtext}. -В поле [Repository URL]{.figtext} вставьте адрес репозитория. -В поле [Project directory name]{.figtext} укажите название папки для проекта --- -т.к. папка `penguins` уже существует, используем название `penguins2`. -Откроется окно проекта, RStudio готова к работе. +![Окно Workspaces: New Folder from Git со списком репозиториев GitHub и выбранным r-course]() - - - - - - - - - -
![](./img/04-03-01-new-project.png){width="320px"}![](./img/04-03-02-new-project.png){width="320px"}
![](./img/04-03-03-new-project.png){width="320px"}![](./img/04-03-04-new-project.png){width="320px"}
+Откройте Source Control Graph и `paper.qmd`. История и код должны совпадать с первым проектом. -Мы склонировали удаленный репозиторий на компьютер и теперь можем работать с ним как с оригинальным проектом --- делать коммиты, загружать изменения в удаленный репозиторий (push) и из него (pull). +Не редактируйте обе копии одновременно без необходимости. Это два независимых рабочих каталога: изменения попадут друг к другу только через Push и Pull. + +Если Positron спрашивает, доверяете ли вы содержимому, подтверждайте доверие только для своего репозитория или известного источника. Открытие чужого проекта ещё не запускает код, но дальнейшее выполнение файлов может это сделать. diff --git a/docs/04-06-conclusion.md b/docs/04-06-conclusion.md index bf1b66e..5b0ed71 100644 --- a/docs/04-06-conclusion.md +++ b/docs/04-06-conclusion.md @@ -1,17 +1,14 @@ -# Заключение +# Итог работы с GitHub {#github-conclusion} -Теперь у вас есть аккаунт на GitHub и вы умеете синхронизировать изменения с удаленным репозиторием, -пользоваться веб-интерфейсом и создавать Pull Request. -Этого достаточно для командной работы на курсе и в большинстве проектов. +Теперь вы умеете: -Диаграмма ниже поможет запомнить как соотносятся действия, которые мы изучили: -[1) создание коммитов](#git-commit), [2) работа с ветками](#branch) и [3) синхронизация с удаленным репозиторием](#git-push-pull). +- публиковать локальный репозиторий через **Publish to GitHub**; +- входить в GitHub через браузер; +- различать Push, Pull, Fetch и Sync Changes; +- публиковать отдельную ветку; +- создавать, проверять и сливать pull request; +- клонировать проект командой **Workspaces: New Folder from Git…**. -![](./img/04-06-sequence.png){width=100%} +Для обычной работы достаточно короткого цикла: Pull → новая ветка → небольшие коммиты → Push → pull request → проверка → merge. -Рекомендуем использовать Git в своих проектах и не бояться экспериментировать с ветками. -Это помогает структурировать рабочий процесс, делает анализ данных воспроизводимым и облегчает командную работу. -Даже если вы работаете в одиночку, история изменений, возможность вернуться к предыдущим версиям и ветвление значительно упрощают развитие проекта. -А со временем вы сможете применять более продвинутые возможности, такие как автоматизация, интеграция с другими сервисами и управление проектами. - -Удачи в прохождении курса! +GitHub — не резервная копия незакоммиченных файлов. Пока изменение не вошло в коммит и не отправлено, оно существует только в вашей рабочей папке. diff --git a/docs/05-01-faq.md b/docs/05-01-faq.md index 128bc53..0bf9008 100644 --- a/docs/05-01-faq.md +++ b/docs/05-01-faq.md @@ -1,57 +1,41 @@ -# (PART) Дополнительные материалы {-} +# (PART) Дополнительно {-} -# Best practices {#faq} +# Частые ситуации {#faq} -## .gitignore {#gitignore} +## Source Control не показывает проект -## Feature бранчи {#feature-branch} +Убедитесь, что в Positron открыта именно папка `r-course`, а не отдельный файл. Затем выполните **Developer: Reload Window**. Если репозитория действительно нет, появится **Initialize Repository**. -Хорошая практика каждое изменение делать в свой ветке. +Для диагностики откройте **Git: Show Git Output**. Последняя строка обычно содержит команду и причину ошибки. Перед отправкой лога удалите из него токены и приватные адреса. -Не всегда это удобно, особенно когда работаешь один. -Чтобы перенести уже сделанные коммиты в отдельную ветку воспользуйтесь [этим рецептом](#commits-to-branch). +## Коммит не содержит файл -## Комитьте и пушьте чаще +Коммит получает только **Staged Changes**. Найдите файл в **Changes**, нажмите `+`, проверьте diff и создайте новый коммит. Не нужно удалять предыдущий коммит ради пропущенного файла. -Так меньше проблем при слиянии +## В коммит попал лишний файл -## Принудительный push {#force-push} +Если коммит ещё не отправлен и вы работаете один, откройте в Source Control меню **More Actions (…) → Commit → Undo Last Commit**. Изменения останутся в **Staged Changes**. Исправьте индекс и создайте коммит снова. -Это может привести к потери изменений загруженных на сервер ранее, например вашим коллегой. -Никогда не делайте так в команде, не уточнив у других. +Если коммит уже отправлен или его могли скачать коллеги, не переписывайте историю. Сделайте новый коммит, который удаляет или исправляет лишнее. -## Как перенести коммиты в ветку {#commits-to-branch} +## Нужно временно переключиться -Идея рецепта в том, -что мы создаем новую ветку из текущего набора коммитов, -переключаемся на оригинальную и в ней ненужные коммиты отменяем. +Сохраните законченную часть коммитом. Для незаконченной используйте **Git: Stash (Include Untracked)**, затем переключитесь. Вернуть выбранный stash можно командой **Git: Pop Stash...**. -::: {.alert .alert-warning} -Этот подход не сработает если вы загрузили коммиты на сервер, -потому что отмена коммитов переписывает историю. -Это потребует выполнения команды `git push --force`. -[Почему это плохо?](#force-push) -::: +## Конфликт возник при Pull -Создайте новую ветку - она будет содержать набор коммитов, который вы имеете сейчас, -при помощи RStudio или командой ниже. +Это то же слияние, что в главе \@ref(merge-conflict). Откройте файлы из **Merge Changes**, соберите осмысленный Result, нажмите **Complete Merge** и создайте коммит. После этого повторите Push. -```sh -git branch some -``` +## Опасные операции -Важно! Убедитесь в том, что создали ветку. Для этого посмотрите журнал или команду `git log` и найдите напротив текущего коммита надпись с названием созданной ветки. +Команды force push, hard reset, удаление неслитой ветки и переписывание опубликованной истории могут стереть доступ к чужим коммитам. -Вернитесь на оригинальную ветку, как правило это `main`, при помощи RStudio или команды ниже. +::: {.callout .callout-warning} +Не используйте **Force Push**, `git reset --hard` и удаление неслитых веток в командном проекте без явного согласования. Сначала создайте резервную ветку или попросите преподавателя помочь. +::: -```sh -git checkout main -``` +## Данные и секреты -Отмените нужное количество комитов, скажем `3`. -Опция `--hard` удалит все изменения. -Ничего страшного, ведь они остались в ветке, созданной на предыдущем шаге. +Git хорошо подходит для кода и небольших учебных данных. Большие файлы быстро раздувают историю, а удалённый из последнего коммита секрет может сохраниться в старых версиях. -```sh -git reset --hard HEAD~3 -``` +Перед первым коммитом добавляйте в `.gitignore` временные файлы, локальные настройки и секреты. Если секрет уже отправлен, сначала отзовите его у провайдера; одного удаления файла недостаточно. diff --git a/docs/05-02-references.md b/docs/05-02-references.md index b1460ee..4e63d99 100644 --- a/docs/05-02-references.md +++ b/docs/05-02-references.md @@ -1,5 +1,25 @@ # Ссылки {#references} -- [Pro Git](https://git-scm.com/book/en/v2) --- небольшая книга рекомендованная разработчиками Git. Из нее вы узнаете о внутреннем устройстве Git и научитесь работать с командой `git` в терминале. Пригодятся главы 1-3 и глава 6. -- [Happy Git and GitHub for the useR](https://happygitwithr.com/) --- материалы практического курса по Git с конференции Posit. -- [Git Cheatsheet](https://ndpsoftware.com/git-cheatsheet.html#loc=local_repo;) - интерактивная шпаргалка. +## Positron + +- [Welcome to Positron](https://positron.posit.co/welcome.html) — исходная точка официальной документации. +- [Git Version Control](https://positron.posit.co/git.html) — Git, Source Control, ветки и конфликты в Positron. +- [Command Palette](https://positron.posit.co/command-palette.html) — поиск и запуск команд. +- [Quarto](https://positron.posit.co/quarto.html) — выполнение и предпросмотр `.qmd`. +- [Folder Templates](https://positron.posit.co/folder-templates.html) — состав проекта, включая `.git` и `.gitignore`. + +## Git и Source Control + +- [Source Control overview](https://code.visualstudio.com/docs/sourcecontrol/overview). +- [Staging and committing changes](https://code.visualstudio.com/docs/sourcecontrol/staging-commits). +- [Source Control history](https://code.visualstudio.com/docs/sourcecontrol/history). +- [Branches and worktrees](https://code.visualstudio.com/docs/sourcecontrol/branches-worktrees). +- [Merge conflicts](https://code.visualstudio.com/docs/sourcecontrol/merge-conflicts). +- [Repositories and remotes](https://code.visualstudio.com/docs/sourcecontrol/repos-remotes). +- [GitHub in Source Control](https://code.visualstudio.com/docs/sourcecontrol/github). +- [Pro Git](https://git-scm.com/book/ru/v2) — подробная бесплатная книга. + +## Практика + +- [Learn Git Branching](https://learngitbranching.js.org/?locale=ru_RU) — интерактивные упражнения с ветками. +- [Happy Git and GitHub for the useR](https://happygitwithr.com/) — Git для проектов анализа данных. diff --git a/docs/05-03-webhooks.md b/docs/05-03-webhooks.md index eae5442..09ee9cd 100644 --- a/docs/05-03-webhooks.md +++ b/docs/05-03-webhooks.md @@ -1,25 +1,23 @@ # Webhooks {#webhooks} -Webhooks — это механизм GitHub для реагирования на события в репозитории. -Когда что-то происходит (например, кто-то сделал push или создал Pull Request), -GitHub отправит информацию о событии на указанный в настройках адрес. +Webhook позволяет GitHub отправить HTTP-запрос внешнему сервису после события: push, создания pull request или слияния. Так запускают уведомления и автоматические проверки. -Для обработки событий по указанному адресу должна работать программа (веб-сервер). -Многие сервисы, например Slack или Microsoft Teams, поддерживают таким образом отправку уведомлений в рабочий чат. -Для Telegram можно воспользоваться ботом [@octo8bot](https://t.me/octo8bot). +Для настройки нужен готовый HTTPS-адрес сервиса. Не указывайте случайный сайт: содержимое запроса может включать имена репозитория, веток и участников. -Добавьте бота в чат и скопируйте присланный им адрес. +1. Откройте репозиторий на GitHub. +2. Перейдите **Settings → Webhooks → Add webhook**. +3. Вставьте адрес в **Payload URL**. +4. Выберите `application/json`. +5. Добавьте отдельный случайный **Secret**, если принимающий сервис умеет проверять подпись. +6. Выберите **Let me select individual events** и оставьте **Pull requests**. +7. Нажмите **Add webhook**. -![](./img/05-03-add-bot.png){width=400px} +![Страница GitHub Add webhook: заполнен Payload URL, content type application/json, выбран Pull requests, секрет скрыт]() -Откройте репозиторий на Github и выберите **Settings → Webhooks → Add webhook**. -Вставьте адрес в поле **Payload URL** и заполните форму как на скриншоте ниже. -Нажмите **Add webhook**. +В разделе **Recent Deliveries** откройте тестовую доставку. Код `2xx` означает, что сервис принял запрос. Код `4xx` обычно указывает на неверный адрес или авторизацию, `5xx` — на ошибку принимающего сервиса. -![](./img/05-03-github.png){width=100%} +::: {.callout .callout-warning} +Webhook может запускать действия во внешней системе. Проверяйте адрес и минимально необходимый набор событий. Не записывайте secret в репозиторий и не показывайте его на скриншоте. +::: -Если webhook настроен правильно, в чат придет сообщение с текстом «Successfully installed». - -Когда создаётся новый Pull Request, в него вносятся изменения или он сливается (merge), бот пришлет уведомление с ссылкой на этот Pull Request. - -![](./img/05-03-notifications.png){width=400px} +Для преподавателя генератор проекта умеет создать такой webhook через `gh` в состоянии `github-webhook`; студенту достаточно один раз пройти настройку в интерфейсе и проверить доставку. diff --git a/docs/404.html b/docs/404.html index 10a7360..e6c9d17 100644 --- a/docs/404.html +++ b/docs/404.html @@ -1,61 +1,38 @@ - + - - - - Page not found | Основы Git - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + -
-
+

Page not found +

The page you requested cannot be found (perhaps it was moved or renamed).

You may want to try searching to find the page's new location, or use the table of contents to find the page you are looking for.

-
- - +
+
+
+
-
-
+

This book was built by the bookdown R package.

-
- - - +
- diff --git a/docs/about-git.html b/docs/about-git.html new file mode 100644 index 0000000..6fbc5c6 --- /dev/null +++ b/docs/about-git.html @@ -0,0 +1,142 @@ + + + + + + +Глава 2 Зачем проекту Git | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 2 Зачем проекту Git +

+

В проекте анализа данных меняются код, текст отчёта и графики. Копии с названиями final, final-2 и really-final сохраняют файлы, но не объясняют, кто и зачем их менял.

+

Git хранит коммиты — снимки выбранных изменений с коротким пояснением. Из них складывается история проекта. По ней можно:

+
    +
  • сравнить текущую работу с предыдущей версией;
  • +
  • вернуть исправный вариант;
  • +
  • вести несколько вариантов анализа в ветках;
  • +
  • объединять изменения разных участников.
  • +
+

Git работает локально. Для коммитов не нужны интернет и аккаунт. GitHub понадобится позже как удалённое место для общей истории и обсуждения изменений.

+
+

+2.1 Что уже есть в проекте +

+

Откройте папку r-course, созданную в предыдущем курсе. Не создавайте новый учебный проект и не переносите файлы.

+

В проекте могут оставаться .R-скрипты, report.qmd, analysis.qmd, другие документы, папки data и out. Это ожидаемое состояние. Git умеет отслеживать любые файлы; расширение не нужно менять ради Git.

+

Новый код этого курса будем писать в paper.qmd. Так текст, команды R и результат останутся в одном воспроизводимом документе Quarto.

+
+
+

+2.2 Репозиторий +

+

Репозиторий — папка проекта вместе со скрытой служебной папкой .git. В .git находится история, ветки и настройки связи с удалённым репозиторием.

+

Шаблон R Project в Positron создаёт .git и .gitignore автоматически. Поэтому проект из R-курса уже должен быть репозиторием, хотя в нём пока нет коммитов. В главе 5 мы это проверим.

+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/about.html b/docs/about.html deleted file mode 100644 index 05e104b..0000000 --- a/docs/about.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - -Глава 2 Что такое Git | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 2 Что такое Git -

-

Git — это программа, выполняющая функции Системы Контроля Версий (VCS, Version Control System). -Многие применяют простую систему контроля версий, вручную копируя файлы и добавляя дату в названия. -Git автоматически отслеживает изменения во время редактирования файлов, позволяет фиксировать состояние файлов в версии, хранить и переключаться между ними. -Вы сможете оценить, какие изменения внесли, а также посмотреть историю изменений — когда, кем и с какой целью они были сделаны.

-
-
-
-

Важная особенность Git в том, что участники могут работать и создавать версии независимо друг от друга на своих компьютерах. Каждый может работать над своей задачей, не мешая другим, даже если все редактируют один и тот же файл. Git поможет объединить изменения в одну общую версию.

-

Проект Git можно загрузить на сервер для надежного хранения и передачи файлов, совместной работы и публикации. -Самым популярным сервисом для этого является GitHub. -Он похож на облачные хранилища, такие как Google Drive или Dropbox, но с более продвинутым отслеживанием и объединением изменений, а также другими полезными функциями. -Вместо GitHub можно использовать другой сервер, например корпоративный во внутренней сети организации или использовать Git оффлайн — только на своем компьютере.

-

Если это всё ещё не убедило вас начать использовать Git, вот несколько примеров, когда он будет полезен:

-
    -
  • Возможно, вы оказывались в следующей ситуации. Вы вносите изменения в работающую программу или файл. Оцениваете результат и решаете отменить изменения. Вот только у вас нет копии оригинального файла, а вернуть прежнее состояние почему-то не получается — программа никак не работает или работает иначе. С Git это делается одной командой, а экспериментальную версию можно сохранить и вернуться к ней позже.

  • -
  • Если вам понадобилась помощь, вы можете одной командой загрузить сделанные изменения на GitHub. Другой участник увидит, что вы пытаетесь сделать, и может загрузить решение проблемы, а вы так же одной командой получите исправленную версию.

  • -
-

Благодаря последовательному внесению и отслеживанию изменений Git помогает организовать процесс анализа данных, обеспечивает воспроизводимость и упрощает совместную работу над проектом.

-
-

Существуют другие системы контроля версий, например Mercurial и Subversion и вероятно, в будущем появятся новые. -Но благодаря простоте, эффективности и приобретенной популярности в основном используется Git.

-
- -
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/branch.html b/docs/branch.html deleted file mode 100644 index 851d80f..0000000 --- a/docs/branch.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - -Глава 9 Введение | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 9 Введение -

-

До этого мы создавали версии только последовательно, -чтобы записывать историю изменений. -Git позволяет создавать параллельные версии. -Это могут быть как версии различных участников (collaborators) с различных устройств, -так и несколько альтернативных версий на одном и том же компьютере. -Таким образом участники могут создавать и обмениваться различными вариантами изменений. -Git позволяет эффективно объединять эти изменения, делая совместную работу комфортной, -чего, к слову, не умеют облачные сервисы вроде Google Drive.

-

Для этого используются так называемые ветки (branch). -Почему ветки? Потому что начиная с выбранного коммита история изменений разветвляется.

-

По умолчанию, мы работаем в ветке main -(ранее ветка по умолчанию называлась master, будьте готовы встретить и такое название). -Ее можно сравнить со стволом дерева — вот он слева на изображении. -В нашем проекте с пингвинами в ветке main 4 коммита, последний из которых содержит гистограмму для публикации.

-
-

Представим ситуацию — из журнала приходит ответ Рецензента 2, в котором он просит заменить гистограмму на ящик с усами. -С одной стороны, можно податься в журнал, где знают, что такое гистограмма, -с другой, можно хотя бы попробовать удовлетворить пожелания рецензента и, -если нам не понравится новая диаграмма, просто удалить изменения.

-
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/branches-conclusion.html b/docs/branches-conclusion.html new file mode 100644 index 0000000..6ad2474 --- /dev/null +++ b/docs/branches-conclusion.html @@ -0,0 +1,134 @@ + + + + + + +Глава 12 Итог работы с ветками | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 12 Итог работы с ветками +

+

Разверните Source Control Graph. От общего коммита расходятся main и boxplot, а коммит слияния снова соединяет линии.

+
+Source Control Graph после слияния: видны расхождение main и boxplot и merge-коммит в main
Source Control Graph после слияния: видны расхождение main и boxplot и merge-коммит в main
+
+

Теперь вы умеете:

+
    +
  • создавать ветку командой Git: Create Branch;
  • +
  • переключаться через индикатор ветки или Git: Checkout to;
  • +
  • объединять ветки командой Git: Merge Branch;
  • +
  • разрешать конфликт в трёхстороннем редакторе;
  • +
  • отменять незавершённое слияние командой Git: Abort Merge.
  • +
+

После проверки слитую локальную ветку можно удалить: переключитесь на main, выполните Git: Delete Branch и выберите boxplot.

+
+

Не удаляйте ветку, пока её изменения не слиты и не стали ненужными. Удаление несохранённой линии истории сложнее отменить, чем обычное редактирование файла.

+
+

В следующей части вынесем репозиторий на GitHub и повторим этот процесс как предложение изменений для коллег.

+ +
+ + + +
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/branches.html b/docs/branches.html new file mode 100644 index 0000000..3c8c5c0 --- /dev/null +++ b/docs/branches.html @@ -0,0 +1,134 @@ + + + + + + +Глава 9 Альтернативный график | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 9 Альтернативный график +

+

Ветка — указатель на последовательность коммитов. Она позволяет экспериментировать, не меняя основную линию main.

+

Представим, что рецензент попросил заменить гистограмму на ящик с усами. Сделаем вариант в отдельной ветке.

+

Убедитесь, что Source Control пуст. Нажмите название main в строке состояния и выберите Create new branch…. То же действие доступно из палитры команд как Git: Create Branch.

+

Введите название boxplot и выберите main как исходную ветку. Positron сразу переключится на новую ветку; её имя появится в строке состояния.

+
+Positron после создания ветки boxplot: имя ветки видно в строке состояния, Source Control пуст
Positron после создания ветки boxplot: имя ветки видно в строке состояния, Source Control пуст
+
+

Замените код графика в paper.qmd:

+
+data <- read.csv("data/penguins.csv")
+x <- data$bill_len |> na.omit()
+
+png("out/penguins-boxplot.png")
+boxplot(x)
+dev.off()
+

Выполните код. Удалите out/penguins-hist.png: в этой версии проекта он больше не нужен. Добавьте в индекс изменение paper.qmd, удаление гистограммы и новый out/penguins-boxplot.png.

+

Создайте коммит Заменил гистограмму на ящик с усами.

+
+Source Control Graph после коммита в boxplot: main указывает на гистограмму, boxplot — на новый коммит с ящиком с усами
Source Control Graph после коммита в boxplot: main указывает на гистограмму, boxplot — на новый коммит с ящиком с усами
+
+ +
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/clone-repository.html b/docs/clone-repository.html new file mode 100644 index 0000000..f0b8fc2 --- /dev/null +++ b/docs/clone-repository.html @@ -0,0 +1,129 @@ + + + + + + +Глава 17 Клонирование | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 17 Клонирование +

+

Клонирование создаёт новую локальную папку из удалённого репозитория. Вместе с файлами загружаются коммиты и ветки, а Git автоматически добавляет remote origin.

+

Не клонируйте репозиторий внутрь уже открытого r-course. Для проверки используйте другую родительскую папку.

+
    +
  1. Откройте новое окно Positron без проекта.
  2. +
  3. Выполните Workspaces: New Folder from Git… из палитры команд.
  4. +
  5. Выберите Clone from GitHub и свой репозиторий r-course.
  6. +
  7. Укажите родительскую папку, например projects-copy.
  8. +
  9. После загрузки нажмите Open.
  10. +
+
+Окно Workspaces: New Folder from Git со списком репозиториев GitHub и выбранным r-course
Окно Workspaces: New Folder from Git со списком репозиториев GitHub и выбранным r-course
+
+

Откройте Source Control Graph и paper.qmd. История и код должны совпадать с первым проектом.

+

Не редактируйте обе копии одновременно без необходимости. Это два независимых рабочих каталога: изменения попадут друг к другу только через Push и Pull.

+

Если Positron спрашивает, доверяете ли вы содержимому, подтверждайте доверие только для своего репозитория или известного источника. Открытие чужого проекта ещё не запускает код, но дальнейшее выполнение файлов может это сделать.

+ +
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/commit-workflow.html b/docs/commit-workflow.html new file mode 100644 index 0000000..fb365ba --- /dev/null +++ b/docs/commit-workflow.html @@ -0,0 +1,166 @@ + + + + + + +Глава 7 Рабочий цикл | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 7 Рабочий цикл +

+

Теперь начнём отдельный анализ для Git-курса. Каждая небольшая законченная задача станет коммитом:

+
    +
  1. изменить и сохранить файл;
  2. +
  3. открыть diff и проверить изменение;
  4. +
  5. добавить нужные файлы в индекс;
  6. +
  7. записать коммит;
  8. +
  9. убедиться, что Source Control снова пуст.
  10. +
+
+

+7.1 Документ Quarto +

+

Создайте в корне проекта файл paper.qmd. Накопленные .R-скрипты остаются без изменений, но весь новый код пишем в Quarto.

+

Добавьте настройки и первый блок R:

+
---
+title: "Длина клюва пингвинов"
+format: html
+---
+
+data <- read.csv("data/penguins.csv")
+x <- data$bill_len |> na.omit()
+x
+

Путь начинается от корня проекта. Данные уже находятся в data, поэтому ничего скачивать и перекладывать не нужно. В новом коде используем базовую трубу |>.

+

Выполните блок в текущей R-сессии. Positron передаст код из документа Quarto в Console. Убедитесь, что вектор x создан без ошибки.

+
+Открытый paper.qmd после выполнения блока: в Console виден результат импорта data/penguins.csv
Открытый paper.qmd после выполнения блока: в Console виден результат импорта data/penguins.csv
+
+

Сохраните файл, проверьте diff и создайте коммит Добавил импорт данных в paper.qmd.

+
+
+

+7.2 Гистограмма +

+

Замените блок кода на следующий:

+
+data <- read.csv("data/penguins.csv")
+x <- data$bill_len |> na.omit()
+
+png("out/penguins-hist.png")
+hist(x, breaks = seq(30, 60, 2))
+dev.off()
+

Выполните блок. В папке out появится penguins-hist.png.

+

В Source Control выберите paper.qmd и проверьте добавленные строки. Затем добавьте в индекс paper.qmd и out/penguins-hist.png, но не остальные случайные изменения. Создайте коммит Сохранил гистограмму длины клюва.

+
+Source Control перед коммитом гистограммы: в Staged Changes находятся только paper.qmd и out/penguins-hist.png
Source Control перед коммитом гистограммы: в Staged Changes находятся только paper.qmd и out/penguins-hist.png
+
+

Теперь у проекта есть исходная версия, импорт данных и готовый график в трёх отдельных коммитах.

+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/faq.html b/docs/faq.html index dec8470..d867c9b 100644 --- a/docs/faq.html +++ b/docs/faq.html @@ -4,20 +4,20 @@ -Глава 20 Best practices | Основы Git +Глава 19 Частые ситуации | Основы Git в Positron - + - + - + - - + + - + + + + + +
+
+
+

+Глава 6 Первый коммит +

+

Коммит состоит из снимка выбранных файлов, автора, времени и сообщения. Сначала файлы попадают в индекс (staging area), затем Git записывает из индекса коммит.

+
+

+6.1 Проверка изменений +

+

В Source Control выберите любой текстовый файл. Откроется редактор различий (diff). Для нового файла одна сторона сравнения пуста, а весь текст отмечен как добавленный.

+

Бинарные файлы, например .png, .xlsx и .rds, Git сохранит, но не покажет построчное сравнение. Перед коммитом откройте их обычным способом и убедитесь, что это нужные файлы.

+
+Редактор различий Positron для нового текстового файла из проекта r-course и список Changes в Source Control
Редактор различий Positron для нового текстового файла из проекта r-course и список Changes в Source Control
+
+
+
+

+6.2 Добавление в индекс +

+

Наведите указатель на заголовок Changes и нажмите + (Stage All Changes). Файлы переместятся в раздел Staged Changes.

+

Проверьте список ещё раз. В первый коммит должны войти все накопленные файлы проекта, кроме уже скрытых правилами .gitignore.

+
+
+

+6.3 Запись коммита +

+

Введите сообщение:

+
Зафиксировал результат курса R
+

Нажмите Commit. Если Positron попросит настроить автора, вернитесь к главе 4.

+
+Source Control сразу после исходного коммита: разделы Changes и Staged Changes пусты, в Graph виден один коммит
Source Control сразу после исходного коммита: разделы Changes и Staged Changes пусты, в Graph виден один коммит
+
+

Пустой список изменений означает, что рабочая папка совпадает с последним коммитом. Старые файлы никуда не переместились: Git только записал их состояние.

+
+

Сообщение коммита отвечает на вопрос «что сделал этот шаг?». Короткая форма с глаголом помогает читать историю: «Добавил импорт данных», «Исправил подпись оси».

+
+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/git-branch.html b/docs/git-branch.html deleted file mode 100644 index 866fe8d..0000000 --- a/docs/git-branch.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - -Глава 10 Создание ветки | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 10 Создание ветки -

-

Чтобы спокойно поэкспериментировать создадим новую ветку. -Так будет проще удалить изменения и они не будут мешать, если мы захотим поправить что-то действительно важное в основной ветке main.

-

В RStudio нажмите кнопку New Branch (A)

-
-

В появившемся окне введите название, например boxplot и нажмите кнопку Create. -Откроется окно с сообщением, что мы переключились на ветку boxplot, -можете закрыть его кнопкой Close.

-
-
-

Обратите внимание, что название ветки на панели Git, рядом с кнопкой создания ветки (A), поменялось с main на boxplot.

-

Вернемся к пингвинам. -Замените содержимое скрипта penguins.R на следующее:

-
-data <- read.csv("penguins.csv")
-x <- data$bill_length_mm
-
-png("penguins-boxplot.png")
-boxplot(x)
-dev.off()
-

Сохраните файл и выполните скрипт. -Обратите внмание, что мы поменяли название файла. -Старый файл penguins-hist.png в этой версии нам не нужен и его необходимо удалить. -Не переживайте, благодаря Git, в основной ветке main он останется. -На панели Files отметьте галочкой файл penguins-hist.png (A) и нажмите кнопку Delete (B).

-
-

Отметьте все изменения для фиксации и создайте коммит. -Обратите внимание, что удаление файла это тоже изменение, которое надо отметить.

-
-

Теперь отложим эксперименты и вернемся к прежней версии.

- -
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-checkout.html b/docs/git-checkout.html deleted file mode 100644 index ac95249..0000000 --- a/docs/git-checkout.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - -Глава 11 Переключение веток | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 11 Переключение веток -

-

Для переключения ветки нажмите на название текущей ветки (A) на панели Git. -В выпадающем списке выберите ветку на которую хотите переключиться (main).

-
-

Убедитесь, что код скрипта вернулся к прежнему состоянию и строит гистограмму, -а в списке файлов находится файл с гистограммой penguins-hist.png и нету файла penguins-boxplot.png.

-
-

Это было просто. -Но есть один случай, когда -Git откажется переключать ветку — если это приведет к потере данных.

-

Например, замените содержимое скрипта penguins.R на следующее (добавилась подпись оси X):

-
-data <- read.csv("penguins.csv")
-x <- data$bill_length_mm
-
-png("penguins-hist.png")
-hist(x, breaks = seq(40, 60, 2), xlab = "Bill length, mm")
-dev.off()
-

Сохраните файл и попробуйте переключиться на ветку boxplot. -Вы получите сообщение как на скриншоте ниже. -Если бы Git переключил ветку, ему бы пришлось перезаписать файл penguins.R, в который мы внесли изменения, но не зафиксировали. -Поэтому, чтобы не потерять изменения при переключении, сначала необходимо их зафиксировать создав коммит.

-
-

Создайте коммит и попробуйте переключиться на ветку boxplot и обратно на ветку main.

- -
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-clone.html b/docs/git-clone.html deleted file mode 100644 index 1e4a4c1..0000000 --- a/docs/git-clone.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - -Глава 18 Клонирование репозитория | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 18 Клонирование репозитория -

-

Сейчас репозиторий доступен публично и -чтобы поделиться проектом достаточно скопировать ссылку из адресной строки браузера. -Отличная идея приложить ее к тексту публикации, если репозиторий содержит данные и код для воспроизведения результатов. -Используйте GitHub чтобы делиться примерами кода. Например, если просите помощи, так другим будет легче понять проблему и предложить решение.

-

Чтобы загрузить удаленный репозиторий на компьютер выполните команду клонирования (clone). -Для этого понадобится адрес репозитория. -Нажмите кнопку Code на странице репозитория, -убедитесь что выбрана опция HTTPS и скопируйте адрес.

-
-

Создадим проект RStudio. -В верхнем меню выберите File → New Project. -В появившемся окне выберите Version Control и далее Git. -В поле Repository URL вставьте адрес репозитория. -В поле Project directory name укажите название папки для проекта — -т.к. папка penguins уже существует, используем название penguins2. -Откроется окно проекта, RStudio готова к работе.

-
- - - - - - - - -
- - - -
- - - -
-

Мы склонировали удаленный репозиторий на компьютер и теперь можем работать с ним как с оригинальным проектом — делать коммиты, загружать изменения в удаленный репозиторий (push) и из него (pull).

- -
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-commit.html b/docs/git-commit.html deleted file mode 100644 index 628b5bc..0000000 --- a/docs/git-commit.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - -Глава 6 Отслеживание изменений | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 6 Отслеживание изменений -

-

Git отслеживает изменения в файлах, находящихся в рабочей папке. -Но не все подряд, как это делают Блокнот или Word при помощи команд «Отменить» и «Повторить», -а при помощи версий — или, в терминах Git, коммитов (commit). -Коммиты нужно создавать вручную, выбирая, какие файлы вы хотите зафиксировать, добавив в версию.

-

Откройте в RStudio панель с названием Git (по умолчанию она в верхнем правом углу). -В отличие от списка файлов, на ней выводятся только те файлы, которые были изменены по сравнению с последней версией (коммитом). -Так как мы еще не создали ни одной версии, то в списке выводятся оба файла, созданных с проектом: .gitignore и penguins.Rproj

-
-
-Нет панели Git? - -Значит, вы не отметили галочку Create a git repository при создании проекта или не установили Git. -Проверьте наличие Git и создайте проект заново. -

Чтобы создать коммит (версию), отметьте файлы галочкой в столбце Staged. -Галочка напротив файла означает, что он добавлен в индекс (staging) — -промежуточную область для выбора файлов, которые будут зафиксированы. -Неотмеченные файлы останутся в рабочей папке, но в коммит не попадут. -Вы можете добавить их в следующую версию позже или отменить изменения. -Нажмите кнопку Commit.

-
-

В открывшемся окне можно подробнее посмотреть, что изменилось в файлах. -Просмотрите изменения и введите краткое описание в поле Commit message. -В нашем примере был создан проект, это и будет подходящим описанием. -Нажмите кнопку Commit под текстовым полем.

-
-

В открывшемся окне не должно быть ошибок, но должно быть сообщение как на изображении ниже.

-
-

Закройте окно с сообщением и окно создания коммита, вернитесь к RStudio. -Обратите внимание, теперь панель Git со списком измененных файлов пуста — -это значит, что изменений по сравнению с последней версией, которую мы только что создали, нет.

-
-

Теперь у нас есть версия проекта, к которой можно вернуться в любой момент и начать работу с этого места.

- -
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-commit2.html b/docs/git-commit2.html deleted file mode 100644 index 4e5670b..0000000 --- a/docs/git-commit2.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - -Глава 7 Рабочий процесс | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 7 Рабочий процесс -

-

В предыдущей главе мы научились создавать коммиты (версии). -Работая с Git, это нужно делать регулярно — -обычно после выполнения задачи или её части, -после внесения исправлений или просто чтобы зафиксировать изменения. -Коммит сохраняет «стабильную» версию проекта, к которой можно вернуться или сравнить с ней сделанные изменения.

-

Рассмотрим процесс работы над проектом подробнее:

-
    -
  1. Мы создали коммит, и с тех пор в рабочей папке не было изменений.
  2. -
  3. Выполняем задачу и добавляем нужные для ее решения изменения в индекс, а лишние, например код для отладки или временные файлы, удаляем.
  4. -
  5. Перед созданием коммита обязательно проверяем изменения, которые в него попадут. -Начинающие пользователи часто либо добавляют ненужный код, не относящийся к задаче, либо забывают добавить код, без которого не будет работать остальная часть проекта.
  6. -
  7. Создаём коммит и получаем чистую рабочую папку — без изменений относительно нового коммита. -Можно переходить к следующей задаче.
  8. -
-
-

Такой процесс помогает упорядочить внесение изменений и сделать результат воспроизводимым. -Он хорошо подходит для анализа данных, потому что его легко разделить на задачи, из которых получатся коммиты. -Попробуем сделать это на практике и проанализируем длину клюва антарктических пингвинов. -Каждая подглава этой главы соответствует одной задаче и завершается одним коммитом.

-
-

-7.1 Импорт данных -

-

Загрузите файл с данными penguins.csv в папку проекта. -Если нужно открыть папку в файловом менеджере операционной системы, в меню на панели Files выберите More → Show Folder in New Window. -Вернитесь в RStudio и убедитесь, что файл penguins.csv появился на панели Git.

-
-

Создайте скрипт для анализа. В меню на панели Files выберите New File → R Script и введите название файла penguins.R

-
-

Скопируйте следующий код для импорта данных и сохраните его в созданном файле. -Выделите обе строки и запустите, нажав кнопку Run в правом верхнем углу редактора RStudio. -Если импорт данных работает, в консоли появится вектор из чисел.

-
-data <- read.csv("penguins.csv")
-data$bill_length_mm
-

Убедитесь, что файл скрипта также появился на панели Git. -Добавьте оба файла в индекс, отметив галочкой в столбце Staged, и создайте коммит. -В окне коммита обязательно проверьте содержимое скрипта penguins.R, -так как часто пользователи забывают сохранить файл перед добавлением в индекс.

-
-

После создания коммита список измененных файлов на панели Git должен быть пуст.

-
-
-

-7.2 Визуализация -

-

Анализ новых данных полезно начинать с исследования распределения. -Для этого присвоим данные с длиной клюва переменной x и построим несколько вариантов гистограммы с разной шириной столбца. -Сохраните приведённый ниже код в тот же файл, запустите и посмотрите графики.

-
-data <- read.csv("penguins.csv")
-x <- data$bill_length_mm
-
-hist(x, breaks = seq(40, 60, 4))
-hist(x, breaks = seq(40, 60, 2))
-hist(x, breaks = seq(40, 60, 1))
-

После сохранения файл penguins.R снова появился в списке изменений на панели Git. -Добавьте его в индекс и проверьте изменения в окне коммита.

-

Вы уже могли заметить, что новые строки выделяются зеленым цветом. -Красным цветом выделяются удаленные строки, а неизмененные остаются белыми. -Такой формат записи изменений называется «дифф» (diff).
-Обратите внимание, что по умолчанию Git анализирует строки, а не отдельные слова или символы. -Поэтому получился следующий дифф: старая вторая строка была удалена, новая вторая строка добавлена (см. номера строк слева), хотя мы всего лишь добавили присвоение x <- в начало строки.

-
-

Убедитесь, что сделанные изменения соответствуют диффу на скриншоте выше, и создайте новый коммит с описанием «Добавили гистограммы для длины клюва».

-
-
-

-7.3 Экспорт -

-

Гистограмма с шириной столбца 2 выглядит наиболее информативно. -Такой график можно и опубликовать. -Чтобы экспортировать изображение, сохраните следующий код в файл скрипта и запустите его.

-
-data <- read.csv("penguins.csv")
-x <- data$bill_length_mm
-
-png("penguins-hist.png")
-hist(x, breaks = seq(40, 60, 2))
-dev.off()
-

После этого в списке изменений на панели Git, кроме файла penguins.R, появился файл с изображением penguins-hist.png. -Его мы тоже добавим в коммит. -Во-первых, так другие участники, загрузив проект, сразу увидят результат без необходимости запускать скрипт. -Во-вторых, если вы измените ширину столбца или другие настройки графика, будет удобно сравнить старую и новую версии.

-

Добавьте оба файла в индекс, проверьте изменения, изучив дифф, и создайте коммит с описанием «Сохранили гистограмму длины клюва».

-

На этом остановимся и посмотрим историю версий в журнале Git.

-
-

Делайте коммиты часто и не придавайте слишком большое значение планированию. -Коммит это не концептуально новая версия проекта, а просто шаг или изменения, которые вы хотите зафиксировать.

-
-
-

Не обязательно добавлять в коммит все изменения сразу или их отменять — они могут оставаться в рабочей папке сколько угодно. -Тем не менее старайтесь не копить изменения, потому что тогда версия в репозитории будет отличаться от версии, с которой вы работаете, а значит, теряется смысл системы контроля версий и возникают ошибки.

-
- -
-
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-identity.html b/docs/git-identity.html new file mode 100644 index 0000000..513081e --- /dev/null +++ b/docs/git-identity.html @@ -0,0 +1,126 @@ + + + + + + +Глава 4 Имя автора | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 4 Имя автора +

+

Каждый коммит хранит имя и электронную почту автора. При первом коммите Positron может попросить их настроить. Укажите имя, по которому коллеги вас узнают, и почту, связанную с GitHub.

+

Если интерфейс показал ошибку Please tell me who you are, откройте терминал и выполните две команды, заменив значения своими:

+
git config --global user.name "Ivan Ivanov"
+git config --global user.email "ivan@example.org"
+

Проверьте результат:

+
git config --global --get user.name
+git config --global --get user.email
+

Настройка --global применяется ко всем будущим проектам этого пользователя. Если рабочий проект требует другую почту, откройте его папку и повторите команды без --global: значение сохранится только в этом репозитории.

+

Пароль GitHub здесь не нужен. Вход в GitHub выполним в браузере в части 13.

+ +
+ + + +
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/git-init.html b/docs/git-init.html deleted file mode 100644 index 0be4717..0000000 --- a/docs/git-init.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - -Глава 5 Создание репозитория | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 5 Создание репозитория -

-

Git может отслеживать изменения в любой папке на вашем компьютере. -Для этого нужно инициализировать в ней Git репозиторий. -Репозиторий — это скрытая подпапка .git, в которой хранятся версии проекта и информация об изменениях. -Всё необходимое для работы Git содержится непосредственно в ней.

-

Самый простой способ создать репозиторий — вместе с проектом RStudio.
-В верхнем меню выберите File → New Project. -В появившемся окне выберите New directory, а затем New Project. -На последнем шаге в поле Directory name введите название папки для проекта: penguins. -Она будет создана на вашем компьютере по адресу, указанному в поле Create project as subdirectory of.
-‼️ Не забудьте поставить галочку напротив опции Create a git repository, иначе проект будет создан без Git репозитория.
-После нажатия кнопки Create Project окно RStudio перезагрузится с открытым проектом.

-
- - - - - - - - -
- - - -
- - - -
-

При следующем запуске RStudio откроет последний проект. -Если этого не произойдет, чтобы открыть проект в верхнем меню выберите File → Open Project или File → Recent Projects.

-

Убедитесь в том, что проект загружен, для этого обратите внимание на следующие элементы интерфейса: -В правом верхнем углу указано название проекта (A). -На панели файлов (по умолчанию она в нижнем правом углу) открыта папка с файлами проекта (B).

-
-

Когда в RStudio открыт проект, R и Git ищут файлы в папке проекта — это так называемая рабочая папка или рабочая область.

-
-Подробнее про поиск и адреса файлов. -

На разных компьютерах, например у разных участников, проект может находиться в разных местах. -У пользователя с именем mjordan это может быть /Users/mjordan/penguins, -а у пользователя scruz допустим
C:\Users\scruz\penguins.

-

Если в скрипте использовать полный адрес файла, например:

-
-read_csv("/Users/mjordan/penguins/data/sample.csv")
-

то он будет работать только у пользователя mjordan. -У других полный адрес будет отличаться, и код «сломается». -Чтобы он работал у всех, нужно указывать адрес файла относительно рабочей папки.

-
-read_csv("data/sample.csv")
-

Рассмотрим созданные RStudio файлы:

-
    -
  • -hello-git.Rproj — содержит настройки проекта
  • -
  • -.gitignore — содержит список файлов, которые Git не будет отслеживать; о том, зачем это нужно и как настроить смотри в отдельном разделе -
  • -
  • -.git — репозиторий; это скрытая папка, чтобы ее увидеть, в меню на панели файлов выберите More → Show Hidden Files -
  • -
-

Если файл .gitignore отсутствует, значит, вы не отметили галочку Create a git repository при создании проекта или не установили Git. -Проверьте наличие Git и создайте проект заново.

-

Итак, у нас есть проект RStudio — папка, в которой мы будем работать, и -внутри нее Git репозиторий — скрытая папка, в которой будут храниться версии проекта. -Приступим к созданию первой версии.

- -
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-log.html b/docs/git-log.html deleted file mode 100644 index 14db9fb..0000000 --- a/docs/git-log.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - -Глава 8 Просмотр истории | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 8 Просмотр истории -

-

До этого мы просматривали изменения только по сравнению с последней версией в момент создания коммита. Предыдущие коммиты можно посмотреть в журнале (log).

-

Журнал позволяет изучить изменения от других участников или вспомнить свои собственные, и зачем они сделаны. -Поэтому так важно писать ясные и содержательные описания коммитов. -Используя журнал, можно найти, когда сделаны изменения, приведшие к ошибке, и вернуть проект к предыдущему состоянию. -В конце концов, его можно использовать для отчетности и бизнесс-аналитики по проекту.

-

Чтобы открыть журнал, нажмите кнопку History на панели Git. -В открывшемся окне выводится список коммитов в обратном порядке — последние коммиты находятся вверху. -В списке выводится краткая информация о коммите, а под списком подробная информация по выделенному коммиту.

-
-
    -
  • SHA — так называемый хэш коммита, который является его уникальным идентификатором в репозитории
  • -
  • Author — автор коммита <email>, которые были указаны в настройках -
  • -
  • Date — дата и время создания коммита
  • -
  • Subject — описание коммита
  • -
  • Parent — хэш (идентификатор) предыдущего коммита
  • -
-

Еще ниже показан дифф — изменения, сделанные в этом коммите по сравнению с предыдущим. -Для больших файлов выводятся только те строки, которые поменялись, а также несколько строк выше и ниже, чтобы был понятен контекст. -Если нажать кнопку View file справа от названия файла, можно увидеть его полное содержимое, каким оно было зафиксировано создания коммита.

-

Даже если вы работаете в одиночку, полезно иметь под рукой историю изменений. -Но по настоящему эта функция полезна, -когда приходится работать с несколькими версиями одновременно, -например при работе в команде. -Об этом далее.

- -
- - - -
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-merge.html b/docs/git-merge.html deleted file mode 100644 index 734cb86..0000000 --- a/docs/git-merge.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - -Глава 12 Слияние веток | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 12 Слияние веток -

-

Откройте окно истории и выберите в фильтре сверху показывать все ветки (all branches) и все коммиты (all commits). -На диграмме наглядно видно почему это называется веткой.

-
-

Если мы или другой участник проекта, решим принять эти изменения в основную ветку main, -нам нужно выполнить операцию «слияния» (merge). -В RStudio нет встроенной возможности слияния веток, это необходимо делать в терминале. -К счастью, команда совсем не сложная.

-

Для начала переключитесь на ветку, в которую будут вливаться изменения — -в нашем случае это main (см. переключение веток). -Откройте терминал 2 и введите команду для слияния с веткой boxplot.

-
git merge boxplot
-

Git попытается автоматически объединить изменения из обеих веток и создать новый коммит. -В большинстве случаев этого достаточно, -но любая совместная работа может приводить к конфликтам — -когда в обеих ветках была изменена одна и та же строка, но разным образом. -Какую версию предпочтет Git? -Git предпочтет выдать ошибку и попросит вас разрешить конфликт.

-

В списке изменений мы видим, -что Git автоматически выбрал изменения связанные с новым и старым файлом для графика -penguins-hist.png и penguins-boxplot.png, -но лишь частично для скрипта penguins.R.

-
-

Причина в том, что мы вносили изменения в код графика в ветке main после того как изменили его в ветке boxplot. -Откройте файл penguins.R. -Git любезно оставил для нас обе версии кода разделив специальными символами. -После строки <<< HEAD идет версия из текущей ветки, -строка === отделяет две версии друг от друга, -а строка >>> boxplot завершает версию из ветки boxplot.

-
-

Наша задача переписать выделенный участок (строки 4-12) в одну версию и убрать спецсимволы. -Важно понимать, что Git просто вставил в скрипт кусок текста, -но это все еще обычный R скрипт и мы должны привести его в рабочее состояние.

-

Нам нужна версия из ветки boxplot, но мы хотим добавить в нее подпись оси, как это было сделано в ветке main. -Для этого оставим нижнюю версию (строки 9-11) и удалим лишние строки (4-8 и 12) -и добавим подпись, только для ящика с усами это должна быть подпись оси Y. -В итоге должен получиться следующий код.

-
-data <- read.csv("penguins.csv")
-x <- data$bill_length_mm
-
-png("penguins-boxplot.png")
-boxplot(x, ylab = "Bill length, mm")
-dev.off()
-

Сохраните файл и выполните скрипт. -Создайте коммит и -не забудьте отметить галочкой внесенные изменения, -в том числе обновившийся файл penguins-boxplot.png, который теперь содержит подпись оси. -Обычно сообщение коммита о слиянии веток содержит следующий текст «Merge branch название-ветки», но можете придумать свое.

-
-

Итак, мы успешно слили изменения из ветки boxplot в основную ветку main. -Теперь можно продолжить работу в основной ветке. -Еще лучше будет создать очередную ветку для новых изменений, выполнить работу в ней и точно так же слить в основную.

-
-
-Как удалить ветку? -

Слитую ветку можно удалить. -В RStudio для этого нет встроенных средств, поэтому придется использовать терминал. -Выполните команду:

-
git branch -d boxplot
-

Если ветка не была слита, Git откажется ее удалять, ведь могут быть потеряны сделанные в ней изменения. -Если вы действительно уверены, что они вам не нужны и вы хотите удалить не слитую ветку, выполните команду:

-
git branch -D boxplot
-
-
- -
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-push-pull.html b/docs/git-push-pull.html deleted file mode 100644 index f8008a7..0000000 --- a/docs/git-push-pull.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - -Глава 16 Загрузка изменений | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 16 Загрузка изменений -

-

На предыдущем шаге мы загрузили изменения из нашего локального репозитория в удаленный репозиторий на GitHub при помощи команды push в терминале.

-

Git не синхронизирует изменения автоматически, это необходимо делать вручную, используя команду push ил кнопку Push в интерфейсе RStudio на панели Git.

-

Создадим и загрузим еще один коммит. Например, добавим небольшой комментарий к коду, чтобы человеку открывшему его впервые было легче разобраться.

-
-data <- read.csv("penguins.csv")
-x <- data$bill_length_mm
-
-# Ящик с усами для длины клюва
-
-png("penguins-boxplot.png")
-boxplot(x, ylab = "Bill length, mm")
-dev.off()
-

Сохраните и закомитьте файл penguins.R. -После чего нажмите кнопку Push в верхнем правом углу.

-
-

Перейдите на страницу репозитория на GitHub и убедитесь, что коммит был загружен. -Это можно понять по тексту сообщения над списком файлов и по тексту и времени изменения напротив файла penguins.R.

-
-

GitHub позволяет вносить изменения в репозиторий из веб-интерфейса. -Эта функция используется редко, потому что код необходимо запускать и проверять на компьютере, но она полезна для небольших правок или загрузки файлов. -Создадим при помощи нее новый файл. -Файл README — это файл, который отображается на главной странице репозитория для краткого описания проекта. Обычно он включает описание данных и скриптов, как начать работу с проектом и тому подобное.

-

Нажмите кнопку Add a README. В открывшемся файле введите текст в формате Markdown4 (используйте или измените текст ниже) -и нажмите кнопку Commit changes в верхнем правом углу. -Откроется окно создания коммита, оставьте текст по умолчанию и подтвердите создание коммита нажатием кнопки Commit changes

-
-
# Пингвины «Палмер» 🐧
-
-Этот репозиторий был создан в рамках курса от [Института биоинформатики](bioinf.me/education/stat),
-чтобы познакомиться с основами Git — фиксацией изменений, ветвлением и работой с GitHub.
-
-В качестве примера использованы данные о длине клюва пингвинов,
-собранные доктором Кристен Горман на станции «Палмер» в Антарктиде.
-
-Содержимое репозитория:
-
-- penguins-boxplot.png — диаграмма ящик с усами, показывающая распределение длины клюва
-- penguins.R — скрипт для построения диаграммы
-- penguins.csv — данные
-

Чтобы загрузить изменения из удаленного репозитория на компьютер используется команда pull.

-

Вернитесь в RStudio и на панели Git нажмите кнопку Pull. -Если команда выполнилась успешно, в списке файлов появится файл README.md, -а в журнале — коммит созданный через GitHub.

-

Как и в случае с переключением веток, Git откажется загружать изменения и выдаст ошибку, если в рабочей папке имеются незафиксированные изменения, которые конфликтуют с загружаемыми.

-

Теперь вы умеете загружать изменения в удалённый репозиторий и из него. Рекомендуем делать это регулярно, чтобы синхронизироваться с другими участниками проекта, по крайней мере, в конце рабочего дня или рабочей сессии.

- -
- -
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/git-remote.html b/docs/git-remote.html deleted file mode 100644 index b2a54dc..0000000 --- a/docs/git-remote.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - -Глава 15 Удаленный репозиторий | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 15 Удаленный репозиторий -

-

Для загрузки репозитория с вашего компьютера (он называется локальный репозиторий) на Github необходимо создать удаленный репозиторий на сайте. -На верхней панели в правом углу нажмите кнопку + и выберите пункт New repository.

-
-

В открывшейся форме достаточно заполнить только название репозитория в поле Repository name, например penguins. -Остальные поля оставьте по умолчанию, мы только разберем за что они отвечают.

-
    -
  • Description — краткое описание
  • -
  • Public / Private — настройка доступа -
      -
    • Public — кто угодно сможет просматривать ваши файлы, но только отдельно добавленные пользователи смогут их изменять
    • -
    • Private — только отдельно добавленные пользователи смогут просматривать и изменять файлы
    • -
    -
  • -
  • Initialize this repository with — этот раздел позволяет добавить в создаваемый репозиторий несколько типовых файлов README .gitignore и LICENSE; не отмечайте ни один из них, потому что в нашем репозитории на компьютере уже есть файлы и они будут конфликтовать с этими.
  • -
-

Внизу страницы нажмите Create repository.

-
-Пример заполненной формы -

Удалить это? Там и так на форме все написано, только что на англ. Оставить только предупреждение, чтобы не жали Initialize this repository with.

-

Со скрином формы репозитория тоже ту мач?

-

Для созданного репозитория GitHub сгенерировал набор команд быстрой настройки, воспользуемся ими. -Сначала необходимо убедиться, что напротив адреса репозитория выбрана опция доступа через HTTPS (A). -Далее скопируйте все три команды из раздела для существующего репозитория (… or push an existing repository from the command line, B) и выполните в терминале 3. -На запрос пароля скопируйте и вставьте сгенерированный в предыдущей главе токен.

-
-

Мы связали наш локальный репозиторий с удаленным при помощи команды remote add — это необходимо было сделать один раз. -И выполнили команду push — отправить сделанные фиксации в удаленный репозиторий, это необходимо делать регулярно и для этого в интерфейсе RStudio есть кнопка на панели Git. -Если команды выполнились успешно, файлы были загружены на GitHub. -Обновите страницу репозитория и проверьте содержимое файлов.

-
- -
- -
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/github-conclusion.html b/docs/github-conclusion.html new file mode 100644 index 0000000..63667db --- /dev/null +++ b/docs/github-conclusion.html @@ -0,0 +1,128 @@ + + + + + + +Глава 18 Итог работы с GitHub | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 18 Итог работы с GitHub +

+

Теперь вы умеете:

+
    +
  • публиковать локальный репозиторий через Publish to GitHub;
  • +
  • входить в GitHub через браузер;
  • +
  • различать Push, Pull, Fetch и Sync Changes;
  • +
  • публиковать отдельную ветку;
  • +
  • создавать, проверять и сливать pull request;
  • +
  • клонировать проект командой Workspaces: New Folder from Git….
  • +
+

Для обычной работы достаточно короткого цикла: Pull → новая ветка → небольшие коммиты → Push → pull request → проверка → merge.

+

GitHub — не резервная копия незакоммиченных файлов. Пока изменение не вошло в коммит и не отправлено, оно существует только в вашей рабочей папке.

+ +
+ + + +
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/github-part.html b/docs/github-part.html new file mode 100644 index 0000000..cc4301a --- /dev/null +++ b/docs/github-part.html @@ -0,0 +1,134 @@ + + + + + + +Глава 13 Аккаунт и вход | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 13 Аккаунт и вход +

+

Git хранит историю на вашем компьютере. GitHub хранит копию репозитория на сервере, поэтому проект можно открыть с другого устройства, показать преподавателю и обсудить изменения с коллегами.

+

Создайте аккаунт на github.com, если его ещё нет. Имя пользователя станет частью адресов репозиториев, поэтому лучше использовать короткое имя латиницей.

+

Positron включает расширения GitHub и GitHub Pull Requests and Issues. При первой публикации или отправке изменений редактор предложит войти. Выберите Sign in with GitHub, подтвердите открытие браузера и разрешите доступ.

+
+Positron показывает запрос Sign in with GitHub перед первой публикацией репозитория
Positron показывает запрос Sign in with GitHub перед первой публикацией репозитория
+
+

После подтверждения вернитесь в Positron. Не создавайте classic personal access token для этого упражнения: обычный путь входа проходит через браузер.

+
+

Никому не отправляйте пароли, токены, приватные ключи и секреты webhook. Не добавляйте их в .qmd, .R, .env или другие файлы репозитория.

+
+
+

+13.1 Git и GitHub — разные системы +

+

Коммит, ветка и слияние работают в Git без GitHub. GitHub добавляет удалённый репозиторий, права доступа, pull request, обсуждения и автоматические проверки.

+

Если сайт GitHub недоступен, локальные коммиты продолжают работать. Когда связь восстановится, их можно отправить на сервер.

+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/github.html b/docs/github.html deleted file mode 100644 index adf2845..0000000 --- a/docs/github.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - -Глава 14 Настройка | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 14 Настройка -

-

GitHub — это веб-сервис для хранения Git репозиториев и совместной работы. -Ваши файлы размещаются на удаленном сервере и доступны публично или приватно для загрузки другими пользователями. В некотором смысле это аналог Dropbox или Google Drive для Git. -Помимо хранения репозиториев, GitHub предоставляет другие инструменты: отслеживание задач, обсуждение изменений, запуск тестов и сборок и многое другое.

-

Для работы с GitHub вам понадобится зарегистрировать учетную запись и создать токен — отдельный пароль для Git на вашем компьютере.

-
-

-14.1 Регистрация на GitHub -

-

Перейдите на сайт github.com и зарегистрируйте учетную запись нажав на кнопку Sign up в верхнем правом углу или войдите в существующую учетную запись нажав Sign in.

-

E-mail при регистрации не обязательно должен совпадать с указанным при настройке Git в Главе 1. Дополнительные e-mail адреса можно добавить после регистрации на странице настроек. -Это рекоммендуется сделать, чтобы GitHub мог ассоциировать сделанные на компьютере коммиты с вашей учетной записью онлайн.

-
-
-

-14.2 Создание токена -

-

В целях безопасности, GitHub не позволяет использовать пароль от веб-сайта при работе с Git, -а требует создать так называемый Personal Access Token — отдельный пароль специально для Git на вашем компьютере. -Во всех случаях, когда Git запрашивает пароль от GitHub, необходимо вводить токен, а не пароль от веб-сайта.

-

Для этого перейдите по ссылке github.com/settings/tokens, -авторизуйтесь и нажмите Generate new token, в выпадающем списке выберите classic. -На новой странице введите название токена, например Work. -Отметьте следующие права repo, workflow, user -и нажмите зеленую кнопку Generate token в конце страницы.

-

-

Не забудьте скопировать и сохранить ваш токен - он выглядит как строка вида ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. -После того как вы закроете страницу посмотреть созданный токен невозможно. -Храните его в надежном месте как пароль.

-
-

Теперь мы готовы опубликовать наш репозиторий на GitHub.

- -
-
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/history-diff.html b/docs/history-diff.html new file mode 100644 index 0000000..3551a4b --- /dev/null +++ b/docs/history-diff.html @@ -0,0 +1,159 @@ + + + + + + +Глава 8 История и различия | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 8 История и различия +

+

Разверните Source Control Graph в Source Control. В нём видны коммиты текущей ветки main.

+

Выберите коммит Сохранил гистограмму длины клюва. Под ним появится список изменённых файлов. Выберите paper.qmd, чтобы открыть diff именно для этого коммита.

+
+Source Control Graph с тремя учебными коммитами и открытым diff файла paper.qmd для коммита с гистограммой
Source Control Graph с тремя учебными коммитами и открытым diff файла paper.qmd для коммита с гистограммой
+
+

В diff удалённые строки отмечены красным, добавленные — зелёным. Git сравнивает строки, поэтому даже изменение одного символа может выглядеть как удаление старой строки и добавление новой.

+

Для истории одного файла откройте paper.qmd, затем разверните Timeline в Explorer. Там можно выбрать прежний коммит и посмотреть, как менялся только этот файл.

+
+

+8.1 Рабочая папка, индекс и коммит +

+

Эти три состояния полезно различать:

+
++++ + + + + + + + + + + + + + + + + + + +
СостояниеЧто содержит
Рабочая папкаСохранённые на диске файлы, включая незаконченные изменения
ИндексТолько изменения, выбранные для следующего коммита
Последний коммитУже записанный снимок проекта
+

Кнопка + переносит изменение из рабочей папки в индекс. Кнопка у Staged Changes убирает его из индекса, но не удаляет из файла. Commit записывает содержимое индекса в историю.

+

Официальное руководство Staging and committing changes использует эту же модель.

+ +
+
+ + + +
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/index.html b/docs/index.html index 3ae9903..abd7a5a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -4,20 +4,20 @@ -Глава 1 Основы Git | Основы Git +Глава 1 Основы Git в Positron | Основы Git в Positron - + - + - + - - + + - + + + + + +
+
+
+

+Глава 3 Установка Git +

+

Positron предоставляет интерфейс Source Control, но использует Git, установленный в операционной системе. Если Git не найден, Source Control покажет предложение его установить. Такое поведение описано в официальной главе Git Version Control.

+
+

+3.1 Проверка +

+

Откройте встроенный терминал командой Terminal: Create New Terminal из палитры команд и выполните:

+
git --version
+

Если команда вывела строку вида git version 2.45.2, установка готова. Конкретный номер может отличаться.

+
+Терминал Positron после проверки версии Git: видна строка с установленной версией
Терминал Positron после проверки версии Git: видна строка с установленной версией
+
+
+
+

+3.2 Если Git не установлен +

+ +

После установки полностью перезапустите Positron и снова выполните git --version.

+
+

Не скачивайте отдельные графические клиенты Git для прохождения курса. Они могут пригодиться позже, но названия действий и расположение элементов будут отличаться от Positron.

+
+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/install.html b/docs/install.html deleted file mode 100644 index 71d3121..0000000 --- a/docs/install.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - -Глава 3 Установка | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 3 Установка -

-
-

-3.1 Проверьте наличие Git -

-

В комплекте с дистрибутивом Git устанавливается программа для терминала. -Чтобы её запустить, откройте Rstudio и в верхнем меню выберите Tools → Terminal → New Terminal. -В появившемся окне терминала введите команду git и нажмите клавишу Enter.

-

Если вы видите результат как на скриншоте ниже, то Git установлен.
-Иначе нужно его установить — см. инструкцию для вашей операционной системы ниже. -После установки перезапустите RStudio и повторите проверку.

-
-
-
-

-3.2 Windows -

-

Загрузите инсталлятор по ссылке git-scm.com/downloads/win -(используйте Standalone, а не Portable версию, если в этом нет необходимости), запустите и следуйте инструкциям на экране, можете везде оставить опции, выбранные по умолчанию.

-
-
-

-3.3 Mac OS -

-

Вариант 1. Git входит в инструменты разработчика от Apple, которые предоставляются бесплатно. Для установки введите в терминал следующую команду:

-
xcode-select --install
-

В появившемся окне нажмите кнопку Install.

-

Вариант 2. Последнюю версию Git можно установить используя сторонний менеджер программ Homebrew. Если он у вас установлен, введите в терминал следующую команду:

-
brew install git
-
-
-

-3.4 Linux -

-

Используйте в терминале одну из следующих команд, в зависимости от вашего дистрибутива Linux.

-

Ubuntu или Debian

-
sudo apt-get update
-sudo apt-get install git
-

Fedora

-
sudo dnf install git
-

Arch Linux

-
sudo pacman -S git
-

Для других дистрибутивов см. git-scm.com/downloads/linux. Не забудьте, что команды нужно запускать с правами администратора, т.е. начав с sudo, как в примере выше.

- -
-
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/libs/bootstrap-4.6.0/bootstrap.min.css b/docs/libs/bootstrap-4.6.0/bootstrap.min.css index 850c4ed..6b53069 100644 --- a/docs/libs/bootstrap-4.6.0/bootstrap.min.css +++ b/docs/libs/bootstrap-4.6.0/bootstrap.min.css @@ -1 +1 @@ -:root{--bslib-bootstrap-version: 4;--bslib-preset-name: ;--bslib-preset-type: }:root{--blue: #007bff;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #dc3545;--orange: #fd7e14;--yellow: #ffc107;--green: #28a745;--teal: #20c997;--cyan: #17a2b8;--white: #fff;--gray: #6c757d;--gray-dark: #343a40;--default: #dee2e6;--primary: #096B72;--secondary: #6c757d;--success: #28a745;--info: #17a2b8;--warning: #ffc107;--danger: #dc3545;--light: #f8f9fa;--dark: #343a40;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0 !important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;text-decoration:underline dotted;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;-ms-text-decoration:underline dotted;-o-text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem;padding:.625rem 1.25rem;border-left:.25rem solid #e9ecef}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#096B72;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:transparent}a:hover{color:#03282b;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role="button"]{cursor:pointer}select{word-wrap:normal}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button:not(:disabled),[type="button"]:not(:disabled),[type="reset"]:not(:disabled),[type="submit"]:not(:disabled){cursor:pointer}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{padding:0;border-style:none}input[type="radio"],input[type="checkbox"]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{outline-offset:-2px;-webkit-appearance:none}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none !important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}h1,.h1{font-size:2.5rem}h2,.h2{font-size:2rem}h3,.h3{font-size:1.75rem}h4,.h4{font-size:1.5rem}h5,.h5{font-size:1.25rem}h6,.h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,0.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#000;background-color:#f6f6f6;border-radius:.25rem;padding:.125rem .25rem;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#000;background-color:#f6f6f6;padding:.5rem;border:1px solid #dee2e6;border-radius:.25rem}pre code{background-color:transparent;font-size:inherit;color:inherit;word-break:normal;padding:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-xl,.container-lg,.container-md,.container-sm{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container-sm,.container{max-width:540px}}@media (min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media (min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media (min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}.row{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*="col-"]{padding-right:0;padding-left:0}.col-xl,.col-xl-auto,.col-xl-12,.col-xl-11,.col-xl-10,.col-xl-9,.col-xl-8,.col-xl-7,.col-xl-6,.col-xl-5,.col-xl-4,.col-xl-3,.col-xl-2,.col-xl-1,.col-lg,.col-lg-auto,.col-lg-12,.col-lg-11,.col-lg-10,.col-lg-9,.col-lg-8,.col-lg-7,.col-lg-6,.col-lg-5,.col-lg-4,.col-lg-3,.col-lg-2,.col-lg-1,.col-md,.col-md-auto,.col-md-12,.col-md-11,.col-md-10,.col-md-9,.col-md-8,.col-md-7,.col-md-6,.col-md-5,.col-md-4,.col-md-3,.col-md-2,.col-md-1,.col-sm,.col-sm-auto,.col-sm-12,.col-sm-11,.col-sm-10,.col-sm-9,.col-sm-8,.col-sm-7,.col-sm-6,.col-sm-5,.col-sm-4,.col-sm-3,.col-sm-2,.col-sm-1,.col,.col-auto,.col-12,.col-11,.col-10,.col-9,.col-8,.col-7,.col-6,.col-5,.col-4,.col-3,.col-2,.col-1{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333%}.offset-2{margin-left:16.66667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333%}.offset-5{margin-left:41.66667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333%}.offset-8{margin-left:66.66667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333%}.offset-11{margin-left:91.66667%}@media (min-width: 576px){.col-sm{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-sm-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-sm-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-sm-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-sm-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-sm-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-sm-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-sm-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-sm-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-sm-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-sm-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333%}.offset-sm-2{margin-left:16.66667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333%}.offset-sm-5{margin-left:41.66667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333%}.offset-sm-8{margin-left:66.66667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333%}.offset-sm-11{margin-left:91.66667%}}@media (min-width: 768px){.col-md{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-md-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-md-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-md-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-md-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-md-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-md-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-md-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-md-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-md-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-md-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-md-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333%}.offset-md-2{margin-left:16.66667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333%}.offset-md-5{margin-left:41.66667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333%}.offset-md-8{margin-left:66.66667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333%}.offset-md-11{margin-left:91.66667%}}@media (min-width: 992px){.col-lg{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-lg-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-lg-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-lg-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-lg-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-lg-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-lg-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-lg-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-lg-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-lg-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-lg-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333%}.offset-lg-2{margin-left:16.66667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333%}.offset-lg-5{margin-left:41.66667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333%}.offset-lg-8{margin-left:66.66667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333%}.offset-lg-11{margin-left:91.66667%}}@media (min-width: 1200px){.col-xl{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-xl-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-xl-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-xl-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-xl-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-xl-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-xl-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-xl-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-xl-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-xl-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-xl-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333%}.offset-xl-2{margin-left:16.66667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333%}.offset-xl-5{margin-left:41.66667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333%}.offset-xl-8{margin-left:66.66667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333%}.offset-xl-11{margin-left:91.66667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table th,.table td{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm th,.table-sm td{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered th,.table-bordered td{border:1px solid #dee2e6}.table-bordered thead th,.table-bordered thead td{border-bottom-width:2px}.table-borderless th,.table-borderless td,.table-borderless thead th,.table-borderless tbody+tbody{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,0.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,0.075)}.table-default,.table-default>th,.table-default>td{background-color:#f6f7f8}.table-default th,.table-default td,.table-default thead th,.table-default tbody+tbody{border-color:#eef0f2}.table-hover .table-default:hover{background-color:#e8eaed}.table-hover .table-default:hover>td,.table-hover .table-default:hover>th{background-color:#e8eaed}.table-primary,.table-primary>th,.table-primary>td{background-color:#bad6d8}.table-primary th,.table-primary td,.table-primary thead th,.table-primary tbody+tbody{border-color:#7fb2b6}.table-hover .table-primary:hover{background-color:#aacccf}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#aacccf}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#d6d8db}.table-secondary th,.table-secondary td,.table-secondary thead th,.table-secondary tbody+tbody{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>th,.table-success>td{background-color:#c3e6cb}.table-success th,.table-success td,.table-success thead th,.table-success tbody+tbody{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>th,.table-info>td{background-color:#bee5eb}.table-info th,.table-info td,.table-info thead th,.table-info tbody+tbody{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>th,.table-warning>td{background-color:#ffeeba}.table-warning th,.table-warning td,.table-warning thead th,.table-warning tbody+tbody{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>th,.table-danger>td{background-color:#f5c6cb}.table-danger th,.table-danger td,.table-danger thead th,.table-danger tbody+tbody{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>th,.table-light>td{background-color:#fdfdfe}.table-light th,.table-light td,.table-light thead th,.table-light tbody+tbody{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>th,.table-dark>td{background-color:#c6c8ca}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>th,.table-active>td{background-color:rgba(0,0,0,0.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,0.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,0.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark th,.table-dark td,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,0.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,0.075)}@media (max-width: 575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width: 767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width: 991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width: 1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#12dae8;outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[size],select.form-control[multiple]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text,.help-text,.help-block{display:block;margin-top:.25rem}.form-row{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*="col-"]{padding-right:5px;padding-left:5px}.form-check,.shiny-input-checkboxgroup .checkbox,.shiny-input-checkboxgroup .radio,.shiny-input-radiogroup .checkbox,.shiny-input-radiogroup .radio{position:relative;display:block;padding-left:1.25rem}.form-check-input,.shiny-input-checkboxgroup .checkbox label>input,.shiny-input-checkboxgroup .radio label>input,.shiny-input-radiogroup .checkbox label>input,.shiny-input-radiogroup .radio label>input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input[disabled]~.form-check-label,.shiny-input-checkboxgroup .checkbox label>input[disabled]~.form-check-label,.shiny-input-checkboxgroup .radio label>input[disabled]~.form-check-label,.shiny-input-radiogroup .checkbox label>input[disabled]~.form-check-label,.shiny-input-radiogroup .radio label>input[disabled]~.form-check-label,.shiny-input-checkboxgroup .checkbox .form-check-input[disabled]~label,.shiny-input-checkboxgroup .checkbox label>input[disabled]~label,.shiny-input-checkboxgroup .radio .form-check-input[disabled]~label,.shiny-input-checkboxgroup .radio label>input[disabled]~label,.shiny-input-radiogroup .checkbox .form-check-input[disabled]~label,.shiny-input-radiogroup .checkbox label>input[disabled]~label,.shiny-input-radiogroup .radio .form-check-input[disabled]~label,.shiny-input-radiogroup .radio label>input[disabled]~label,.form-check-input:disabled~.form-check-label,.shiny-input-checkboxgroup .checkbox label>input:disabled~.form-check-label,.shiny-input-checkboxgroup .radio label>input:disabled~.form-check-label,.shiny-input-radiogroup .checkbox label>input:disabled~.form-check-label,.shiny-input-radiogroup .radio label>input:disabled~.form-check-label,.shiny-input-checkboxgroup .checkbox .form-check-input:disabled~label,.shiny-input-checkboxgroup .checkbox label>input:disabled~label,.shiny-input-checkboxgroup .radio .form-check-input:disabled~label,.shiny-input-checkboxgroup .radio label>input:disabled~label,.shiny-input-radiogroup .checkbox .form-check-input:disabled~label,.shiny-input-radiogroup .checkbox label>input:disabled~label,.shiny-input-radiogroup .radio .form-check-input:disabled~label,.shiny-input-radiogroup .radio label>input:disabled~label{color:#6c757d}.form-check-label,.shiny-input-checkboxgroup .checkbox label,.shiny-input-checkboxgroup .radio label,.shiny-input-radiogroup .checkbox label,.shiny-input-radiogroup .radio label{margin-bottom:0}.form-check-inline{display:inline-flex;align-items:center;-webkit-align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input,.form-check-inline .shiny-input-checkboxgroup .checkbox label>input,.shiny-input-checkboxgroup .checkbox .form-check-inline label>input,.form-check-inline .shiny-input-checkboxgroup .radio label>input,.shiny-input-checkboxgroup .radio .form-check-inline label>input,.form-check-inline .shiny-input-radiogroup .checkbox label>input,.shiny-input-radiogroup .checkbox .form-check-inline label>input,.form-check-inline .shiny-input-radiogroup .radio label>input,.shiny-input-radiogroup .radio .form-check-inline label>input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,0.9);border-radius:.25rem}.form-row>.col>.valid-tooltip,.form-row>[class*="col-"]>.valid-tooltip{left:5px}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,0.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,0.25)}.was-validated .form-check-input:valid~.form-check-label,.was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~.form-check-label,.shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~.form-check-label,.was-validated .shiny-input-checkboxgroup .radio label>input:valid~.form-check-label,.shiny-input-checkboxgroup .radio .was-validated label>input:valid~.form-check-label,.was-validated .shiny-input-radiogroup .checkbox label>input:valid~.form-check-label,.shiny-input-radiogroup .checkbox .was-validated label>input:valid~.form-check-label,.was-validated .shiny-input-radiogroup .radio label>input:valid~.form-check-label,.shiny-input-radiogroup .radio .was-validated label>input:valid~.form-check-label,.was-validated .shiny-input-checkboxgroup .checkbox .form-check-input:valid~label,.was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~label,.was-validated .shiny-input-checkboxgroup .checkbox .radio label>input:valid~label,.was-validated .shiny-input-checkboxgroup .radio .checkbox label>input:valid~label,.was-validated .shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input:valid~label,.shiny-input-radiogroup .was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~label,.was-validated .shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input:valid~label,.shiny-input-radiogroup .radio .was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated .form-check-input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated .radio label>input:valid~label,.shiny-input-checkboxgroup .radio .checkbox .was-validated label>input:valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox .was-validated label>input:valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated .shiny-input-radiogroup .radio label>input:valid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~label,.was-validated .shiny-input-checkboxgroup .radio .form-check-input:valid~label,.was-validated .shiny-input-checkboxgroup .radio .checkbox label>input:valid~label,.was-validated .shiny-input-checkboxgroup .checkbox .radio label>input:valid~label,.was-validated .shiny-input-checkboxgroup .radio label>input:valid~label,.was-validated .shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated .shiny-input-checkboxgroup .radio label>input:valid~label,.was-validated .shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input:valid~label,.shiny-input-radiogroup .was-validated .shiny-input-checkboxgroup .radio label>input:valid~label,.shiny-input-checkboxgroup .radio .was-validated .form-check-input:valid~label,.shiny-input-checkboxgroup .radio .was-validated .checkbox label>input:valid~label,.shiny-input-checkboxgroup .checkbox .radio .was-validated label>input:valid~label,.shiny-input-checkboxgroup .radio .was-validated label>input:valid~label,.shiny-input-checkboxgroup .radio .was-validated .shiny-input-radiogroup .checkbox label>input:valid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio .was-validated label>input:valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio .was-validated label>input:valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio .was-validated label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox .form-check-input:valid~label,.was-validated .shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input:valid~label,.shiny-input-checkboxgroup .was-validated .shiny-input-radiogroup .checkbox label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input:valid~label,.shiny-input-checkboxgroup .radio .was-validated .shiny-input-radiogroup .checkbox label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox .radio label>input:valid~label,.was-validated .shiny-input-radiogroup .radio .checkbox label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated .form-check-input:valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox .was-validated label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated .shiny-input-checkboxgroup .radio label>input:valid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox .was-validated label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated .radio label>input:valid~label,.shiny-input-radiogroup .radio .checkbox .was-validated label>input:valid~label,.was-validated .shiny-input-radiogroup .radio .form-check-input:valid~label,.was-validated .shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated .shiny-input-radiogroup .radio label>input:valid~label,.was-validated .shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input:valid~label,.shiny-input-checkboxgroup .was-validated .shiny-input-radiogroup .radio label>input:valid~label,.was-validated .shiny-input-radiogroup .radio .checkbox label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox .radio label>input:valid~label,.was-validated .shiny-input-radiogroup .radio label>input:valid~label,.shiny-input-radiogroup .radio .was-validated .form-check-input:valid~label,.shiny-input-radiogroup .radio .was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio .was-validated label>input:valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio .was-validated label>input:valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio .was-validated label>input:valid~label,.shiny-input-radiogroup .radio .was-validated .checkbox label>input:valid~label,.shiny-input-radiogroup .checkbox .radio .was-validated label>input:valid~label,.shiny-input-radiogroup .radio .was-validated label>input:valid~label,.form-check-input.is-valid~.form-check-label,.shiny-input-checkboxgroup .checkbox label>input.is-valid~.form-check-label,.shiny-input-checkboxgroup .radio label>input.is-valid~.form-check-label,.shiny-input-radiogroup .checkbox label>input.is-valid~.form-check-label,.shiny-input-radiogroup .radio label>input.is-valid~.form-check-label,.shiny-input-checkboxgroup .checkbox .form-check-input.is-valid~label,.shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .checkbox .radio label>input.is-valid~label,.shiny-input-checkboxgroup .radio .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input.is-valid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .radio .form-check-input.is-valid~label,.shiny-input-checkboxgroup .radio .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .checkbox .radio label>input.is-valid~label,.shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input.is-valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-radiogroup .checkbox .form-check-input.is-valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox .radio label>input.is-valid~label,.shiny-input-radiogroup .radio .checkbox label>input.is-valid~label,.shiny-input-radiogroup .radio .form-check-input.is-valid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input.is-valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input.is-valid~label,.shiny-input-radiogroup .radio .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox .radio label>input.is-valid~label,.shiny-input-radiogroup .radio label>input.is-valid~label{color:#28a745}.was-validated .form-check-input:valid~.valid-feedback,.was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~.valid-feedback,.shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~.valid-feedback,.was-validated .shiny-input-checkboxgroup .radio label>input:valid~.valid-feedback,.shiny-input-checkboxgroup .radio .was-validated label>input:valid~.valid-feedback,.was-validated .shiny-input-radiogroup .checkbox label>input:valid~.valid-feedback,.shiny-input-radiogroup .checkbox .was-validated label>input:valid~.valid-feedback,.was-validated .shiny-input-radiogroup .radio label>input:valid~.valid-feedback,.shiny-input-radiogroup .radio .was-validated label>input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip,.was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~.valid-tooltip,.shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~.valid-tooltip,.was-validated .shiny-input-checkboxgroup .radio label>input:valid~.valid-tooltip,.shiny-input-checkboxgroup .radio .was-validated label>input:valid~.valid-tooltip,.was-validated .shiny-input-radiogroup .checkbox label>input:valid~.valid-tooltip,.shiny-input-radiogroup .checkbox .was-validated label>input:valid~.valid-tooltip,.was-validated .shiny-input-radiogroup .radio label>input:valid~.valid-tooltip,.shiny-input-radiogroup .radio .was-validated label>input:valid~.valid-tooltip,.form-check-input.is-valid~.valid-feedback,.shiny-input-checkboxgroup .checkbox label>input.is-valid~.valid-feedback,.shiny-input-checkboxgroup .radio label>input.is-valid~.valid-feedback,.shiny-input-radiogroup .checkbox label>input.is-valid~.valid-feedback,.shiny-input-radiogroup .radio label>input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.shiny-input-checkboxgroup .checkbox label>input.is-valid~.valid-tooltip,.shiny-input-checkboxgroup .radio label>input.is-valid~.valid-tooltip,.shiny-input-radiogroup .checkbox label>input.is-valid~.valid-tooltip,.shiny-input-radiogroup .radio label>input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid~.custom-control-label,.custom-control-input.is-valid~.custom-control-label{color:#28a745}.was-validated .custom-control-input:valid~.custom-control-label::before,.custom-control-input.is-valid~.custom-control-label::before{border-color:#28a745}.was-validated .custom-control-input:valid:checked~.custom-control-label::before,.custom-control-input.is-valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.was-validated .custom-control-input:valid:focus~.custom-control-label::before,.custom-control-input.is-valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,0.25)}.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before,.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.was-validated .custom-file-input:valid~.custom-file-label,.custom-file-input.is-valid~.custom-file-label{border-color:#28a745}.was-validated .custom-file-input:valid:focus~.custom-file-label,.custom-file-input.is-valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,0.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,0.9);border-radius:.25rem}.form-row>.col>.invalid-tooltip,.form-row>[class*="col-"]>.invalid-tooltip{left:5px}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated .form-check-input:invalid~.form-check-label,.was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~.form-check-label,.shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~.form-check-label,.was-validated .shiny-input-checkboxgroup .radio label>input:invalid~.form-check-label,.shiny-input-checkboxgroup .radio .was-validated label>input:invalid~.form-check-label,.was-validated .shiny-input-radiogroup .checkbox label>input:invalid~.form-check-label,.shiny-input-radiogroup .checkbox .was-validated label>input:invalid~.form-check-label,.was-validated .shiny-input-radiogroup .radio label>input:invalid~.form-check-label,.shiny-input-radiogroup .radio .was-validated label>input:invalid~.form-check-label,.was-validated .shiny-input-checkboxgroup .checkbox .form-check-input:invalid~label,.was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .checkbox .radio label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio .checkbox label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input:invalid~label,.shiny-input-radiogroup .was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input:invalid~label,.shiny-input-radiogroup .radio .was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated .form-check-input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated .radio label>input:invalid~label,.shiny-input-checkboxgroup .radio .checkbox .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox .was-validated label>input:invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated .shiny-input-radiogroup .radio label>input:invalid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio .form-check-input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio .checkbox label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .checkbox .radio label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated .shiny-input-checkboxgroup .radio label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input:invalid~label,.shiny-input-radiogroup .was-validated .shiny-input-checkboxgroup .radio label>input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated .form-check-input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .radio .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated .shiny-input-radiogroup .checkbox label>input:invalid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio .was-validated label>input:invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio .was-validated label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox .form-check-input:invalid~label,.was-validated .shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .was-validated .shiny-input-radiogroup .checkbox label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated .shiny-input-radiogroup .checkbox label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox .radio label>input:invalid~label,.was-validated .shiny-input-radiogroup .radio .checkbox label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated .form-check-input:invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox .was-validated label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated .shiny-input-checkboxgroup .radio label>input:invalid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox .was-validated label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated .radio label>input:invalid~label,.shiny-input-radiogroup .radio .checkbox .was-validated label>input:invalid~label,.was-validated .shiny-input-radiogroup .radio .form-check-input:invalid~label,.was-validated .shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated .shiny-input-radiogroup .radio label>input:invalid~label,.was-validated .shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input:invalid~label,.shiny-input-checkboxgroup .was-validated .shiny-input-radiogroup .radio label>input:invalid~label,.was-validated .shiny-input-radiogroup .radio .checkbox label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox .radio label>input:invalid~label,.was-validated .shiny-input-radiogroup .radio label>input:invalid~label,.shiny-input-radiogroup .radio .was-validated .form-check-input:invalid~label,.shiny-input-radiogroup .radio .was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio .was-validated label>input:invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio .was-validated label>input:invalid~label,.shiny-input-radiogroup .radio .was-validated .checkbox label>input:invalid~label,.shiny-input-radiogroup .checkbox .radio .was-validated label>input:invalid~label,.shiny-input-radiogroup .radio .was-validated label>input:invalid~label,.form-check-input.is-invalid~.form-check-label,.shiny-input-checkboxgroup .checkbox label>input.is-invalid~.form-check-label,.shiny-input-checkboxgroup .radio label>input.is-invalid~.form-check-label,.shiny-input-radiogroup .checkbox label>input.is-invalid~.form-check-label,.shiny-input-radiogroup .radio label>input.is-invalid~.form-check-label,.shiny-input-checkboxgroup .checkbox .form-check-input.is-invalid~label,.shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .checkbox .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .radio .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .radio .form-check-input.is-invalid~label,.shiny-input-checkboxgroup .radio .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .checkbox .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .form-check-input.is-invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .radio label>input.is-invalid~label,.shiny-input-radiogroup .radio .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .radio .form-check-input.is-invalid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .radio .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .radio label>input.is-invalid~label,.shiny-input-radiogroup .radio label>input.is-invalid~label{color:#dc3545}.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~.invalid-feedback,.shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~.invalid-feedback,.was-validated .shiny-input-checkboxgroup .radio label>input:invalid~.invalid-feedback,.shiny-input-checkboxgroup .radio .was-validated label>input:invalid~.invalid-feedback,.was-validated .shiny-input-radiogroup .checkbox label>input:invalid~.invalid-feedback,.shiny-input-radiogroup .checkbox .was-validated label>input:invalid~.invalid-feedback,.was-validated .shiny-input-radiogroup .radio label>input:invalid~.invalid-feedback,.shiny-input-radiogroup .radio .was-validated label>input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip,.was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~.invalid-tooltip,.shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~.invalid-tooltip,.was-validated .shiny-input-checkboxgroup .radio label>input:invalid~.invalid-tooltip,.shiny-input-checkboxgroup .radio .was-validated label>input:invalid~.invalid-tooltip,.was-validated .shiny-input-radiogroup .checkbox label>input:invalid~.invalid-tooltip,.shiny-input-radiogroup .checkbox .was-validated label>input:invalid~.invalid-tooltip,.was-validated .shiny-input-radiogroup .radio label>input:invalid~.invalid-tooltip,.shiny-input-radiogroup .radio .was-validated label>input:invalid~.invalid-tooltip,.form-check-input.is-invalid~.invalid-feedback,.shiny-input-checkboxgroup .checkbox label>input.is-invalid~.invalid-feedback,.shiny-input-checkboxgroup .radio label>input.is-invalid~.invalid-feedback,.shiny-input-radiogroup .checkbox label>input.is-invalid~.invalid-feedback,.shiny-input-radiogroup .radio label>input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.shiny-input-checkboxgroup .checkbox label>input.is-invalid~.invalid-tooltip,.shiny-input-checkboxgroup .radio label>input.is-invalid~.invalid-tooltip,.shiny-input-radiogroup .checkbox label>input.is-invalid~.invalid-tooltip,.shiny-input-radiogroup .radio label>input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid~.custom-control-label,.custom-control-input.is-invalid~.custom-control-label{color:#dc3545}.was-validated .custom-control-input:invalid~.custom-control-label::before,.custom-control-input.is-invalid~.custom-control-label::before{border-color:#dc3545}.was-validated .custom-control-input:invalid:checked~.custom-control-label::before,.custom-control-input.is-invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.was-validated .custom-control-input:invalid:focus~.custom-control-label::before,.custom-control-input.is-invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before,.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.was-validated .custom-file-input:invalid~.custom-file-label,.custom-file-input.is-invalid~.custom-file-label{border-color:#dc3545}.was-validated .custom-file-input:invalid:focus~.custom-file-label,.custom-file-input.is-invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.form-inline{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap;align-items:center;-webkit-align-items:center}.form-inline .form-check,.form-inline .shiny-input-checkboxgroup .checkbox,.shiny-input-checkboxgroup .form-inline .checkbox,.form-inline .shiny-input-checkboxgroup .radio,.shiny-input-checkboxgroup .form-inline .radio,.form-inline .shiny-input-radiogroup .checkbox,.shiny-input-radiogroup .form-inline .checkbox,.form-inline .shiny-input-radiogroup .radio,.shiny-input-radiogroup .form-inline .radio{width:100%}@media (min-width: 576px){.form-inline label{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;margin-bottom:0}.form-inline .form-group{display:flex;display:-webkit-flex;flex:0 0 auto;-webkit-flex:0 0 auto;flex-flow:row wrap;-webkit-flex-flow:row wrap;align-items:center;-webkit-align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check,.form-inline .shiny-input-checkboxgroup .checkbox,.shiny-input-checkboxgroup .form-inline .checkbox,.form-inline .shiny-input-checkboxgroup .radio,.shiny-input-checkboxgroup .form-inline .radio,.form-inline .shiny-input-radiogroup .checkbox,.shiny-input-radiogroup .form-inline .checkbox,.form-inline .shiny-input-radiogroup .radio,.shiny-input-radiogroup .form-inline .radio{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input,.form-inline .shiny-input-checkboxgroup .checkbox label>input,.shiny-input-checkboxgroup .checkbox .form-inline label>input,.form-inline .shiny-input-checkboxgroup .radio label>input,.shiny-input-checkboxgroup .radio .form-inline label>input,.form-inline .shiny-input-radiogroup .checkbox label>input,.shiny-input-radiogroup .checkbox .form-inline label>input,.form-inline .shiny-input-radiogroup .radio label>input,.shiny-input-radiogroup .radio .form-inline label>input{position:relative;flex-shrink:0;-webkit-flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn:focus,.btn.focus{outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-default{color:#000;background-color:#dee2e6;border-color:#dee2e6}.btn-default:hover{color:#000;background-color:#c8cfd6;border-color:#c1c9d0}.btn-default:focus,.btn-default.focus{color:#000;background-color:#c8cfd6;border-color:#c1c9d0;box-shadow:0 0 0 .2rem rgba(189,192,196,0.5)}.btn-default.disabled,.btn-default:disabled{color:#000;background-color:#dee2e6;border-color:#dee2e6}.btn-default:not(:disabled):not(.disabled):active,.btn-default:not(:disabled):not(.disabled).active,.show>.btn-default.dropdown-toggle,.in>.btn-default.dropdown-toggle{color:#000;background-color:#c1c9d0;border-color:#bac2cb}.btn-default:not(:disabled):not(.disabled):active:focus,.btn-default:not(:disabled):not(.disabled).active:focus,.show>.btn-default.dropdown-toggle:focus,.in>.btn-default.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(189,192,196,0.5)}.btn-primary{color:#fff;background-color:#096B72;border-color:#096B72}.btn-primary:hover{color:#fff;background-color:#064a4f;border-color:#053f43}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#064a4f;border-color:#053f43;box-shadow:0 0 0 .2rem rgba(46,129,135,0.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#096B72;border-color:#096B72}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle,.in>.btn-primary.dropdown-toggle{color:#fff;background-color:#053f43;border-color:#043437}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus,.in>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(46,129,135,0.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary:focus,.btn-secondary.focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,0.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled):active,.btn-secondary:not(:disabled):not(.disabled).active,.show>.btn-secondary.dropdown-toggle,.in>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled):active:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-secondary.dropdown-toggle:focus,.in>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,0.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,0.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled):active,.btn-success:not(:disabled):not(.disabled).active,.show>.btn-success.dropdown-toggle,.in>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled):active:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.show>.btn-success.dropdown-toggle:focus,.in>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,0.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,0.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled):active,.btn-info:not(:disabled):not(.disabled).active,.show>.btn-info.dropdown-toggle,.in>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled):active:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.show>.btn-info.dropdown-toggle:focus,.in>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,0.5)}.btn-warning{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#000;background-color:#e0a800;border-color:#d39e00}.btn-warning:focus,.btn-warning.focus{color:#000;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(217,164,6,0.5)}.btn-warning.disabled,.btn-warning:disabled{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled):active,.btn-warning:not(:disabled):not(.disabled).active,.show>.btn-warning.dropdown-toggle,.in>.btn-warning.dropdown-toggle{color:#000;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled):active:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-warning.dropdown-toggle:focus,.in>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(217,164,6,0.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,0.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled):active,.btn-danger:not(:disabled):not(.disabled).active,.show>.btn-danger.dropdown-toggle,.in>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled):active:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-danger.dropdown-toggle:focus,.in>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,0.5)}.btn-light{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#000;background-color:#e2e6ea;border-color:#dae0e5}.btn-light:focus,.btn-light.focus{color:#000;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(211,212,213,0.5)}.btn-light.disabled,.btn-light:disabled{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle,.in>.btn-light.dropdown-toggle{color:#000;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus,.in>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(211,212,213,0.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark:focus,.btn-dark.focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,0.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled):active,.btn-dark:not(:disabled):not(.disabled).active,.show>.btn-dark.dropdown-toggle,.in>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled):active:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-dark.dropdown-toggle:focus,.in>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,0.5)}.btn-outline-default{color:#dee2e6;border-color:#dee2e6;background-color:transparent}.btn-outline-default:hover{color:#000;background-color:#dee2e6;border-color:#dee2e6}.btn-outline-default:focus,.btn-outline-default.focus{box-shadow:0 0 0 .2rem rgba(222,226,230,0.5)}.btn-outline-default.disabled,.btn-outline-default:disabled{color:#dee2e6;background-color:transparent}.btn-outline-default:not(:disabled):not(.disabled):active,.btn-outline-default:not(:disabled):not(.disabled).active,.show>.btn-outline-default.dropdown-toggle,.in>.btn-outline-default.dropdown-toggle{color:#000;background-color:#dee2e6;border-color:#dee2e6}.btn-outline-default:not(:disabled):not(.disabled):active:focus,.btn-outline-default:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-default.dropdown-toggle:focus,.in>.btn-outline-default.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,226,230,0.5)}.btn-outline-primary{color:#096B72;border-color:#096B72;background-color:transparent}.btn-outline-primary:hover{color:#fff;background-color:#096B72;border-color:#096B72}.btn-outline-primary:focus,.btn-outline-primary.focus{box-shadow:0 0 0 .2rem rgba(9,107,114,0.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#096B72;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled):active,.btn-outline-primary:not(:disabled):not(.disabled).active,.show>.btn-outline-primary.dropdown-toggle,.in>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#096B72;border-color:#096B72}.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-primary.dropdown-toggle:focus,.in>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(9,107,114,0.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d;background-color:transparent}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:focus,.btn-outline-secondary.focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled):active,.btn-outline-secondary:not(:disabled):not(.disabled).active,.show>.btn-outline-secondary.dropdown-toggle,.in>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus,.in>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-outline-success{color:#28a745;border-color:#28a745;background-color:transparent}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:focus,.btn-outline-success.focus{box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled):active,.btn-outline-success:not(:disabled):not(.disabled).active,.show>.btn-outline-success.dropdown-toggle,.in>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled):active:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-success.dropdown-toggle:focus,.in>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8;background-color:transparent}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:focus,.btn-outline-info.focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled):active,.btn-outline-info:not(:disabled):not(.disabled).active,.show>.btn-outline-info.dropdown-toggle,.in>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled):active:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-info.dropdown-toggle:focus,.in>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107;background-color:transparent}.btn-outline-warning:hover{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:focus,.btn-outline-warning.focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled):active,.btn-outline-warning:not(:disabled):not(.disabled).active,.show>.btn-outline-warning.dropdown-toggle,.in>.btn-outline-warning.dropdown-toggle{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-warning.dropdown-toggle:focus,.in>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545;background-color:transparent}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:focus,.btn-outline-danger.focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled):active,.btn-outline-danger:not(:disabled):not(.disabled).active,.show>.btn-outline-danger.dropdown-toggle,.in>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-danger.dropdown-toggle:focus,.in>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa;background-color:transparent}.btn-outline-light:hover{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:focus,.btn-outline-light.focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled):active,.btn-outline-light:not(:disabled):not(.disabled).active,.show>.btn-outline-light.dropdown-toggle,.in>.btn-outline-light.dropdown-toggle{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled):active:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-light.dropdown-toggle:focus,.in>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-outline-dark{color:#343a40;border-color:#343a40;background-color:transparent}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:focus,.btn-outline-dark.focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled):active,.btn-outline-dark:not(:disabled):not(.disabled).active,.show>.btn-outline-dark.dropdown-toggle,.in>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-dark.dropdown-toggle:focus,.in>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-link{font-weight:400;color:#096B72;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none}.btn-link:hover{color:#03282b;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:focus,.btn-link.focus{text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:disabled,.btn-link.disabled{color:#6c757d;pointer-events:none}.btn-lg,.btn-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-sm,.btn-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{transition:opacity 0.15s linear}@media (prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show):not(.in){opacity:0}.collapse:not(.show):not(.in){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height 0.35s ease}@media (prefers-reduced-motion: reduce){.collapsing{transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,0.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width: 576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width: 768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width: 992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width: 1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^="top"],.dropdown-menu[x-placement^="right"],.dropdown-menu[x-placement^="bottom"],.dropdown-menu[x-placement^="left"]{right:auto;bottom:auto}.dropdown-divider,.dropdown-menu>li.divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item,.dropdown-menu>li>a{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-menu>li>a:hover,.dropdown-item:focus,.dropdown-menu>li>a:focus{color:#16181b;text-decoration:none;background-color:#e9ecef}.dropdown-item.active,.dropdown-menu>li>a.active,.dropdown-item:active,.dropdown-menu>li>a:active{color:#fff;text-decoration:none;background-color:#096B72}.dropdown-item.disabled,.dropdown-menu>li>a.disabled,.dropdown-item:disabled,.dropdown-menu>li>a:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show,.dropdown-menu.in{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover{z-index:1}.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;justify-content:flex-start;-webkit-justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child){margin-left:-1px}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;-webkit-flex-direction:column;align-items:flex-start;-webkit-align-items:flex-start;justify-content:center;-webkit-justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type="radio"],.btn-group-toggle>.btn input[type="checkbox"],.btn-group-toggle>.btn-group>.btn input[type="radio"],.btn-group-toggle>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:stretch;-webkit-align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-control-plaintext,.input-group>.custom-select,.input-group>.custom-file{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.form-control+.form-control,.input-group>.form-control+.custom-select,.input-group>.form-control+.custom-file,.input-group>.form-control-plaintext+.form-control,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.custom-file,.input-group>.custom-select+.form-control,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.custom-file,.input-group>.custom-file+.form-control,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.custom-file{margin-left:-1px}.input-group>.form-control:focus,.input-group>.custom-select:focus,.input-group>.custom-file .custom-file-input:focus~.custom-file-label{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.form-control:not(:first-child),.input-group>.custom-select:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group:not(.has-validation)>.form-control:not(:last-child),.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.form-control:nth-last-child(n + 3),.input-group.has-validation>.custom-select:nth-last-child(n + 3),.input-group.has-validation>.custom-file:nth-last-child(n + 3) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-prepend,.input-group-append{display:flex;display:-webkit-flex}.input-group-prepend .btn,.input-group-append .btn{position:relative;z-index:2}.input-group-prepend .btn:focus,.input-group-append .btn:focus{z-index:3}.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.input-group-text,.input-group-append .input-group-text+.btn{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type="radio"],.input-group-text input[type="checkbox"]{margin-top:0}.input-group-lg>.form-control:not(textarea),.input-group-lg>.custom-select{height:calc(1.5em + 1rem + 2px)}.input-group-lg>.form-control,.input-group-lg>.custom-select,.input-group-lg>.input-group-prepend>.input-group-text,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-append>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.form-control:not(textarea),.input-group-sm>.custom-select{height:calc(1.5em + .5rem + 2px)}.input-group-sm>.form-control,.input-group-sm>.custom-select,.input-group-sm>.input-group-prepend>.input-group-text,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-append>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group.has-validation>.input-group-append:nth-last-child(n + 3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n + 3)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem;color-adjust:exact;-webkit-print-color-adjust:exact}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#096B72;background-color:#096B72}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#12dae8}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#000;background-color:#3ee4f0;border-color:#3ee4f0}.custom-control-input[disabled]~.custom-control-label,.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input[disabled]~.custom-control-label::before,.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:50% / 50% 50% no-repeat}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#096B72;background-color:#096B72}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(9,107,114,0.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(9,107,114,0.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(9,107,114,0.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:transform 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(9,107,114,0.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}.custom-select:focus{border-color:#12dae8;outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;overflow:hidden;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#12dae8;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.custom-file-input[disabled]~.custom-file-label,.custom-file-input:disabled~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;overflow:hidden;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(9,107,114,0.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(9,107,114,0.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(9,107,114,0.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#096B72;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#3ee4f0}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#096B72;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#3ee4f0}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#096B72;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#3ee4f0}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link,.nav-tabs>li>a,.nav-pills>li>a,:where(ul.nav.navbar-nav > li)>a{display:block;padding:.5rem 1rem}.nav-link:hover,.nav-tabs>li>a:hover,.nav-pills>li>a:hover,:where(ul.nav.navbar-nav > li)>a:hover,.nav-link:focus,.nav-tabs>li>a:focus,.nav-pills>li>a:focus,:where(ul.nav.navbar-nav > li)>a:focus{text-decoration:none}.nav-link.disabled,.nav-tabs>li>a.disabled,.nav-pills>li>a.disabled,:where(ul.nav.navbar-nav > li)>a.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link,.nav-tabs>li>a,.nav-tabs .nav-pills>li>a,.nav-tabs :where(ul.nav.navbar-nav > li)>a{margin-bottom:-1px;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:hover,.nav-tabs>li>a:hover,.nav-tabs .nav-pills>li>a:hover,.nav-tabs :where(ul.nav.navbar-nav > li)>a:hover,.nav-tabs .nav-link:focus,.nav-tabs>li>a:focus,.nav-tabs .nav-pills>li>a:focus,.nav-tabs :where(ul.nav.navbar-nav > li)>a:focus{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled,.nav-tabs>li>a.disabled,.nav-tabs .nav-pills>li>a.disabled,.nav-tabs :where(ul.nav.navbar-nav > li)>a.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs>li>a.active,.nav-tabs .nav-pills>li>a.active,.nav-tabs :where(ul.nav.navbar-nav > li)>a.active,.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-item.in .nav-link,.nav-tabs .nav-item.show .nav-tabs>li>a,.nav-tabs .nav-item.in .nav-tabs>li>a,.nav-tabs .nav-item.show .nav-pills>li>a,.nav-tabs .nav-item.in .nav-pills>li>a,.nav-tabs>li.show .nav-link,.nav-tabs>li.in .nav-link,.nav-tabs>li.show .nav-tabs>li>a,.nav-tabs>li.in .nav-tabs>li>a,.nav-tabs>li.show .nav-pills>li>a,.nav-tabs>li.in .nav-pills>li>a,.nav-tabs .nav-pills>li.show .nav-link,.nav-tabs .nav-pills>li.in .nav-link,.nav-tabs .nav-pills>li.show .nav-tabs>li>a,.nav-tabs .nav-pills>li.in .nav-tabs>li>a,.nav-tabs .nav-pills>li.show .nav-pills>li>a,.nav-tabs .nav-pills>li.in .nav-pills>li>a,.nav-tabs .nav-item.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-item.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs>li.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs>li.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-pills>li.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-pills>li.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-link,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-link,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-tabs>li>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-tabs>li>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-pills>li>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-pills>li>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) :where(ul.nav.navbar-nav > li)>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) :where(ul.nav.navbar-nav > li)>a{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link,.nav-pills .nav-tabs>li>a,.nav-pills>li>a,.nav-pills :where(ul.nav.navbar-nav > li)>a{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .nav-tabs>li>a.active,.nav-pills>li>a.active,.nav-pills :where(ul.nav.navbar-nav > li)>a.active,.nav-pills .show>.nav-link,.nav-pills .in>.nav-link,.nav-pills .nav-tabs>li.show>a,.nav-pills .nav-tabs>li.in>a,.nav-pills>li.show>a,.nav-pills>li.in>a,.nav-pills .show:where(ul.nav.navbar-nav > li)>a,.nav-pills .in:where(ul.nav.navbar-nav > li)>a{color:#fff;background-color:#096B72}.nav-fill>.nav-link,.nav-tabs>li.nav-fill>a,.nav-pills>li.nav-fill>a,.nav-fill:where(ul.nav.navbar-nav > li)>a,.nav-fill .nav-item,.nav-fill .nav-tabs>li,.nav-fill .nav-pills>li,.nav-fill :where(ul.nav.navbar-nav > li):not(.dropdown){flex:1 1 auto;-webkit-flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-tabs>li.nav-justified>a,.nav-pills>li.nav-justified>a,.nav-justified:where(ul.nav.navbar-nav > li)>a,.nav-justified .nav-item,.nav-justified .nav-tabs>li,.nav-justified .nav-pills>li,.nav-justified :where(ul.nav.navbar-nav > li):not(.dropdown){flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-sm,.navbar .container-md,.navbar .container-lg,.navbar .container-xl{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link,.navbar-nav .nav-tabs>li>a,.navbar-nav .nav-pills>li>a,.navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;-webkit-flex-basis:100%;flex-grow:1;-webkit-flex-grow:1;align-items:center;-webkit-align-items:center}.navbar-toggler,.navbar-toggle{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:hover,.navbar-toggle:hover,.navbar-toggler:focus,.navbar-toggle:focus{text-decoration:none}.navbar-toggler-icon,.navbar-toggle>.icon-bar:last-child{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:50% / 100% 100% no-repeat}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width: 575.98px){.navbar-expand-sm>.container,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container,.navbar-expand-sm>.container-fluid,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-fluid,.navbar-expand-sm>.container-sm,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-sm,.navbar-expand-sm>.container-md,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-md,.navbar-expand-sm>.container-lg,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-lg,.navbar-expand-sm>.container-xl,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 576px){.navbar-expand-sm,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl){flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-sm .navbar-nav,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link,.navbar-expand-sm .navbar-nav .nav-tabs>li>a,.navbar-expand-sm .navbar-nav .nav-pills>li>a,.navbar-expand-sm .navbar-nav :where(ul.nav.navbar-nav > li)>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-link,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-tabs>li>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-pills>li>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container,.navbar-expand-sm>.container-fluid,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-fluid,.navbar-expand-sm>.container-sm,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-sm,.navbar-expand-sm>.container-md,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-md,.navbar-expand-sm>.container-lg,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-lg,.navbar-expand-sm>.container-xl,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-sm .navbar-toggler,.navbar-expand-sm .navbar-toggle,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-toggler,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-toggle{display:none}}@media (max-width: 767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 768px){.navbar-expand-md{flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link,.navbar-expand-md .navbar-nav .nav-tabs>li>a,.navbar-expand-md .navbar-nav .nav-pills>li>a,.navbar-expand-md .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-md .navbar-toggler,.navbar-expand-md .navbar-toggle{display:none}}@media (max-width: 991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 992px){.navbar-expand-lg{flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link,.navbar-expand-lg .navbar-nav .nav-tabs>li>a,.navbar-expand-lg .navbar-nav .nav-pills>li>a,.navbar-expand-lg .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-lg .navbar-toggler,.navbar-expand-lg .navbar-toggle{display:none}}@media (max-width: 1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 1200px){.navbar-expand-xl{flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link,.navbar-expand-xl .navbar-nav .nav-tabs>li>a,.navbar-expand-xl .navbar-nav .nav-pills>li>a,.navbar-expand-xl .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xl .navbar-toggler,.navbar-expand-xl .navbar-toggle{display:none}}.navbar-expand{flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link,.navbar-expand .navbar-nav .nav-tabs>li>a,.navbar-expand .navbar-nav .nav-pills>li>a,.navbar-expand .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand .navbar-toggler,.navbar-expand .navbar-toggle{display:none}.navbar-light,.navbar.navbar-default{background-color:#f8f9fa}.navbar-light .navbar-brand,.navbar.navbar-default .navbar-brand{color:#000}.navbar-light .navbar-brand:hover,.navbar.navbar-default .navbar-brand:hover,.navbar-light .navbar-brand:focus,.navbar.navbar-default .navbar-brand:focus{color:#000}.navbar-light .navbar-nav .nav-link,.navbar-light .navbar-nav .nav-tabs>li>a,.navbar-light .navbar-nav .nav-pills>li>a,.navbar.navbar-default .navbar-nav .nav-link,.navbar.navbar-default .navbar-nav .nav-tabs>li>a,.navbar.navbar-default .navbar-nav .nav-pills>li>a,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a{color:rgba(0,0,0,0.5)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-tabs>li>a:hover,.navbar-light .navbar-nav .nav-pills>li>a:hover,.navbar.navbar-default .navbar-nav .nav-link:hover,.navbar.navbar-default .navbar-nav .nav-tabs>li>a:hover,.navbar.navbar-default .navbar-nav .nav-pills>li>a:hover,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a:hover,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a:hover,.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-tabs>li>a:focus,.navbar-light .navbar-nav .nav-pills>li>a:focus,.navbar.navbar-default .navbar-nav .nav-link:focus,.navbar.navbar-default .navbar-nav .nav-tabs>li>a:focus,.navbar.navbar-default .navbar-nav .nav-pills>li>a:focus,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a:focus,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a:focus{color:rgba(0,0,0,0.75)}.navbar-light .navbar-nav .nav-link.disabled,.navbar-light .navbar-nav .nav-tabs>li>a.disabled,.navbar-light .navbar-nav .nav-pills>li>a.disabled,.navbar.navbar-default .navbar-nav .nav-link.disabled,.navbar.navbar-default .navbar-nav .nav-tabs>li>a.disabled,.navbar.navbar-default .navbar-nav .nav-pills>li>a.disabled,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a.disabled,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a.disabled{color:rgba(0,0,0,0.25)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .in>.nav-link,.navbar-light .navbar-nav .nav-tabs>li.show>a,.navbar-light .navbar-nav .nav-tabs>li.in>a,.navbar-light .navbar-nav .nav-pills>li.show>a,.navbar-light .navbar-nav .nav-pills>li.in>a,.navbar.navbar-default .navbar-nav .show>.nav-link,.navbar.navbar-default .navbar-nav .in>.nav-link,.navbar.navbar-default .navbar-nav .nav-tabs>li.show>a,.navbar.navbar-default .navbar-nav .nav-tabs>li.in>a,.navbar.navbar-default .navbar-nav .nav-pills>li.show>a,.navbar.navbar-default .navbar-nav .nav-pills>li.in>a,.navbar-light .navbar-nav .show:where(ul.nav.navbar-nav > li)>a,.navbar-light .navbar-nav .in:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-default .navbar-nav .show:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-default .navbar-nav .in:where(ul.nav.navbar-nav > li)>a,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-tabs>li.active>a,.navbar-light .navbar-nav .nav-pills>li.active>a,.navbar.navbar-default .navbar-nav .active>.nav-link,.navbar.navbar-default .navbar-nav .nav-tabs>li.active>a,.navbar.navbar-default .navbar-nav .nav-pills>li.active>a,.navbar-light .navbar-nav .active:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-default .navbar-nav .active:where(ul.nav.navbar-nav > li)>a,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.in,.navbar-light .navbar-nav .nav-tabs>li>a.show,.navbar-light .navbar-nav .nav-tabs>li>a.in,.navbar-light .navbar-nav .nav-pills>li>a.show,.navbar-light .navbar-nav .nav-pills>li>a.in,.navbar.navbar-default .navbar-nav .nav-link.show,.navbar.navbar-default .navbar-nav .nav-link.in,.navbar.navbar-default .navbar-nav .nav-tabs>li>a.show,.navbar.navbar-default .navbar-nav .nav-tabs>li>a.in,.navbar.navbar-default .navbar-nav .nav-pills>li>a.show,.navbar.navbar-default .navbar-nav .nav-pills>li>a.in,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a.in,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a.in,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-tabs>li>a.active,.navbar-light .navbar-nav .nav-pills>li>a.active,.navbar.navbar-default .navbar-nav .nav-link.active,.navbar.navbar-default .navbar-nav .nav-tabs>li>a.active,.navbar.navbar-default .navbar-nav .nav-pills>li>a.active,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a.active,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a.active{color:#000}.navbar-light .navbar-toggler,.navbar-light .navbar-toggle,.navbar.navbar-default .navbar-toggler,.navbar.navbar-default .navbar-toggle{color:rgba(0,0,0,0.5);border-color:rgba(0,0,0,0.1)}.navbar-light .navbar-toggler-icon,.navbar-light .navbar-toggle>.icon-bar:last-child,.navbar.navbar-default .navbar-toggler-icon,.navbar.navbar-default .navbar-toggle>.icon-bar:last-child{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280,0,0,0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text,.navbar.navbar-default .navbar-text{color:rgba(0,0,0,0.5)}.navbar-light .navbar-text a,.navbar.navbar-default .navbar-text a{color:#000}.navbar-light .navbar-text a:hover,.navbar.navbar-default .navbar-text a:hover,.navbar-light .navbar-text a:focus,.navbar.navbar-default .navbar-text a:focus{color:#000}.navbar-dark,.navbar.navbar-inverse{background-color:#343a40}.navbar-dark .navbar-brand,.navbar.navbar-inverse .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar.navbar-inverse .navbar-brand:hover,.navbar-dark .navbar-brand:focus,.navbar.navbar-inverse .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link,.navbar-dark .navbar-nav .nav-tabs>li>a,.navbar-dark .navbar-nav .nav-pills>li>a,.navbar.navbar-inverse .navbar-nav .nav-link,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a{color:rgba(255,255,255,0.5)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-tabs>li>a:hover,.navbar-dark .navbar-nav .nav-pills>li>a:hover,.navbar.navbar-inverse .navbar-nav .nav-link:hover,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a:hover,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a:hover,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a:hover,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a:hover,.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-tabs>li>a:focus,.navbar-dark .navbar-nav .nav-pills>li>a:focus,.navbar.navbar-inverse .navbar-nav .nav-link:focus,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a:focus,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a:focus,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a:focus,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a:focus{color:rgba(255,255,255,0.75)}.navbar-dark .navbar-nav .nav-link.disabled,.navbar-dark .navbar-nav .nav-tabs>li>a.disabled,.navbar-dark .navbar-nav .nav-pills>li>a.disabled,.navbar.navbar-inverse .navbar-nav .nav-link.disabled,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a.disabled,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a.disabled,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a.disabled,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a.disabled{color:rgba(255,255,255,0.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .in>.nav-link,.navbar-dark .navbar-nav .nav-tabs>li.show>a,.navbar-dark .navbar-nav .nav-tabs>li.in>a,.navbar-dark .navbar-nav .nav-pills>li.show>a,.navbar-dark .navbar-nav .nav-pills>li.in>a,.navbar.navbar-inverse .navbar-nav .show>.nav-link,.navbar.navbar-inverse .navbar-nav .in>.nav-link,.navbar.navbar-inverse .navbar-nav .nav-tabs>li.show>a,.navbar.navbar-inverse .navbar-nav .nav-tabs>li.in>a,.navbar.navbar-inverse .navbar-nav .nav-pills>li.show>a,.navbar.navbar-inverse .navbar-nav .nav-pills>li.in>a,.navbar-dark .navbar-nav .show:where(ul.nav.navbar-nav > li)>a,.navbar-dark .navbar-nav .in:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-inverse .navbar-nav .show:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-inverse .navbar-nav .in:where(ul.nav.navbar-nav > li)>a,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-tabs>li.active>a,.navbar-dark .navbar-nav .nav-pills>li.active>a,.navbar.navbar-inverse .navbar-nav .active>.nav-link,.navbar.navbar-inverse .navbar-nav .nav-tabs>li.active>a,.navbar.navbar-inverse .navbar-nav .nav-pills>li.active>a,.navbar-dark .navbar-nav .active:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-inverse .navbar-nav .active:where(ul.nav.navbar-nav > li)>a,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.in,.navbar-dark .navbar-nav .nav-tabs>li>a.show,.navbar-dark .navbar-nav .nav-tabs>li>a.in,.navbar-dark .navbar-nav .nav-pills>li>a.show,.navbar-dark .navbar-nav .nav-pills>li>a.in,.navbar.navbar-inverse .navbar-nav .nav-link.show,.navbar.navbar-inverse .navbar-nav .nav-link.in,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a.show,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a.in,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a.show,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a.in,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a.in,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a.in,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-tabs>li>a.active,.navbar-dark .navbar-nav .nav-pills>li>a.active,.navbar.navbar-inverse .navbar-nav .nav-link.active,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a.active,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a.active,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a.active,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a.active{color:#fff}.navbar-dark .navbar-toggler,.navbar-dark .navbar-toggle,.navbar.navbar-inverse .navbar-toggler,.navbar.navbar-inverse .navbar-toggle{color:rgba(255,255,255,0.5);border-color:rgba(255,255,255,0.1)}.navbar-dark .navbar-toggler-icon,.navbar-dark .navbar-toggle>.icon-bar:last-child,.navbar.navbar-inverse .navbar-toggler-icon,.navbar.navbar-inverse .navbar-toggle>.icon-bar:last-child{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255,255,255,0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text,.navbar.navbar-inverse .navbar-text{color:rgba(255,255,255,0.5)}.navbar-dark .navbar-text a,.navbar.navbar-inverse .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar.navbar-inverse .navbar-text a:hover,.navbar-dark .navbar-text a:focus,.navbar.navbar-inverse .navbar-text a:focus{color:#fff}.card,.well{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,0.125);border-radius:.25rem}.card>hr,.well>hr{margin-right:0;margin-left:0}.card>.list-group,.well>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child,.well>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child,.well>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.well>.card-header+.list-group,.card>.list-group+.card-footer,.well>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;-webkit-flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,0.03);border-bottom:1px solid rgba(0,0,0,0.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,0.03);border-top:1px solid rgba(0,0,0,0.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-top,.card-img-bottom{flex-shrink:0;-webkit-flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card,.card-deck .well{margin-bottom:15px}@media (min-width: 576px){.card-deck{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card,.card-deck .well{flex:1 0 0%;-webkit-flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card,.card-group>.well{margin-bottom:15px}@media (min-width: 576px){.card-group{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap}.card-group>.card,.card-group>.well{flex:1 0 0%;-webkit-flex:1 0 0%;margin-bottom:0}.card-group>.card+.card,.card-group>.well+.card,.card-group>.card+.well,.card-group>.well+.well{margin-left:0;border-left:0}.card-group>.card:not(:last-child),.card-group>.well:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.well:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header,.card-group>.well:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.well:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer,.card-group>.well:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child),.card-group>.well:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.well:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header,.card-group>.well:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.well:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer,.card-group>.well:not(:first-child) .card-footer{border-bottom-left-radius:0}}.card-columns .card,.card-columns .well{margin-bottom:.75rem}@media (min-width: 576px){.card-columns{column-count:3;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card,.card-columns .well{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card,.accordion>.well{overflow:hidden}.accordion>.card:not(:last-of-type),.accordion>.well:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type),.accordion>.well:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header,.accordion>.well>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;display:-webkit-flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#096B72;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#03282b;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#096B72;border-color:#096B72}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.badge{transition:none}}a.badge:hover,a.badge:focus{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-default{color:#000;background-color:#dee2e6}a.badge-default:hover,a.badge-default:focus{color:#000;background-color:#c1c9d0}a.badge-default:focus,a.badge-default.focus{outline:0;box-shadow:0 0 0 .2rem rgba(222,226,230,0.5)}.badge-primary{color:#fff;background-color:#096B72}a.badge-primary:hover,a.badge-primary:focus{color:#fff;background-color:#053f43}a.badge-primary:focus,a.badge-primary.focus{outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:hover,a.badge-secondary:focus{color:#fff;background-color:#545b62}a.badge-secondary:focus,a.badge-secondary.focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:hover,a.badge-success:focus{color:#fff;background-color:#1e7e34}a.badge-success:focus,a.badge-success.focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:hover,a.badge-info:focus{color:#fff;background-color:#117a8b}a.badge-info:focus,a.badge-info.focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.badge-warning{color:#000;background-color:#ffc107}a.badge-warning:hover,a.badge-warning:focus{color:#000;background-color:#d39e00}a.badge-warning:focus,a.badge-warning.focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:hover,a.badge-danger:focus{color:#fff;background-color:#bd2130}a.badge-danger:focus,a.badge-danger.focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.badge-light{color:#000;background-color:#f8f9fa}a.badge-light:hover,a.badge-light:focus{color:#000;background-color:#dae0e5}a.badge-light:focus,a.badge-light.focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:hover,a.badge-dark:focus{color:#fff;background-color:#1d2124}a.badge-dark:focus,a.badge-dark.focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width: 576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-default{color:#737678;background-color:#f8f9fa;border-color:#f6f7f8}.alert-default hr{border-top-color:#e8eaed}.alert-default .alert-link{color:#5a5c5e}.alert-primary{color:#05383b;background-color:#cee1e3;border-color:#bad6d8}.alert-primary hr{border-top-color:#aacccf}.alert-primary .alert-link{color:#010b0c}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:flex;display:-webkit-flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#096B72;transition:width 0.6s ease}@media (prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:1rem 1rem}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.media{display:flex;display:-webkit-flex;align-items:flex-start;-webkit-align-items:flex-start}.media-body{flex:1;-webkit-flex:1}.list-group{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,0.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#096B72;border-color:#096B72}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width: 576px){.list-group-horizontal-sm{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 768px){.list-group-horizontal-md{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 992px){.list-group-horizontal-lg{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 1200px){.list-group-horizontal-xl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-default{color:#737678;background-color:#f6f7f8}.list-group-item-default.list-group-item-action:hover,.list-group-item-default.list-group-item-action:focus{color:#737678;background-color:#e8eaed}.list-group-item-default.list-group-item-action.active{color:#fff;background-color:#737678;border-color:#737678}.list-group-item-primary{color:#05383b;background-color:#bad6d8}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#05383b;background-color:#aacccf}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#05383b;border-color:#05383b}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):hover,.close:not(:disabled):not(.disabled):focus{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{flex-basis:350px;-webkit-flex-basis:350px;max-width:350px;font-size:.875rem;background-color:rgba(255,255,255,0.85);background-clip:padding-box;border:1px solid rgba(0,0,0,0.1);box-shadow:0 0.25rem 0.75rem rgba(0,0,0,0.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show,.toast.in{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,0.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,0.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform 0.3s ease-out;transform:translate(0, -50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog,.modal.in .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;display:-webkit-flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-header,.modal-dialog-scrollable .modal-footer{flex-shrink:0;-webkit-flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:min-content;height:-webkit-min-content;height:-moz-min-content;height:-ms-min-content;height:-o-min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show,.modal-backdrop.in{opacity:.5}.modal-header{display:flex;display:-webkit-flex;align-items:flex-start;-webkit-align-items:flex-start;justify-content:space-between;-webkit-justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;padding:1rem}.modal-footer{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:flex-end;-webkit-justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:min-content;height:-webkit-min-content;height:-moz-min-content;height:-ms-min-content;height:-o-min-content}.modal-sm{max-width:300px}}@media (min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width: 1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show,.tooltip.in{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^="top"]{padding:.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^="top"] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^="top"] .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^="right"]{padding:0 .4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^="right"] .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^="right"] .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^="bottom"]{padding:.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^="bottom"] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^="bottom"] .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^="left"]{padding:0 .4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^="left"] .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^="left"] .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::before,.popover .arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-top,.bs-popover-auto[x-placement^="top"]{margin-bottom:.5rem}.bs-popover-top>.arrow,.bs-popover-auto[x-placement^="top"]>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-top>.arrow::before,.bs-popover-auto[x-placement^="top"]>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,0.25)}.bs-popover-top>.arrow::after,.bs-popover-auto[x-placement^="top"]>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-right,.bs-popover-auto[x-placement^="right"]{margin-left:.5rem}.bs-popover-right>.arrow,.bs-popover-auto[x-placement^="right"]>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-right>.arrow::before,.bs-popover-auto[x-placement^="right"]>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,0.25)}.bs-popover-right>.arrow::after,.bs-popover-auto[x-placement^="right"]>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-bottom,.bs-popover-auto[x-placement^="bottom"]{margin-top:.5rem}.bs-popover-bottom>.arrow,.bs-popover-auto[x-placement^="bottom"]>.arrow{top:calc(-.5rem - 1px)}.bs-popover-bottom>.arrow::before,.bs-popover-auto[x-placement^="bottom"]>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,0.25)}.bs-popover-bottom>.arrow::after,.bs-popover-auto[x-placement^="bottom"]>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[x-placement^="bottom"] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-left,.bs-popover-auto[x-placement^="left"]{margin-right:.5rem}.bs-popover-left>.arrow,.bs-popover-auto[x-placement^="left"]>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-left>.arrow::before,.bs-popover-auto[x-placement^="left"]>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,0.25)}.bs-popover-left>.arrow::after,.bs-popover-auto[x-placement^="left"]>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y;-webkit-touch-action:pan-y;-moz-touch-action:pan-y;-ms-touch-action:pan-y;-o-touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-left),.active.carousel-item-right{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-right),.active.carousel-item-left{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity 0.15s ease}@media (prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:20px;height:20px;background:50% / 100% 100% no-repeat}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:flex;display:-webkit-flex;justify-content:center;-webkit-justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;flex:0 1 auto;-webkit-flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity 0.6s ease}@media (prefers-reduced-motion: reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{animation-duration:1.5s;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s}}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.bg-default{background-color:#dee2e6 !important;color:#000}a.bg-default:hover,a.bg-default:focus,button.bg-default:hover,button.bg-default:focus{background-color:#c1c9d0 !important}.bg-primary{background-color:#096B72 !important;color:#fff}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#053f43 !important}.bg-secondary{background-color:#6c757d !important;color:#fff}a.bg-secondary:hover,a.bg-secondary:focus,button.bg-secondary:hover,button.bg-secondary:focus{background-color:#545b62 !important}.bg-success{background-color:#28a745 !important;color:#fff}a.bg-success:hover,a.bg-success:focus,button.bg-success:hover,button.bg-success:focus{background-color:#1e7e34 !important}.bg-info{background-color:#17a2b8 !important;color:#fff}a.bg-info:hover,a.bg-info:focus,button.bg-info:hover,button.bg-info:focus{background-color:#117a8b !important}.bg-warning{background-color:#ffc107 !important;color:#000}a.bg-warning:hover,a.bg-warning:focus,button.bg-warning:hover,button.bg-warning:focus{background-color:#d39e00 !important}.bg-danger{background-color:#dc3545 !important;color:#fff}a.bg-danger:hover,a.bg-danger:focus,button.bg-danger:hover,button.bg-danger:focus{background-color:#bd2130 !important}.bg-light{background-color:#f8f9fa !important;color:#000}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#dae0e5 !important}.bg-dark{background-color:#343a40 !important;color:#fff}a.bg-dark:hover,a.bg-dark:focus,button.bg-dark:hover,button.bg-dark:focus{background-color:#1d2124 !important}.bg-white{background-color:#fff !important;color:#000}.bg-transparent{background-color:transparent !important}.border{border:1px solid #dee2e6 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-right{border-right:1px solid #dee2e6 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-left{border-left:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top-0{border-top:0 !important}.border-right-0{border-right:0 !important}.border-bottom-0{border-bottom:0 !important}.border-left-0{border-left:0 !important}.border-default{border-color:#dee2e6 !important}.border-primary{border-color:#096B72 !important}.border-secondary{border-color:#6c757d !important}.border-success{border-color:#28a745 !important}.border-info{border-color:#17a2b8 !important}.border-warning{border-color:#ffc107 !important}.border-danger{border-color:#dc3545 !important}.border-light{border-color:#f8f9fa !important}.border-dark{border-color:#343a40 !important}.border-white{border-color:#fff !important}.rounded-sm{border-radius:.2rem !important}.rounded{border-radius:.25rem !important}.rounded-top{border-top-left-radius:.25rem !important;border-top-right-radius:.25rem !important}.rounded-right{border-top-right-radius:.25rem !important;border-bottom-right-radius:.25rem !important}.rounded-bottom{border-bottom-right-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-left{border-top-left-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-lg{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-0{border-radius:0 !important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}@media (min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}}@media (min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}}@media (min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}}@media (min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.85714%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-fill{flex:1 1 auto !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}@media (min-width: 576px){.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}}@media (min-width: 768px){.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}}@media (min-width: 992px){.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}}@media (min-width: 1200px){.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}}.float-left{float:left !important}.float-right{float:right !important}.float-none{float:none !important}@media (min-width: 576px){.float-sm-left{float:left !important}.float-sm-right{float:right !important}.float-sm-none{float:none !important}}@media (min-width: 768px){.float-md-left{float:left !important}.float-md-right{float:right !important}.float-md-none{float:none !important}}@media (min-width: 992px){.float-lg-left{float:left !important}.float-lg-right{float:right !important}.float-lg-none{float:none !important}}@media (min-width: 1200px){.float-xl-left{float:left !important}.float-xl-right{float:right !important}.float-xl-none{float:none !important}}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.fixed-top,.navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom,.navbar-fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports (position: sticky){.sticky-top,.navbar-sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important}.shadow{box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important}.shadow-none{box-shadow:none !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mw-100{max-width:100% !important}.mh-100{max-height:100% !important}.min-vw-100{min-width:100vw !important}.min-vh-100{min-height:100vh !important}.vw-100{width:100vw !important}.vh-100{height:100vh !important}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:.25rem !important}.mt-1,.my-1{margin-top:.25rem !important}.mr-1,.mx-1{margin-right:.25rem !important}.mb-1,.my-1{margin-bottom:.25rem !important}.ml-1,.mx-1{margin-left:.25rem !important}.m-2{margin:.5rem !important}.mt-2,.my-2{margin-top:.5rem !important}.mr-2,.mx-2{margin-right:.5rem !important}.mb-2,.my-2{margin-bottom:.5rem !important}.ml-2,.mx-2{margin-left:.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:.25rem !important}.pt-1,.py-1{padding-top:.25rem !important}.pr-1,.px-1{padding-right:.25rem !important}.pb-1,.py-1{padding-bottom:.25rem !important}.pl-1,.px-1{padding-left:.25rem !important}.p-2{padding:.5rem !important}.pt-2,.py-2{padding-top:.5rem !important}.pr-2,.px-2{padding-right:.5rem !important}.pb-2,.py-2{padding-bottom:.5rem !important}.pl-2,.px-2{padding-left:.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-n1{margin:-.25rem !important}.mt-n1,.my-n1{margin-top:-.25rem !important}.mr-n1,.mx-n1{margin-right:-.25rem !important}.mb-n1,.my-n1{margin-bottom:-.25rem !important}.ml-n1,.mx-n1{margin-left:-.25rem !important}.m-n2{margin:-.5rem !important}.mt-n2,.my-n2{margin-top:-.5rem !important}.mr-n2,.mx-n2{margin-right:-.5rem !important}.mb-n2,.my-n2{margin-bottom:-.5rem !important}.ml-n2,.mx-n2{margin-left:-.5rem !important}.m-n3{margin:-1rem !important}.mt-n3,.my-n3{margin-top:-1rem !important}.mr-n3,.mx-n3{margin-right:-1rem !important}.mb-n3,.my-n3{margin-bottom:-1rem !important}.ml-n3,.mx-n3{margin-left:-1rem !important}.m-n4{margin:-1.5rem !important}.mt-n4,.my-n4{margin-top:-1.5rem !important}.mr-n4,.mx-n4{margin-right:-1.5rem !important}.mb-n4,.my-n4{margin-bottom:-1.5rem !important}.ml-n4,.mx-n4{margin-left:-1.5rem !important}.m-n5{margin:-3rem !important}.mt-n5,.my-n5{margin-top:-3rem !important}.mr-n5,.mx-n5{margin-right:-3rem !important}.mb-n5,.my-n5{margin-bottom:-3rem !important}.ml-n5,.mx-n5{margin-left:-3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media (min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:.25rem !important}.mt-sm-1,.my-sm-1{margin-top:.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:.25rem !important}.m-sm-2{margin:.5rem !important}.mt-sm-2,.my-sm-2{margin-top:.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:.5rem !important}.m-sm-3{margin:1rem !important}.mt-sm-3,.my-sm-3{margin-top:1rem !important}.mr-sm-3,.mx-sm-3{margin-right:1rem !important}.mb-sm-3,.my-sm-3{margin-bottom:1rem !important}.ml-sm-3,.mx-sm-3{margin-left:1rem !important}.m-sm-4{margin:1.5rem !important}.mt-sm-4,.my-sm-4{margin-top:1.5rem !important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem !important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem !important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem !important}.m-sm-5{margin:3rem !important}.mt-sm-5,.my-sm-5{margin-top:3rem !important}.mr-sm-5,.mx-sm-5{margin-right:3rem !important}.mb-sm-5,.my-sm-5{margin-bottom:3rem !important}.ml-sm-5,.mx-sm-5{margin-left:3rem !important}.p-sm-0{padding:0 !important}.pt-sm-0,.py-sm-0{padding-top:0 !important}.pr-sm-0,.px-sm-0{padding-right:0 !important}.pb-sm-0,.py-sm-0{padding-bottom:0 !important}.pl-sm-0,.px-sm-0{padding-left:0 !important}.p-sm-1{padding:.25rem !important}.pt-sm-1,.py-sm-1{padding-top:.25rem !important}.pr-sm-1,.px-sm-1{padding-right:.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem !important}.pl-sm-1,.px-sm-1{padding-left:.25rem !important}.p-sm-2{padding:.5rem !important}.pt-sm-2,.py-sm-2{padding-top:.5rem !important}.pr-sm-2,.px-sm-2{padding-right:.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem !important}.pl-sm-2,.px-sm-2{padding-left:.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-n1{margin:-.25rem !important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem !important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem !important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem !important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem !important}.m-sm-n2{margin:-.5rem !important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem !important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem !important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem !important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem !important}.m-sm-n3{margin:-1rem !important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem !important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem !important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem !important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem !important}.m-sm-n4{margin:-1.5rem !important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem !important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem !important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem !important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem !important}.m-sm-n5{margin:-3rem !important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem !important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem !important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem !important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:.25rem !important}.mt-md-1,.my-md-1{margin-top:.25rem !important}.mr-md-1,.mx-md-1{margin-right:.25rem !important}.mb-md-1,.my-md-1{margin-bottom:.25rem !important}.ml-md-1,.mx-md-1{margin-left:.25rem !important}.m-md-2{margin:.5rem !important}.mt-md-2,.my-md-2{margin-top:.5rem !important}.mr-md-2,.mx-md-2{margin-right:.5rem !important}.mb-md-2,.my-md-2{margin-bottom:.5rem !important}.ml-md-2,.mx-md-2{margin-left:.5rem !important}.m-md-3{margin:1rem !important}.mt-md-3,.my-md-3{margin-top:1rem !important}.mr-md-3,.mx-md-3{margin-right:1rem !important}.mb-md-3,.my-md-3{margin-bottom:1rem !important}.ml-md-3,.mx-md-3{margin-left:1rem !important}.m-md-4{margin:1.5rem !important}.mt-md-4,.my-md-4{margin-top:1.5rem !important}.mr-md-4,.mx-md-4{margin-right:1.5rem !important}.mb-md-4,.my-md-4{margin-bottom:1.5rem !important}.ml-md-4,.mx-md-4{margin-left:1.5rem !important}.m-md-5{margin:3rem !important}.mt-md-5,.my-md-5{margin-top:3rem !important}.mr-md-5,.mx-md-5{margin-right:3rem !important}.mb-md-5,.my-md-5{margin-bottom:3rem !important}.ml-md-5,.mx-md-5{margin-left:3rem !important}.p-md-0{padding:0 !important}.pt-md-0,.py-md-0{padding-top:0 !important}.pr-md-0,.px-md-0{padding-right:0 !important}.pb-md-0,.py-md-0{padding-bottom:0 !important}.pl-md-0,.px-md-0{padding-left:0 !important}.p-md-1{padding:.25rem !important}.pt-md-1,.py-md-1{padding-top:.25rem !important}.pr-md-1,.px-md-1{padding-right:.25rem !important}.pb-md-1,.py-md-1{padding-bottom:.25rem !important}.pl-md-1,.px-md-1{padding-left:.25rem !important}.p-md-2{padding:.5rem !important}.pt-md-2,.py-md-2{padding-top:.5rem !important}.pr-md-2,.px-md-2{padding-right:.5rem !important}.pb-md-2,.py-md-2{padding-bottom:.5rem !important}.pl-md-2,.px-md-2{padding-left:.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-n1{margin:-.25rem !important}.mt-md-n1,.my-md-n1{margin-top:-.25rem !important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem !important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem !important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem !important}.m-md-n2{margin:-.5rem !important}.mt-md-n2,.my-md-n2{margin-top:-.5rem !important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem !important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem !important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem !important}.m-md-n3{margin:-1rem !important}.mt-md-n3,.my-md-n3{margin-top:-1rem !important}.mr-md-n3,.mx-md-n3{margin-right:-1rem !important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem !important}.ml-md-n3,.mx-md-n3{margin-left:-1rem !important}.m-md-n4{margin:-1.5rem !important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem !important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem !important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem !important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem !important}.m-md-n5{margin:-3rem !important}.mt-md-n5,.my-md-n5{margin-top:-3rem !important}.mr-md-n5,.mx-md-n5{margin-right:-3rem !important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem !important}.ml-md-n5,.mx-md-n5{margin-left:-3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media (min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:.25rem !important}.mt-lg-1,.my-lg-1{margin-top:.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:.25rem !important}.m-lg-2{margin:.5rem !important}.mt-lg-2,.my-lg-2{margin-top:.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:.5rem !important}.m-lg-3{margin:1rem !important}.mt-lg-3,.my-lg-3{margin-top:1rem !important}.mr-lg-3,.mx-lg-3{margin-right:1rem !important}.mb-lg-3,.my-lg-3{margin-bottom:1rem !important}.ml-lg-3,.mx-lg-3{margin-left:1rem !important}.m-lg-4{margin:1.5rem !important}.mt-lg-4,.my-lg-4{margin-top:1.5rem !important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem !important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem !important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem !important}.m-lg-5{margin:3rem !important}.mt-lg-5,.my-lg-5{margin-top:3rem !important}.mr-lg-5,.mx-lg-5{margin-right:3rem !important}.mb-lg-5,.my-lg-5{margin-bottom:3rem !important}.ml-lg-5,.mx-lg-5{margin-left:3rem !important}.p-lg-0{padding:0 !important}.pt-lg-0,.py-lg-0{padding-top:0 !important}.pr-lg-0,.px-lg-0{padding-right:0 !important}.pb-lg-0,.py-lg-0{padding-bottom:0 !important}.pl-lg-0,.px-lg-0{padding-left:0 !important}.p-lg-1{padding:.25rem !important}.pt-lg-1,.py-lg-1{padding-top:.25rem !important}.pr-lg-1,.px-lg-1{padding-right:.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem !important}.pl-lg-1,.px-lg-1{padding-left:.25rem !important}.p-lg-2{padding:.5rem !important}.pt-lg-2,.py-lg-2{padding-top:.5rem !important}.pr-lg-2,.px-lg-2{padding-right:.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem !important}.pl-lg-2,.px-lg-2{padding-left:.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-n1{margin:-.25rem !important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem !important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem !important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem !important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem !important}.m-lg-n2{margin:-.5rem !important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem !important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem !important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem !important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem !important}.m-lg-n3{margin:-1rem !important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem !important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem !important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem !important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem !important}.m-lg-n4{margin:-1.5rem !important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem !important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem !important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem !important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem !important}.m-lg-n5{margin:-3rem !important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem !important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem !important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem !important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media (min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:.25rem !important}.mt-xl-1,.my-xl-1{margin-top:.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:.25rem !important}.m-xl-2{margin:.5rem !important}.mt-xl-2,.my-xl-2{margin-top:.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:.5rem !important}.m-xl-3{margin:1rem !important}.mt-xl-3,.my-xl-3{margin-top:1rem !important}.mr-xl-3,.mx-xl-3{margin-right:1rem !important}.mb-xl-3,.my-xl-3{margin-bottom:1rem !important}.ml-xl-3,.mx-xl-3{margin-left:1rem !important}.m-xl-4{margin:1.5rem !important}.mt-xl-4,.my-xl-4{margin-top:1.5rem !important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem !important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem !important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem !important}.m-xl-5{margin:3rem !important}.mt-xl-5,.my-xl-5{margin-top:3rem !important}.mr-xl-5,.mx-xl-5{margin-right:3rem !important}.mb-xl-5,.my-xl-5{margin-bottom:3rem !important}.ml-xl-5,.mx-xl-5{margin-left:3rem !important}.p-xl-0{padding:0 !important}.pt-xl-0,.py-xl-0{padding-top:0 !important}.pr-xl-0,.px-xl-0{padding-right:0 !important}.pb-xl-0,.py-xl-0{padding-bottom:0 !important}.pl-xl-0,.px-xl-0{padding-left:0 !important}.p-xl-1{padding:.25rem !important}.pt-xl-1,.py-xl-1{padding-top:.25rem !important}.pr-xl-1,.px-xl-1{padding-right:.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem !important}.pl-xl-1,.px-xl-1{padding-left:.25rem !important}.p-xl-2{padding:.5rem !important}.pt-xl-2,.py-xl-2{padding-top:.5rem !important}.pr-xl-2,.px-xl-2{padding-right:.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem !important}.pl-xl-2,.px-xl-2{padding-left:.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-n1{margin:-.25rem !important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem !important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem !important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem !important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem !important}.m-xl-n2{margin:-.5rem !important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem !important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem !important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem !important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem !important}.m-xl-n3{margin:-1rem !important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem !important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem !important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem !important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem !important}.m-xl-n4{margin:-1.5rem !important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem !important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem !important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem !important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem !important}.m-xl-n5{margin:-3rem !important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem !important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem !important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem !important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace !important}.text-justify{text-align:justify !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}@media (min-width: 576px){.text-sm-left{text-align:left !important}.text-sm-right{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.text-md-left{text-align:left !important}.text-md-right{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.text-lg-left{text-align:left !important}.text-lg-right{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.text-xl-left{text-align:left !important}.text-xl-right{text-align:right !important}.text-xl-center{text-align:center !important}}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.font-weight-light{font-weight:300 !important}.font-weight-lighter{font-weight:lighter !important}.font-weight-normal{font-weight:400 !important}.font-weight-bold{font-weight:700 !important}.font-weight-bolder{font-weight:bolder !important}.font-italic{font-style:italic !important}.text-white{color:#fff !important}.text-default{color:#dee2e6 !important}a.text-default:hover,a.text-default:focus{color:#b2bcc5 !important}.text-primary{color:#096B72 !important}a.text-primary:hover,a.text-primary:focus{color:#03282b !important}.text-secondary{color:#6c757d !important}a.text-secondary:hover,a.text-secondary:focus{color:#494f54 !important}.text-success{color:#28a745 !important}a.text-success:hover,a.text-success:focus{color:#19692c !important}.text-info{color:#17a2b8 !important}a.text-info:hover,a.text-info:focus{color:#0f6674 !important}.text-warning{color:#ffc107 !important}a.text-warning:hover,a.text-warning:focus{color:#ba8b00 !important}.text-danger{color:#dc3545 !important}a.text-danger:hover,a.text-danger:focus{color:#a71d2a !important}.text-light{color:#f8f9fa !important}a.text-light:hover,a.text-light:focus{color:#cbd3da !important}.text-dark{color:#343a40 !important}a.text-dark:hover,a.text-dark:focus{color:#121416 !important}.text-body{color:#212529 !important}.text-muted,.help-text,.help-block{color:#6c757d !important}.text-black-50{color:rgba(0,0,0,0.5) !important}.text-white-50{color:rgba(255,255,255,0.5) !important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none !important}.text-break{word-break:break-word !important;word-wrap:break-word !important}.text-reset{color:inherit !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media print{*,*::before,*::after{text-shadow:none !important;box-shadow:none !important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap !important}pre,blockquote{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px !important}.container{min-width:992px !important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #dee2e6 !important}.table-dark{color:inherit}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}.table th[align=left]{text-align:left}.table th[align=right]{text-align:right}.table th[align=center]{text-align:center}.well{display:block;background-color:rgba(0,0,0,0.03);color:#212529;padding:1.25rem;border-radius:.25rem}.well-lg{padding:1.5rem;border-radius:.3rem}.well-sm{padding:0.5rem;border-radius:.2rem}.draggable .well{background-color:#f7f7f7}.dropdown-menu>li.active>a{color:#fff;text-decoration:none;background-color:#096B72}.navbar .nav.nav-underline{--bs-navbar-nav-link-padding-x: 0}.navbar:not(.fixed-bottom):not(.navbar-fixed-bottom):not(.navbar-fixed-bottom)+div>.tab-content>.tab-pane{--bslib-navbar-margin: 20px;margin-top:var(--bslib-navbar-margin)}ul.nav.navbar-nav{flex:1;-webkit-flex:1}ul.nav.navbar-nav.navbar-right{flex:unset;-webkit-flex:unset;display:flex;display:-webkit-flex;justify-content:flex-end;-webkit-justify-content:flex-end}:where(ul.nav.navbar-nav > li).active>a,:where(ul.nav.navbar-nav > li).show>a,.in:where(ul.nav.navbar-nav > li)>a{color:var(--bs-navbar-active-color)}:where(ul.nav.navbar-nav > li).bslib-nav-item{color:var(--bs-navbar-active-color)}:root{--bslib-navbar-light-bg: var(--bslib-navbar-default-bg, var(--bs-light));--bslib-navbar-dark-bg: var(--bslib-navbar-inverse-bg, var(--bs-black))}.navbar{--bslib-navbar-light-bg: #f8f9fa;--bslib-navbar-dark-bg: #343a40}.navbar.navbar-default{background-color:var(--bslib-navbar-light-bg) !important}.navbar.navbar-inverse{background-color:var(--bslib-navbar-dark-bg) !important}.navbar-toggle>.icon-bar{display:none}@media (max-width: 575.98px){.navbar-header{width:100%}.navbar-header .navbar-toggle{float:right}}.nav-tabs>li.active>a{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-pills>li.active>a{color:#fff;background-color:#096B72}.nav-stacked{flex-direction:column;-webkit-flex-direction:column}.progress-bar-default{background-color:#dee2e6;color:#000}.progress-bar-primary{background-color:#096B72;color:#fff}.progress-bar-secondary{background-color:#6c757d;color:#fff}.progress-bar-success{background-color:#28a745;color:#fff}.progress-bar-info{background-color:#17a2b8;color:#fff}.progress-bar-warning{background-color:#ffc107;color:#000}.progress-bar-danger{background-color:#dc3545;color:#fff}.progress-bar-light{background-color:#f8f9fa;color:#000}.progress-bar-dark{background-color:#343a40;color:#fff}@font-face{font-family:'Glyphicons Halflings';src:url("fonts/bootstrap/glyphicons-halflings-regular.eot");src:url("fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("fonts/bootstrap/glyphicons-halflings-regular.woff2") format("woff2"),url("fonts/bootstrap/glyphicons-halflings-regular.woff") format("woff"),url("fonts/bootstrap/glyphicons-halflings-regular.ttf") format("truetype"),url("fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}.form-group{margin-bottom:1rem}.shiny-input-checkboxgroup .checkbox-inline,.shiny-input-checkboxgroup .radio-inline,.shiny-input-radiogroup .checkbox-inline,.shiny-input-radiogroup .radio-inline{padding-left:0;margin-right:.75rem}.shiny-input-checkboxgroup .checkbox-inline label>input,.shiny-input-checkboxgroup .radio-inline label>input,.shiny-input-radiogroup .checkbox-inline label>input,.shiny-input-radiogroup .radio-inline label>input{margin-top:0;margin-right:.3125rem;margin-bottom:0}.input-daterange .input-group-addon.input-group-prepend.input-group-append{padding:inherit;line-height:inherit;text-shadow:inherit;border-width:0}.input-daterange .input-group-addon.input-group-prepend.input-group-append .input-group-text{border-radius:0}.shiny-input-checkboxgroup .checkbox-inline,.shiny-input-radiogroup .radio-inline{cursor:pointer}pre.shiny-code{padding:0.5rem}h1,h2,h3{margin-top:1.5rem}h4,h5,h6{margin-top:1rem}:root{--bslib-spacer: 1rem;--bslib-mb-spacer: var(--bslib-spacer, 1rem)}.bslib-mb-spacing{margin-bottom:var(--bslib-mb-spacer)}.bslib-gap-spacing{gap:var(--bslib-mb-spacer)}.bslib-gap-spacing>.bslib-mb-spacing,.bslib-gap-spacing>.form-group,.bslib-gap-spacing>p,.bslib-gap-spacing>pre,.bslib-gap-spacing>.shiny-html-output>.bslib-mb-spacing,.bslib-gap-spacing>.shiny-html-output>.form-group,.bslib-gap-spacing>.shiny-html-output>p,.bslib-gap-spacing>.shiny-html-output>pre,.bslib-gap-spacing>.shiny-panel-conditional>.bslib-mb-spacing,.bslib-gap-spacing>.shiny-panel-conditional>.form-group,.bslib-gap-spacing>.shiny-panel-conditional>p,.bslib-gap-spacing>.shiny-panel-conditional>pre{margin-bottom:0}.html-fill-container>.html-fill-item.bslib-mb-spacing{margin-bottom:0}.tab-content>.tab-pane.html-fill-container{display:none}.tab-content>.active.html-fill-container{display:flex}.tab-content.html-fill-container{padding:0} +:root{--bslib-bootstrap-version: 4;--bslib-preset-name: ;--bslib-preset-type: }:root{--blue: #007bff;--indigo: #6610f2;--purple: #6f42c1;--pink: #e83e8c;--red: #dc3545;--orange: #fd7e14;--yellow: #ffc107;--green: #28a745;--teal: #20c997;--cyan: #17a2b8;--white: #fff;--gray: #6c757d;--gray-dark: #343a40;--default: #dee2e6;--primary: #096B72;--secondary: #6c757d;--success: #28a745;--info: #17a2b8;--warning: #ffc107;--danger: #dc3545;--light: #f8f9fa;--dark: #343a40;--breakpoint-xs: 0;--breakpoint-sm: 576px;--breakpoint-md: 768px;--breakpoint-lg: 992px;--breakpoint-xl: 1200px;--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace}*,*::before,*::after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0 !important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[title],abbr[data-original-title]{text-decoration:underline;text-decoration:underline dotted;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;-ms-text-decoration:underline dotted;-o-text-decoration:underline dotted;cursor:help;border-bottom:0;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul,dl{margin-top:0;margin-bottom:1rem}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem;padding:.625rem 1.25rem;border-left:.25rem solid #e9ecef}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#096B72;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none;background-color:transparent}a:hover{color:#03282b;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}pre,code,kbd,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}input,button,select,optgroup,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role="button"]{cursor:pointer}select{word-wrap:normal}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button:not(:disabled),[type="button"]:not(:disabled),[type="reset"]:not(:disabled),[type="submit"]:not(:disabled){cursor:pointer}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{padding:0;border-style:none}input[type="radio"],input[type="checkbox"]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{outline-offset:-2px;-webkit-appearance:none}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none !important}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}h1,.h1{font-size:2.5rem}h2,.h2{font-size:2rem}h3,.h3{font-size:1.75rem}h4,.h4{font-size:1.5rem}h5,.h5{font-size:1.25rem}h6,.h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,0.1)}small,.small{font-size:80%;font-weight:400}mark,.mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014\00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code{font-size:87.5%;color:#000;background-color:#f6f6f6;border-radius:.25rem;padding:.125rem .25rem;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#000;background-color:#f6f6f6;padding:.5rem;border:1px solid #dee2e6;border-radius:.25rem}pre code{background-color:transparent;font-size:inherit;color:inherit;word-break:normal;padding:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,.container-fluid,.container-xl,.container-lg,.container-md,.container-sm{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container-sm,.container{max-width:540px}}@media (min-width: 768px){.container-md,.container-sm,.container{max-width:720px}}@media (min-width: 992px){.container-lg,.container-md,.container-sm,.container{max-width:960px}}@media (min-width: 1200px){.container-xl,.container-lg,.container-md,.container-sm,.container{max-width:1140px}}.row{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*="col-"]{padding-right:0;padding-left:0}.col-xl,.col-xl-auto,.col-xl-12,.col-xl-11,.col-xl-10,.col-xl-9,.col-xl-8,.col-xl-7,.col-xl-6,.col-xl-5,.col-xl-4,.col-xl-3,.col-xl-2,.col-xl-1,.col-lg,.col-lg-auto,.col-lg-12,.col-lg-11,.col-lg-10,.col-lg-9,.col-lg-8,.col-lg-7,.col-lg-6,.col-lg-5,.col-lg-4,.col-lg-3,.col-lg-2,.col-lg-1,.col-md,.col-md-auto,.col-md-12,.col-md-11,.col-md-10,.col-md-9,.col-md-8,.col-md-7,.col-md-6,.col-md-5,.col-md-4,.col-md-3,.col-md-2,.col-md-1,.col-sm,.col-sm-auto,.col-sm-12,.col-sm-11,.col-sm-10,.col-sm-9,.col-sm-8,.col-sm-7,.col-sm-6,.col-sm-5,.col-sm-4,.col-sm-3,.col-sm-2,.col-sm-1,.col,.col-auto,.col-12,.col-11,.col-10,.col-9,.col-8,.col-7,.col-6,.col-5,.col-4,.col-3,.col-2,.col-1{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-first{order:-1}.order-last{order:13}.order-0{order:0}.order-1{order:1}.order-2{order:2}.order-3{order:3}.order-4{order:4}.order-5{order:5}.order-6{order:6}.order-7{order:7}.order-8{order:8}.order-9{order:9}.order-10{order:10}.order-11{order:11}.order-12{order:12}.offset-1{margin-left:8.33333%}.offset-2{margin-left:16.66667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333%}.offset-5{margin-left:41.66667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333%}.offset-8{margin-left:66.66667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333%}.offset-11{margin-left:91.66667%}@media (min-width: 576px){.col-sm{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-sm-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-sm-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-sm-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-sm-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-sm-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-sm-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-sm-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-sm-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-sm-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-sm-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-sm-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-sm-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-sm-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-sm-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-sm-first{order:-1}.order-sm-last{order:13}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333%}.offset-sm-2{margin-left:16.66667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333%}.offset-sm-5{margin-left:41.66667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333%}.offset-sm-8{margin-left:66.66667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333%}.offset-sm-11{margin-left:91.66667%}}@media (min-width: 768px){.col-md{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-md-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-md-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-md-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-md-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-md-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-md-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-md-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-md-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-md-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-md-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-md-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-md-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-md-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-md-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-md-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-md-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-md-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-md-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-md-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-md-first{order:-1}.order-md-last{order:13}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333%}.offset-md-2{margin-left:16.66667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333%}.offset-md-5{margin-left:41.66667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333%}.offset-md-8{margin-left:66.66667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333%}.offset-md-11{margin-left:91.66667%}}@media (min-width: 992px){.col-lg{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-lg-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-lg-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-lg-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-lg-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-lg-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-lg-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-lg-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-lg-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-lg-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-lg-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-lg-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-lg-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-lg-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-lg-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-lg-first{order:-1}.order-lg-last{order:13}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333%}.offset-lg-2{margin-left:16.66667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333%}.offset-lg-5{margin-left:41.66667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333%}.offset-lg-8{margin-left:66.66667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333%}.offset-lg-11{margin-left:91.66667%}}@media (min-width: 1200px){.col-xl{flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;max-width:100%}.row-cols-xl-1>*{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.row-cols-xl-4>*{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{flex:0 0 20%;-webkit-flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-xl-auto{flex:0 0 auto;-webkit-flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{flex:0 0 8.33333%;-webkit-flex:0 0 8.33333%;max-width:8.33333%}.col-xl-2{flex:0 0 16.66667%;-webkit-flex:0 0 16.66667%;max-width:16.66667%}.col-xl-3{flex:0 0 25%;-webkit-flex:0 0 25%;max-width:25%}.col-xl-4{flex:0 0 33.33333%;-webkit-flex:0 0 33.33333%;max-width:33.33333%}.col-xl-5{flex:0 0 41.66667%;-webkit-flex:0 0 41.66667%;max-width:41.66667%}.col-xl-6{flex:0 0 50%;-webkit-flex:0 0 50%;max-width:50%}.col-xl-7{flex:0 0 58.33333%;-webkit-flex:0 0 58.33333%;max-width:58.33333%}.col-xl-8{flex:0 0 66.66667%;-webkit-flex:0 0 66.66667%;max-width:66.66667%}.col-xl-9{flex:0 0 75%;-webkit-flex:0 0 75%;max-width:75%}.col-xl-10{flex:0 0 83.33333%;-webkit-flex:0 0 83.33333%;max-width:83.33333%}.col-xl-11{flex:0 0 91.66667%;-webkit-flex:0 0 91.66667%;max-width:91.66667%}.col-xl-12{flex:0 0 100%;-webkit-flex:0 0 100%;max-width:100%}.order-xl-first{order:-1}.order-xl-last{order:13}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333%}.offset-xl-2{margin-left:16.66667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333%}.offset-xl-5{margin-left:41.66667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333%}.offset-xl-8{margin-left:66.66667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333%}.offset-xl-11{margin-left:91.66667%}}.table{width:100%;margin-bottom:1rem;color:#212529}.table th,.table td{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table-sm th,.table-sm td{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered th,.table-bordered td{border:1px solid #dee2e6}.table-bordered thead th,.table-bordered thead td{border-bottom-width:2px}.table-borderless th,.table-borderless td,.table-borderless thead th,.table-borderless tbody+tbody{border:0}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,0.05)}.table-hover tbody tr:hover{color:#212529;background-color:rgba(0,0,0,0.075)}.table-default,.table-default>th,.table-default>td{background-color:#f6f7f8}.table-default th,.table-default td,.table-default thead th,.table-default tbody+tbody{border-color:#eef0f2}.table-hover .table-default:hover{background-color:#e8eaed}.table-hover .table-default:hover>td,.table-hover .table-default:hover>th{background-color:#e8eaed}.table-primary,.table-primary>th,.table-primary>td{background-color:#bad6d8}.table-primary th,.table-primary td,.table-primary thead th,.table-primary tbody+tbody{border-color:#7fb2b6}.table-hover .table-primary:hover{background-color:#aacccf}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#aacccf}.table-secondary,.table-secondary>th,.table-secondary>td{background-color:#d6d8db}.table-secondary th,.table-secondary td,.table-secondary thead th,.table-secondary tbody+tbody{border-color:#b3b7bb}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>th,.table-success>td{background-color:#c3e6cb}.table-success th,.table-success td,.table-success thead th,.table-success tbody+tbody{border-color:#8fd19e}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>th,.table-info>td{background-color:#bee5eb}.table-info th,.table-info td,.table-info thead th,.table-info tbody+tbody{border-color:#86cfda}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>th,.table-warning>td{background-color:#ffeeba}.table-warning th,.table-warning td,.table-warning thead th,.table-warning tbody+tbody{border-color:#ffdf7e}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>th,.table-danger>td{background-color:#f5c6cb}.table-danger th,.table-danger td,.table-danger thead th,.table-danger tbody+tbody{border-color:#ed969e}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>th,.table-light>td{background-color:#fdfdfe}.table-light th,.table-light td,.table-light thead th,.table-light tbody+tbody{border-color:#fbfcfc}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>th,.table-dark>td{background-color:#c6c8ca}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#95999c}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>th,.table-active>td{background-color:rgba(0,0,0,0.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,0.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,0.075)}.table .thead-dark th{color:#fff;background-color:#343a40;border-color:#454d55}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#343a40}.table-dark th,.table-dark td,.table-dark thead th{border-color:#454d55}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,0.05)}.table-dark.table-hover tbody tr:hover{color:#fff;background-color:rgba(255,255,255,0.075)}@media (max-width: 575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-sm>.table-bordered{border:0}}@media (max-width: 767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-md>.table-bordered{border:0}}@media (max-width: 991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-lg>.table-bordered{border:0}}@media (max-width: 1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.form-control{transition:none}}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.form-control:focus{color:#495057;background-color:#fff;border-color:#12dae8;outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;font-size:1rem;line-height:1.5;color:#212529;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-sm,.form-control-plaintext.form-control-lg{padding-right:0;padding-left:0}.form-control-sm{height:calc(1.5em + .5rem + 2px);padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.form-control-lg{height:calc(1.5em + 1rem + 2px);padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}select.form-control[size],select.form-control[multiple]{height:auto}textarea.form-control{height:auto}.form-group{margin-bottom:1rem}.form-text,.help-text,.help-block{display:block;margin-top:.25rem}.form-row{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*="col-"]{padding-right:5px;padding-left:5px}.form-check,.shiny-input-checkboxgroup .checkbox,.shiny-input-checkboxgroup .radio,.shiny-input-radiogroup .checkbox,.shiny-input-radiogroup .radio{position:relative;display:block;padding-left:1.25rem}.form-check-input,.shiny-input-checkboxgroup .checkbox label>input,.shiny-input-checkboxgroup .radio label>input,.shiny-input-radiogroup .checkbox label>input,.shiny-input-radiogroup .radio label>input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input[disabled]~.form-check-label,.shiny-input-checkboxgroup .checkbox label>input[disabled]~.form-check-label,.shiny-input-checkboxgroup .radio label>input[disabled]~.form-check-label,.shiny-input-radiogroup .checkbox label>input[disabled]~.form-check-label,.shiny-input-radiogroup .radio label>input[disabled]~.form-check-label,.shiny-input-checkboxgroup .checkbox .form-check-input[disabled]~label,.shiny-input-checkboxgroup .checkbox label>input[disabled]~label,.shiny-input-checkboxgroup .radio .form-check-input[disabled]~label,.shiny-input-checkboxgroup .radio label>input[disabled]~label,.shiny-input-radiogroup .checkbox .form-check-input[disabled]~label,.shiny-input-radiogroup .checkbox label>input[disabled]~label,.shiny-input-radiogroup .radio .form-check-input[disabled]~label,.shiny-input-radiogroup .radio label>input[disabled]~label,.form-check-input:disabled~.form-check-label,.shiny-input-checkboxgroup .checkbox label>input:disabled~.form-check-label,.shiny-input-checkboxgroup .radio label>input:disabled~.form-check-label,.shiny-input-radiogroup .checkbox label>input:disabled~.form-check-label,.shiny-input-radiogroup .radio label>input:disabled~.form-check-label,.shiny-input-checkboxgroup .checkbox .form-check-input:disabled~label,.shiny-input-checkboxgroup .checkbox label>input:disabled~label,.shiny-input-checkboxgroup .radio .form-check-input:disabled~label,.shiny-input-checkboxgroup .radio label>input:disabled~label,.shiny-input-radiogroup .checkbox .form-check-input:disabled~label,.shiny-input-radiogroup .checkbox label>input:disabled~label,.shiny-input-radiogroup .radio .form-check-input:disabled~label,.shiny-input-radiogroup .radio label>input:disabled~label{color:#6c757d}.form-check-label,.shiny-input-checkboxgroup .checkbox label,.shiny-input-checkboxgroup .radio label,.shiny-input-radiogroup .checkbox label,.shiny-input-radiogroup .radio label{margin-bottom:0}.form-check-inline{display:inline-flex;align-items:center;-webkit-align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input,.form-check-inline .shiny-input-checkboxgroup .checkbox label>input,.shiny-input-checkboxgroup .checkbox .form-check-inline label>input,.form-check-inline .shiny-input-checkboxgroup .radio label>input,.shiny-input-checkboxgroup .radio .form-check-inline label>input,.form-check-inline .shiny-input-radiogroup .checkbox label>input,.shiny-input-radiogroup .checkbox .form-check-inline label>input,.form-check-inline .shiny-input-radiogroup .radio label>input,.shiny-input-radiogroup .radio .form-check-inline label>input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(40,167,69,0.9);border-radius:.25rem}.form-row>.col>.valid-tooltip,.form-row>[class*="col-"]>.valid-tooltip{left:5px}.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip,.is-valid~.valid-feedback,.is-valid~.valid-tooltip{display:block}.was-validated .form-control:valid,.form-control.is-valid{border-color:#28a745;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:valid:focus,.form-control.is-valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,0.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .custom-select:valid,.custom-select.is-valid{border-color:#28a745;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.was-validated .custom-select:valid:focus,.custom-select.is-valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,0.25)}.was-validated .form-check-input:valid~.form-check-label,.was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~.form-check-label,.shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~.form-check-label,.was-validated .shiny-input-checkboxgroup .radio label>input:valid~.form-check-label,.shiny-input-checkboxgroup .radio .was-validated label>input:valid~.form-check-label,.was-validated .shiny-input-radiogroup .checkbox label>input:valid~.form-check-label,.shiny-input-radiogroup .checkbox .was-validated label>input:valid~.form-check-label,.was-validated .shiny-input-radiogroup .radio label>input:valid~.form-check-label,.shiny-input-radiogroup .radio .was-validated label>input:valid~.form-check-label,.was-validated .shiny-input-checkboxgroup .checkbox .form-check-input:valid~label,.was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~label,.was-validated .shiny-input-checkboxgroup .checkbox .radio label>input:valid~label,.was-validated .shiny-input-checkboxgroup .radio .checkbox label>input:valid~label,.was-validated .shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input:valid~label,.shiny-input-radiogroup .was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~label,.was-validated .shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input:valid~label,.shiny-input-radiogroup .radio .was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated .form-check-input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated .radio label>input:valid~label,.shiny-input-checkboxgroup .radio .checkbox .was-validated label>input:valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox .was-validated label>input:valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated .shiny-input-radiogroup .radio label>input:valid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~label,.was-validated .shiny-input-checkboxgroup .radio .form-check-input:valid~label,.was-validated .shiny-input-checkboxgroup .radio .checkbox label>input:valid~label,.was-validated .shiny-input-checkboxgroup .checkbox .radio label>input:valid~label,.was-validated .shiny-input-checkboxgroup .radio label>input:valid~label,.was-validated .shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated .shiny-input-checkboxgroup .radio label>input:valid~label,.was-validated .shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input:valid~label,.shiny-input-radiogroup .was-validated .shiny-input-checkboxgroup .radio label>input:valid~label,.shiny-input-checkboxgroup .radio .was-validated .form-check-input:valid~label,.shiny-input-checkboxgroup .radio .was-validated .checkbox label>input:valid~label,.shiny-input-checkboxgroup .checkbox .radio .was-validated label>input:valid~label,.shiny-input-checkboxgroup .radio .was-validated label>input:valid~label,.shiny-input-checkboxgroup .radio .was-validated .shiny-input-radiogroup .checkbox label>input:valid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio .was-validated label>input:valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio .was-validated label>input:valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio .was-validated label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox .form-check-input:valid~label,.was-validated .shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input:valid~label,.shiny-input-checkboxgroup .was-validated .shiny-input-radiogroup .checkbox label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input:valid~label,.shiny-input-checkboxgroup .radio .was-validated .shiny-input-radiogroup .checkbox label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox .radio label>input:valid~label,.was-validated .shiny-input-radiogroup .radio .checkbox label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated .form-check-input:valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox .was-validated label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated .shiny-input-checkboxgroup .radio label>input:valid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox .was-validated label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated label>input:valid~label,.shiny-input-radiogroup .checkbox .was-validated .radio label>input:valid~label,.shiny-input-radiogroup .radio .checkbox .was-validated label>input:valid~label,.was-validated .shiny-input-radiogroup .radio .form-check-input:valid~label,.was-validated .shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input:valid~label,.shiny-input-checkboxgroup .checkbox .was-validated .shiny-input-radiogroup .radio label>input:valid~label,.was-validated .shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input:valid~label,.shiny-input-checkboxgroup .was-validated .shiny-input-radiogroup .radio label>input:valid~label,.was-validated .shiny-input-radiogroup .radio .checkbox label>input:valid~label,.was-validated .shiny-input-radiogroup .checkbox .radio label>input:valid~label,.was-validated .shiny-input-radiogroup .radio label>input:valid~label,.shiny-input-radiogroup .radio .was-validated .form-check-input:valid~label,.shiny-input-radiogroup .radio .was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio .was-validated label>input:valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio .was-validated label>input:valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio .was-validated label>input:valid~label,.shiny-input-radiogroup .radio .was-validated .checkbox label>input:valid~label,.shiny-input-radiogroup .checkbox .radio .was-validated label>input:valid~label,.shiny-input-radiogroup .radio .was-validated label>input:valid~label,.form-check-input.is-valid~.form-check-label,.shiny-input-checkboxgroup .checkbox label>input.is-valid~.form-check-label,.shiny-input-checkboxgroup .radio label>input.is-valid~.form-check-label,.shiny-input-radiogroup .checkbox label>input.is-valid~.form-check-label,.shiny-input-radiogroup .radio label>input.is-valid~.form-check-label,.shiny-input-checkboxgroup .checkbox .form-check-input.is-valid~label,.shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .checkbox .radio label>input.is-valid~label,.shiny-input-checkboxgroup .radio .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input.is-valid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .radio .form-check-input.is-valid~label,.shiny-input-checkboxgroup .radio .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .checkbox .radio label>input.is-valid~label,.shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input.is-valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-radiogroup .checkbox .form-check-input.is-valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox .radio label>input.is-valid~label,.shiny-input-radiogroup .radio .checkbox label>input.is-valid~label,.shiny-input-radiogroup .radio .form-check-input.is-valid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input.is-valid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input.is-valid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input.is-valid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input.is-valid~label,.shiny-input-radiogroup .radio .checkbox label>input.is-valid~label,.shiny-input-radiogroup .checkbox .radio label>input.is-valid~label,.shiny-input-radiogroup .radio label>input.is-valid~label{color:#28a745}.was-validated .form-check-input:valid~.valid-feedback,.was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~.valid-feedback,.shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~.valid-feedback,.was-validated .shiny-input-checkboxgroup .radio label>input:valid~.valid-feedback,.shiny-input-checkboxgroup .radio .was-validated label>input:valid~.valid-feedback,.was-validated .shiny-input-radiogroup .checkbox label>input:valid~.valid-feedback,.shiny-input-radiogroup .checkbox .was-validated label>input:valid~.valid-feedback,.was-validated .shiny-input-radiogroup .radio label>input:valid~.valid-feedback,.shiny-input-radiogroup .radio .was-validated label>input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip,.was-validated .shiny-input-checkboxgroup .checkbox label>input:valid~.valid-tooltip,.shiny-input-checkboxgroup .checkbox .was-validated label>input:valid~.valid-tooltip,.was-validated .shiny-input-checkboxgroup .radio label>input:valid~.valid-tooltip,.shiny-input-checkboxgroup .radio .was-validated label>input:valid~.valid-tooltip,.was-validated .shiny-input-radiogroup .checkbox label>input:valid~.valid-tooltip,.shiny-input-radiogroup .checkbox .was-validated label>input:valid~.valid-tooltip,.was-validated .shiny-input-radiogroup .radio label>input:valid~.valid-tooltip,.shiny-input-radiogroup .radio .was-validated label>input:valid~.valid-tooltip,.form-check-input.is-valid~.valid-feedback,.shiny-input-checkboxgroup .checkbox label>input.is-valid~.valid-feedback,.shiny-input-checkboxgroup .radio label>input.is-valid~.valid-feedback,.shiny-input-radiogroup .checkbox label>input.is-valid~.valid-feedback,.shiny-input-radiogroup .radio label>input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.shiny-input-checkboxgroup .checkbox label>input.is-valid~.valid-tooltip,.shiny-input-checkboxgroup .radio label>input.is-valid~.valid-tooltip,.shiny-input-radiogroup .checkbox label>input.is-valid~.valid-tooltip,.shiny-input-radiogroup .radio label>input.is-valid~.valid-tooltip{display:block}.was-validated .custom-control-input:valid~.custom-control-label,.custom-control-input.is-valid~.custom-control-label{color:#28a745}.was-validated .custom-control-input:valid~.custom-control-label::before,.custom-control-input.is-valid~.custom-control-label::before{border-color:#28a745}.was-validated .custom-control-input:valid:checked~.custom-control-label::before,.custom-control-input.is-valid:checked~.custom-control-label::before{border-color:#34ce57;background-color:#34ce57}.was-validated .custom-control-input:valid:focus~.custom-control-label::before,.custom-control-input.is-valid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(40,167,69,0.25)}.was-validated .custom-control-input:valid:focus:not(:checked)~.custom-control-label::before,.custom-control-input.is-valid:focus:not(:checked)~.custom-control-label::before{border-color:#28a745}.was-validated .custom-file-input:valid~.custom-file-label,.custom-file-input.is-valid~.custom-file-label{border-color:#28a745}.was-validated .custom-file-input:valid:focus~.custom-file-label,.custom-file-input.is-valid:focus~.custom-file-label{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,0.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;left:0;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;line-height:1.5;color:#fff;background-color:rgba(220,53,69,0.9);border-radius:.25rem}.form-row>.col>.invalid-tooltip,.form-row>[class*="col-"]>.invalid-tooltip{left:5px}.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip,.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip{display:block}.was-validated .form-control:invalid,.form-control.is-invalid{border-color:#dc3545;padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.was-validated .form-control:invalid:focus,.form-control.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.was-validated .custom-select:invalid,.custom-select.is-invalid{border-color:#dc3545;padding-right:calc(.75em + 2.3125rem);background:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat,#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(.75em + .375rem) calc(.75em + .375rem) no-repeat}.was-validated .custom-select:invalid:focus,.custom-select.is-invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated .form-check-input:invalid~.form-check-label,.was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~.form-check-label,.shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~.form-check-label,.was-validated .shiny-input-checkboxgroup .radio label>input:invalid~.form-check-label,.shiny-input-checkboxgroup .radio .was-validated label>input:invalid~.form-check-label,.was-validated .shiny-input-radiogroup .checkbox label>input:invalid~.form-check-label,.shiny-input-radiogroup .checkbox .was-validated label>input:invalid~.form-check-label,.was-validated .shiny-input-radiogroup .radio label>input:invalid~.form-check-label,.shiny-input-radiogroup .radio .was-validated label>input:invalid~.form-check-label,.was-validated .shiny-input-checkboxgroup .checkbox .form-check-input:invalid~label,.was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .checkbox .radio label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio .checkbox label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input:invalid~label,.shiny-input-radiogroup .was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input:invalid~label,.shiny-input-radiogroup .radio .was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated .form-check-input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated .radio label>input:invalid~label,.shiny-input-checkboxgroup .radio .checkbox .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox .was-validated label>input:invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated .shiny-input-radiogroup .radio label>input:invalid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio .form-check-input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio .checkbox label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .checkbox .radio label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated .shiny-input-checkboxgroup .radio label>input:invalid~label,.was-validated .shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input:invalid~label,.shiny-input-radiogroup .was-validated .shiny-input-checkboxgroup .radio label>input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated .form-check-input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .radio .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated .shiny-input-radiogroup .checkbox label>input:invalid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio .was-validated label>input:invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio .was-validated label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox .form-check-input:invalid~label,.was-validated .shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .was-validated .shiny-input-radiogroup .checkbox label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input:invalid~label,.shiny-input-checkboxgroup .radio .was-validated .shiny-input-radiogroup .checkbox label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox .radio label>input:invalid~label,.was-validated .shiny-input-radiogroup .radio .checkbox label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated .form-check-input:invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox .was-validated label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated .shiny-input-checkboxgroup .radio label>input:invalid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox .was-validated label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated label>input:invalid~label,.shiny-input-radiogroup .checkbox .was-validated .radio label>input:invalid~label,.shiny-input-radiogroup .radio .checkbox .was-validated label>input:invalid~label,.was-validated .shiny-input-radiogroup .radio .form-check-input:invalid~label,.was-validated .shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .was-validated .shiny-input-radiogroup .radio label>input:invalid~label,.was-validated .shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input:invalid~label,.shiny-input-checkboxgroup .was-validated .shiny-input-radiogroup .radio label>input:invalid~label,.was-validated .shiny-input-radiogroup .radio .checkbox label>input:invalid~label,.was-validated .shiny-input-radiogroup .checkbox .radio label>input:invalid~label,.was-validated .shiny-input-radiogroup .radio label>input:invalid~label,.shiny-input-radiogroup .radio .was-validated .form-check-input:invalid~label,.shiny-input-radiogroup .radio .was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio .was-validated label>input:invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio .was-validated label>input:invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio .was-validated label>input:invalid~label,.shiny-input-radiogroup .radio .was-validated .checkbox label>input:invalid~label,.shiny-input-radiogroup .checkbox .radio .was-validated label>input:invalid~label,.shiny-input-radiogroup .radio .was-validated label>input:invalid~label,.form-check-input.is-invalid~.form-check-label,.shiny-input-checkboxgroup .checkbox label>input.is-invalid~.form-check-label,.shiny-input-checkboxgroup .radio label>input.is-invalid~.form-check-label,.shiny-input-radiogroup .checkbox label>input.is-invalid~.form-check-label,.shiny-input-radiogroup .radio label>input.is-invalid~.form-check-label,.shiny-input-checkboxgroup .checkbox .form-check-input.is-invalid~label,.shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .checkbox .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .radio .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .radio .form-check-input.is-invalid~label,.shiny-input-checkboxgroup .radio .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .checkbox .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .form-check-input.is-invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .radio .shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .radio label>input.is-invalid~label,.shiny-input-radiogroup .radio .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .radio .form-check-input.is-invalid~label,.shiny-input-radiogroup .radio .shiny-input-checkboxgroup .checkbox label>input.is-invalid~label,.shiny-input-checkboxgroup .checkbox .shiny-input-radiogroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .shiny-input-checkboxgroup .radio label>input.is-invalid~label,.shiny-input-checkboxgroup .shiny-input-radiogroup .radio label>input.is-invalid~label,.shiny-input-radiogroup .radio .checkbox label>input.is-invalid~label,.shiny-input-radiogroup .checkbox .radio label>input.is-invalid~label,.shiny-input-radiogroup .radio label>input.is-invalid~label{color:#dc3545}.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~.invalid-feedback,.shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~.invalid-feedback,.was-validated .shiny-input-checkboxgroup .radio label>input:invalid~.invalid-feedback,.shiny-input-checkboxgroup .radio .was-validated label>input:invalid~.invalid-feedback,.was-validated .shiny-input-radiogroup .checkbox label>input:invalid~.invalid-feedback,.shiny-input-radiogroup .checkbox .was-validated label>input:invalid~.invalid-feedback,.was-validated .shiny-input-radiogroup .radio label>input:invalid~.invalid-feedback,.shiny-input-radiogroup .radio .was-validated label>input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip,.was-validated .shiny-input-checkboxgroup .checkbox label>input:invalid~.invalid-tooltip,.shiny-input-checkboxgroup .checkbox .was-validated label>input:invalid~.invalid-tooltip,.was-validated .shiny-input-checkboxgroup .radio label>input:invalid~.invalid-tooltip,.shiny-input-checkboxgroup .radio .was-validated label>input:invalid~.invalid-tooltip,.was-validated .shiny-input-radiogroup .checkbox label>input:invalid~.invalid-tooltip,.shiny-input-radiogroup .checkbox .was-validated label>input:invalid~.invalid-tooltip,.was-validated .shiny-input-radiogroup .radio label>input:invalid~.invalid-tooltip,.shiny-input-radiogroup .radio .was-validated label>input:invalid~.invalid-tooltip,.form-check-input.is-invalid~.invalid-feedback,.shiny-input-checkboxgroup .checkbox label>input.is-invalid~.invalid-feedback,.shiny-input-checkboxgroup .radio label>input.is-invalid~.invalid-feedback,.shiny-input-radiogroup .checkbox label>input.is-invalid~.invalid-feedback,.shiny-input-radiogroup .radio label>input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.shiny-input-checkboxgroup .checkbox label>input.is-invalid~.invalid-tooltip,.shiny-input-checkboxgroup .radio label>input.is-invalid~.invalid-tooltip,.shiny-input-radiogroup .checkbox label>input.is-invalid~.invalid-tooltip,.shiny-input-radiogroup .radio label>input.is-invalid~.invalid-tooltip{display:block}.was-validated .custom-control-input:invalid~.custom-control-label,.custom-control-input.is-invalid~.custom-control-label{color:#dc3545}.was-validated .custom-control-input:invalid~.custom-control-label::before,.custom-control-input.is-invalid~.custom-control-label::before{border-color:#dc3545}.was-validated .custom-control-input:invalid:checked~.custom-control-label::before,.custom-control-input.is-invalid:checked~.custom-control-label::before{border-color:#e4606d;background-color:#e4606d}.was-validated .custom-control-input:invalid:focus~.custom-control-label::before,.custom-control-input.is-invalid:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.was-validated .custom-control-input:invalid:focus:not(:checked)~.custom-control-label::before,.custom-control-input.is-invalid:focus:not(:checked)~.custom-control-label::before{border-color:#dc3545}.was-validated .custom-file-input:invalid~.custom-file-label,.custom-file-input.is-invalid~.custom-file-label{border-color:#dc3545}.was-validated .custom-file-input:invalid:focus~.custom-file-label,.custom-file-input.is-invalid:focus~.custom-file-label{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,0.25)}.form-inline{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap;align-items:center;-webkit-align-items:center}.form-inline .form-check,.form-inline .shiny-input-checkboxgroup .checkbox,.shiny-input-checkboxgroup .form-inline .checkbox,.form-inline .shiny-input-checkboxgroup .radio,.shiny-input-checkboxgroup .form-inline .radio,.form-inline .shiny-input-radiogroup .checkbox,.shiny-input-radiogroup .form-inline .checkbox,.form-inline .shiny-input-radiogroup .radio,.shiny-input-radiogroup .form-inline .radio{width:100%}@media (min-width: 576px){.form-inline label{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;margin-bottom:0}.form-inline .form-group{display:flex;display:-webkit-flex;flex:0 0 auto;-webkit-flex:0 0 auto;flex-flow:row wrap;-webkit-flex-flow:row wrap;align-items:center;-webkit-align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group,.form-inline .custom-select{width:auto}.form-inline .form-check,.form-inline .shiny-input-checkboxgroup .checkbox,.shiny-input-checkboxgroup .form-inline .checkbox,.form-inline .shiny-input-checkboxgroup .radio,.shiny-input-checkboxgroup .form-inline .radio,.form-inline .shiny-input-radiogroup .checkbox,.shiny-input-radiogroup .form-inline .checkbox,.form-inline .shiny-input-radiogroup .radio,.shiny-input-radiogroup .form-inline .radio{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input,.form-inline .shiny-input-checkboxgroup .checkbox label>input,.shiny-input-checkboxgroup .checkbox .form-inline label>input,.form-inline .shiny-input-checkboxgroup .radio label>input,.shiny-input-checkboxgroup .radio .form-inline label>input,.form-inline .shiny-input-radiogroup .checkbox label>input,.shiny-input-radiogroup .checkbox .form-inline label>input,.form-inline .shiny-input-radiogroup .radio label>input,.shiny-input-radiogroup .radio .form-inline label>input{position:relative;flex-shrink:0;-webkit-flex-shrink:0;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;color:#212529;text-align:center;vertical-align:middle;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;background-color:transparent;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.btn{transition:none}}.btn:hover{color:#212529;text-decoration:none}.btn:focus,.btn.focus{outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-default{color:#000;background-color:#dee2e6;border-color:#dee2e6}.btn-default:hover{color:#000;background-color:#c8cfd6;border-color:#c1c9d0}.btn-default:focus,.btn-default.focus{color:#000;background-color:#c8cfd6;border-color:#c1c9d0;box-shadow:0 0 0 .2rem rgba(189,192,196,0.5)}.btn-default.disabled,.btn-default:disabled{color:#000;background-color:#dee2e6;border-color:#dee2e6}.btn-default:not(:disabled):not(.disabled):active,.btn-default:not(:disabled):not(.disabled).active,.show>.btn-default.dropdown-toggle,.in>.btn-default.dropdown-toggle{color:#000;background-color:#c1c9d0;border-color:#bac2cb}.btn-default:not(:disabled):not(.disabled):active:focus,.btn-default:not(:disabled):not(.disabled).active:focus,.show>.btn-default.dropdown-toggle:focus,.in>.btn-default.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(189,192,196,0.5)}.btn-primary{color:#fff;background-color:#096B72;border-color:#096B72}.btn-primary:hover{color:#fff;background-color:#064a4f;border-color:#053f43}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#064a4f;border-color:#053f43;box-shadow:0 0 0 .2rem rgba(46,129,135,0.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#096B72;border-color:#096B72}.btn-primary:not(:disabled):not(.disabled):active,.btn-primary:not(:disabled):not(.disabled).active,.show>.btn-primary.dropdown-toggle,.in>.btn-primary.dropdown-toggle{color:#fff;background-color:#053f43;border-color:#043437}.btn-primary:not(:disabled):not(.disabled):active:focus,.btn-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-primary.dropdown-toggle:focus,.in>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(46,129,135,0.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary:focus,.btn-secondary.focus{color:#fff;background-color:#5a6268;border-color:#545b62;box-shadow:0 0 0 .2rem rgba(130,138,145,0.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled):active,.btn-secondary:not(:disabled):not(.disabled).active,.show>.btn-secondary.dropdown-toggle,.in>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled):active:focus,.btn-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-secondary.dropdown-toggle:focus,.in>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(130,138,145,0.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#218838;border-color:#1e7e34;box-shadow:0 0 0 .2rem rgba(72,180,97,0.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled):active,.btn-success:not(:disabled):not(.disabled).active,.show>.btn-success.dropdown-toggle,.in>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled):active:focus,.btn-success:not(:disabled):not(.disabled).active:focus,.show>.btn-success.dropdown-toggle:focus,.in>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(72,180,97,0.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#138496;border-color:#117a8b;box-shadow:0 0 0 .2rem rgba(58,176,195,0.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled):active,.btn-info:not(:disabled):not(.disabled).active,.show>.btn-info.dropdown-toggle,.in>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled):active:focus,.btn-info:not(:disabled):not(.disabled).active:focus,.show>.btn-info.dropdown-toggle:focus,.in>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(58,176,195,0.5)}.btn-warning{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#000;background-color:#e0a800;border-color:#d39e00}.btn-warning:focus,.btn-warning.focus{color:#000;background-color:#e0a800;border-color:#d39e00;box-shadow:0 0 0 .2rem rgba(217,164,6,0.5)}.btn-warning.disabled,.btn-warning:disabled{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled):active,.btn-warning:not(:disabled):not(.disabled).active,.show>.btn-warning.dropdown-toggle,.in>.btn-warning.dropdown-toggle{color:#000;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled):active:focus,.btn-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-warning.dropdown-toggle:focus,.in>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(217,164,6,0.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c82333;border-color:#bd2130;box-shadow:0 0 0 .2rem rgba(225,83,97,0.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled):active,.btn-danger:not(:disabled):not(.disabled).active,.show>.btn-danger.dropdown-toggle,.in>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled):active:focus,.btn-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-danger.dropdown-toggle:focus,.in>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(225,83,97,0.5)}.btn-light{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#000;background-color:#e2e6ea;border-color:#dae0e5}.btn-light:focus,.btn-light.focus{color:#000;background-color:#e2e6ea;border-color:#dae0e5;box-shadow:0 0 0 .2rem rgba(211,212,213,0.5)}.btn-light.disabled,.btn-light:disabled{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled):active,.btn-light:not(:disabled):not(.disabled).active,.show>.btn-light.dropdown-toggle,.in>.btn-light.dropdown-toggle{color:#000;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled):active:focus,.btn-light:not(:disabled):not(.disabled).active:focus,.show>.btn-light.dropdown-toggle:focus,.in>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(211,212,213,0.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark:focus,.btn-dark.focus{color:#fff;background-color:#23272b;border-color:#1d2124;box-shadow:0 0 0 .2rem rgba(82,88,93,0.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled):active,.btn-dark:not(:disabled):not(.disabled).active,.show>.btn-dark.dropdown-toggle,.in>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled):active:focus,.btn-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-dark.dropdown-toggle:focus,.in>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(82,88,93,0.5)}.btn-outline-default{color:#dee2e6;border-color:#dee2e6;background-color:transparent}.btn-outline-default:hover{color:#000;background-color:#dee2e6;border-color:#dee2e6}.btn-outline-default:focus,.btn-outline-default.focus{box-shadow:0 0 0 .2rem rgba(222,226,230,0.5)}.btn-outline-default.disabled,.btn-outline-default:disabled{color:#dee2e6;background-color:transparent}.btn-outline-default:not(:disabled):not(.disabled):active,.btn-outline-default:not(:disabled):not(.disabled).active,.show>.btn-outline-default.dropdown-toggle,.in>.btn-outline-default.dropdown-toggle{color:#000;background-color:#dee2e6;border-color:#dee2e6}.btn-outline-default:not(:disabled):not(.disabled):active:focus,.btn-outline-default:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-default.dropdown-toggle:focus,.in>.btn-outline-default.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(222,226,230,0.5)}.btn-outline-primary{color:#096B72;border-color:#096B72;background-color:transparent}.btn-outline-primary:hover{color:#fff;background-color:#096B72;border-color:#096B72}.btn-outline-primary:focus,.btn-outline-primary.focus{box-shadow:0 0 0 .2rem rgba(9,107,114,0.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#096B72;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled):active,.btn-outline-primary:not(:disabled):not(.disabled).active,.show>.btn-outline-primary.dropdown-toggle,.in>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#096B72;border-color:#096B72}.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-primary.dropdown-toggle:focus,.in>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(9,107,114,0.5)}.btn-outline-secondary{color:#6c757d;border-color:#6c757d;background-color:transparent}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:focus,.btn-outline-secondary.focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled):active,.btn-outline-secondary:not(:disabled):not(.disabled).active,.show>.btn-outline-secondary.dropdown-toggle,.in>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus,.in>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.btn-outline-success{color:#28a745;border-color:#28a745;background-color:transparent}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:focus,.btn-outline-success.focus{box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled):active,.btn-outline-success:not(:disabled):not(.disabled).active,.show>.btn-outline-success.dropdown-toggle,.in>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled):active:focus,.btn-outline-success:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-success.dropdown-toggle:focus,.in>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.btn-outline-info{color:#17a2b8;border-color:#17a2b8;background-color:transparent}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:focus,.btn-outline-info.focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled):active,.btn-outline-info:not(:disabled):not(.disabled).active,.show>.btn-outline-info.dropdown-toggle,.in>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled):active:focus,.btn-outline-info:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-info.dropdown-toggle:focus,.in>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.btn-outline-warning{color:#ffc107;border-color:#ffc107;background-color:transparent}.btn-outline-warning:hover{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:focus,.btn-outline-warning.focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled):active,.btn-outline-warning:not(:disabled):not(.disabled).active,.show>.btn-outline-warning.dropdown-toggle,.in>.btn-outline-warning.dropdown-toggle{color:#000;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-warning.dropdown-toggle:focus,.in>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.btn-outline-danger{color:#dc3545;border-color:#dc3545;background-color:transparent}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:focus,.btn-outline-danger.focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled):active,.btn-outline-danger:not(:disabled):not(.disabled).active,.show>.btn-outline-danger.dropdown-toggle,.in>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-danger.dropdown-toggle:focus,.in>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.btn-outline-light{color:#f8f9fa;border-color:#f8f9fa;background-color:transparent}.btn-outline-light:hover{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:focus,.btn-outline-light.focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled):active,.btn-outline-light:not(:disabled):not(.disabled).active,.show>.btn-outline-light.dropdown-toggle,.in>.btn-outline-light.dropdown-toggle{color:#000;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled):active:focus,.btn-outline-light:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-light.dropdown-toggle:focus,.in>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.btn-outline-dark{color:#343a40;border-color:#343a40;background-color:transparent}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:focus,.btn-outline-dark.focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled):active,.btn-outline-dark:not(:disabled):not(.disabled).active,.show>.btn-outline-dark.dropdown-toggle,.in>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.show>.btn-outline-dark.dropdown-toggle:focus,.in>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.btn-link{font-weight:400;color:#096B72;text-decoration:none;-webkit-text-decoration:none;-moz-text-decoration:none;-ms-text-decoration:none;-o-text-decoration:none}.btn-link:hover{color:#03282b;text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:focus,.btn-link.focus{text-decoration:underline;-webkit-text-decoration:underline;-moz-text-decoration:underline;-ms-text-decoration:underline;-o-text-decoration:underline}.btn-link:disabled,.btn-link.disabled{color:#6c757d;pointer-events:none}.btn-lg,.btn-group-lg>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-sm,.btn-group-sm>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{transition:opacity 0.15s linear}@media (prefers-reduced-motion: reduce){.fade{transition:none}}.fade:not(.show):not(.in){opacity:0}.collapse:not(.show):not(.in){display:none}.collapsing{position:relative;height:0;overflow:hidden;transition:height 0.35s ease}@media (prefers-reduced-motion: reduce){.collapsing{transition:none}}.dropup,.dropright,.dropdown,.dropleft{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,0.15);border-radius:.25rem}.dropdown-menu-left{right:auto;left:0}.dropdown-menu-right{right:0;left:auto}@media (min-width: 576px){.dropdown-menu-sm-left{right:auto;left:0}.dropdown-menu-sm-right{right:0;left:auto}}@media (min-width: 768px){.dropdown-menu-md-left{right:auto;left:0}.dropdown-menu-md-right{right:0;left:auto}}@media (min-width: 992px){.dropdown-menu-lg-left{right:auto;left:0}.dropdown-menu-lg-right{right:0;left:auto}}@media (min-width: 1200px){.dropdown-menu-xl-left{right:auto;left:0}.dropdown-menu-xl-right{right:0;left:auto}}.dropup .dropdown-menu{top:auto;bottom:100%;margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{top:0;right:auto;left:100%;margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{top:0;right:100%;left:auto;margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-menu[x-placement^="top"],.dropdown-menu[x-placement^="right"],.dropdown-menu[x-placement^="bottom"],.dropdown-menu[x-placement^="left"]{right:auto;bottom:auto}.dropdown-divider,.dropdown-menu>li.divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item,.dropdown-menu>li>a{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:hover,.dropdown-menu>li>a:hover,.dropdown-item:focus,.dropdown-menu>li>a:focus{color:#16181b;text-decoration:none;background-color:#e9ecef}.dropdown-item.active,.dropdown-menu>li>a.active,.dropdown-item:active,.dropdown-menu>li>a:active{color:#fff;text-decoration:none;background-color:#096B72}.dropdown-item.disabled,.dropdown-menu>li>a.disabled,.dropdown-item:disabled,.dropdown-menu>li>a:disabled{color:#adb5bd;pointer-events:none;background-color:transparent}.dropdown-menu.show,.dropdown-menu.in{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.dropdown-item-text{display:block;padding:.25rem 1.5rem;color:#212529}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover{z-index:1}.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn.active{z-index:1}.btn-toolbar{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;justify-content:flex-start;-webkit-justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child){margin-left:-1px}.btn-group>.btn:not(:last-child):not(.dropdown-toggle),.btn-group>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:not(:first-child),.btn-group>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after,.dropright .dropdown-toggle-split::after{margin-left:0}.dropleft .dropdown-toggle-split::before{margin-right:0}.btn-sm+.dropdown-toggle-split,.btn-group-sm>.btn+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-lg+.dropdown-toggle-split,.btn-group-lg>.btn+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;-webkit-flex-direction:column;align-items:flex-start;-webkit-align-items:flex-start;justify-content:center;-webkit-justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child){margin-top:-1px}.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle),.btn-group-vertical>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:not(:first-child),.btn-group-vertical>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type="radio"],.btn-group-toggle>.btn input[type="checkbox"],.btn-group-toggle>.btn-group>.btn input[type="radio"],.btn-group-toggle>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:stretch;-webkit-align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-control-plaintext,.input-group>.custom-select,.input-group>.custom-file{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;width:1%;min-width:0;margin-bottom:0}.input-group>.form-control+.form-control,.input-group>.form-control+.custom-select,.input-group>.form-control+.custom-file,.input-group>.form-control-plaintext+.form-control,.input-group>.form-control-plaintext+.custom-select,.input-group>.form-control-plaintext+.custom-file,.input-group>.custom-select+.form-control,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.custom-file,.input-group>.custom-file+.form-control,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.custom-file{margin-left:-1px}.input-group>.form-control:focus,.input-group>.custom-select:focus,.input-group>.custom-file .custom-file-input:focus~.custom-file-label{z-index:3}.input-group>.custom-file .custom-file-input:focus{z-index:4}.input-group>.form-control:not(:first-child),.input-group>.custom-select:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:first-child) .custom-file-label{border-top-left-radius:0;border-bottom-left-radius:0}.input-group:not(.has-validation)>.form-control:not(:last-child),.input-group:not(.has-validation)>.custom-select:not(:last-child),.input-group:not(.has-validation)>.custom-file:not(:last-child) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.form-control:nth-last-child(n + 3),.input-group.has-validation>.custom-select:nth-last-child(n + 3),.input-group.has-validation>.custom-file:nth-last-child(n + 3) .custom-file-label::after{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-prepend,.input-group-append{display:flex;display:-webkit-flex}.input-group-prepend .btn,.input-group-append .btn{position:relative;z-index:2}.input-group-prepend .btn:focus,.input-group-append .btn:focus{z-index:3}.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.input-group-text,.input-group-append .input-group-text+.btn{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type="radio"],.input-group-text input[type="checkbox"]{margin-top:0}.input-group-lg>.form-control:not(textarea),.input-group-lg>.custom-select{height:calc(1.5em + 1rem + 2px)}.input-group-lg>.form-control,.input-group-lg>.custom-select,.input-group-lg>.input-group-prepend>.input-group-text,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-append>.btn{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-sm>.form-control:not(textarea),.input-group-sm>.custom-select{height:calc(1.5em + .5rem + 2px)}.input-group-sm>.form-control,.input-group-sm>.custom-select,.input-group-sm>.input-group-prepend>.input-group-text,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-append>.btn{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-lg>.custom-select,.input-group-sm>.custom-select{padding-right:1.75rem}.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.btn,.input-group:not(.has-validation)>.input-group-append:not(:last-child)>.input-group-text,.input-group.has-validation>.input-group-append:nth-last-child(n + 3)>.btn,.input-group.has-validation>.input-group-append:nth-last-child(n + 3)>.input-group-text,.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;z-index:1;display:block;min-height:1.5rem;padding-left:1.5rem;color-adjust:exact;-webkit-print-color-adjust:exact}.custom-control-inline{display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;left:0;z-index:-1;width:1rem;height:1.25rem;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;border-color:#096B72;background-color:#096B72}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.custom-control-input:focus:not(:checked)~.custom-control-label::before{border-color:#12dae8}.custom-control-input:not(:disabled):active~.custom-control-label::before{color:#000;background-color:#3ee4f0;border-color:#3ee4f0}.custom-control-input[disabled]~.custom-control-label,.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input[disabled]~.custom-control-label::before,.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{position:relative;margin-bottom:0;vertical-align:top}.custom-control-label::before{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;pointer-events:none;content:"";background-color:#fff;border:#adb5bd solid 1px}.custom-control-label::after{position:absolute;top:.25rem;left:-1.5rem;display:block;width:1rem;height:1rem;content:"";background:50% / 50% 50% no-repeat}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26l2.974 2.99L8 2.193z'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{border-color:#096B72;background-color:#096B72}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='4' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(9,107,114,0.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(9,107,114,0.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(9,107,114,0.5)}.custom-switch{padding-left:2.25rem}.custom-switch .custom-control-label::before{left:-2.25rem;width:1.75rem;pointer-events:all;border-radius:.5rem}.custom-switch .custom-control-label::after{top:calc(.25rem + 2px);left:calc(-2.25rem + 2px);width:calc(1rem - 4px);height:calc(1rem - 4px);background-color:#adb5bd;border-radius:.5rem;transition:transform 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.custom-switch .custom-control-label::after{transition:none}}.custom-switch .custom-control-input:checked~.custom-control-label::after{background-color:#fff;transform:translateX(.75rem)}.custom-switch .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(9,107,114,0.5)}.custom-select{display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);padding:.375rem 1.75rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;border:1px solid #ced4da;border-radius:.25rem;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}.custom-select:focus{border-color:#12dae8;outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{display:none}.custom-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #495057}.custom-select-sm{height:calc(1.5em + .5rem + 2px);padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem}.custom-select-lg{height:calc(1.5em + 1rem + 2px);padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem}.custom-file{position:relative;display:inline-block;width:100%;height:calc(1.5em + .75rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(1.5em + .75rem + 2px);margin:0;overflow:hidden;opacity:0}.custom-file-input:focus~.custom-file-label{border-color:#12dae8;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.custom-file-input[disabled]~.custom-file-label,.custom-file-input:disabled~.custom-file-label{background-color:#e9ecef}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-input~.custom-file-label[data-browse]::after{content:attr(data-browse)}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(1.5em + .75rem + 2px);padding:.375rem .75rem;overflow:hidden;font-weight:400;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(1.5em + .75rem);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:inherit;border-radius:0 .25rem .25rem 0}.custom-range{width:100%;height:1.4rem;padding:0;background-color:transparent;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}.custom-range:focus{outline:0}.custom-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(9,107,114,0.25)}.custom-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(9,107,114,0.25)}.custom-range:focus::-ms-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(9,107,114,0.25)}.custom-range::-moz-focus-outer{border:0}.custom-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;background-color:#096B72;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-webkit-slider-thumb{transition:none}}.custom-range::-webkit-slider-thumb:active{background-color:#3ee4f0}.custom-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-moz-range-thumb{width:1rem;height:1rem;background-color:#096B72;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-moz-range-thumb{transition:none}}.custom-range::-moz-range-thumb:active{background-color:#3ee4f0}.custom-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:#dee2e6;border-color:transparent;border-radius:1rem}.custom-range::-ms-thumb{width:1rem;height:1rem;margin-top:0;margin-right:.2rem;margin-left:.2rem;background-color:#096B72;border:0;border-radius:1rem;transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out;appearance:none;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;-o-appearance:none}@media (prefers-reduced-motion: reduce){.custom-range::-ms-thumb{transition:none}}.custom-range::-ms-thumb:active{background-color:#3ee4f0}.custom-range::-ms-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:transparent;border-color:transparent;border-width:.5rem}.custom-range::-ms-fill-lower{background-color:#dee2e6;border-radius:1rem}.custom-range::-ms-fill-upper{margin-right:15px;background-color:#dee2e6;border-radius:1rem}.custom-range:disabled::-webkit-slider-thumb{background-color:#adb5bd}.custom-range:disabled::-webkit-slider-runnable-track{cursor:default}.custom-range:disabled::-moz-range-thumb{background-color:#adb5bd}.custom-range:disabled::-moz-range-track{cursor:default}.custom-range:disabled::-ms-thumb{background-color:#adb5bd}.custom-control-label::before,.custom-file-label,.custom-select{transition:background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.custom-control-label::before,.custom-file-label,.custom-select{transition:none}}.nav{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link,.nav-tabs>li>a,.nav-pills>li>a,:where(ul.nav.navbar-nav > li)>a{display:block;padding:.5rem 1rem}.nav-link:hover,.nav-tabs>li>a:hover,.nav-pills>li>a:hover,:where(ul.nav.navbar-nav > li)>a:hover,.nav-link:focus,.nav-tabs>li>a:focus,.nav-pills>li>a:focus,:where(ul.nav.navbar-nav > li)>a:focus{text-decoration:none}.nav-link.disabled,.nav-tabs>li>a.disabled,.nav-pills>li>a.disabled,:where(ul.nav.navbar-nav > li)>a.disabled{color:#6c757d;pointer-events:none;cursor:default}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-link,.nav-tabs>li>a,.nav-tabs .nav-pills>li>a,.nav-tabs :where(ul.nav.navbar-nav > li)>a{margin-bottom:-1px;border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:hover,.nav-tabs>li>a:hover,.nav-tabs .nav-pills>li>a:hover,.nav-tabs :where(ul.nav.navbar-nav > li)>a:hover,.nav-tabs .nav-link:focus,.nav-tabs>li>a:focus,.nav-tabs .nav-pills>li>a:focus,.nav-tabs :where(ul.nav.navbar-nav > li)>a:focus{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled,.nav-tabs>li>a.disabled,.nav-tabs .nav-pills>li>a.disabled,.nav-tabs :where(ul.nav.navbar-nav > li)>a.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-link.active,.nav-tabs>li>a.active,.nav-tabs .nav-pills>li>a.active,.nav-tabs :where(ul.nav.navbar-nav > li)>a.active,.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-item.in .nav-link,.nav-tabs .nav-item.show .nav-tabs>li>a,.nav-tabs .nav-item.in .nav-tabs>li>a,.nav-tabs .nav-item.show .nav-pills>li>a,.nav-tabs .nav-item.in .nav-pills>li>a,.nav-tabs>li.show .nav-link,.nav-tabs>li.in .nav-link,.nav-tabs>li.show .nav-tabs>li>a,.nav-tabs>li.in .nav-tabs>li>a,.nav-tabs>li.show .nav-pills>li>a,.nav-tabs>li.in .nav-pills>li>a,.nav-tabs .nav-pills>li.show .nav-link,.nav-tabs .nav-pills>li.in .nav-link,.nav-tabs .nav-pills>li.show .nav-tabs>li>a,.nav-tabs .nav-pills>li.in .nav-tabs>li>a,.nav-tabs .nav-pills>li.show .nav-pills>li>a,.nav-tabs .nav-pills>li.in .nav-pills>li>a,.nav-tabs .nav-item.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-item.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs>li.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs>li.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-pills>li.show :where(ul.nav.navbar-nav > li)>a,.nav-tabs .nav-pills>li.in :where(ul.nav.navbar-nav > li)>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-link,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-link,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-tabs>li>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-tabs>li>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-pills>li>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) .nav-pills>li>a,.nav-tabs .show:where(ul.nav.navbar-nav > li):not(.dropdown) :where(ul.nav.navbar-nav > li)>a,.nav-tabs .in:where(ul.nav.navbar-nav > li):not(.dropdown) :where(ul.nav.navbar-nav > li)>a{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link,.nav-pills .nav-tabs>li>a,.nav-pills>li>a,.nav-pills :where(ul.nav.navbar-nav > li)>a{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .nav-tabs>li>a.active,.nav-pills>li>a.active,.nav-pills :where(ul.nav.navbar-nav > li)>a.active,.nav-pills .show>.nav-link,.nav-pills .in>.nav-link,.nav-pills .nav-tabs>li.show>a,.nav-pills .nav-tabs>li.in>a,.nav-pills>li.show>a,.nav-pills>li.in>a,.nav-pills .show:where(ul.nav.navbar-nav > li)>a,.nav-pills .in:where(ul.nav.navbar-nav > li)>a{color:#fff;background-color:#096B72}.nav-fill>.nav-link,.nav-tabs>li.nav-fill>a,.nav-pills>li.nav-fill>a,.nav-fill:where(ul.nav.navbar-nav > li)>a,.nav-fill .nav-item,.nav-fill .nav-tabs>li,.nav-fill .nav-pills>li,.nav-fill :where(ul.nav.navbar-nav > li):not(.dropdown){flex:1 1 auto;-webkit-flex:1 1 auto;text-align:center}.nav-justified>.nav-link,.nav-tabs>li.nav-justified>a,.nav-pills>li.nav-justified>a,.nav-justified:where(ul.nav.navbar-nav > li)>a,.nav-justified .nav-item,.nav-justified .nav-tabs>li,.nav-justified .nav-pills>li,.nav-justified :where(ul.nav.navbar-nav > li):not(.dropdown){flex-basis:0;-webkit-flex-basis:0;flex-grow:1;-webkit-flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between;padding:.5rem 1rem}.navbar .container,.navbar .container-fluid,.navbar .container-sm,.navbar .container-md,.navbar .container-lg,.navbar .container-xl{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:space-between;-webkit-justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-nav{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link,.navbar-nav .nav-tabs>li>a,.navbar-nav .nav-pills>li>a,.navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{flex-basis:100%;-webkit-flex-basis:100%;flex-grow:1;-webkit-flex-grow:1;align-items:center;-webkit-align-items:center}.navbar-toggler,.navbar-toggle{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:hover,.navbar-toggle:hover,.navbar-toggler:focus,.navbar-toggle:focus{text-decoration:none}.navbar-toggler-icon,.navbar-toggle>.icon-bar:last-child{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:50% / 100% 100% no-repeat}.navbar-nav-scroll{max-height:75vh;overflow-y:auto}@media (max-width: 575.98px){.navbar-expand-sm>.container,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container,.navbar-expand-sm>.container-fluid,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-fluid,.navbar-expand-sm>.container-sm,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-sm,.navbar-expand-sm>.container-md,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-md,.navbar-expand-sm>.container-lg,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-lg,.navbar-expand-sm>.container-xl,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 576px){.navbar-expand-sm,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl){flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-sm .navbar-nav,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link,.navbar-expand-sm .navbar-nav .nav-tabs>li>a,.navbar-expand-sm .navbar-nav .nav-pills>li>a,.navbar-expand-sm .navbar-nav :where(ul.nav.navbar-nav > li)>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-link,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-tabs>li>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav .nav-pills>li>a,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container,.navbar-expand-sm>.container-fluid,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-fluid,.navbar-expand-sm>.container-sm,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-sm,.navbar-expand-sm>.container-md,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-md,.navbar-expand-sm>.container-lg,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-lg,.navbar-expand-sm>.container-xl,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl)>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand-sm .navbar-nav-scroll,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-sm .navbar-toggler,.navbar-expand-sm .navbar-toggle,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-toggler,.navbar:not(.navbar-expand):not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl) .navbar-toggle{display:none}}@media (max-width: 767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 768px){.navbar-expand-md{flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link,.navbar-expand-md .navbar-nav .nav-tabs>li>a,.navbar-expand-md .navbar-nav .nav-pills>li>a,.navbar-expand-md .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid,.navbar-expand-md>.container-sm,.navbar-expand-md>.container-md,.navbar-expand-md>.container-lg,.navbar-expand-md>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-md .navbar-toggler,.navbar-expand-md .navbar-toggle{display:none}}@media (max-width: 991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 992px){.navbar-expand-lg{flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link,.navbar-expand-lg .navbar-nav .nav-tabs>li>a,.navbar-expand-lg .navbar-nav .nav-pills>li>a,.navbar-expand-lg .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid,.navbar-expand-lg>.container-sm,.navbar-expand-lg>.container-md,.navbar-expand-lg>.container-lg,.navbar-expand-lg>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-lg .navbar-toggler,.navbar-expand-lg .navbar-toggle{display:none}}@media (max-width: 1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{padding-right:0;padding-left:0}}@media (min-width: 1200px){.navbar-expand-xl{flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link,.navbar-expand-xl .navbar-nav .nav-tabs>li>a,.navbar-expand-xl .navbar-nav .nav-pills>li>a,.navbar-expand-xl .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid,.navbar-expand-xl>.container-sm,.navbar-expand-xl>.container-md,.navbar-expand-xl>.container-lg,.navbar-expand-xl>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand-xl .navbar-toggler,.navbar-expand-xl .navbar-toggle{display:none}}.navbar-expand{flex-flow:row nowrap;-webkit-flex-flow:row nowrap;justify-content:flex-start;-webkit-justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{flex-direction:row;-webkit-flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link,.navbar-expand .navbar-nav .nav-tabs>li>a,.navbar-expand .navbar-nav .nav-pills>li>a,.navbar-expand .navbar-nav :where(ul.nav.navbar-nav > li)>a{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid,.navbar-expand>.container-sm,.navbar-expand>.container-md,.navbar-expand>.container-lg,.navbar-expand>.container-xl{flex-wrap:nowrap;-webkit-flex-wrap:nowrap}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex !important;display:-webkit-flex !important;flex-basis:auto;-webkit-flex-basis:auto}.navbar-expand .navbar-toggler,.navbar-expand .navbar-toggle{display:none}.navbar-light,.navbar.navbar-default{background-color:#f8f9fa}.navbar-light .navbar-brand,.navbar.navbar-default .navbar-brand{color:#000}.navbar-light .navbar-brand:hover,.navbar.navbar-default .navbar-brand:hover,.navbar-light .navbar-brand:focus,.navbar.navbar-default .navbar-brand:focus{color:#000}.navbar-light .navbar-nav .nav-link,.navbar-light .navbar-nav .nav-tabs>li>a,.navbar-light .navbar-nav .nav-pills>li>a,.navbar.navbar-default .navbar-nav .nav-link,.navbar.navbar-default .navbar-nav .nav-tabs>li>a,.navbar.navbar-default .navbar-nav .nav-pills>li>a,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a{color:rgba(0,0,0,0.5)}.navbar-light .navbar-nav .nav-link:hover,.navbar-light .navbar-nav .nav-tabs>li>a:hover,.navbar-light .navbar-nav .nav-pills>li>a:hover,.navbar.navbar-default .navbar-nav .nav-link:hover,.navbar.navbar-default .navbar-nav .nav-tabs>li>a:hover,.navbar.navbar-default .navbar-nav .nav-pills>li>a:hover,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a:hover,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a:hover,.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-tabs>li>a:focus,.navbar-light .navbar-nav .nav-pills>li>a:focus,.navbar.navbar-default .navbar-nav .nav-link:focus,.navbar.navbar-default .navbar-nav .nav-tabs>li>a:focus,.navbar.navbar-default .navbar-nav .nav-pills>li>a:focus,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a:focus,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a:focus{color:rgba(0,0,0,0.75)}.navbar-light .navbar-nav .nav-link.disabled,.navbar-light .navbar-nav .nav-tabs>li>a.disabled,.navbar-light .navbar-nav .nav-pills>li>a.disabled,.navbar.navbar-default .navbar-nav .nav-link.disabled,.navbar.navbar-default .navbar-nav .nav-tabs>li>a.disabled,.navbar.navbar-default .navbar-nav .nav-pills>li>a.disabled,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a.disabled,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a.disabled{color:rgba(0,0,0,0.25)}.navbar-light .navbar-nav .show>.nav-link,.navbar-light .navbar-nav .in>.nav-link,.navbar-light .navbar-nav .nav-tabs>li.show>a,.navbar-light .navbar-nav .nav-tabs>li.in>a,.navbar-light .navbar-nav .nav-pills>li.show>a,.navbar-light .navbar-nav .nav-pills>li.in>a,.navbar.navbar-default .navbar-nav .show>.nav-link,.navbar.navbar-default .navbar-nav .in>.nav-link,.navbar.navbar-default .navbar-nav .nav-tabs>li.show>a,.navbar.navbar-default .navbar-nav .nav-tabs>li.in>a,.navbar.navbar-default .navbar-nav .nav-pills>li.show>a,.navbar.navbar-default .navbar-nav .nav-pills>li.in>a,.navbar-light .navbar-nav .show:where(ul.nav.navbar-nav > li)>a,.navbar-light .navbar-nav .in:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-default .navbar-nav .show:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-default .navbar-nav .in:where(ul.nav.navbar-nav > li)>a,.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-tabs>li.active>a,.navbar-light .navbar-nav .nav-pills>li.active>a,.navbar.navbar-default .navbar-nav .active>.nav-link,.navbar.navbar-default .navbar-nav .nav-tabs>li.active>a,.navbar.navbar-default .navbar-nav .nav-pills>li.active>a,.navbar-light .navbar-nav .active:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-default .navbar-nav .active:where(ul.nav.navbar-nav > li)>a,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .nav-link.in,.navbar-light .navbar-nav .nav-tabs>li>a.show,.navbar-light .navbar-nav .nav-tabs>li>a.in,.navbar-light .navbar-nav .nav-pills>li>a.show,.navbar-light .navbar-nav .nav-pills>li>a.in,.navbar.navbar-default .navbar-nav .nav-link.show,.navbar.navbar-default .navbar-nav .nav-link.in,.navbar.navbar-default .navbar-nav .nav-tabs>li>a.show,.navbar.navbar-default .navbar-nav .nav-tabs>li>a.in,.navbar.navbar-default .navbar-nav .nav-pills>li>a.show,.navbar.navbar-default .navbar-nav .nav-pills>li>a.in,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a.in,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a.in,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-tabs>li>a.active,.navbar-light .navbar-nav .nav-pills>li>a.active,.navbar.navbar-default .navbar-nav .nav-link.active,.navbar.navbar-default .navbar-nav .nav-tabs>li>a.active,.navbar.navbar-default .navbar-nav .nav-pills>li>a.active,.navbar-light .navbar-nav :where(ul.nav.navbar-nav > li)>a.active,.navbar.navbar-default .navbar-nav :where(ul.nav.navbar-nav > li)>a.active{color:#000}.navbar-light .navbar-toggler,.navbar-light .navbar-toggle,.navbar.navbar-default .navbar-toggler,.navbar.navbar-default .navbar-toggle{color:rgba(0,0,0,0.5);border-color:rgba(0,0,0,0.1)}.navbar-light .navbar-toggler-icon,.navbar-light .navbar-toggle>.icon-bar:last-child,.navbar.navbar-default .navbar-toggler-icon,.navbar.navbar-default .navbar-toggle>.icon-bar:last-child{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280,0,0,0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-light .navbar-text,.navbar.navbar-default .navbar-text{color:rgba(0,0,0,0.5)}.navbar-light .navbar-text a,.navbar.navbar-default .navbar-text a{color:#000}.navbar-light .navbar-text a:hover,.navbar.navbar-default .navbar-text a:hover,.navbar-light .navbar-text a:focus,.navbar.navbar-default .navbar-text a:focus{color:#000}.navbar-dark,.navbar.navbar-inverse{background-color:#343a40}.navbar-dark .navbar-brand,.navbar.navbar-inverse .navbar-brand{color:#fff}.navbar-dark .navbar-brand:hover,.navbar.navbar-inverse .navbar-brand:hover,.navbar-dark .navbar-brand:focus,.navbar.navbar-inverse .navbar-brand:focus{color:#fff}.navbar-dark .navbar-nav .nav-link,.navbar-dark .navbar-nav .nav-tabs>li>a,.navbar-dark .navbar-nav .nav-pills>li>a,.navbar.navbar-inverse .navbar-nav .nav-link,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a{color:rgba(255,255,255,0.5)}.navbar-dark .navbar-nav .nav-link:hover,.navbar-dark .navbar-nav .nav-tabs>li>a:hover,.navbar-dark .navbar-nav .nav-pills>li>a:hover,.navbar.navbar-inverse .navbar-nav .nav-link:hover,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a:hover,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a:hover,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a:hover,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a:hover,.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-tabs>li>a:focus,.navbar-dark .navbar-nav .nav-pills>li>a:focus,.navbar.navbar-inverse .navbar-nav .nav-link:focus,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a:focus,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a:focus,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a:focus,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a:focus{color:rgba(255,255,255,0.75)}.navbar-dark .navbar-nav .nav-link.disabled,.navbar-dark .navbar-nav .nav-tabs>li>a.disabled,.navbar-dark .navbar-nav .nav-pills>li>a.disabled,.navbar.navbar-inverse .navbar-nav .nav-link.disabled,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a.disabled,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a.disabled,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a.disabled,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a.disabled{color:rgba(255,255,255,0.25)}.navbar-dark .navbar-nav .show>.nav-link,.navbar-dark .navbar-nav .in>.nav-link,.navbar-dark .navbar-nav .nav-tabs>li.show>a,.navbar-dark .navbar-nav .nav-tabs>li.in>a,.navbar-dark .navbar-nav .nav-pills>li.show>a,.navbar-dark .navbar-nav .nav-pills>li.in>a,.navbar.navbar-inverse .navbar-nav .show>.nav-link,.navbar.navbar-inverse .navbar-nav .in>.nav-link,.navbar.navbar-inverse .navbar-nav .nav-tabs>li.show>a,.navbar.navbar-inverse .navbar-nav .nav-tabs>li.in>a,.navbar.navbar-inverse .navbar-nav .nav-pills>li.show>a,.navbar.navbar-inverse .navbar-nav .nav-pills>li.in>a,.navbar-dark .navbar-nav .show:where(ul.nav.navbar-nav > li)>a,.navbar-dark .navbar-nav .in:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-inverse .navbar-nav .show:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-inverse .navbar-nav .in:where(ul.nav.navbar-nav > li)>a,.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-tabs>li.active>a,.navbar-dark .navbar-nav .nav-pills>li.active>a,.navbar.navbar-inverse .navbar-nav .active>.nav-link,.navbar.navbar-inverse .navbar-nav .nav-tabs>li.active>a,.navbar.navbar-inverse .navbar-nav .nav-pills>li.active>a,.navbar-dark .navbar-nav .active:where(ul.nav.navbar-nav > li)>a,.navbar.navbar-inverse .navbar-nav .active:where(ul.nav.navbar-nav > li)>a,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .nav-link.in,.navbar-dark .navbar-nav .nav-tabs>li>a.show,.navbar-dark .navbar-nav .nav-tabs>li>a.in,.navbar-dark .navbar-nav .nav-pills>li>a.show,.navbar-dark .navbar-nav .nav-pills>li>a.in,.navbar.navbar-inverse .navbar-nav .nav-link.show,.navbar.navbar-inverse .navbar-nav .nav-link.in,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a.show,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a.in,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a.show,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a.in,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a.in,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a.show,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a.in,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-tabs>li>a.active,.navbar-dark .navbar-nav .nav-pills>li>a.active,.navbar.navbar-inverse .navbar-nav .nav-link.active,.navbar.navbar-inverse .navbar-nav .nav-tabs>li>a.active,.navbar.navbar-inverse .navbar-nav .nav-pills>li>a.active,.navbar-dark .navbar-nav :where(ul.nav.navbar-nav > li)>a.active,.navbar.navbar-inverse .navbar-nav :where(ul.nav.navbar-nav > li)>a.active{color:#fff}.navbar-dark .navbar-toggler,.navbar-dark .navbar-toggle,.navbar.navbar-inverse .navbar-toggler,.navbar.navbar-inverse .navbar-toggle{color:rgba(255,255,255,0.5);border-color:rgba(255,255,255,0.1)}.navbar-dark .navbar-toggler-icon,.navbar-dark .navbar-toggle>.icon-bar:last-child,.navbar.navbar-inverse .navbar-toggler-icon,.navbar.navbar-inverse .navbar-toggle>.icon-bar:last-child{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255,255,255,0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.navbar-dark .navbar-text,.navbar.navbar-inverse .navbar-text{color:rgba(255,255,255,0.5)}.navbar-dark .navbar-text a,.navbar.navbar-inverse .navbar-text a{color:#fff}.navbar-dark .navbar-text a:hover,.navbar.navbar-inverse .navbar-text a:hover,.navbar-dark .navbar-text a:focus,.navbar.navbar-inverse .navbar-text a:focus{color:#fff}.card,.well{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,0.125);border-radius:.25rem}.card>hr,.well>hr{margin-right:0;margin-left:0}.card>.list-group,.well>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child,.well>.list-group:first-child{border-top-width:0;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card>.list-group:last-child,.well>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card>.card-header+.list-group,.well>.card-header+.list-group,.card>.list-group+.card-footer,.well>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;-webkit-flex:1 1 auto;min-height:1px;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,0.03);border-bottom:1px solid rgba(0,0,0,0.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,0.03);border-top:1px solid rgba(0,0,0,0.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem;border-radius:calc(.25rem - 1px)}.card-img,.card-img-top,.card-img-bottom{flex-shrink:0;-webkit-flex-shrink:0;width:100%}.card-img,.card-img-top{border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img,.card-img-bottom{border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck .card,.card-deck .well{margin-bottom:15px}@media (min-width: 576px){.card-deck{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card,.card-deck .well{flex:1 0 0%;-webkit-flex:1 0 0%;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group>.card,.card-group>.well{margin-bottom:15px}@media (min-width: 576px){.card-group{display:flex;display:-webkit-flex;flex-flow:row wrap;-webkit-flex-flow:row wrap}.card-group>.card,.card-group>.well{flex:1 0 0%;-webkit-flex:1 0 0%;margin-bottom:0}.card-group>.card+.card,.card-group>.well+.card,.card-group>.card+.well,.card-group>.well+.well{margin-left:0;border-left:0}.card-group>.card:not(:last-child),.card-group>.well:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child) .card-img-top,.card-group>.well:not(:last-child) .card-img-top,.card-group>.card:not(:last-child) .card-header,.card-group>.well:not(:last-child) .card-header{border-top-right-radius:0}.card-group>.card:not(:last-child) .card-img-bottom,.card-group>.well:not(:last-child) .card-img-bottom,.card-group>.card:not(:last-child) .card-footer,.card-group>.well:not(:last-child) .card-footer{border-bottom-right-radius:0}.card-group>.card:not(:first-child),.card-group>.well:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child) .card-img-top,.card-group>.well:not(:first-child) .card-img-top,.card-group>.card:not(:first-child) .card-header,.card-group>.well:not(:first-child) .card-header{border-top-left-radius:0}.card-group>.card:not(:first-child) .card-img-bottom,.card-group>.well:not(:first-child) .card-img-bottom,.card-group>.card:not(:first-child) .card-footer,.card-group>.well:not(:first-child) .card-footer{border-bottom-left-radius:0}}.card-columns .card,.card-columns .well{margin-bottom:.75rem}@media (min-width: 576px){.card-columns{column-count:3;column-gap:1.25rem;orphans:1;widows:1}.card-columns .card,.card-columns .well{display:inline-block;width:100%}}.accordion{overflow-anchor:none}.accordion>.card,.accordion>.well{overflow:hidden}.accordion>.card:not(:last-of-type),.accordion>.well:not(:last-of-type){border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.accordion>.card:not(:first-of-type),.accordion>.well:not(:first-of-type){border-top-left-radius:0;border-top-right-radius:0}.accordion>.card>.card-header,.accordion>.well>.card-header{border-radius:0;margin-bottom:-1px}.breadcrumb{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item{padding-left:.5rem}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:flex;display:-webkit-flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#096B72;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{z-index:2;color:#03282b;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:3;outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.25)}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:3;color:#fff;background-color:#096B72;border-color:#096B72}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem;transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out}@media (prefers-reduced-motion: reduce){.badge{transition:none}}a.badge:hover,a.badge:focus{text-decoration:none}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-default{color:#000;background-color:#dee2e6}a.badge-default:hover,a.badge-default:focus{color:#000;background-color:#c1c9d0}a.badge-default:focus,a.badge-default.focus{outline:0;box-shadow:0 0 0 .2rem rgba(222,226,230,0.5)}.badge-primary{color:#fff;background-color:#096B72}a.badge-primary:hover,a.badge-primary:focus{color:#fff;background-color:#053f43}a.badge-primary:focus,a.badge-primary.focus{outline:0;box-shadow:0 0 0 .2rem rgba(9,107,114,0.5)}.badge-secondary{color:#fff;background-color:#6c757d}a.badge-secondary:hover,a.badge-secondary:focus{color:#fff;background-color:#545b62}a.badge-secondary:focus,a.badge-secondary.focus{outline:0;box-shadow:0 0 0 .2rem rgba(108,117,125,0.5)}.badge-success{color:#fff;background-color:#28a745}a.badge-success:hover,a.badge-success:focus{color:#fff;background-color:#1e7e34}a.badge-success:focus,a.badge-success.focus{outline:0;box-shadow:0 0 0 .2rem rgba(40,167,69,0.5)}.badge-info{color:#fff;background-color:#17a2b8}a.badge-info:hover,a.badge-info:focus{color:#fff;background-color:#117a8b}a.badge-info:focus,a.badge-info.focus{outline:0;box-shadow:0 0 0 .2rem rgba(23,162,184,0.5)}.badge-warning{color:#000;background-color:#ffc107}a.badge-warning:hover,a.badge-warning:focus{color:#000;background-color:#d39e00}a.badge-warning:focus,a.badge-warning.focus{outline:0;box-shadow:0 0 0 .2rem rgba(255,193,7,0.5)}.badge-danger{color:#fff;background-color:#dc3545}a.badge-danger:hover,a.badge-danger:focus{color:#fff;background-color:#bd2130}a.badge-danger:focus,a.badge-danger.focus{outline:0;box-shadow:0 0 0 .2rem rgba(220,53,69,0.5)}.badge-light{color:#000;background-color:#f8f9fa}a.badge-light:hover,a.badge-light:focus{color:#000;background-color:#dae0e5}a.badge-light:focus,a.badge-light.focus{outline:0;box-shadow:0 0 0 .2rem rgba(248,249,250,0.5)}.badge-dark{color:#fff;background-color:#343a40}a.badge-dark:hover,a.badge-dark:focus{color:#fff;background-color:#1d2124}a.badge-dark:focus,a.badge-dark.focus{outline:0;box-shadow:0 0 0 .2rem rgba(52,58,64,0.5)}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width: 576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;z-index:2;padding:.75rem 1.25rem;color:inherit}.alert-default{color:#737678;background-color:#f8f9fa;border-color:#f6f7f8}.alert-default hr{border-top-color:#e8eaed}.alert-default .alert-link{color:#5a5c5e}.alert-primary{color:#05383b;background-color:#cee1e3;border-color:#bad6d8}.alert-primary hr{border-top-color:#aacccf}.alert-primary .alert-link{color:#010b0c}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:flex;display:-webkit-flex;height:1rem;overflow:hidden;line-height:0;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;overflow:hidden;color:#fff;text-align:center;white-space:nowrap;background-color:#096B72;transition:width 0.6s ease}@media (prefers-reduced-motion: reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:1rem 1rem}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion: reduce){.progress-bar-animated{animation:none}}.media{display:flex;display:-webkit-flex;align-items:flex-start;-webkit-align-items:flex-start}.media-body{flex:1;-webkit-flex:1}.list-group{display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;padding-left:0;margin-bottom:0;border-radius:.25rem}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:hover,.list-group-item-action:focus{z-index:1;color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;background-color:#fff;border:1px solid rgba(0,0,0,0.125)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;pointer-events:none;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#096B72;border-color:#096B72}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:-1px;border-top-width:1px}.list-group-horizontal{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}@media (min-width: 576px){.list-group-horizontal-sm{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 768px){.list-group-horizontal-md{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 992px){.list-group-horizontal-lg{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}@media (min-width: 1200px){.list-group-horizontal-xl{flex-direction:row;-webkit-flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child{border-bottom-left-radius:.25rem;border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child{border-top-right-radius:.25rem;border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:1px;border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:-1px;border-left-width:1px}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 1px}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-default{color:#737678;background-color:#f6f7f8}.list-group-item-default.list-group-item-action:hover,.list-group-item-default.list-group-item-action:focus{color:#737678;background-color:#e8eaed}.list-group-item-default.list-group-item-action.active{color:#fff;background-color:#737678;border-color:#737678}.list-group-item-primary{color:#05383b;background-color:#bad6d8}.list-group-item-primary.list-group-item-action:hover,.list-group-item-primary.list-group-item-action:focus{color:#05383b;background-color:#aacccf}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#05383b;border-color:#05383b}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:hover,.list-group-item-secondary.list-group-item-action:focus{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:hover,.list-group-item-success.list-group-item-action:focus{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:hover,.list-group-item-info.list-group-item-action:focus{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:hover,.list-group-item-warning.list-group-item-action:focus{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:hover,.list-group-item-danger.list-group-item-action:focus{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:hover,.list-group-item-light.list-group-item-action:focus{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:hover,.list-group-item-dark.list-group-item-action:focus{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:hover{color:#000;text-decoration:none}.close:not(:disabled):not(.disabled):hover,.close:not(:disabled):not(.disabled):focus{opacity:.75}button.close{padding:0;background-color:transparent;border:0}a.close.disabled{pointer-events:none}.toast{flex-basis:350px;-webkit-flex-basis:350px;max-width:350px;font-size:.875rem;background-color:rgba(255,255,255,0.85);background-clip:padding-box;border:1px solid rgba(0,0,0,0.1);box-shadow:0 0.25rem 0.75rem rgba(0,0,0,0.1);opacity:0;border-radius:.25rem}.toast:not(:last-child){margin-bottom:.75rem}.toast.showing{opacity:1}.toast.show,.toast.in{display:block;opacity:1}.toast.hide{display:none}.toast-header{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;padding:.25rem .75rem;color:#6c757d;background-color:rgba(255,255,255,0.85);background-clip:padding-box;border-bottom:1px solid rgba(0,0,0,0.05);border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.toast-body{padding:.75rem}.modal-open{overflow:hidden}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal{position:fixed;top:0;left:0;z-index:1050;display:none;width:100%;height:100%;overflow:hidden;outline:0}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:transform 0.3s ease-out;transform:translate(0, -50px)}@media (prefers-reduced-motion: reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog,.modal.in .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{display:flex;display:-webkit-flex;max-height:calc(100% - 1rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 1rem);overflow:hidden}.modal-dialog-scrollable .modal-header,.modal-dialog-scrollable .modal-footer{flex-shrink:0;-webkit-flex-shrink:0}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;min-height:calc(100% - 1rem)}.modal-dialog-centered::before{display:block;height:calc(100vh - 1rem);height:min-content;height:-webkit-min-content;height:-moz-min-content;height:-ms-min-content;height:-o-min-content;content:""}.modal-dialog-centered.modal-dialog-scrollable{flex-direction:column;-webkit-flex-direction:column;justify-content:center;-webkit-justify-content:center;height:100%}.modal-dialog-centered.modal-dialog-scrollable .modal-content{max-height:none}.modal-dialog-centered.modal-dialog-scrollable::before{content:none}.modal-content{position:relative;display:flex;display:-webkit-flex;flex-direction:column;-webkit-flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show,.modal-backdrop.in{opacity:.5}.modal-header{display:flex;display:-webkit-flex;align-items:flex-start;-webkit-align-items:flex-start;justify-content:space-between;-webkit-justify-content:space-between;padding:1rem 1rem;border-bottom:1px solid #dee2e6;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.modal-header .close{padding:1rem 1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;flex:1 1 auto;-webkit-flex:1 1 auto;padding:1rem}.modal-footer{display:flex;display:-webkit-flex;flex-wrap:wrap;-webkit-flex-wrap:wrap;align-items:center;-webkit-align-items:center;justify-content:flex-end;-webkit-justify-content:flex-end;padding:.75rem;border-top:1px solid #dee2e6;border-bottom-right-radius:calc(.3rem - 1px);border-bottom-left-radius:calc(.3rem - 1px)}.modal-footer>*{margin:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-scrollable{max-height:calc(100% - 3.5rem)}.modal-dialog-scrollable .modal-content{max-height:calc(100vh - 3.5rem)}.modal-dialog-centered{min-height:calc(100% - 3.5rem)}.modal-dialog-centered::before{height:calc(100vh - 3.5rem);height:min-content;height:-webkit-min-content;height:-moz-min-content;height:-ms-min-content;height:-o-min-content}.modal-sm{max-width:300px}}@media (min-width: 992px){.modal-lg,.modal-xl{max-width:800px}}@media (min-width: 1200px){.modal-xl{max-width:1140px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show,.tooltip.in{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-top,.bs-tooltip-auto[x-placement^="top"]{padding:.4rem 0}.bs-tooltip-top .arrow,.bs-tooltip-auto[x-placement^="top"] .arrow{bottom:0}.bs-tooltip-top .arrow::before,.bs-tooltip-auto[x-placement^="top"] .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-right,.bs-tooltip-auto[x-placement^="right"]{padding:0 .4rem}.bs-tooltip-right .arrow,.bs-tooltip-auto[x-placement^="right"] .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-right .arrow::before,.bs-tooltip-auto[x-placement^="right"] .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-bottom,.bs-tooltip-auto[x-placement^="bottom"]{padding:.4rem 0}.bs-tooltip-bottom .arrow,.bs-tooltip-auto[x-placement^="bottom"] .arrow{top:0}.bs-tooltip-bottom .arrow::before,.bs-tooltip-auto[x-placement^="bottom"] .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-left,.bs-tooltip-auto[x-placement^="left"]{padding:0 .4rem}.bs-tooltip-left .arrow,.bs-tooltip-auto[x-placement^="left"] .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-left .arrow::before,.bs-tooltip-auto[x-placement^="left"] .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,0.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::before,.popover .arrow::after{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-top,.bs-popover-auto[x-placement^="top"]{margin-bottom:.5rem}.bs-popover-top>.arrow,.bs-popover-auto[x-placement^="top"]>.arrow{bottom:calc(-.5rem - 1px)}.bs-popover-top>.arrow::before,.bs-popover-auto[x-placement^="top"]>.arrow::before{bottom:0;border-width:.5rem .5rem 0;border-top-color:rgba(0,0,0,0.25)}.bs-popover-top>.arrow::after,.bs-popover-auto[x-placement^="top"]>.arrow::after{bottom:1px;border-width:.5rem .5rem 0;border-top-color:#fff}.bs-popover-right,.bs-popover-auto[x-placement^="right"]{margin-left:.5rem}.bs-popover-right>.arrow,.bs-popover-auto[x-placement^="right"]>.arrow{left:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-right>.arrow::before,.bs-popover-auto[x-placement^="right"]>.arrow::before{left:0;border-width:.5rem .5rem .5rem 0;border-right-color:rgba(0,0,0,0.25)}.bs-popover-right>.arrow::after,.bs-popover-auto[x-placement^="right"]>.arrow::after{left:1px;border-width:.5rem .5rem .5rem 0;border-right-color:#fff}.bs-popover-bottom,.bs-popover-auto[x-placement^="bottom"]{margin-top:.5rem}.bs-popover-bottom>.arrow,.bs-popover-auto[x-placement^="bottom"]>.arrow{top:calc(-.5rem - 1px)}.bs-popover-bottom>.arrow::before,.bs-popover-auto[x-placement^="bottom"]>.arrow::before{top:0;border-width:0 .5rem .5rem .5rem;border-bottom-color:rgba(0,0,0,0.25)}.bs-popover-bottom>.arrow::after,.bs-popover-auto[x-placement^="bottom"]>.arrow::after{top:1px;border-width:0 .5rem .5rem .5rem;border-bottom-color:#fff}.bs-popover-bottom .popover-header::before,.bs-popover-auto[x-placement^="bottom"] .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-left,.bs-popover-auto[x-placement^="left"]{margin-right:.5rem}.bs-popover-left>.arrow,.bs-popover-auto[x-placement^="left"]>.arrow{right:calc(-.5rem - 1px);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-left>.arrow::before,.bs-popover-auto[x-placement^="left"]>.arrow::before{right:0;border-width:.5rem 0 .5rem .5rem;border-left-color:rgba(0,0,0,0.25)}.bs-popover-left>.arrow::after,.bs-popover-auto[x-placement^="left"]>.arrow::after{right:1px;border-width:.5rem 0 .5rem .5rem;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y;-webkit-touch-action:pan-y;-moz-touch-action:pan-y;-ms-touch-action:pan-y;-o-touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;-o-backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion: reduce){.carousel-item{transition:none}}.carousel-item.active,.carousel-item-next,.carousel-item-prev{display:block}.carousel-item-next:not(.carousel-item-left),.active.carousel-item-right{transform:translateX(100%)}.carousel-item-prev:not(.carousel-item-right),.active.carousel-item-left{transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item.active,.carousel-fade .carousel-item-next.carousel-item-left,.carousel-fade .carousel-item-prev.carousel-item-right{z-index:1;opacity:1}.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion: reduce){.carousel-fade .active.carousel-item-left,.carousel-fade .active.carousel-item-right{transition:none}}.carousel-control-prev,.carousel-control-next{position:absolute;top:0;bottom:0;z-index:1;display:flex;display:-webkit-flex;align-items:center;-webkit-align-items:center;justify-content:center;-webkit-justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5;transition:opacity 0.15s ease}@media (prefers-reduced-motion: reduce){.carousel-control-prev,.carousel-control-next{transition:none}}.carousel-control-prev:hover,.carousel-control-prev:focus,.carousel-control-next:hover,.carousel-control-next:focus{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-prev-icon,.carousel-control-next-icon{display:inline-block;width:20px;height:20px;background:50% / 100% 100% no-repeat}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5L4.25 4l2.5-2.5L5.25 0z'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5L3.75 4l-2.5 2.5L2.75 8l4-4-4-4z'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:15;display:flex;display:-webkit-flex;justify-content:center;-webkit-justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{box-sizing:content-box;flex:0 1 auto;-webkit-flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:#fff;background-clip:padding-box;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity 0.6s ease}@media (prefers-reduced-motion: reduce){.carousel-indicators li{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;border:.25em solid currentColor;border-right-color:transparent;border-radius:50%;animation:.75s linear infinite spinner-border}.spinner-border-sm{width:1rem;height:1rem;border-width:.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{display:inline-block;width:2rem;height:2rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;animation:.75s linear infinite spinner-grow}.spinner-grow-sm{width:1rem;height:1rem}@media (prefers-reduced-motion: reduce){.spinner-border,.spinner-grow{animation-duration:1.5s;-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-ms-animation-duration:1.5s;-o-animation-duration:1.5s}}.align-baseline{vertical-align:baseline !important}.align-top{vertical-align:top !important}.align-middle{vertical-align:middle !important}.align-bottom{vertical-align:bottom !important}.align-text-bottom{vertical-align:text-bottom !important}.align-text-top{vertical-align:text-top !important}.bg-default{background-color:#dee2e6 !important;color:#000}a.bg-default:hover,a.bg-default:focus,button.bg-default:hover,button.bg-default:focus{background-color:#c1c9d0 !important}.bg-primary{background-color:#096B72 !important;color:#fff}a.bg-primary:hover,a.bg-primary:focus,button.bg-primary:hover,button.bg-primary:focus{background-color:#053f43 !important}.bg-secondary{background-color:#6c757d !important;color:#fff}a.bg-secondary:hover,a.bg-secondary:focus,button.bg-secondary:hover,button.bg-secondary:focus{background-color:#545b62 !important}.bg-success{background-color:#28a745 !important;color:#fff}a.bg-success:hover,a.bg-success:focus,button.bg-success:hover,button.bg-success:focus{background-color:#1e7e34 !important}.bg-info{background-color:#17a2b8 !important;color:#fff}a.bg-info:hover,a.bg-info:focus,button.bg-info:hover,button.bg-info:focus{background-color:#117a8b !important}.bg-warning{background-color:#ffc107 !important;color:#000}a.bg-warning:hover,a.bg-warning:focus,button.bg-warning:hover,button.bg-warning:focus{background-color:#d39e00 !important}.bg-danger{background-color:#dc3545 !important;color:#fff}a.bg-danger:hover,a.bg-danger:focus,button.bg-danger:hover,button.bg-danger:focus{background-color:#bd2130 !important}.bg-light{background-color:#f8f9fa !important;color:#000}a.bg-light:hover,a.bg-light:focus,button.bg-light:hover,button.bg-light:focus{background-color:#dae0e5 !important}.bg-dark{background-color:#343a40 !important;color:#fff}a.bg-dark:hover,a.bg-dark:focus,button.bg-dark:hover,button.bg-dark:focus{background-color:#1d2124 !important}.bg-white{background-color:#fff !important;color:#000}.bg-transparent{background-color:transparent !important}.border{border:1px solid #dee2e6 !important}.border-top{border-top:1px solid #dee2e6 !important}.border-right{border-right:1px solid #dee2e6 !important}.border-bottom{border-bottom:1px solid #dee2e6 !important}.border-left{border-left:1px solid #dee2e6 !important}.border-0{border:0 !important}.border-top-0{border-top:0 !important}.border-right-0{border-right:0 !important}.border-bottom-0{border-bottom:0 !important}.border-left-0{border-left:0 !important}.border-default{border-color:#dee2e6 !important}.border-primary{border-color:#096B72 !important}.border-secondary{border-color:#6c757d !important}.border-success{border-color:#28a745 !important}.border-info{border-color:#17a2b8 !important}.border-warning{border-color:#ffc107 !important}.border-danger{border-color:#dc3545 !important}.border-light{border-color:#f8f9fa !important}.border-dark{border-color:#343a40 !important}.border-white{border-color:#fff !important}.rounded-sm{border-radius:.2rem !important}.rounded{border-radius:.25rem !important}.rounded-top{border-top-left-radius:.25rem !important;border-top-right-radius:.25rem !important}.rounded-right{border-top-right-radius:.25rem !important;border-bottom-right-radius:.25rem !important}.rounded-bottom{border-bottom-right-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-left{border-top-left-radius:.25rem !important;border-bottom-left-radius:.25rem !important}.rounded-lg{border-radius:.3rem !important}.rounded-circle{border-radius:50% !important}.rounded-pill{border-radius:50rem !important}.rounded-0{border-radius:0 !important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:flex !important}.d-inline-flex{display:inline-flex !important}@media (min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:flex !important}.d-sm-inline-flex{display:inline-flex !important}}@media (min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:flex !important}.d-md-inline-flex{display:inline-flex !important}}@media (min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:flex !important}.d-lg-inline-flex{display:inline-flex !important}}@media (min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:flex !important}.d-xl-inline-flex{display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:flex !important}.d-print-inline-flex{display:inline-flex !important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.85714%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{flex-direction:row !important}.flex-column{flex-direction:column !important}.flex-row-reverse{flex-direction:row-reverse !important}.flex-column-reverse{flex-direction:column-reverse !important}.flex-wrap{flex-wrap:wrap !important}.flex-nowrap{flex-wrap:nowrap !important}.flex-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-fill{flex:1 1 auto !important}.flex-grow-0{flex-grow:0 !important}.flex-grow-1{flex-grow:1 !important}.flex-shrink-0{flex-shrink:0 !important}.flex-shrink-1{flex-shrink:1 !important}.justify-content-start{justify-content:flex-start !important}.justify-content-end{justify-content:flex-end !important}.justify-content-center{justify-content:center !important}.justify-content-between{justify-content:space-between !important}.justify-content-around{justify-content:space-around !important}.align-items-start{align-items:flex-start !important}.align-items-end{align-items:flex-end !important}.align-items-center{align-items:center !important}.align-items-baseline{align-items:baseline !important}.align-items-stretch{align-items:stretch !important}.align-content-start{align-content:flex-start !important}.align-content-end{align-content:flex-end !important}.align-content-center{align-content:center !important}.align-content-between{align-content:space-between !important}.align-content-around{align-content:space-around !important}.align-content-stretch{align-content:stretch !important}.align-self-auto{align-self:auto !important}.align-self-start{align-self:flex-start !important}.align-self-end{align-self:flex-end !important}.align-self-center{align-self:center !important}.align-self-baseline{align-self:baseline !important}.align-self-stretch{align-self:stretch !important}@media (min-width: 576px){.flex-sm-row{flex-direction:row !important}.flex-sm-column{flex-direction:column !important}.flex-sm-row-reverse{flex-direction:row-reverse !important}.flex-sm-column-reverse{flex-direction:column-reverse !important}.flex-sm-wrap{flex-wrap:wrap !important}.flex-sm-nowrap{flex-wrap:nowrap !important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-sm-fill{flex:1 1 auto !important}.flex-sm-grow-0{flex-grow:0 !important}.flex-sm-grow-1{flex-grow:1 !important}.flex-sm-shrink-0{flex-shrink:0 !important}.flex-sm-shrink-1{flex-shrink:1 !important}.justify-content-sm-start{justify-content:flex-start !important}.justify-content-sm-end{justify-content:flex-end !important}.justify-content-sm-center{justify-content:center !important}.justify-content-sm-between{justify-content:space-between !important}.justify-content-sm-around{justify-content:space-around !important}.align-items-sm-start{align-items:flex-start !important}.align-items-sm-end{align-items:flex-end !important}.align-items-sm-center{align-items:center !important}.align-items-sm-baseline{align-items:baseline !important}.align-items-sm-stretch{align-items:stretch !important}.align-content-sm-start{align-content:flex-start !important}.align-content-sm-end{align-content:flex-end !important}.align-content-sm-center{align-content:center !important}.align-content-sm-between{align-content:space-between !important}.align-content-sm-around{align-content:space-around !important}.align-content-sm-stretch{align-content:stretch !important}.align-self-sm-auto{align-self:auto !important}.align-self-sm-start{align-self:flex-start !important}.align-self-sm-end{align-self:flex-end !important}.align-self-sm-center{align-self:center !important}.align-self-sm-baseline{align-self:baseline !important}.align-self-sm-stretch{align-self:stretch !important}}@media (min-width: 768px){.flex-md-row{flex-direction:row !important}.flex-md-column{flex-direction:column !important}.flex-md-row-reverse{flex-direction:row-reverse !important}.flex-md-column-reverse{flex-direction:column-reverse !important}.flex-md-wrap{flex-wrap:wrap !important}.flex-md-nowrap{flex-wrap:nowrap !important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-md-fill{flex:1 1 auto !important}.flex-md-grow-0{flex-grow:0 !important}.flex-md-grow-1{flex-grow:1 !important}.flex-md-shrink-0{flex-shrink:0 !important}.flex-md-shrink-1{flex-shrink:1 !important}.justify-content-md-start{justify-content:flex-start !important}.justify-content-md-end{justify-content:flex-end !important}.justify-content-md-center{justify-content:center !important}.justify-content-md-between{justify-content:space-between !important}.justify-content-md-around{justify-content:space-around !important}.align-items-md-start{align-items:flex-start !important}.align-items-md-end{align-items:flex-end !important}.align-items-md-center{align-items:center !important}.align-items-md-baseline{align-items:baseline !important}.align-items-md-stretch{align-items:stretch !important}.align-content-md-start{align-content:flex-start !important}.align-content-md-end{align-content:flex-end !important}.align-content-md-center{align-content:center !important}.align-content-md-between{align-content:space-between !important}.align-content-md-around{align-content:space-around !important}.align-content-md-stretch{align-content:stretch !important}.align-self-md-auto{align-self:auto !important}.align-self-md-start{align-self:flex-start !important}.align-self-md-end{align-self:flex-end !important}.align-self-md-center{align-self:center !important}.align-self-md-baseline{align-self:baseline !important}.align-self-md-stretch{align-self:stretch !important}}@media (min-width: 992px){.flex-lg-row{flex-direction:row !important}.flex-lg-column{flex-direction:column !important}.flex-lg-row-reverse{flex-direction:row-reverse !important}.flex-lg-column-reverse{flex-direction:column-reverse !important}.flex-lg-wrap{flex-wrap:wrap !important}.flex-lg-nowrap{flex-wrap:nowrap !important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-lg-fill{flex:1 1 auto !important}.flex-lg-grow-0{flex-grow:0 !important}.flex-lg-grow-1{flex-grow:1 !important}.flex-lg-shrink-0{flex-shrink:0 !important}.flex-lg-shrink-1{flex-shrink:1 !important}.justify-content-lg-start{justify-content:flex-start !important}.justify-content-lg-end{justify-content:flex-end !important}.justify-content-lg-center{justify-content:center !important}.justify-content-lg-between{justify-content:space-between !important}.justify-content-lg-around{justify-content:space-around !important}.align-items-lg-start{align-items:flex-start !important}.align-items-lg-end{align-items:flex-end !important}.align-items-lg-center{align-items:center !important}.align-items-lg-baseline{align-items:baseline !important}.align-items-lg-stretch{align-items:stretch !important}.align-content-lg-start{align-content:flex-start !important}.align-content-lg-end{align-content:flex-end !important}.align-content-lg-center{align-content:center !important}.align-content-lg-between{align-content:space-between !important}.align-content-lg-around{align-content:space-around !important}.align-content-lg-stretch{align-content:stretch !important}.align-self-lg-auto{align-self:auto !important}.align-self-lg-start{align-self:flex-start !important}.align-self-lg-end{align-self:flex-end !important}.align-self-lg-center{align-self:center !important}.align-self-lg-baseline{align-self:baseline !important}.align-self-lg-stretch{align-self:stretch !important}}@media (min-width: 1200px){.flex-xl-row{flex-direction:row !important}.flex-xl-column{flex-direction:column !important}.flex-xl-row-reverse{flex-direction:row-reverse !important}.flex-xl-column-reverse{flex-direction:column-reverse !important}.flex-xl-wrap{flex-wrap:wrap !important}.flex-xl-nowrap{flex-wrap:nowrap !important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse !important}.flex-xl-fill{flex:1 1 auto !important}.flex-xl-grow-0{flex-grow:0 !important}.flex-xl-grow-1{flex-grow:1 !important}.flex-xl-shrink-0{flex-shrink:0 !important}.flex-xl-shrink-1{flex-shrink:1 !important}.justify-content-xl-start{justify-content:flex-start !important}.justify-content-xl-end{justify-content:flex-end !important}.justify-content-xl-center{justify-content:center !important}.justify-content-xl-between{justify-content:space-between !important}.justify-content-xl-around{justify-content:space-around !important}.align-items-xl-start{align-items:flex-start !important}.align-items-xl-end{align-items:flex-end !important}.align-items-xl-center{align-items:center !important}.align-items-xl-baseline{align-items:baseline !important}.align-items-xl-stretch{align-items:stretch !important}.align-content-xl-start{align-content:flex-start !important}.align-content-xl-end{align-content:flex-end !important}.align-content-xl-center{align-content:center !important}.align-content-xl-between{align-content:space-between !important}.align-content-xl-around{align-content:space-around !important}.align-content-xl-stretch{align-content:stretch !important}.align-self-xl-auto{align-self:auto !important}.align-self-xl-start{align-self:flex-start !important}.align-self-xl-end{align-self:flex-end !important}.align-self-xl-center{align-self:center !important}.align-self-xl-baseline{align-self:baseline !important}.align-self-xl-stretch{align-self:stretch !important}}.float-left{float:left !important}.float-right{float:right !important}.float-none{float:none !important}@media (min-width: 576px){.float-sm-left{float:left !important}.float-sm-right{float:right !important}.float-sm-none{float:none !important}}@media (min-width: 768px){.float-md-left{float:left !important}.float-md-right{float:right !important}.float-md-none{float:none !important}}@media (min-width: 992px){.float-lg-left{float:left !important}.float-lg-right{float:right !important}.float-lg-none{float:none !important}}@media (min-width: 1200px){.float-xl-left{float:left !important}.float-xl-right{float:right !important}.float-xl-none{float:none !important}}.user-select-all{user-select:all !important}.user-select-auto{user-select:auto !important}.user-select-none{user-select:none !important}.overflow-auto{overflow:auto !important}.overflow-hidden{overflow:hidden !important}.position-static{position:static !important}.position-relative{position:relative !important}.position-absolute{position:absolute !important}.position-fixed{position:fixed !important}.position-sticky{position:sticky !important}.fixed-top,.navbar-fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom,.navbar-fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports (position: sticky){.sticky-top,.navbar-sticky-top{position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}.shadow-sm{box-shadow:0 0.125rem 0.25rem rgba(0,0,0,0.075) !important}.shadow{box-shadow:0 0.5rem 1rem rgba(0,0,0,0.15) !important}.shadow-lg{box-shadow:0 1rem 3rem rgba(0,0,0,0.175) !important}.shadow-none{box-shadow:none !important}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mw-100{max-width:100% !important}.mh-100{max-height:100% !important}.min-vw-100{min-width:100vw !important}.min-vh-100{min-height:100vh !important}.vw-100{width:100vw !important}.vh-100{height:100vh !important}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:.25rem !important}.mt-1,.my-1{margin-top:.25rem !important}.mr-1,.mx-1{margin-right:.25rem !important}.mb-1,.my-1{margin-bottom:.25rem !important}.ml-1,.mx-1{margin-left:.25rem !important}.m-2{margin:.5rem !important}.mt-2,.my-2{margin-top:.5rem !important}.mr-2,.mx-2{margin-right:.5rem !important}.mb-2,.my-2{margin-bottom:.5rem !important}.ml-2,.mx-2{margin-left:.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:.25rem !important}.pt-1,.py-1{padding-top:.25rem !important}.pr-1,.px-1{padding-right:.25rem !important}.pb-1,.py-1{padding-bottom:.25rem !important}.pl-1,.px-1{padding-left:.25rem !important}.p-2{padding:.5rem !important}.pt-2,.py-2{padding-top:.5rem !important}.pr-2,.px-2{padding-right:.5rem !important}.pb-2,.py-2{padding-bottom:.5rem !important}.pl-2,.px-2{padding-left:.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-n1{margin:-.25rem !important}.mt-n1,.my-n1{margin-top:-.25rem !important}.mr-n1,.mx-n1{margin-right:-.25rem !important}.mb-n1,.my-n1{margin-bottom:-.25rem !important}.ml-n1,.mx-n1{margin-left:-.25rem !important}.m-n2{margin:-.5rem !important}.mt-n2,.my-n2{margin-top:-.5rem !important}.mr-n2,.mx-n2{margin-right:-.5rem !important}.mb-n2,.my-n2{margin-bottom:-.5rem !important}.ml-n2,.mx-n2{margin-left:-.5rem !important}.m-n3{margin:-1rem !important}.mt-n3,.my-n3{margin-top:-1rem !important}.mr-n3,.mx-n3{margin-right:-1rem !important}.mb-n3,.my-n3{margin-bottom:-1rem !important}.ml-n3,.mx-n3{margin-left:-1rem !important}.m-n4{margin:-1.5rem !important}.mt-n4,.my-n4{margin-top:-1.5rem !important}.mr-n4,.mx-n4{margin-right:-1.5rem !important}.mb-n4,.my-n4{margin-bottom:-1.5rem !important}.ml-n4,.mx-n4{margin-left:-1.5rem !important}.m-n5{margin:-3rem !important}.mt-n5,.my-n5{margin-top:-3rem !important}.mr-n5,.mx-n5{margin-right:-3rem !important}.mb-n5,.my-n5{margin-bottom:-3rem !important}.ml-n5,.mx-n5{margin-left:-3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media (min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:.25rem !important}.mt-sm-1,.my-sm-1{margin-top:.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:.25rem !important}.m-sm-2{margin:.5rem !important}.mt-sm-2,.my-sm-2{margin-top:.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:.5rem !important}.m-sm-3{margin:1rem !important}.mt-sm-3,.my-sm-3{margin-top:1rem !important}.mr-sm-3,.mx-sm-3{margin-right:1rem !important}.mb-sm-3,.my-sm-3{margin-bottom:1rem !important}.ml-sm-3,.mx-sm-3{margin-left:1rem !important}.m-sm-4{margin:1.5rem !important}.mt-sm-4,.my-sm-4{margin-top:1.5rem !important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem !important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem !important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem !important}.m-sm-5{margin:3rem !important}.mt-sm-5,.my-sm-5{margin-top:3rem !important}.mr-sm-5,.mx-sm-5{margin-right:3rem !important}.mb-sm-5,.my-sm-5{margin-bottom:3rem !important}.ml-sm-5,.mx-sm-5{margin-left:3rem !important}.p-sm-0{padding:0 !important}.pt-sm-0,.py-sm-0{padding-top:0 !important}.pr-sm-0,.px-sm-0{padding-right:0 !important}.pb-sm-0,.py-sm-0{padding-bottom:0 !important}.pl-sm-0,.px-sm-0{padding-left:0 !important}.p-sm-1{padding:.25rem !important}.pt-sm-1,.py-sm-1{padding-top:.25rem !important}.pr-sm-1,.px-sm-1{padding-right:.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem !important}.pl-sm-1,.px-sm-1{padding-left:.25rem !important}.p-sm-2{padding:.5rem !important}.pt-sm-2,.py-sm-2{padding-top:.5rem !important}.pr-sm-2,.px-sm-2{padding-right:.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem !important}.pl-sm-2,.px-sm-2{padding-left:.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-n1{margin:-.25rem !important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem !important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem !important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem !important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem !important}.m-sm-n2{margin:-.5rem !important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem !important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem !important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem !important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem !important}.m-sm-n3{margin:-1rem !important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem !important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem !important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem !important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem !important}.m-sm-n4{margin:-1.5rem !important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem !important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem !important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem !important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem !important}.m-sm-n5{margin:-3rem !important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem !important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem !important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem !important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:.25rem !important}.mt-md-1,.my-md-1{margin-top:.25rem !important}.mr-md-1,.mx-md-1{margin-right:.25rem !important}.mb-md-1,.my-md-1{margin-bottom:.25rem !important}.ml-md-1,.mx-md-1{margin-left:.25rem !important}.m-md-2{margin:.5rem !important}.mt-md-2,.my-md-2{margin-top:.5rem !important}.mr-md-2,.mx-md-2{margin-right:.5rem !important}.mb-md-2,.my-md-2{margin-bottom:.5rem !important}.ml-md-2,.mx-md-2{margin-left:.5rem !important}.m-md-3{margin:1rem !important}.mt-md-3,.my-md-3{margin-top:1rem !important}.mr-md-3,.mx-md-3{margin-right:1rem !important}.mb-md-3,.my-md-3{margin-bottom:1rem !important}.ml-md-3,.mx-md-3{margin-left:1rem !important}.m-md-4{margin:1.5rem !important}.mt-md-4,.my-md-4{margin-top:1.5rem !important}.mr-md-4,.mx-md-4{margin-right:1.5rem !important}.mb-md-4,.my-md-4{margin-bottom:1.5rem !important}.ml-md-4,.mx-md-4{margin-left:1.5rem !important}.m-md-5{margin:3rem !important}.mt-md-5,.my-md-5{margin-top:3rem !important}.mr-md-5,.mx-md-5{margin-right:3rem !important}.mb-md-5,.my-md-5{margin-bottom:3rem !important}.ml-md-5,.mx-md-5{margin-left:3rem !important}.p-md-0{padding:0 !important}.pt-md-0,.py-md-0{padding-top:0 !important}.pr-md-0,.px-md-0{padding-right:0 !important}.pb-md-0,.py-md-0{padding-bottom:0 !important}.pl-md-0,.px-md-0{padding-left:0 !important}.p-md-1{padding:.25rem !important}.pt-md-1,.py-md-1{padding-top:.25rem !important}.pr-md-1,.px-md-1{padding-right:.25rem !important}.pb-md-1,.py-md-1{padding-bottom:.25rem !important}.pl-md-1,.px-md-1{padding-left:.25rem !important}.p-md-2{padding:.5rem !important}.pt-md-2,.py-md-2{padding-top:.5rem !important}.pr-md-2,.px-md-2{padding-right:.5rem !important}.pb-md-2,.py-md-2{padding-bottom:.5rem !important}.pl-md-2,.px-md-2{padding-left:.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-n1{margin:-.25rem !important}.mt-md-n1,.my-md-n1{margin-top:-.25rem !important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem !important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem !important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem !important}.m-md-n2{margin:-.5rem !important}.mt-md-n2,.my-md-n2{margin-top:-.5rem !important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem !important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem !important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem !important}.m-md-n3{margin:-1rem !important}.mt-md-n3,.my-md-n3{margin-top:-1rem !important}.mr-md-n3,.mx-md-n3{margin-right:-1rem !important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem !important}.ml-md-n3,.mx-md-n3{margin-left:-1rem !important}.m-md-n4{margin:-1.5rem !important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem !important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem !important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem !important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem !important}.m-md-n5{margin:-3rem !important}.mt-md-n5,.my-md-n5{margin-top:-3rem !important}.mr-md-n5,.mx-md-n5{margin-right:-3rem !important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem !important}.ml-md-n5,.mx-md-n5{margin-left:-3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media (min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:.25rem !important}.mt-lg-1,.my-lg-1{margin-top:.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:.25rem !important}.m-lg-2{margin:.5rem !important}.mt-lg-2,.my-lg-2{margin-top:.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:.5rem !important}.m-lg-3{margin:1rem !important}.mt-lg-3,.my-lg-3{margin-top:1rem !important}.mr-lg-3,.mx-lg-3{margin-right:1rem !important}.mb-lg-3,.my-lg-3{margin-bottom:1rem !important}.ml-lg-3,.mx-lg-3{margin-left:1rem !important}.m-lg-4{margin:1.5rem !important}.mt-lg-4,.my-lg-4{margin-top:1.5rem !important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem !important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem !important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem !important}.m-lg-5{margin:3rem !important}.mt-lg-5,.my-lg-5{margin-top:3rem !important}.mr-lg-5,.mx-lg-5{margin-right:3rem !important}.mb-lg-5,.my-lg-5{margin-bottom:3rem !important}.ml-lg-5,.mx-lg-5{margin-left:3rem !important}.p-lg-0{padding:0 !important}.pt-lg-0,.py-lg-0{padding-top:0 !important}.pr-lg-0,.px-lg-0{padding-right:0 !important}.pb-lg-0,.py-lg-0{padding-bottom:0 !important}.pl-lg-0,.px-lg-0{padding-left:0 !important}.p-lg-1{padding:.25rem !important}.pt-lg-1,.py-lg-1{padding-top:.25rem !important}.pr-lg-1,.px-lg-1{padding-right:.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem !important}.pl-lg-1,.px-lg-1{padding-left:.25rem !important}.p-lg-2{padding:.5rem !important}.pt-lg-2,.py-lg-2{padding-top:.5rem !important}.pr-lg-2,.px-lg-2{padding-right:.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem !important}.pl-lg-2,.px-lg-2{padding-left:.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-n1{margin:-.25rem !important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem !important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem !important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem !important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem !important}.m-lg-n2{margin:-.5rem !important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem !important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem !important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem !important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem !important}.m-lg-n3{margin:-1rem !important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem !important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem !important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem !important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem !important}.m-lg-n4{margin:-1.5rem !important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem !important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem !important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem !important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem !important}.m-lg-n5{margin:-3rem !important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem !important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem !important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem !important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media (min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:.25rem !important}.mt-xl-1,.my-xl-1{margin-top:.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:.25rem !important}.m-xl-2{margin:.5rem !important}.mt-xl-2,.my-xl-2{margin-top:.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:.5rem !important}.m-xl-3{margin:1rem !important}.mt-xl-3,.my-xl-3{margin-top:1rem !important}.mr-xl-3,.mx-xl-3{margin-right:1rem !important}.mb-xl-3,.my-xl-3{margin-bottom:1rem !important}.ml-xl-3,.mx-xl-3{margin-left:1rem !important}.m-xl-4{margin:1.5rem !important}.mt-xl-4,.my-xl-4{margin-top:1.5rem !important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem !important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem !important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem !important}.m-xl-5{margin:3rem !important}.mt-xl-5,.my-xl-5{margin-top:3rem !important}.mr-xl-5,.mx-xl-5{margin-right:3rem !important}.mb-xl-5,.my-xl-5{margin-bottom:3rem !important}.ml-xl-5,.mx-xl-5{margin-left:3rem !important}.p-xl-0{padding:0 !important}.pt-xl-0,.py-xl-0{padding-top:0 !important}.pr-xl-0,.px-xl-0{padding-right:0 !important}.pb-xl-0,.py-xl-0{padding-bottom:0 !important}.pl-xl-0,.px-xl-0{padding-left:0 !important}.p-xl-1{padding:.25rem !important}.pt-xl-1,.py-xl-1{padding-top:.25rem !important}.pr-xl-1,.px-xl-1{padding-right:.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem !important}.pl-xl-1,.px-xl-1{padding-left:.25rem !important}.p-xl-2{padding:.5rem !important}.pt-xl-2,.py-xl-2{padding-top:.5rem !important}.pr-xl-2,.px-xl-2{padding-right:.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem !important}.pl-xl-2,.px-xl-2{padding-left:.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-n1{margin:-.25rem !important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem !important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem !important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem !important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem !important}.m-xl-n2{margin:-.5rem !important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem !important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem !important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem !important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem !important}.m-xl-n3{margin:-1rem !important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem !important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem !important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem !important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem !important}.m-xl-n4{margin:-1.5rem !important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem !important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem !important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem !important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem !important}.m-xl-n5{margin:-3rem !important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem !important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem !important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem !important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;pointer-events:auto;content:"";background-color:rgba(0,0,0,0)}.text-monospace{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace !important}.text-justify{text-align:justify !important}.text-wrap{white-space:normal !important}.text-nowrap{white-space:nowrap !important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left !important}.text-right{text-align:right !important}.text-center{text-align:center !important}@media (min-width: 576px){.text-sm-left{text-align:left !important}.text-sm-right{text-align:right !important}.text-sm-center{text-align:center !important}}@media (min-width: 768px){.text-md-left{text-align:left !important}.text-md-right{text-align:right !important}.text-md-center{text-align:center !important}}@media (min-width: 992px){.text-lg-left{text-align:left !important}.text-lg-right{text-align:right !important}.text-lg-center{text-align:center !important}}@media (min-width: 1200px){.text-xl-left{text-align:left !important}.text-xl-right{text-align:right !important}.text-xl-center{text-align:center !important}}.text-lowercase{text-transform:lowercase !important}.text-uppercase{text-transform:uppercase !important}.text-capitalize{text-transform:capitalize !important}.font-weight-light{font-weight:300 !important}.font-weight-lighter{font-weight:lighter !important}.font-weight-normal{font-weight:400 !important}.font-weight-bold{font-weight:700 !important}.font-weight-bolder{font-weight:bolder !important}.font-italic{font-style:italic !important}.text-white{color:#fff !important}.text-default{color:#dee2e6 !important}a.text-default:hover,a.text-default:focus{color:#b2bcc5 !important}.text-primary{color:#096B72 !important}a.text-primary:hover,a.text-primary:focus{color:#03282b !important}.text-secondary{color:#6c757d !important}a.text-secondary:hover,a.text-secondary:focus{color:#494f54 !important}.text-success{color:#28a745 !important}a.text-success:hover,a.text-success:focus{color:#19692c !important}.text-info{color:#17a2b8 !important}a.text-info:hover,a.text-info:focus{color:#0f6674 !important}.text-warning{color:#ffc107 !important}a.text-warning:hover,a.text-warning:focus{color:#ba8b00 !important}.text-danger{color:#dc3545 !important}a.text-danger:hover,a.text-danger:focus{color:#a71d2a !important}.text-light{color:#f8f9fa !important}a.text-light:hover,a.text-light:focus{color:#cbd3da !important}.text-dark{color:#343a40 !important}a.text-dark:hover,a.text-dark:focus{color:#121416 !important}.text-body{color:#212529 !important}.text-muted,.help-text,.help-block{color:#6c757d !important}.text-black-50{color:rgba(0,0,0,0.5) !important}.text-white-50{color:rgba(255,255,255,0.5) !important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.text-decoration-none{text-decoration:none !important}.text-break{word-break:break-word !important;word-wrap:break-word !important}.text-reset{color:inherit !important}.visible{visibility:visible !important}.invisible{visibility:hidden !important}@media print{*,*::before,*::after{text-shadow:none !important;box-shadow:none !important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap !important}pre,blockquote{border:1px solid #adb5bd;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px !important}.container{min-width:992px !important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #dee2e6 !important}.table-dark{color:inherit}.table-dark th,.table-dark td,.table-dark thead th,.table-dark tbody+tbody{border-color:#dee2e6}.table .thead-dark th{color:inherit;border-color:#dee2e6}}.table th[align=left]{text-align:left}.table th[align=right]{text-align:right}.table th[align=center]{text-align:center}.well{display:block;background-color:rgba(0,0,0,0.03);color:#212529;padding:1.25rem;border-radius:.25rem}.well-lg{padding:1.5rem;border-radius:.3rem}.well-sm{padding:0.5rem;border-radius:.2rem}.draggable .well{background-color:#f7f7f7}.dropdown-menu>li.active>a{color:#fff;text-decoration:none;background-color:#096B72}.navbar .nav.nav-underline{--bs-navbar-nav-link-padding-x: 0}.navbar:not(.fixed-bottom):not(.navbar-fixed-bottom):not(.navbar-fixed-bottom)+div>.tab-content>.tab-pane{--bslib-navbar-margin: 20px;margin-top:var(--bslib-navbar-margin)}ul.nav.navbar-nav{flex:1;-webkit-flex:1}ul.nav.navbar-nav.navbar-right{flex:unset;-webkit-flex:unset;display:flex;display:-webkit-flex;justify-content:flex-end;-webkit-justify-content:flex-end}:where(ul.nav.navbar-nav > li).active>a,:where(ul.nav.navbar-nav > li).show>a,.in:where(ul.nav.navbar-nav > li)>a{color:var(--bs-navbar-active-color)}:where(ul.nav.navbar-nav > li).bslib-nav-item{color:var(--bs-navbar-active-color)}:root{--bslib-navbar-light-bg: var(--bslib-navbar-default-bg, var(--bs-light));--bslib-navbar-dark-bg: var(--bslib-navbar-inverse-bg, var(--bs-black))}.navbar{--bslib-navbar-light-bg: #f8f9fa;--bslib-navbar-dark-bg: #343a40}.navbar.navbar-default{background-color:var(--bslib-navbar-light-bg) !important}.navbar.navbar-inverse{background-color:var(--bslib-navbar-dark-bg) !important}.navbar-toggle>.icon-bar{display:none}@media (max-width: 575.98px){.navbar-header{width:100%}.navbar-header .navbar-toggle{float:right}}.nav-tabs>li.active>a{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-pills>li.active>a{color:#fff;background-color:#096B72}.nav-stacked{flex-direction:column;-webkit-flex-direction:column}.progress-bar-default{background-color:#dee2e6;color:#000}.progress-bar-primary{background-color:#096B72;color:#fff}.progress-bar-secondary{background-color:#6c757d;color:#fff}.progress-bar-success{background-color:#28a745;color:#fff}.progress-bar-info{background-color:#17a2b8;color:#fff}.progress-bar-warning{background-color:#ffc107;color:#000}.progress-bar-danger{background-color:#dc3545;color:#fff}.progress-bar-light{background-color:#f8f9fa;color:#000}.progress-bar-dark{background-color:#343a40;color:#fff}@font-face{font-family:'Glyphicons Halflings';src:url("fonts/bootstrap/glyphicons-halflings-regular.eot");src:url("fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),url("fonts/bootstrap/glyphicons-halflings-regular.woff2") format("woff2"),url("fonts/bootstrap/glyphicons-halflings-regular.woff") format("woff"),url("fonts/bootstrap/glyphicons-halflings-regular.ttf") format("truetype"),url("fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}.form-group{margin-bottom:1rem}.shiny-input-checkboxgroup .checkbox-inline,.shiny-input-checkboxgroup .radio-inline,.shiny-input-radiogroup .checkbox-inline,.shiny-input-radiogroup .radio-inline{padding-left:0;margin-right:.75rem}.shiny-input-checkboxgroup .checkbox-inline label>input,.shiny-input-checkboxgroup .radio-inline label>input,.shiny-input-radiogroup .checkbox-inline label>input,.shiny-input-radiogroup .radio-inline label>input{margin-top:0;margin-right:.3125rem;margin-bottom:0}.input-daterange .input-group-addon.input-group-prepend.input-group-append{padding:inherit;line-height:inherit;text-shadow:inherit;border-width:0}.input-daterange .input-group-addon.input-group-prepend.input-group-append .input-group-text{border-radius:0}.shiny-input-checkboxgroup .checkbox-inline,.shiny-input-radiogroup .radio-inline{cursor:pointer}pre.shiny-code{padding:0.5rem}h1,h2,h3{margin-top:1.5rem}h4,h5,h6{margin-top:1rem}:root{--bslib-spacer: 1rem;--bslib-mb-spacer: var(--bslib-spacer, 1rem)}.bslib-mb-spacing{margin-bottom:var(--bslib-mb-spacer)}.bslib-gap-spacing{gap:var(--bslib-mb-spacer)}.bslib-gap-spacing>.bslib-mb-spacing,.bslib-gap-spacing>.form-group,.bslib-gap-spacing>p,.bslib-gap-spacing>pre,.bslib-gap-spacing>.shiny-html-output>.bslib-mb-spacing,.bslib-gap-spacing>.shiny-html-output>.form-group,.bslib-gap-spacing>.shiny-html-output>p,.bslib-gap-spacing>.shiny-html-output>pre,.bslib-gap-spacing>.shiny-panel-conditional>.bslib-mb-spacing,.bslib-gap-spacing>.shiny-panel-conditional>.form-group,.bslib-gap-spacing>.shiny-panel-conditional>p,.bslib-gap-spacing>.shiny-panel-conditional>pre{margin-bottom:0}.html-fill-container>.html-fill-item.bslib-mb-spacing{margin-bottom:0}.tab-content>.tab-pane.html-fill-container{display:none}.tab-content>.active.html-fill-container{display:flex}.tab-content.html-fill-container{padding:0}.nav-link[disabled],:where(ul.nav.navbar-nav > li)>a[disabled],.nav-tabs>li>a[disabled],.nav-pills>li>a[disabled]{display:none !important} diff --git a/docs/libs/bs3compat-0.11.0/bs3compat.js b/docs/libs/bs3compat-0.11.0/bs3compat.js new file mode 100644 index 0000000..4f029dc --- /dev/null +++ b/docs/libs/bs3compat-0.11.0/bs3compat.js @@ -0,0 +1,48 @@ +// Inform the world that we have the ability to use BS3 nav/navbar markup in BS4 +window.BS3_COMPAT = true; + +// This logic needs to execute after both the BS4+ (new) as well as BS3 (legacy) +// jQuery plugins have been registered. For BS5, plugin registration happens +// after DOM content is loaded, which is why we do the same here. +// https://github.com/twbs/bootstrap/blob/08139c22/js/dist/tab.js#L87 +$(function() { + + // The legacy plugin needs to be registered after the new one + if (!$.fn.tab.Constructor.VERSION.match(/^3\./)) { + (console.warn || console.error || console.log)("bs3compat.js couldn't find bs3 tab impl; bs3 tabs will not be properly supported"); + return; + } + var legacyTabPlugin = $.fn.tab.noConflict(); + + if (!$.fn.tab || !$.fn.tab.Constructor || !$.fn.tab.noConflict) { + (console.warn || console.error || console.log)("bs3compat.js couldn't find a jQuery tab impl; bs3 tabs will not be properly supported"); + } + var newTabPlugin = $.fn.tab.noConflict(); + + // Re-define the tab click event + // https://github.com/twbs/bootstrap/blob/08139c2/js/src/tab.js#L33 + var EVENT_KEY = "click.bs.tab.data-api"; + $(document).off(EVENT_KEY); + + var SELECTOR = '[data-toggle="tab"], [data-toggle="pill"], [data-bs-toggle="tab"], [data-bs-toggle="pill"]'; + $(document).on(EVENT_KEY, SELECTOR, function(event) { + event.preventDefault(); + $(this).tab("show"); + }); + + function TabPlugin(config) { + // Legacy (bs3) tabs: li.active > a + // New (bs4+) tabs: li.nav-item > a.active.nav-link + var legacy = $(this).closest(".nav").find("li:not(.dropdown).active > a").length > 0; + var plugin = legacy ? legacyTabPlugin : newTabPlugin; + plugin.call($(this), config); + } + + var noconflict = $.fn.tab; + $.fn.tab = TabPlugin; + $.fn.tab.Constructor = newTabPlugin.Constructor; + $.fn.tab.noConflict = function() { + $.fn.tab = noconflict; + return TabPlugin; + }; +}); diff --git a/docs/libs/bs3compat-0.11.0/tabs.js b/docs/libs/bs3compat-0.11.0/tabs.js new file mode 100644 index 0000000..79825cc --- /dev/null +++ b/docs/libs/bs3compat-0.11.0/tabs.js @@ -0,0 +1,157 @@ +/* ======================================================================== + * Bootstrap: tab.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#tabs + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + +// Register tab plugin after DOM content loaded in order to +// override BS5's plugin +// https://github.com/twbs/bootstrap/blob/08139c22/js/dist/tab.js#L87 +$(function() { + 'use strict'; + + // TAB CLASS DEFINITION + // ==================== + + var Tab = function (element) { + // jscs:disable requireDollarBeforejQueryAssignment + this.element = $(element) + // jscs:enable requireDollarBeforejQueryAssignment + } + + Tab.VERSION = '3.4.1' + + Tab.TRANSITION_DURATION = 150 + + Tab.prototype.show = function () { + var $this = this.element + var $ul = $this.closest('ul:not(.dropdown-menu)') + var selector = $this.data('target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + if ($this.parent('li').hasClass('active')) return + + var $previous = $ul.find('.active:last a') + var hideEvent = $.Event('hide.bs.tab', { + relatedTarget: $this[0] + }) + var showEvent = $.Event('show.bs.tab', { + relatedTarget: $previous[0] + }) + + $previous.trigger(hideEvent) + $this.trigger(showEvent) + + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return + + var $target = $(document).find(selector) + + this.activate($this.closest('li'), $ul) + this.activate($target, $target.parent(), function () { + $previous.trigger({ + type: 'hidden.bs.tab', + relatedTarget: $this[0] + }) + $this.trigger({ + type: 'shown.bs.tab', + relatedTarget: $previous[0] + }) + }) + } + + Tab.prototype.activate = function (element, container, callback) { + var $active = container.find('> .active') + var transition = callback + && $.support.transition + && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) + + function next() { + $active + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', false) + + element + .addClass('active') + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + + if (transition) { + element[0].offsetWidth // reflow for transition + element.addClass('in') + } else { + element.removeClass('fade') + } + + if (element.parent('.dropdown-menu').length) { + element + .closest('li.dropdown') + .addClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + } + + callback && callback() + } + + $active.length && transition ? + $active + .one('bsTransitionEnd', next) + .emulateTransitionEnd(Tab.TRANSITION_DURATION) : + next() + + $active.removeClass('in') + } + + + // TAB PLUGIN DEFINITION + // ===================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tab') + + if (!data) $this.data('bs.tab', (data = new Tab(this))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tab + + $.fn.tab = Plugin + $.fn.tab.Constructor = Tab + + + // TAB NO CONFLICT + // =============== + + $.fn.tab.noConflict = function () { + $.fn.tab = old + return this + } + + + // TAB DATA-API + // ============ + + var clickHandler = function (e) { + e.preventDefault() + Plugin.call($(this), 'show') + } + + $(document) + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) + +}); diff --git a/docs/libs/bs3compat-0.11.0/transition.js b/docs/libs/bs3compat-0.11.0/transition.js new file mode 100644 index 0000000..81e7122 --- /dev/null +++ b/docs/libs/bs3compat-0.11.0/transition.js @@ -0,0 +1,59 @@ +/* ======================================================================== + * Bootstrap: transition.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#transitions + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/v3-dev/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/) + // ============================================================ + + function transitionEnd() { + var el = document.createElement('bootstrap') + + var transEndEventNames = { + WebkitTransition : 'webkitTransitionEnd', + MozTransition : 'transitionend', + OTransition : 'oTransitionEnd otransitionend', + transition : 'transitionend' + } + + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { end: transEndEventNames[name] } + } + } + + return false // explicit for ie8 ( ._.) + } + + // https://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false + var $el = this + $(this).one('bsTransitionEnd', function () { called = true }) + var callback = function () { if (!called) $($el).trigger($.support.transition.end) } + setTimeout(callback, duration) + return this + } + + $(function () { + $.support.transition = transitionEnd() + + if (!$.support.transition) return + + $.event.special.bsTransitionEnd = { + bindType: $.support.transition.end, + delegateType: $.support.transition.end, + handle: function (e) { + if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) + } + } + }) + +}(jQuery); diff --git a/docs/merge-conflict.html b/docs/merge-conflict.html new file mode 100644 index 0000000..545faac --- /dev/null +++ b/docs/merge-conflict.html @@ -0,0 +1,149 @@ + + + + + + +Глава 11 Слияние и конфликт | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 11 Слияние и конфликт +

+

Сейчас main и boxplot по-разному изменили одну строку paper.qmd. Объединим ветки и разрешим конфликт осознанно.

+

Переключитесь на main. Откройте палитру команд, выполните Git: Merge Branch и выберите boxplot.

+

Git автоматически объединит независимые изменения, но остановится на paper.qmd: обе ветки изменили код графика, и программа не знает, какой вариант нужен.

+

В Source Control файл появится в разделе Merge Changes с предупреждением. Это незавершённое слияние, а не повреждение проекта.

+
+Source Control после Git: Merge Branch: paper.qmd находится в Merge Changes, слияние ожидает решения
Source Control после Git: Merge Branch: paper.qmd находится в Merge Changes, слияние ожидает решения
+
+
+

+11.1 Редактор слияний +

+

Нажмите paper.qmd правой кнопкой и выберите Open in Merge Editor. Редактор показывает три области:

+
    +
  • +Incoming — изменение из boxplot;
  • +
  • +Current — изменение из main;
  • +
  • +Result — итог, который будет записан.
  • +
+

В Result оставьте боксплот из Incoming и добавьте к нему подпись из Current:

+
+png("out/penguins-boxplot.png")
+boxplot(x, ylab = "Bill length, mm")
+dev.off()
+

Нажмите Complete Merge. Убедитесь, что в Result нет строк <<<<<<<, ======= и >>>>>>>, а paper.qmd находится в Staged Changes.

+
+Редактор слияний Positron: Incoming содержит boxplot, Current — hist с подписью, Result — boxplot с ylab
Редактор слияний Positron: Incoming содержит boxplot, Current — hist с подписью, Result — boxplot с ylab
+
+

Обновите out/penguins-boxplot.png, добавьте его в индекс и создайте коммит Слил ветку boxplot.

+

Если нужно отказаться от всего слияния, выполните Git: Abort Merge из палитры команд. Git вернёт проект к состоянию до попытки merge.

+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/open-project.html b/docs/open-project.html new file mode 100644 index 0000000..d1afb0a --- /dev/null +++ b/docs/open-project.html @@ -0,0 +1,140 @@ + + + + + + +Глава 5 Открытие проекта | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 5 Открытие проекта +

+

На экране Welcome в Positron выберите Open Folder и откройте папку r-course. Убедитесь, что в Explorer видны накопленные файлы R-курса, в том числе папка data.

+

Откройте Source Control на панели активности слева. У изменённых файлов стоят обозначения состояния: U у ещё не отслеживаемых и M у изменённых.

+
+Окно Positron с открытым проектом r-course: в Explorer видны накопленные файлы, а в Source Control перечислены незафиксированные изменения
Окно Positron с открытым проектом r-course: в Explorer видны накопленные файлы, а в Source Control перечислены незафиксированные изменения
+
+

Если Source Control уже показывает файлы, репозиторий готов. Не нажимайте Initialize Repository повторно и не удаляйте .git.

+
+

+5.1 Если репозитория нет +

+

В старой версии R-курса проект мог быть создан без Git. Тогда Source Control покажет кнопку Initialize Repository. Нажмите её один раз. Positron создаст .git и начнёт показывать изменения.

+

Официальная документация Positron описывает те же шаги: открыть папку, перейти в Source Control и выбрать Initialize Repository.

+
+
+

+5.2 Что сейчас видит Git +

+

Все накопленные файлы ещё не входят ни в один коммит. Это не ошибка и не повод чистить проект. В следующей главе сделаем один исходный коммит, который станет точкой отсчёта для новой работы.

+
+

Не переводите старые .R-файлы в .qmd, не удаляйте дополнительные данные и не заменяйте результаты. Исходный коммит должен быть точной фиксацией конца R-курса.

+
+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/pr.html b/docs/pr.html deleted file mode 100644 index 46ea555..0000000 --- a/docs/pr.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - -Глава 17 Pull Request | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 17 Pull Request -

-

Pull Request — это механизм GitHub для слияния веток загруженных в удаленный репозиторий, позволяющий просмотреть, обсудить и проверить предлагаемые изменения перед слиянием. Похожий механизм существует и на других платформах.

-

Орнитолог проходящий мимо нашего репозитория обратит внимание, что длину клюва пингвина лучше рассматривать в зависимости от пола. Он даже может предложить необходимые изменения при помощи Pull Request.

-

Создайте ветку с названием adjust-by-sex при помощи кнопки New branch на панели Git в RStudio. Убедитесь, что справа от кнопки вместо названия ветки по умолчанию main выводится название созданной ветки adjust-by-sex.

-
-

Отредактируйте скрипт penguins.R, добавив пол в код для построения ящика с усами. Код приведен ниже, не забывайте, что вы можете сравнить изменения по сравнению с оригиналом при помощи кнопки Diff на панели Git.

-
-data <- read.csv("penguins.csv")
-x <- data$bill_length_mm
-g <- data$sex
-
-png("penguins-boxplot.png")
-boxplot(x ~ g, xlab = "Sex", ylab = "Bill length, mm")
-dev.off()
-

Сохраните и выполните скрипт penguins.R. -Создайте коммит включив в него скрипт и обновленную диаграмму penguins-boxplot.png.

-
-

После создания коммита нажмите кнопку Push в верхнем правом углу или на панели Git. Так как у вас полные права на редактирование репозитория, то новая ветка будет загружена на GitHub. Прохожему орнитологу пришлось бы создать свою копию репозитория или просить дать доступ средствами GitHub.

-

Перейдите на страницу репозитория в GitHub и убедитесь, что ветка была загружена и содержит сделанные измнения, для этого выберите ее в выпадающем меню появляющемся при нажатии кнопки с названием ветки main.

-
-

При просмотре ветки отличной от основной, GitHub предложит создать из нее Pull Request — предложение автору репозитория слить изменения из этой ветки. Нажмите кнопку Contribute и в выпадающем меню выберите Open pull request.

-
-

GitHub предложит ввести заголовок и описание предлагаемых изменений, правило хорошего тона кратко описать причину изменений и суть предлагаемого решения. А также, прокрутите страницу создания Pull Request и проверьте изменения, которые вы предлагаете, после чего нажмите кнопку Create pull Request под полем с описанием.

-
-

На странице Pull Request владельцу репозитория доступна опция слить предложенные изменения. -Нажмите кнопку Merge pull request внизу страницы. -В открывшемся окне GitHub предложить ввести текст коммита, как если бы мы делали слияние ветки в терминале. Оставьте или измените текст и нажмите кнопку Confirm merge -После успешного слияния ветку можно удалить.

-

-

Вернемся к нашему проекту в RStudio. -Слияние было выполнено онлайн на GitHub, а значит необходимо загрузить изменения в наш локальный репозиторий, т.е. сделать pull. -Переключитесь на ветку main при помощи панели Git и нажмите кнопку Pull. -Убедитесь, что теперь ветка main содержит актуальные изменения в файлах penguins.R и penguins-boxplot.png.

- -
-
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/publish-github.html b/docs/publish-github.html new file mode 100644 index 0000000..f3ba71c --- /dev/null +++ b/docs/publish-github.html @@ -0,0 +1,132 @@ + + + + + + +Глава 14 Публикация репозитория | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 14 Публикация репозитория +

+

Убедитесь, что выбрана ветка main, Source Control пуст и последний коммит — Слил ветку boxplot.

+

В Source Control нажмите Publish to GitHub. Если кнопка не видна, откройте палитру команд и найдите Publish to GitHub.

+

Выберите имя репозитория, например r-course, и доступ Private repository. Для учебного проекта приватный режим безопаснее: открыть репозиторий позже можно в настройках GitHub.

+

Если Positron предложит выбрать файлы, оставьте все уже отслеживаемые файлы. В проекте не должно быть секретов.

+
+Диалог Publish to GitHub с именем r-course и выбранным вариантом Private repository
Диалог Publish to GitHub с именем r-course и выбранным вариантом Private repository
+
+

Positron выполнит три связанных действия:

+
    +
  1. создаст репозиторий на GitHub;
  2. +
  3. добавит его как удалённый репозиторий origin;
  4. +
  5. отправит коммиты ветки main.
  6. +
+

После публикации откройте созданный репозиторий на GitHub и сравните список файлов с Explorer. Убедитесь, что на сайте есть paper.qmd, папка data и история коммитов.

+

Удалённый репозиторий (remote) — адрес другой копии проекта. Имя origin условное, но Git назначает его основной удалённой копии при публикации и клонировании.

+
+

GitHub не выполняет код Quarto при обычной отправке. Файлы и история появятся на сервере, но готовый сайт требует отдельной настройки публикации.

+
+ +
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/pull-request.html b/docs/pull-request.html new file mode 100644 index 0000000..e524e10 --- /dev/null +++ b/docs/pull-request.html @@ -0,0 +1,167 @@ + + + + + + +Глава 16 Pull request | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 16 Pull request +

+

Pull request — предложение объединить одну ветку с другой на GitHub. Перед слиянием коллеги могут посмотреть diff, обсудить решение и запустить проверки.

+
+

+16.1 Изменение в ветке +

+

Создайте от актуальной main ветку adjust-by-sex. В paper.qmd замените блок кода:

+
+data <- read.csv("data/penguins.csv")
+x <- data$bill_len
+g <- data$sex
+
+png("out/penguins-boxplot.png")
+boxplot(x ~ g, xlab = "Sex", ylab = "Bill length, mm")
+dev.off()
+

Соберите документ, проверьте обновлённый график и создайте коммит Сгруппировал пингвинов по полу.

+

Нажмите Publish Branch. Это создаст adjust-by-sex в origin и свяжет локальную ветку с удалённой.

+
+Ветка adjust-by-sex после Publish Branch: Source Control Graph показывает локальную и удалённую ветки на одном коммите
Ветка adjust-by-sex после Publish Branch: Source Control Graph показывает локальную и удалённую ветки на одном коммите
+
+
+
+

+16.2 Создание предложения +

+

Откройте представление Pull Requests на панели активности. Нажмите Create Pull Request или выполните команду GitHub Pull Requests: Create Pull Request.

+

Выберите:

+
    +
  • базовый репозиторий — ваш r-course;
  • +
  • базовую ветку — main;
  • +
  • ветку с изменением — adjust-by-sex;
  • +
  • заголовок — Сгруппировал пингвинов по полу.
  • +
+

В описании объясните причину: распределение длины клюва теперь показано отдельно для каждого пола. Перед созданием откройте список файлов и проверьте diff.

+
+Форма Create Pull Request в Positron: base main, compare adjust-by-sex, заполнены заголовок и описание
Форма Create Pull Request в Positron: base main, compare adjust-by-sex, заполнены заголовок и описание
+
+

Нажмите Create. Откроется режим просмотра pull request. Здесь можно оставить комментарий к строке, запросить проверку и увидеть обсуждение.

+
+
+

+16.3 Слияние +

+

Нажмите Merge только после проверки файлов. Выберите обычное создание merge-коммита, затем подтвердите операцию. После успешного слияния удалите ветку, когда Positron предложит это сделать.

+

Переключитесь на локальную main и выполните Pull. Убедитесь, что paper.qmd содержит группировку по полу, а Source Control Graph — коммит слияния с GitHub.

+
+Локальная main после Pull: в paper.qmd код boxplot по sex, в Graph виден слитый pull request
Локальная main после Pull: в paper.qmd код boxplot по sex, в Graph виден слитый pull request
+
+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/reference-keys.txt b/docs/reference-keys.txt index b8f1342..ba823b9 100644 --- a/docs/reference-keys.txt +++ b/docs/reference-keys.txt @@ -1,40 +1,51 @@ -основы-git -about -install -terminal -windows -mac-os -linux -setup -git-init -git-commit -git-commit2 -импорт-данных -визуализация -экспорт -git-log -branch -git-branch -git-checkout -git-merge -заключение -тематические-ветки-feature-branch -долгоживущие-ветки-long-running-branches -когда-не-стоит-использовать-ветки -github -регистрация-на-github -создание-токена -git-remote -git-push-pull -pr -git-clone -заключение-1 +основы-git-в-positron +about-git +что-уже-есть-в-проекте +репозиторий +install-git +проверка +если-git-не-установлен +git-identity +open-project +если-репозитория-нет +что-сейчас-видит-git +first-commit +проверка-изменений +добавление-в-индекс +запись-коммита +commit-workflow +документ-quarto +гистограмма +history-diff +рабочая-папка-индекс-и-коммит +branches +switch-branches +защита-незаписанной-работы +merge-conflict +редактор-слияний +branches-conclusion +github-part +git-и-github-разные-системы +publish-github +sync-remote +небольшая-проверка +перед-началом-работы +pull-request +изменение-в-ветке +создание-предложения +слияние +clone-repository +github-conclusion faq -gitignore -feature-branch -комитьте-и-пушьте-чаще -force-push -commits-to-branch -references +source-control-не-показывает-проект +коммит-не-содержит-файл +в-коммит-попал-лишний-файл +нужно-временно-переключиться +конфликт-возник-при-pull +опасные-операции +данные-и-секреты webhooks -cover-image-path-to-the-social-sharing-image-like-imagescover.jpg +references +positron +git-и-source-control +практика diff --git a/docs/references.html b/docs/references.html index 6559ed4..767651a 100644 --- a/docs/references.html +++ b/docs/references.html @@ -4,20 +4,20 @@ -Глава 21 Ссылки | Основы Git +Глава 21 Ссылки | Основы Git в Positron - + - + - + - - + + - + - - - - -
-
-
-

-Глава 4 Настройка -

-

Основной способ работы с Git — это команда git, которую мы выполнили в предыдущей главе. -Команды для терминала вы встретите в документации и в интернете, ими легко поделиться и использовать в скриптах. -Кроме терминала есть много других способов и их даже можно использовать одновременно.

-

Графические интерфейсы — все они имеют ограничения и реализуют только часть возможностей Git, но достаточны для решения большинства задач. Это может быть интерфейс, встроенный в другие программы (например RStudio, Pycharm, VS Code) или самостоятельная программа (например GitHub Desktop, GitKraken и многие другие);

-

Веб-интерфейсы — прямо на сайте GitHub можно редактировать отдельные файлы, а также выполнять некоторые команды.

-

В этом курсе мы будем работать с Git одновременно в интерфейсе RStudio и в терминале, как это делает большинство пользователей R каждый день, а также через GitHub. -Поэтому запомните, как запустить терминал в RStudio — -в верхнем меню выберите Tools → Terminal → New Terminal (см. скриншот в предыдущей главе).

-

Перед началом работы необходимо сделать несколько настроек. -Укажите свое имя и адрес электронной почты, чтобы Git верно записывал информацию об авторе изменений. -В терминале выполните следующие команды, заменив Your Name на свое имя и на свой email, не стирая кавычки.

-
git config --global user.name "Your Name"
-git config --global user.email "your@email.com"
-

Если вы уже использовали Git, то чтобы вывести в терминале текущее значение настроек выполните эти же команды, но не указывая новых значений.

-
git config --global user.name
-git config --global user.email
-

Также заранее настроим способ объединения изменений, чтобы не возвращаться к этому позже.

-
git config --global pull.rebase false
-

Опция --global означает, что эти настройки будут использованы для всех проектов на компьютере и их достаточно сделать один раз. -Чтобы изменить настройки для отдельного проекта, выполните в нем эти же команды без опции --global. Например, иногда требуется указать корпоративный email для рабочего проекта на персональном компьютере.

-

Это все настройки, которые понадобятся для курса. -Всего через команду git config их доступно более 800.

- -
- - - -
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/docs/switch-branches.html b/docs/switch-branches.html new file mode 100644 index 0000000..fa65647 --- /dev/null +++ b/docs/switch-branches.html @@ -0,0 +1,137 @@ + + + + + + +Глава 10 Переключение веток | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 10 Переключение веток +

+

Нажмите boxplot в строке состояния и выберите main. Эта операция называется переключением, а в терминах Git — checkout или switch.

+

Откройте paper.qmd и папку out. В main снова должна быть гистограмма и не должно быть нового боксплота. Git привёл рабочую папку к коммиту выбранной ветки.

+
+Ветка main после переключения: paper.qmd содержит hist(), в out виден penguins-hist.png
Ветка main после переключения: paper.qmd содержит hist(), в out виден penguins-hist.png
+
+
+

+10.1 Защита незаписанной работы +

+

В paper.qmd добавьте подпись оси:

+
+hist(x, breaks = seq(30, 60, 2), xlab = "Bill length, mm")
+

Сохраните файл, но пока не создавайте коммит. Попробуйте переключиться на boxplot.

+

Если переключение перезапишет изменённые строки, Git остановит операцию и предложит сначала сохранить работу. Это защитное поведение: незакоммиченные изменения не потеряны, вы по-прежнему на main.

+
+Уведомление Positron об отказе переключить ветку из-за незакоммиченных изменений в paper.qmd
Уведомление Positron об отказе переключить ветку из-за незакоммиченных изменений в paper.qmd
+
+

Вернитесь в Source Control, проверьте diff и создайте коммит Добавил подпись оси гистограммы. После этого переключитесь на boxplot и обратно на main, чтобы проверить обе версии.

+

Если нужно временно убрать незаконченные изменения без коммита, используйте Git: Stash (Include Untracked). Для основного упражнения stash не нужен.

+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/sync-remote.html b/docs/sync-remote.html new file mode 100644 index 0000000..4ea6095 --- /dev/null +++ b/docs/sync-remote.html @@ -0,0 +1,162 @@ + + + + + + +Глава 15 Push, pull и синхронизация | Основы Git в Positron + + + + + + + + + + + + + + + + + + +
+
+
+

+Глава 15 Push, pull и синхронизация +

+

Локальная и удалённая копии меняются независимо. Три операции поддерживают их в согласованном состоянии.

+
++++ + + + + + + + + + + + + + + + + + + +
ДействиеРезультат
PushОтправляет локальные коммиты на GitHub
PullЗагружает удалённые коммиты и объединяет их с текущей веткой
Sync ChangesСначала выполняет pull, затем push
+

Эти определения соответствуют официальной документации Working with repositories and remotes.

+
+

+15.1 Небольшая проверка +

+

Добавьте после заголовка paper.qmd одно предложение о цели анализа. Сохраните файл, проверьте diff и создайте коммит Уточнил цель анализа.

+

В строке состояния появится исходящий коммит ↑1. Нажмите Sync Changes. После синхронизации счётчик исчезнет, а коммит появится на GitHub.

+
+Source Control перед Sync Changes: локальная main опережает origin/main на один коммит, в строке состояния показано ↑1
Source Control перед Sync Changes: локальная main опережает origin/main на один коммит, в строке состояния показано ↑1
+
+
+
+

+15.2 Перед началом работы +

+

В совместном проекте начинайте с Pull, а заканчивайте Push. Так вы раньше увидите чужие изменения и реже столкнётесь с конфликтом.

+

Sync Changes удобно, когда вы понимаете обе половины операции. Если нужно отдельно проверить входящие коммиты, выполните Fetch, посмотрите их в Source Control Graph и только затем нажмите Pull.

+

Если push отклонён, обычно удалённая ветка содержит новые коммиты. Не применяйте force push. Сначала выполните Pull, разрешите возможный конфликт и повторите Push.

+ +
+
+
+ +
+
+ +
+ +
+

This book was built by the bookdown R package.

+
+ +
+
+ + diff --git a/docs/webhooks.html b/docs/webhooks.html index bfa38ac..52dbcbb 100644 --- a/docs/webhooks.html +++ b/docs/webhooks.html @@ -4,20 +4,20 @@ -Глава 21 Webhooks | Основы Git +Глава 20 Webhooks | Основы Git в Positron - + - + - + - - + + - + - - - - -
-
-
-

-Глава 19 Заключение -

-

Теперь у вас есть аккаунт на GitHub и вы умеете синхронизировать изменения с удаленным репозиторием, -пользоваться веб-интерфейсом и создавать Pull Request. -Этого достаточно для командной работы на курсе и в большинстве проектов.

-

Диаграмма ниже поможет запомнить как соотносятся действия, которые мы изучили: -1) создание коммитов, 2) работа с ветками и 3) синхронизация с удаленным репозиторием.

-
-

Рекомендуем использовать Git в своих проектах и не бояться экспериментировать с ветками. -Это помогает структурировать рабочий процесс, делает анализ данных воспроизводимым и облегчает командную работу. -Даже если вы работаете в одиночку, история изменений, возможность вернуться к предыдущим версиям и ветвление значительно упрощают развитие проекта. -А со временем вы сможете применять более продвинутые возможности, такие как автоматизация, интеграция с другими сервисами и управление проектами.

-

Удачи в прохождении курса!

- -
- - - -
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git "a/docs/\320\267\320\260\320\272\320\273\321\216\321\207\320\265\320\275\320\270\320\265.html" "b/docs/\320\267\320\260\320\272\320\273\321\216\321\207\320\265\320\275\320\270\320\265.html" deleted file mode 100644 index 199ac4d..0000000 --- "a/docs/\320\267\320\260\320\272\320\273\321\216\321\207\320\265\320\275\320\270\320\265.html" +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - -Глава 13 Заключение | Основы Git - - - - - - - - - - - - - - - - - - -
-
-
-

-Глава 13 Заключение -

-

Теперь вы умеете создавать и объединять ветки — -это одни из ключевых функций Git, особенно при совместной работе. -Благодаря простоте работы с ветками, рекомендуется создавать их чаще. -Чем меньше в ветке изменений, тем проще ее слить, и тем ниже вероятность конфликтов из-за одновременных правок одной и той же части проекта. Это отражает известную идею, что при работе в команде лучше синхронизироваться чаще.

-

Рассмотрим продвинутые способы использования веток, а также для чего их использовать не стоит.

-

Для начала уточним, что можно создать ветку от любой другой, а не только от основной ветки main. Уровень вложенности и количество веток не ограничены. -После слияния ветки она не прекращает свое существование — в ней можно продолжить работу, а после слить еще раз. -На практике вам вряд ли понадобится больше 3-х уровней вложенности, а ветки лучше периодически удалять, чтобы не запутаться.

-
-

-13.1 Тематические ветки (feature branch) -

-

Тематическая ветка содержит изменения, связанные с конкретной задачей или направлением работы. -Это может быть новый этап анализа или изменения в уже сделанные этапы, например:

-
    -
  • ветка в которой мы визуализировали данные при помощи графиков, может называться visualize или plot;
  • -
  • ветка в которой добавляются модели, может называться model или, если это более специфическая модель, например нелинейная, то model-nle;
  • -
  • ветка в которой обновлены данные для уже выполненного анализа update-data;
  • -
  • в нашем репозитории, когда мы заменили график на ящик с усами, ветка называлась boxplot.
  • -
-

Если в проекте используется трекер задач или ошибок, -то зачастую работа выполняется в отдельной ветке с названием соответствующим номеру из трекера, -например issue42 или ticket58.

-

Это самый частый способ использования веток, применяемый независимо от размеров проекта и количества участников.

-
-
-

-13.2 Долгоживущие ветки (long-running branches) -

-

Этот подход часто применяется для крупных проектов, когда нужно обеспечить высокую стабильность продукта, как правило при разработке программного обеспечения.

-

Ветка main содержит стабильную версию. -От нее создается ветка develop в которой ведется разработка. -Тематические ветки создаются от ветки develop и вливаются в нее. -Когда разработка очередной версии завершилась, -изменения из ветки develop стабилизируются — проходят тестирование и ревью, -после чего вливаются в стабильную ветку main.

-

Далее цикл повторяется — разработка следующей версии продолжается в ветке develop с использованием тематических веток, после чего она снова сливается с веткой main.

-
-
-

-13.3 Когда не стоит использовать ветки -

-

Выше описаны лишь некоторые наиболее часто используемые процессы работы построенные вокруг веток. -Существует и можно придумать много других, подходящих для вас или вашей команды.

-

Но у всех применений веток есть общая черта — это способ организации внесения изменений в проект и рано или поздно эти изменения должны быть слиты или удалены.

-

Ветки это не способ структурирования самого анализа или программы. -Например, если у вас есть несколько моделей и вы собираетесь поддерживать их все, то вероятно они должны быть в одной ветке, а не в отдельных. -Иначе потребуется следить за тем, чтобы изменения вносились в каждую ветку — это утомительно и чревато ошибками. -Для работы с несколькими моделями одновременно придется переключаться и работать с несколькими ветками, что противоречит большинству способов их использования, например описанных выше.

-

Другая частая ошибка — участники создают ветки с собственным именем (ivan, masha-work) и используют их как личные папки для хранения своих файлов не связанных с файлами других участников. -Ветки предназначены для внесения изменений в один общий проект. Следует либо интегрировать эти файлы в проект, возможно отдельной веткой, либо хранить в другом месте.

-

В следующей части мы посмотрим как организовать совместную работу при помощи «удаленных» (remote) веток и сервиса GitHub.

- -
-
- - - -
- -
-
- -
- -
-

This book was built by the bookdown R package.

-
- -
-
- - diff --git a/index.Rmd b/index.Rmd index cf8b965..1d851b2 100644 --- a/index.Rmd +++ b/index.Rmd @@ -1,66 +1,30 @@ ---- -title: "Основы Git" +--- +title: "Основы Git в Positron" author: "Kirill Voronin" -date: "2025-08-01" +date: "2026-08-26" site: bookdown::bookdown_site documentclass: book -bibliography: [book.bib, packages.bib] url: https://yoursdearboy.github.io/git-101 -# cover-image: path to the social sharing image like images/cover.jpg description: | - Руководство по Git для Института Биоинформатики. -biblio-style: apalike -csl: chicago-fullnote-bibliography.csl + Практическое продолжение курса R: история проекта, ветки и совместная работа через GitHub. --- -# Основы Git +# Основы Git в Positron -Привет! -Перед вами краткое руководство по работе с системой контроля версий Git и сервисом GitHub, написанное для биоинформатиков, статистиков и других специалистов занимающихся анализом данных. +Вы закончили курс R и уже собрали проект `r-course`: в нём есть данные, скрипты, отчёты Quarto и результаты. Теперь научимся сохранять историю этого проекта и работать над ним вместе. -::: {style="float: left; clear: both; width: 200px; margin-right: 20px;"} -![](./img/git-logo.png){width=200px} -::: +Мы не будем перекладывать или переименовывать накопленные файлы. Первый коммит зафиксирует проект ровно в том состоянии, в котором он остался после R-курса. Затем создадим новый документ `paper.qmd` и на примере пингвинов пройдём основной рабочий цикл Git: -Эти инструменты пригодятся вам во время курса и при выполнении учебных проектов, хотя их настоящая ценность проявляется в ежедневной работе. -Git помогает организовать процесс анализа данных, отслеживать изменения, наладить совместную работу и обеспечить воспроизводимость исследований. -Он используется не только в крупных компаниях, но и небольшими командами и отдельными специалистами. +1. проверим и зафиксируем изменения; +2. создадим ветку с альтернативным графиком; +3. разрешим конфликт слияния; +4. опубликуем проект на GitHub; +5. предложим изменение через pull request. -Git очень простой инструмент, можно даже сказать, примитивный или глупый -^[именно это означает сленговое слово *git* в английском], -поэтому освоить его не составит труда. -Однако спешу вас заверить, что даже те, кто сейчас эффективно использует Git, в первое время сталкивались с проблемами. -Умение работать с Git — это практический навык, который приходит с опытом. +Основной маршрут выполняется в интерфейсе **Source Control** в Positron. Терминал понадобится только для проверки установки и устранения неполадок. -::: {style="float: right; width: 50%; max-width: 250px"} -![](./img/penguins2.png){width=100%} +::: {.callout .callout-info} +Этот курс использует Positron и Quarto. Не переносите сюда инструкции для другого редактора или другого формата отчётов: учебный анализ Git-курса находится в `paper.qmd`. ::: -Существует множество руководств и даже книг, ссылки на которые есть в последней главе, -но предпочтительный способ изучения --- больше использовать Git на практике. -Поэтому от главы к главе выполняйте инструкции и команды приведенные в курсе. -В качестве примера мы будем использовать данные о длине клюва пингвинов с антарктической станции Палмер. -К концу у вас должен получиться полноценный проект с очень небольшим анализом. - -Курс состоит из четырех частей, рассчитанных в среднем на 1-2 часа. -В первой части мы установим и настроим Git. -Во второй части научимся записывать и просматривать историю версий. -В третьей части научимся создавать альтернативные версии --- это важная функция Git и основа для совместной работы. -В последней четвёртой части зарегистрируемся на GitHub, выложим наш проект и научимся синхронизировать изменения с сервером, чтобы работать в команде. -Этих навыков достаточно для работы с большинством реальных проектов. - -```{r, include=FALSE} -# Немного подробней описать содержимое? - -# важная функция Git звучит так себе и -# должно быть согласовано с этим же тезисом в следующей главе. -``` - -[В предпоследней главе](#faq) приведены советы, которые помогут эффективней работать с Git без страха что-то сломать. А в [последней главе](#references) вы найдете ссылки на другие руководства, книги и полезные ресурсы. - -```{r include=FALSE} -# automatically create a bib database for R packages -knitr::write_bib(c( - .packages(), "bookdown", "knitr", "rmarkdown" -), "packages.bib") -``` +Инструкции по интерфейсу сверены с официальной документацией [Positron](https://positron.posit.co/welcome.html). Positron построен на Code OSS и для общих возможностей редактора, включая Source Control, сам направляет читателя к [документации VS Code](https://code.visualstudio.com/docs/sourcecontrol/overview). diff --git a/penguins.R b/penguins.R deleted file mode 100644 index 19103f2..0000000 --- a/penguins.R +++ /dev/null @@ -1,5 +0,0 @@ -library(palmerpenguins) - -gentoo <- penguins[penguins$species == "Gentoo",] - -write.csv(gentoo, "penguins.csv", row.names = FALSE, na = "") diff --git a/penguins.csv b/penguins.csv deleted file mode 100644 index 7508a89..0000000 --- a/penguins.csv +++ /dev/null @@ -1,125 +0,0 @@ -"species","island","bill_length_mm","bill_depth_mm","flipper_length_mm","body_mass_g","sex","year" -"Gentoo","Biscoe",46.1,13.2,211,4500,"female",2007 -"Gentoo","Biscoe",50,16.3,230,5700,"male",2007 -"Gentoo","Biscoe",48.7,14.1,210,4450,"female",2007 -"Gentoo","Biscoe",50,15.2,218,5700,"male",2007 -"Gentoo","Biscoe",47.6,14.5,215,5400,"male",2007 -"Gentoo","Biscoe",46.5,13.5,210,4550,"female",2007 -"Gentoo","Biscoe",45.4,14.6,211,4800,"female",2007 -"Gentoo","Biscoe",46.7,15.3,219,5200,"male",2007 -"Gentoo","Biscoe",43.3,13.4,209,4400,"female",2007 -"Gentoo","Biscoe",46.8,15.4,215,5150,"male",2007 -"Gentoo","Biscoe",40.9,13.7,214,4650,"female",2007 -"Gentoo","Biscoe",49,16.1,216,5550,"male",2007 -"Gentoo","Biscoe",45.5,13.7,214,4650,"female",2007 -"Gentoo","Biscoe",48.4,14.6,213,5850,"male",2007 -"Gentoo","Biscoe",45.8,14.6,210,4200,"female",2007 -"Gentoo","Biscoe",49.3,15.7,217,5850,"male",2007 -"Gentoo","Biscoe",42,13.5,210,4150,"female",2007 -"Gentoo","Biscoe",49.2,15.2,221,6300,"male",2007 -"Gentoo","Biscoe",46.2,14.5,209,4800,"female",2007 -"Gentoo","Biscoe",48.7,15.1,222,5350,"male",2007 -"Gentoo","Biscoe",50.2,14.3,218,5700,"male",2007 -"Gentoo","Biscoe",45.1,14.5,215,5000,"female",2007 -"Gentoo","Biscoe",46.5,14.5,213,4400,"female",2007 -"Gentoo","Biscoe",46.3,15.8,215,5050,"male",2007 -"Gentoo","Biscoe",42.9,13.1,215,5000,"female",2007 -"Gentoo","Biscoe",46.1,15.1,215,5100,"male",2007 -"Gentoo","Biscoe",44.5,14.3,216,4100,,2007 -"Gentoo","Biscoe",47.8,15,215,5650,"male",2007 -"Gentoo","Biscoe",48.2,14.3,210,4600,"female",2007 -"Gentoo","Biscoe",50,15.3,220,5550,"male",2007 -"Gentoo","Biscoe",47.3,15.3,222,5250,"male",2007 -"Gentoo","Biscoe",42.8,14.2,209,4700,"female",2007 -"Gentoo","Biscoe",45.1,14.5,207,5050,"female",2007 -"Gentoo","Biscoe",59.6,17,230,6050,"male",2007 -"Gentoo","Biscoe",49.1,14.8,220,5150,"female",2008 -"Gentoo","Biscoe",48.4,16.3,220,5400,"male",2008 -"Gentoo","Biscoe",42.6,13.7,213,4950,"female",2008 -"Gentoo","Biscoe",44.4,17.3,219,5250,"male",2008 -"Gentoo","Biscoe",44,13.6,208,4350,"female",2008 -"Gentoo","Biscoe",48.7,15.7,208,5350,"male",2008 -"Gentoo","Biscoe",42.7,13.7,208,3950,"female",2008 -"Gentoo","Biscoe",49.6,16,225,5700,"male",2008 -"Gentoo","Biscoe",45.3,13.7,210,4300,"female",2008 -"Gentoo","Biscoe",49.6,15,216,4750,"male",2008 -"Gentoo","Biscoe",50.5,15.9,222,5550,"male",2008 -"Gentoo","Biscoe",43.6,13.9,217,4900,"female",2008 -"Gentoo","Biscoe",45.5,13.9,210,4200,"female",2008 -"Gentoo","Biscoe",50.5,15.9,225,5400,"male",2008 -"Gentoo","Biscoe",44.9,13.3,213,5100,"female",2008 -"Gentoo","Biscoe",45.2,15.8,215,5300,"male",2008 -"Gentoo","Biscoe",46.6,14.2,210,4850,"female",2008 -"Gentoo","Biscoe",48.5,14.1,220,5300,"male",2008 -"Gentoo","Biscoe",45.1,14.4,210,4400,"female",2008 -"Gentoo","Biscoe",50.1,15,225,5000,"male",2008 -"Gentoo","Biscoe",46.5,14.4,217,4900,"female",2008 -"Gentoo","Biscoe",45,15.4,220,5050,"male",2008 -"Gentoo","Biscoe",43.8,13.9,208,4300,"female",2008 -"Gentoo","Biscoe",45.5,15,220,5000,"male",2008 -"Gentoo","Biscoe",43.2,14.5,208,4450,"female",2008 -"Gentoo","Biscoe",50.4,15.3,224,5550,"male",2008 -"Gentoo","Biscoe",45.3,13.8,208,4200,"female",2008 -"Gentoo","Biscoe",46.2,14.9,221,5300,"male",2008 -"Gentoo","Biscoe",45.7,13.9,214,4400,"female",2008 -"Gentoo","Biscoe",54.3,15.7,231,5650,"male",2008 -"Gentoo","Biscoe",45.8,14.2,219,4700,"female",2008 -"Gentoo","Biscoe",49.8,16.8,230,5700,"male",2008 -"Gentoo","Biscoe",46.2,14.4,214,4650,,2008 -"Gentoo","Biscoe",49.5,16.2,229,5800,"male",2008 -"Gentoo","Biscoe",43.5,14.2,220,4700,"female",2008 -"Gentoo","Biscoe",50.7,15,223,5550,"male",2008 -"Gentoo","Biscoe",47.7,15,216,4750,"female",2008 -"Gentoo","Biscoe",46.4,15.6,221,5000,"male",2008 -"Gentoo","Biscoe",48.2,15.6,221,5100,"male",2008 -"Gentoo","Biscoe",46.5,14.8,217,5200,"female",2008 -"Gentoo","Biscoe",46.4,15,216,4700,"female",2008 -"Gentoo","Biscoe",48.6,16,230,5800,"male",2008 -"Gentoo","Biscoe",47.5,14.2,209,4600,"female",2008 -"Gentoo","Biscoe",51.1,16.3,220,6000,"male",2008 -"Gentoo","Biscoe",45.2,13.8,215,4750,"female",2008 -"Gentoo","Biscoe",45.2,16.4,223,5950,"male",2008 -"Gentoo","Biscoe",49.1,14.5,212,4625,"female",2009 -"Gentoo","Biscoe",52.5,15.6,221,5450,"male",2009 -"Gentoo","Biscoe",47.4,14.6,212,4725,"female",2009 -"Gentoo","Biscoe",50,15.9,224,5350,"male",2009 -"Gentoo","Biscoe",44.9,13.8,212,4750,"female",2009 -"Gentoo","Biscoe",50.8,17.3,228,5600,"male",2009 -"Gentoo","Biscoe",43.4,14.4,218,4600,"female",2009 -"Gentoo","Biscoe",51.3,14.2,218,5300,"male",2009 -"Gentoo","Biscoe",47.5,14,212,4875,"female",2009 -"Gentoo","Biscoe",52.1,17,230,5550,"male",2009 -"Gentoo","Biscoe",47.5,15,218,4950,"female",2009 -"Gentoo","Biscoe",52.2,17.1,228,5400,"male",2009 -"Gentoo","Biscoe",45.5,14.5,212,4750,"female",2009 -"Gentoo","Biscoe",49.5,16.1,224,5650,"male",2009 -"Gentoo","Biscoe",44.5,14.7,214,4850,"female",2009 -"Gentoo","Biscoe",50.8,15.7,226,5200,"male",2009 -"Gentoo","Biscoe",49.4,15.8,216,4925,"male",2009 -"Gentoo","Biscoe",46.9,14.6,222,4875,"female",2009 -"Gentoo","Biscoe",48.4,14.4,203,4625,"female",2009 -"Gentoo","Biscoe",51.1,16.5,225,5250,"male",2009 -"Gentoo","Biscoe",48.5,15,219,4850,"female",2009 -"Gentoo","Biscoe",55.9,17,228,5600,"male",2009 -"Gentoo","Biscoe",47.2,15.5,215,4975,"female",2009 -"Gentoo","Biscoe",49.1,15,228,5500,"male",2009 -"Gentoo","Biscoe",47.3,13.8,216,4725,,2009 -"Gentoo","Biscoe",46.8,16.1,215,5500,"male",2009 -"Gentoo","Biscoe",41.7,14.7,210,4700,"female",2009 -"Gentoo","Biscoe",53.4,15.8,219,5500,"male",2009 -"Gentoo","Biscoe",43.3,14,208,4575,"female",2009 -"Gentoo","Biscoe",48.1,15.1,209,5500,"male",2009 -"Gentoo","Biscoe",50.5,15.2,216,5000,"female",2009 -"Gentoo","Biscoe",49.8,15.9,229,5950,"male",2009 -"Gentoo","Biscoe",43.5,15.2,213,4650,"female",2009 -"Gentoo","Biscoe",51.5,16.3,230,5500,"male",2009 -"Gentoo","Biscoe",46.2,14.1,217,4375,"female",2009 -"Gentoo","Biscoe",55.1,16,230,5850,"male",2009 -"Gentoo","Biscoe",44.5,15.7,217,4875,,2009 -"Gentoo","Biscoe",48.8,16.2,222,6000,"male",2009 -"Gentoo","Biscoe",47.2,13.7,214,4925,"female",2009 -"Gentoo","Biscoe",,,,,,2009 -"Gentoo","Biscoe",46.8,14.3,215,4850,"female",2009 -"Gentoo","Biscoe",50.4,15.7,222,5750,"male",2009 -"Gentoo","Biscoe",45.2,14.8,212,5200,"female",2009 -"Gentoo","Biscoe",49.9,16.1,213,5400,"male",2009 diff --git a/renv.lock b/renv.lock index dddc475..e2ee1c1 100644 --- a/renv.lock +++ b/renv.lock @@ -1,6 +1,6 @@ { "R": { - "Version": "4.4.3", + "Version": "4.5.1", "Repositories": [ { "Name": "CRAN", @@ -9,6 +9,58 @@ ] }, "Packages": { + "DBI": { + "Package": "DBI", + "Version": "1.3.0", + "Source": "Repository", + "Title": "R Database Interface", + "Date": "2026-02-11", + "Authors@R": "c( person(\"R Special Interest Group on Databases (R-SIG-DB)\", role = \"aut\"), person(\"Hadley\", \"Wickham\", role = \"aut\"), person(\"Kirill\", \"Müller\", , \"kirill@cynkra.com\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-1416-3412\")), person(\"R Consortium\", role = \"fnd\") )", + "Description": "A database interface definition for communication between R and relational database management systems. All classes in this package are virtual and need to be extended by the various R/DBMS implementations.", + "License": "LGPL (>= 2.1)", + "URL": "https://dbi.r-dbi.org, https://github.com/r-dbi/DBI", + "BugReports": "https://github.com/r-dbi/DBI/issues", + "Depends": [ + "methods", + "R (>= 3.0.0)" + ], + "Suggests": [ + "arrow", + "blob", + "callr", + "covr", + "DBItest (>= 1.8.2)", + "dbplyr", + "downlit", + "dplyr", + "glue", + "hms", + "knitr", + "magrittr", + "nanoarrow (>= 0.3.0.1)", + "otel", + "otelsdk", + "RMariaDB", + "rmarkdown", + "rprojroot", + "RSQLite (>= 1.1-2)", + "testthat (>= 3.0.0)", + "vctrs", + "xml2" + ], + "VignetteBuilder": "knitr", + "Config/autostyle/scope": "line_breaks", + "Config/autostyle/strict": "false", + "Config/Needs/check": "r-dbi/DBItest", + "Config/Needs/website": "r-dbi/DBItest, r-dbi/dbitemplate, adbi, AzureKusto, bigrquery, DatabaseConnector, dittodb, duckdb, implyr, lazysf, odbc, pool, RAthena, IMSMWU/RClickhouse, RH2, RJDBC, RMariaDB, RMySQL, RPostgres, RPostgreSQL, RPresto, RSQLite, sergeant, sparklyr, withr", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3.9000", + "NeedsCompilation": "no", + "Author": "R Special Interest Group on Databases (R-SIG-DB) [aut], Hadley Wickham [aut], Kirill Müller [aut, cre] (ORCID: ), R Consortium [fnd]", + "Maintainer": "Kirill Müller ", + "Repository": "CRAN" + }, "R6": { "Package": "R6", "Version": "2.6.1", @@ -50,16 +102,20 @@ "Description": "Provides color schemes for maps (and other graphics) designed by Cynthia Brewer as described at http://colorbrewer2.org.", "License": "Apache License 2.0", "NeedsCompilation": "no", - "Repository": "CRAN" + "Repository": "RSPM", + "Encoding": "UTF-8" }, "Rcpp": { "Package": "Rcpp", - "Version": "1.0.14", + "Version": "1.1.1-1.1", "Source": "Repository", "Title": "Seamless R and C++ Integration", - "Date": "2025-01-11", + "Date": "2026-04-19", "Authors@R": "c(person(\"Dirk\", \"Eddelbuettel\", role = c(\"aut\", \"cre\"), email = \"edd@debian.org\", comment = c(ORCID = \"0000-0001-6419-907X\")), person(\"Romain\", \"Francois\", role = \"aut\", comment = c(ORCID = \"0000-0002-2444-4226\")), person(\"JJ\", \"Allaire\", role = \"aut\", comment = c(ORCID = \"0000-0003-0174-9868\")), person(\"Kevin\", \"Ushey\", role = \"aut\", comment = c(ORCID = \"0000-0003-2880-7407\")), person(\"Qiang\", \"Kou\", role = \"aut\", comment = c(ORCID = \"0000-0001-6786-5453\")), person(\"Nathan\", \"Russell\", role = \"aut\"), person(\"Iñaki\", \"Ucar\", role = \"aut\", comment = c(ORCID = \"0000-0001-6403-5550\")), person(\"Doug\", \"Bates\", role = \"aut\", comment = c(ORCID = \"0000-0001-8316-9503\")), person(\"John\", \"Chambers\", role = \"aut\"))", "Description": "The 'Rcpp' package provides R functions as well as C++ classes which offer a seamless integration of R and C++. Many R data types and objects can be mapped back and forth to C++ equivalents which facilitates both writing of new code as well as easier integration of third-party libraries. Documentation about 'Rcpp' is provided by several vignettes included in this package, via the 'Rcpp Gallery' site at , the paper by Eddelbuettel and Francois (2011, ), the book by Eddelbuettel (2013, ) and the paper by Eddelbuettel and Balamuta (2018, ); see 'citation(\"Rcpp\")' for details.", + "Depends": [ + "R (>= 3.5.0)" + ], "Imports": [ "methods", "utils" @@ -76,11 +132,51 @@ "MailingList": "rcpp-devel@lists.r-forge.r-project.org", "RoxygenNote": "6.1.1", "Encoding": "UTF-8", + "VignetteBuilder": "Rcpp", "NeedsCompilation": "yes", - "Author": "Dirk Eddelbuettel [aut, cre] (), Romain Francois [aut] (), JJ Allaire [aut] (), Kevin Ushey [aut] (), Qiang Kou [aut] (), Nathan Russell [aut], Iñaki Ucar [aut] (), Doug Bates [aut] (), John Chambers [aut]", + "Author": "Dirk Eddelbuettel [aut, cre] (ORCID: ), Romain Francois [aut] (ORCID: ), JJ Allaire [aut] (ORCID: ), Kevin Ushey [aut] (ORCID: ), Qiang Kou [aut] (ORCID: ), Nathan Russell [aut], Iñaki Ucar [aut] (ORCID: ), Doug Bates [aut] (ORCID: ), John Chambers [aut]", "Maintainer": "Dirk Eddelbuettel ", "Repository": "CRAN" }, + "S7": { + "Package": "S7", + "Version": "0.2.2", + "Source": "Repository", + "Title": "An Object Oriented System Meant to Become a Successor to S3 and S4", + "Authors@R": "c( person(\"Object-Oriented Programming Working Group\", role = \"cph\"), person(\"Davis\", \"Vaughan\", role = \"aut\"), person(\"Jim\", \"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Tomasz\", \"Kalinowski\", role = \"aut\"), person(\"Will\", \"Landau\", role = \"aut\"), person(\"Michael\", \"Lawrence\", role = \"aut\"), person(\"Martin\", \"Maechler\", role = \"aut\", comment = c(ORCID = \"0000-0002-8685-9910\")), person(\"Luke\", \"Tierney\", role = \"aut\"), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0003-4757-117X\")) )", + "Description": "A new object oriented programming system designed to be a successor to S3 and S4. It includes formal class, generic, and method specification, and a limited form of multiple dispatch. It has been designed and implemented collaboratively by the R Consortium Object-Oriented Programming Working Group, which includes representatives from R-Core, 'Bioconductor', 'Posit'/'tidyverse', and the wider R community.", + "License": "MIT + file LICENSE", + "URL": "https://rconsortium.github.io/S7/, https://github.com/RConsortium/S7", + "BugReports": "https://github.com/RConsortium/S7/issues", + "Depends": [ + "R (>= 3.5.0)" + ], + "Imports": [ + "utils" + ], + "Suggests": [ + "bench", + "callr", + "covr", + "knitr", + "methods", + "rmarkdown", + "testthat (>= 3.2.0)", + "tibble" + ], + "VignetteBuilder": "knitr", + "Config/build/compilation-database": "true", + "Config/Needs/website": "sloop", + "Config/testthat/edition": "3", + "Config/testthat/parallel": "TRUE", + "Config/testthat/start-first": "external-generic", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "yes", + "Author": "Object-Oriented Programming Working Group [cph], Davis Vaughan [aut], Jim Hester [aut] (ORCID: ), Tomasz Kalinowski [aut], Will Landau [aut], Michael Lawrence [aut], Martin Maechler [aut] (ORCID: ), Luke Tierney [aut], Hadley Wickham [aut, cre] (ORCID: )", + "Maintainer": "Hadley Wickham ", + "Repository": "CRAN" + }, "V8": { "Package": "V8", "Version": "6.0.3", @@ -115,7 +211,7 @@ "Biarch": "true", "Author": "Jeroen Ooms [aut, cre] (), Jan Marvin Garbuszus [ctb]", "Maintainer": "Jeroen Ooms ", - "Repository": "CRAN" + "Repository": "RSPM" }, "askpass": { "Package": "askpass", @@ -142,12 +238,35 @@ "Maintainer": "Jeroen Ooms ", "Repository": "CRAN" }, + "backports": { + "Package": "backports", + "Version": "1.5.1", + "Source": "Repository", + "Type": "Package", + "Title": "Reimplementations of Functions Introduced Since R-3.0.0", + "Authors@R": "c( person(\"Michel\", \"Lang\", NULL, \"michellang@gmail.com\", role = c(\"cre\", \"aut\"), comment = c(ORCID = \"0000-0001-9754-0393\")), person(\"Duncan\", \"Murdoch\", NULL, \"murdoch.duncan@gmail.com\", role = c(\"aut\")), person(\"R Core Team\", role = \"aut\"))", + "Maintainer": "Michel Lang ", + "Description": "Functions introduced or changed since R v3.0.0 are re-implemented in this package. The backports are conditionally exported in order to let R resolve the function name to either the implemented backport, or the respective base version, if available. Package developers can make use of new functions or arguments by selectively importing specific backports to support older installations.", + "URL": "https://github.com/r-lib/backports", + "BugReports": "https://github.com/r-lib/backports/issues", + "License": "GPL-2 | GPL-3", + "NeedsCompilation": "yes", + "ByteCompile": "yes", + "Depends": [ + "R (>= 3.0.0)" + ], + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "Author": "Michel Lang [cre, aut] (ORCID: ), Duncan Murdoch [aut], R Core Team [aut]", + "Repository": "CRAN" + }, "base64enc": { "Package": "base64enc", - "Version": "0.1-3", + "Version": "0.1-6", "Source": "Repository", - "Title": "Tools for base64 encoding", - "Author": "Simon Urbanek ", + "Title": "Tools for 'base64' Encoding", + "Author": "Simon Urbanek [aut, cre, cph] (https://urbanek.nz, ORCID: )", + "Authors@R": "person(\"Simon\", \"Urbanek\", role=c(\"aut\",\"cre\",\"cph\"), email=\"Simon.Urbanek@r-project.org\", comment=c(\"https://urbanek.nz\", ORCID=\"0000-0003-2297-1732\"))", "Maintainer": "Simon Urbanek ", "Depends": [ "R (>= 2.9.0)" @@ -155,9 +274,10 @@ "Enhances": [ "png" ], - "Description": "This package provides tools for handling base64 encoding. It is more flexible than the orphaned base64 package.", + "Description": "Tools for handling 'base64' encoding. It is more flexible than the orphaned 'base64' package.", "License": "GPL-2 | GPL-3", - "URL": "http://www.rforge.net/base64enc", + "URL": "https://www.rforge.net/base64enc", + "BugReports": "https://github.com/s-u/base64enc/issues", "NeedsCompilation": "yes", "Repository": "CRAN" }, @@ -224,35 +344,37 @@ }, "bit64": { "Package": "bit64", - "Version": "4.6.0-1", + "Version": "4.8.2", "Source": "Repository", "Title": "A S3 Class for Vectors of 64bit Integers", - "Authors@R": "c( person(\"Michael\", \"Chirico\", email = \"michaelchirico4@gmail.com\", role = c(\"aut\", \"cre\")), person(\"Jens\", \"Oehlschlägel\", role = \"aut\"), person(\"Leonardo\", \"Silvestri\", role = \"ctb\"), person(\"Ofek\", \"Shilon\", role = \"ctb\") )", + "Authors@R": "c( person(\"Michael\", \"Chirico\", email=\"michaelchirico4@gmail.com\", role=c(\"aut\", \"cre\")), person(\"Jens\", \"Oehlschlägel\", role=\"aut\"), person(\"Leonardo\", \"Silvestri\", role=\"ctb\"), person(\"Ofek\", \"Shilon\", role=\"ctb\"), person(\"Christian\", \"Ullerich\", role=\"ctb\") )", "Depends": [ - "R (>= 3.4.0)", - "bit (>= 4.0.0)" + "R (>= 3.5.0)" ], "Description": "Package 'bit64' provides serializable S3 atomic 64bit (signed) integers. These are useful for handling database keys and exact counting in +-2^63. WARNING: do not use them as replacement for 32bit integers, integer64 are not supported for subscripting by R-core and they have different semantics when combined with double, e.g. integer64 + double => integer64. Class integer64 can be used in vectors, matrices, arrays and data.frames. Methods are available for coercion from and to logicals, integers, doubles, characters and factors as well as many elementwise and summary functions. Many fast algorithmic operations such as 'match' and 'order' support inter- active data exploration and manipulation and optionally leverage caching.", "License": "GPL-2 | GPL-3", "LazyLoad": "yes", "ByteCompile": "yes", - "URL": "https://github.com/r-lib/bit64", + "URL": "https://github.com/r-lib/bit64, https://bit64.r-lib.org", "Encoding": "UTF-8", "Imports": [ + "bit (>= 4.0.0)", "graphics", "methods", "stats", "utils" ], "Suggests": [ - "testthat (>= 3.0.3)", + "patrick (>= 0.3.0)", + "testthat (>= 3.3.0)", "withr" ], "Config/testthat/edition": "3", - "Config/needs/development": "testthat", - "RoxygenNote": "7.3.2", + "Config/Needs/development": "patrick, testthat", + "Config/Needs/website": "tidyverse/tidytemplate", + "RoxygenNote": "7.3.3", "NeedsCompilation": "yes", - "Author": "Michael Chirico [aut, cre], Jens Oehlschlägel [aut], Leonardo Silvestri [ctb], Ofek Shilon [ctb]", + "Author": "Michael Chirico [aut, cre], Jens Oehlschlägel [aut], Leonardo Silvestri [ctb], Ofek Shilon [ctb], Christian Ullerich [ctb]", "Maintainer": "Michael Chirico ", "Repository": "CRAN" }, @@ -270,6 +392,39 @@ "NeedsCompilation": "yes", "Author": "Steve Dutky [aut] (S original; then (after MM's port) revised and modified), Martin Maechler [cre, aut] (Initial R port; tweaks, )", "Maintainer": "Martin Maechler ", + "Repository": "RSPM", + "Encoding": "UTF-8" + }, + "blob": { + "Package": "blob", + "Version": "1.3.0", + "Source": "Repository", + "Title": "A Simple S3 Class for Representing Vectors of Binary Data ('BLOBS')", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", role = \"aut\"), person(\"Kirill\", \"Müller\", , \"kirill@cynkra.com\", role = \"cre\"), person(\"RStudio\", role = c(\"cph\", \"fnd\")) )", + "Description": "R's raw vector is useful for storing a single binary object. What if you want to put a vector of them in a data frame? The 'blob' package provides the blob object, a list of raw vectors, suitable for use as a column in data frame.", + "License": "MIT + file LICENSE", + "URL": "https://blob.tidyverse.org, https://github.com/tidyverse/blob", + "BugReports": "https://github.com/tidyverse/blob/issues", + "Imports": [ + "methods", + "rlang", + "vctrs (>= 0.2.1)" + ], + "Suggests": [ + "covr", + "crayon", + "pillar (>= 1.2.1)", + "testthat (>= 3.0.0)" + ], + "Config/autostyle/scope": "line_breaks", + "Config/autostyle/strict": "false", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3.9000", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut], Kirill Müller [cre], RStudio [cph, fnd]", + "Maintainer": "Kirill Müller ", "Repository": "CRAN" }, "bookdown": { @@ -326,9 +481,158 @@ "Author": "Yihui Xie [aut, cre] (), Christophe Dervieux [ctb] (), JJ Allaire [ctb], Albert Kim [ctb], Alessandro Samuel-Rosa [ctb], Andrzej Oles [ctb], Atsushi Yasumoto [ctb] (), Aust Frederik [ctb] (), Bastiaan Quast [ctb], Ben Marwick [ctb], Chester Ismay [ctb], Clifton Franklund [ctb], Daniel Emaasit [ctb], David Shuman [ctb], Dean Attali [ctb], Drew Tyre [ctb], Ellis Valentiner [ctb], Frans van Dunne [ctb], Hadley Wickham [ctb], Jeff Allen [ctb], Jennifer Bryan [ctb], Jonathan McPhers [ctb], JooYoung Seo [ctb] (), Joyce Robbins [ctb], Junwen Huang [ctb], Kevin Cheung [ctb], Kevin Ushey [ctb], Kim Seonghyun [ctb], Kirill Muller [ctb], Luciano Selzer [ctb], Matthew Lincoln [ctb], Maximilian Held [ctb], Michael Sachs [ctb], Michal Bojanowski [ctb], Nathan Werth [ctb], Noam Ross [ctb], Peter Hickey [ctb], Pedro Rafael D. Marinho [ctb] (), Romain Lesur [ctb] (), Sahir Bhatnagar [ctb], Shir Dekel [ctb] (), Steve Simpson [ctb], Thierry Onkelinx [ctb] (), Vincent Fulco [ctb], Yixuan Qiu [ctb], Zhuoer Dong [ctb], Posit Software, PBC [cph, fnd], Bartek Szopka [ctb] (The jQuery Highlight plugin), Zeno Rocha [cph] (clipboard.js library), MathQuill contributors [ctb] (The MathQuill library; authors listed in inst/resources/AUTHORS), FriendCode Inc [cph, ctb] (The gitbook style, with modifications)", "Repository": "CRAN" }, + "brio": { + "Package": "brio", + "Version": "1.1.5", + "Source": "Repository", + "Title": "Basic R Input Output", + "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Gábor\", \"Csárdi\", , \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\")), person(given = \"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Functions to handle basic input output, these functions always read and write UTF-8 (8-bit Unicode Transformation Format) files and provide more explicit control over line endings.", + "License": "MIT + file LICENSE", + "URL": "https://brio.r-lib.org, https://github.com/r-lib/brio", + "BugReports": "https://github.com/r-lib/brio/issues", + "Depends": [ + "R (>= 3.6)" + ], + "Suggests": [ + "covr", + "testthat (>= 3.0.0)" + ], + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.2.3", + "NeedsCompilation": "yes", + "Author": "Jim Hester [aut] (), Gábor Csárdi [aut, cre], Posit Software, PBC [cph, fnd]", + "Maintainer": "Gábor Csárdi ", + "Repository": "RSPM" + }, + "broom": { + "Package": "broom", + "Version": "1.0.13", + "Source": "Repository", + "Type": "Package", + "Title": "Convert Statistical Objects into Tidy Tibbles", + "Authors@R": "c( person(\"David\", \"Robinson\", , \"admiral.david@gmail.com\", role = \"aut\"), person(\"Alex\", \"Hayes\", , \"alexpghayes@gmail.com\", role = \"aut\", comment = c(ORCID = \"0000-0002-4985-5160\")), person(\"Simon\", \"Couch\", , \"simon.couch@posit.co\", role = c(\"aut\"), comment = c(ORCID = \"0000-0001-5676-5107\")), person(\"Emil\", \"Hvitfeldt\", , \"emil.hvitfeldt@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-0679-1945\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")), person(\"Indrajeet\", \"Patil\", , \"patilindrajeet.science@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0003-1995-6531\")), person(\"Derek\", \"Chiu\", , \"dchiu@bccrc.ca\", role = \"ctb\"), person(\"Matthieu\", \"Gomez\", , \"mattg@princeton.edu\", role = \"ctb\"), person(\"Boris\", \"Demeshev\", , \"boris.demeshev@gmail.com\", role = \"ctb\"), person(\"Dieter\", \"Menne\", , \"dieter.menne@menne-biomed.de\", role = \"ctb\"), person(\"Benjamin\", \"Nutter\", , \"nutter@battelle.org\", role = \"ctb\"), person(\"Luke\", \"Johnston\", , \"luke.johnston@mail.utoronto.ca\", role = \"ctb\"), person(\"Ben\", \"Bolker\", , \"bolker@mcmaster.ca\", role = \"ctb\"), person(\"Francois\", \"Briatte\", , \"f.briatte@gmail.com\", role = \"ctb\"), person(\"Jeffrey\", \"Arnold\", , \"jeffrey.arnold@gmail.com\", role = \"ctb\"), person(\"Jonah\", \"Gabry\", , \"jsg2201@columbia.edu\", role = \"ctb\"), person(\"Luciano\", \"Selzer\", , \"luciano.selzer@gmail.com\", role = \"ctb\"), person(\"Gavin\", \"Simpson\", , \"ucfagls@gmail.com\", role = \"ctb\"), person(\"Jens\", \"Preussner\", , \"jens.preussner@mpi-bn.mpg.de\", role = \"ctb\"), person(\"Jay\", \"Hesselberth\", , \"jay.hesselberth@gmail.com\", role = \"ctb\"), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"ctb\"), person(\"Matthew\", \"Lincoln\", , \"matthew.d.lincoln@gmail.com\", role = \"ctb\"), person(\"Alessandro\", \"Gasparini\", , \"ag475@leicester.ac.uk\", role = \"ctb\"), person(\"Lukasz\", \"Komsta\", , \"lukasz.komsta@umlub.pl\", role = \"ctb\"), person(\"Frederick\", \"Novometsky\", role = \"ctb\"), person(\"Wilson\", \"Freitas\", role = \"ctb\"), person(\"Michelle\", \"Evans\", role = \"ctb\"), person(\"Jason Cory\", \"Brunson\", , \"cornelioid@gmail.com\", role = \"ctb\"), person(\"Simon\", \"Jackson\", , \"drsimonjackson@gmail.com\", role = \"ctb\"), person(\"Ben\", \"Whalley\", , \"ben.whalley@plymouth.ac.uk\", role = \"ctb\"), person(\"Karissa\", \"Whiting\", , \"karissa.whiting@gmail.com\", role = \"ctb\"), person(\"Yves\", \"Rosseel\", , \"yrosseel@gmail.com\", role = \"ctb\"), person(\"Michael\", \"Kuehn\", , \"mkuehn10@gmail.com\", role = \"ctb\"), person(\"Jorge\", \"Cimentada\", , \"cimentadaj@gmail.com\", role = \"ctb\"), person(\"Erle\", \"Holgersen\", , \"erle.holgersen@gmail.com\", role = \"ctb\"), person(\"Karl\", \"Dunkle Werner\", role = \"ctb\", comment = c(ORCID = \"0000-0003-0523-7309\")), person(\"Ethan\", \"Christensen\", , \"christensen.ej@gmail.com\", role = \"ctb\"), person(\"Steven\", \"Pav\", , \"shabbychef@gmail.com\", role = \"ctb\"), person(\"Paul\", \"PJ\", , \"pjpaul.stephens@gmail.com\", role = \"ctb\"), person(\"Ben\", \"Schneider\", , \"benjamin.julius.schneider@gmail.com\", role = \"ctb\"), person(\"Patrick\", \"Kennedy\", , \"pkqstr@protonmail.com\", role = \"ctb\"), person(\"Lily\", \"Medina\", , \"lilymiru@gmail.com\", role = \"ctb\"), person(\"Brian\", \"Fannin\", , \"captain@pirategrunt.com\", role = \"ctb\"), person(\"Jason\", \"Muhlenkamp\", , \"jason.muhlenkamp@gmail.com\", role = \"ctb\"), person(\"Matt\", \"Lehman\", role = \"ctb\"), person(\"Bill\", \"Denney\", , \"wdenney@humanpredictions.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-5759-428X\")), person(\"Nic\", \"Crane\", role = \"ctb\"), person(\"Andrew\", \"Bates\", role = \"ctb\"), person(\"Vincent\", \"Arel-Bundock\", , \"vincent.arel-bundock@umontreal.ca\", role = \"ctb\", comment = c(ORCID = \"0000-0003-2042-7063\")), person(\"Hideaki\", \"Hayashi\", role = \"ctb\"), person(\"Luis\", \"Tobalina\", role = \"ctb\"), person(\"Annie\", \"Wang\", , \"anniewang.uc@gmail.com\", role = \"ctb\"), person(\"Wei Yang\", \"Tham\", , \"weiyang.tham@gmail.com\", role = \"ctb\"), person(\"Clara\", \"Wang\", , \"clara.wang.94@gmail.com\", role = \"ctb\"), person(\"Abby\", \"Smith\", , \"als1@u.northwestern.edu\", role = \"ctb\", comment = c(ORCID = \"0000-0002-3207-0375\")), person(\"Jasper\", \"Cooper\", , \"jaspercooper@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-8639-3188\")), person(\"E Auden\", \"Krauska\", , \"krauskae@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-1466-5850\")), person(\"Alex\", \"Wang\", , \"x249wang@uwaterloo.ca\", role = \"ctb\"), person(\"Malcolm\", \"Barrett\", , \"malcolmbarrett@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0003-0299-5825\")), person(\"Charles\", \"Gray\", , \"charlestigray@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-9978-011X\")), person(\"Jared\", \"Wilber\", role = \"ctb\"), person(\"Vilmantas\", \"Gegzna\", , \"GegznaV@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-9500-5167\")), person(\"Eduard\", \"Szoecs\", , \"eduardszoecs@gmail.com\", role = \"ctb\"), person(\"Frederik\", \"Aust\", , \"frederik.aust@uni-koeln.de\", role = \"ctb\", comment = c(ORCID = \"0000-0003-4900-788X\")), person(\"Angus\", \"Moore\", , \"angusmoore9@gmail.com\", role = \"ctb\"), person(\"Nick\", \"Williams\", , \"ntwilliams.personal@gmail.com\", role = \"ctb\"), person(\"Marius\", \"Barth\", , \"marius.barth.uni.koeln@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-3421-6665\")), person(\"Bruna\", \"Wundervald\", , \"brunadaviesw@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0001-8163-220X\")), person(\"Joyce\", \"Cahoon\", , \"joyceyu48@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0001-7217-4702\")), person(\"Grant\", \"McDermott\", , \"grantmcd@uoregon.edu\", role = \"ctb\", comment = c(ORCID = \"0000-0001-7883-8573\")), person(\"Kevin\", \"Zarca\", , \"kevin.zarca@gmail.com\", role = \"ctb\"), person(\"Shiro\", \"Kuriwaki\", , \"shirokuriwaki@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-5687-2647\")), person(\"Lukas\", \"Wallrich\", , \"lukas.wallrich@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0003-2121-5177\")), person(\"James\", \"Martherus\", , \"james@martherus.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-8285-3300\")), person(\"Chuliang\", \"Xiao\", , \"cxiao@umich.edu\", role = \"ctb\", comment = c(ORCID = \"0000-0002-8466-9398\")), person(\"Joseph\", \"Larmarange\", , \"joseph@larmarange.net\", role = \"ctb\"), person(\"Max\", \"Kuhn\", , \"max@posit.co\", role = \"ctb\"), person(\"Michal\", \"Bojanowski\", , \"michal2992@gmail.com\", role = \"ctb\"), person(\"Hakon\", \"Malmedal\", , \"hmalmedal@gmail.com\", role = \"ctb\"), person(\"Clara\", \"Wang\", role = \"ctb\"), person(\"Sergio\", \"Oller\", , \"sergioller@gmail.com\", role = \"ctb\"), person(\"Luke\", \"Sonnet\", , \"luke.sonnet@gmail.com\", role = \"ctb\"), person(\"Jim\", \"Hester\", , \"jim.hester@posit.co\", role = \"ctb\"), person(\"Ben\", \"Schneider\", , \"benjamin.julius.schneider@gmail.com\", role = \"ctb\"), person(\"Bernie\", \"Gray\", , \"bfgray3@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0001-9190-6032\")), person(\"Mara\", \"Averick\", , \"mara@posit.co\", role = \"ctb\"), person(\"Aaron\", \"Jacobs\", , \"atheriel@gmail.com\", role = \"ctb\"), person(\"Andreas\", \"Bender\", , \"bender.at.R@gmail.com\", role = \"ctb\"), person(\"Sven\", \"Templer\", , \"sven.templer@gmail.com\", role = \"ctb\"), person(\"Paul-Christian\", \"Buerkner\", , \"paul.buerkner@gmail.com\", role = \"ctb\"), person(\"Matthew\", \"Kay\", , \"mjskay@umich.edu\", role = \"ctb\"), person(\"Erwan\", \"Le Pennec\", , \"lepennec@gmail.com\", role = \"ctb\"), person(\"Johan\", \"Junkka\", , \"johan.junkka@umu.se\", role = \"ctb\"), person(\"Hao\", \"Zhu\", , \"haozhu233@gmail.com\", role = \"ctb\"), person(\"Benjamin\", \"Soltoff\", , \"soltoffbc@uchicago.edu\", role = \"ctb\"), person(\"Zoe\", \"Wilkinson Saldana\", , \"zoewsaldana@gmail.com\", role = \"ctb\"), person(\"Tyler\", \"Littlefield\", , \"tylurp1@gmail.com\", role = \"ctb\"), person(\"Charles T.\", \"Gray\", , \"charlestigray@gmail.com\", role = \"ctb\"), person(\"Shabbh E.\", \"Banks\", role = \"ctb\"), person(\"Serina\", \"Robinson\", , \"robi0916@umn.edu\", role = \"ctb\"), person(\"Roger\", \"Bivand\", , \"Roger.Bivand@nhh.no\", role = \"ctb\"), person(\"Riinu\", \"Ots\", , \"riinuots@gmail.com\", role = \"ctb\"), person(\"Nicholas\", \"Williams\", , \"ntwilliams.personal@gmail.com\", role = \"ctb\"), person(\"Nina\", \"Jakobsen\", role = \"ctb\"), person(\"Michael\", \"Weylandt\", , \"michael.weylandt@gmail.com\", role = \"ctb\"), person(\"Lisa\", \"Lendway\", , \"llendway@macalester.edu\", role = \"ctb\"), person(\"Karl\", \"Hailperin\", , \"khailper@gmail.com\", role = \"ctb\"), person(\"Josue\", \"Rodriguez\", , \"jerrodriguez@ucdavis.edu\", role = \"ctb\"), person(\"Jenny\", \"Bryan\", , \"jenny@posit.co\", role = \"ctb\"), person(\"Chris\", \"Jarvis\", , \"Christopher1.jarvis@gmail.com\", role = \"ctb\"), person(\"Greg\", \"Macfarlane\", , \"gregmacfarlane@gmail.com\", role = \"ctb\"), person(\"Brian\", \"Mannakee\", , \"bmannakee@gmail.com\", role = \"ctb\"), person(\"Drew\", \"Tyre\", , \"atyre2@unl.edu\", role = \"ctb\"), person(\"Shreyas\", \"Singh\", , \"shreyas.singh.298@gmail.com\", role = \"ctb\"), person(\"Laurens\", \"Geffert\", , \"laurensgeffert@gmail.com\", role = \"ctb\"), person(\"Hong\", \"Ooi\", , \"hongooi@microsoft.com\", role = \"ctb\"), person(\"Henrik\", \"Bengtsson\", , \"henrikb@braju.com\", role = \"ctb\"), person(\"Eduard\", \"Szocs\", , \"eduardszoecs@gmail.com\", role = \"ctb\"), person(\"David\", \"Hugh-Jones\", , \"davidhughjones@gmail.com\", role = \"ctb\"), person(\"Matthieu\", \"Stigler\", , \"Matthieu.Stigler@gmail.com\", role = \"ctb\"), person(\"Hugo\", \"Tavares\", , \"hm533@cam.ac.uk\", role = \"ctb\", comment = c(ORCID = \"0000-0001-9373-2726\")), person(\"R. Willem\", \"Vervoort\", , \"Willemvervoort@gmail.com\", role = \"ctb\"), person(\"Brenton M.\", \"Wiernik\", , \"brenton@wiernik.org\", role = \"ctb\"), person(\"Josh\", \"Yamamoto\", , \"joshuayamamoto5@gmail.com\", role = \"ctb\"), person(\"Jasme\", \"Lee\", role = \"ctb\"), person(\"Taren\", \"Sanders\", , \"taren.sanders@acu.edu.au\", role = \"ctb\", comment = c(ORCID = \"0000-0002-4504-6008\")), person(\"Ilaria\", \"Prosdocimi\", , \"prosdocimi.ilaria@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0001-8565-094X\")), person(\"Daniel D.\", \"Sjoberg\", , \"danield.sjoberg@gmail.com\", role = \"ctb\", comment = c(ORCID = \"0000-0003-0862-2018\")), person(\"Alex\", \"Reinhart\", , \"areinhar@stat.cmu.edu\", role = \"ctb\", comment = c(ORCID = \"0000-0002-6658-514X\")) )", + "Description": "Summarizes key information about statistical objects in tidy tibbles. This makes it easy to report results, create plots and consistently work with large numbers of models at once. Broom provides three verbs that each provide different types of information about a model. tidy() summarizes information about model components such as coefficients of a regression. glance() reports information about an entire model, such as goodness of fit measures like AIC and BIC. augment() adds information about individual observations to a dataset, such as fitted values or influence measures.", + "License": "MIT + file LICENSE", + "URL": "https://broom.tidymodels.org/, https://github.com/tidymodels/broom", + "BugReports": "https://github.com/tidymodels/broom/issues", + "Depends": [ + "R (>= 4.1)" + ], + "Imports": [ + "backports", + "cli", + "dplyr (>= 1.0.0)", + "generics (>= 0.0.2)", + "glue", + "lifecycle", + "purrr", + "rlang (>= 1.1.0)", + "stringr", + "tibble (>= 3.0.0)", + "tidyr (>= 1.0.0)" + ], + "Suggests": [ + "AER", + "AUC", + "bbmle", + "betareg (>= 3.2-1)", + "biglm", + "binGroup", + "boot", + "btergm (>= 1.10.6)", + "car (>= 3.1-2)", + "carData", + "caret", + "cluster", + "cmprsk", + "coda", + "covr", + "drc", + "e1071", + "emmeans", + "epiR (>= 2.0.85)", + "ergm (>= 3.10.4)", + "fixest (>= 0.9.0)", + "gam (>= 1.15)", + "gee", + "geepack", + "ggplot2", + "glmnet", + "glmnetUtils", + "gmm", + "Hmisc", + "interp", + "irlba", + "joineRML", + "Kendall", + "knitr", + "ks", + "Lahman", + "lavaan (>= 0.6.18)", + "leaps", + "lfe", + "lm.beta", + "lme4", + "lmodel2", + "lmtest (>= 0.9.38)", + "lsmeans", + "maps", + "margins", + "MASS", + "mclust", + "mediation", + "metafor", + "mfx", + "mgcv", + "mlogit", + "modeldata", + "modeltests (>= 0.1.6)", + "muhaz", + "multcomp", + "network", + "nnet", + "ordinal", + "plm", + "poLCA", + "psych", + "quantreg", + "rmarkdown", + "robust", + "robustbase", + "rsample", + "sandwich", + "spatialreg", + "spdep (>= 1.1)", + "speedglm", + "spelling", + "stats4", + "survey", + "survival (>= 3.6-4)", + "systemfit", + "testthat (>= 3.0.0)", + "tseries", + "vars", + "zoo" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-25", + "Encoding": "UTF-8", + "Language": "en-US", + "RoxygenNote": "7.3.3", + "Collate": "'aaa-documentation-helper.R' 'null-and-default.R' 'aer.R' 'auc.R' 'base.R' 'bbmle.R' 'betareg.R' 'biglm.R' 'bingroup.R' 'boot.R' 'broom-package.R' 'broom.R' 'btergm.R' 'car.R' 'caret.R' 'cluster.R' 'cmprsk.R' 'data-frame.R' 'deprecated-0-7-0.R' 'drc.R' 'emmeans.R' 'epiR.R' 'ergm.R' 'fixest.R' 'gam.R' 'geepack.R' 'glmnet-cv-glmnet.R' 'glmnet-glmnet.R' 'gmm.R' 'hmisc.R' 'import-standalone-obj-type.R' 'import-standalone-types-check.R' 'joinerml.R' 'kendall.R' 'ks.R' 'lavaan.R' 'leaps.R' 'lfe.R' 'list-irlba.R' 'list-optim.R' 'list-svd.R' 'list-xyz.R' 'list.R' 'lm-beta.R' 'lmodel2.R' 'lmtest.R' 'maps.R' 'margins.R' 'mass-fitdistr.R' 'mass-negbin.R' 'mass-polr.R' 'mass-ridgelm.R' 'stats-lm.R' 'mass-rlm.R' 'mclust.R' 'mediation.R' 'metafor.R' 'mfx.R' 'mgcv.R' 'mlogit.R' 'muhaz.R' 'multcomp.R' 'nnet.R' 'nobs.R' 'ordinal-clm.R' 'ordinal-clmm.R' 'plm.R' 'polca.R' 'psych.R' 'stats-nls.R' 'quantreg-nlrq.R' 'quantreg-rq.R' 'quantreg-rqs.R' 'robust-glmrob.R' 'robust-lmrob.R' 'robustbase-glmrob.R' 'robustbase-lmrob.R' 'sp.R' 'spdep.R' 'speedglm-speedglm.R' 'speedglm-speedlm.R' 'stats-anova.R' 'stats-arima.R' 'stats-decompose.R' 'stats-factanal.R' 'stats-glm.R' 'stats-htest.R' 'stats-kmeans.R' 'stats-loess.R' 'stats-mlm.R' 'stats-prcomp.R' 'stats-smooth.spline.R' 'stats-summary-lm.R' 'stats-time-series.R' 'survey.R' 'survival-aareg.R' 'survival-cch.R' 'survival-coxph.R' 'survival-pyears.R' 'survival-survdiff.R' 'survival-survexp.R' 'survival-survfit.R' 'survival-survreg.R' 'systemfit.R' 'tseries.R' 'utilities.R' 'vars.R' 'zoo.R' 'zzz.R'", + "NeedsCompilation": "no", + "Author": "David Robinson [aut], Alex Hayes [aut] (ORCID: ), Simon Couch [aut] (ORCID: ), Emil Hvitfeldt [aut, cre] (ORCID: ), Posit Software, PBC [cph, fnd] (ROR: ), Indrajeet Patil [ctb] (ORCID: ), Derek Chiu [ctb], Matthieu Gomez [ctb], Boris Demeshev [ctb], Dieter Menne [ctb], Benjamin Nutter [ctb], Luke Johnston [ctb], Ben Bolker [ctb], Francois Briatte [ctb], Jeffrey Arnold [ctb], Jonah Gabry [ctb], Luciano Selzer [ctb], Gavin Simpson [ctb], Jens Preussner [ctb], Jay Hesselberth [ctb], Hadley Wickham [ctb], Matthew Lincoln [ctb], Alessandro Gasparini [ctb], Lukasz Komsta [ctb], Frederick Novometsky [ctb], Wilson Freitas [ctb], Michelle Evans [ctb], Jason Cory Brunson [ctb], Simon Jackson [ctb], Ben Whalley [ctb], Karissa Whiting [ctb], Yves Rosseel [ctb], Michael Kuehn [ctb], Jorge Cimentada [ctb], Erle Holgersen [ctb], Karl Dunkle Werner [ctb] (ORCID: ), Ethan Christensen [ctb], Steven Pav [ctb], Paul PJ [ctb], Ben Schneider [ctb], Patrick Kennedy [ctb], Lily Medina [ctb], Brian Fannin [ctb], Jason Muhlenkamp [ctb], Matt Lehman [ctb], Bill Denney [ctb] (ORCID: ), Nic Crane [ctb], Andrew Bates [ctb], Vincent Arel-Bundock [ctb] (ORCID: ), Hideaki Hayashi [ctb], Luis Tobalina [ctb], Annie Wang [ctb], Wei Yang Tham [ctb], Clara Wang [ctb], Abby Smith [ctb] (ORCID: ), Jasper Cooper [ctb] (ORCID: ), E Auden Krauska [ctb] (ORCID: ), Alex Wang [ctb], Malcolm Barrett [ctb] (ORCID: ), Charles Gray [ctb] (ORCID: ), Jared Wilber [ctb], Vilmantas Gegzna [ctb] (ORCID: ), Eduard Szoecs [ctb], Frederik Aust [ctb] (ORCID: ), Angus Moore [ctb], Nick Williams [ctb], Marius Barth [ctb] (ORCID: ), Bruna Wundervald [ctb] (ORCID: ), Joyce Cahoon [ctb] (ORCID: ), Grant McDermott [ctb] (ORCID: ), Kevin Zarca [ctb], Shiro Kuriwaki [ctb] (ORCID: ), Lukas Wallrich [ctb] (ORCID: ), James Martherus [ctb] (ORCID: ), Chuliang Xiao [ctb] (ORCID: ), Joseph Larmarange [ctb], Max Kuhn [ctb], Michal Bojanowski [ctb], Hakon Malmedal [ctb], Clara Wang [ctb], Sergio Oller [ctb], Luke Sonnet [ctb], Jim Hester [ctb], Ben Schneider [ctb], Bernie Gray [ctb] (ORCID: ), Mara Averick [ctb], Aaron Jacobs [ctb], Andreas Bender [ctb], Sven Templer [ctb], Paul-Christian Buerkner [ctb], Matthew Kay [ctb], Erwan Le Pennec [ctb], Johan Junkka [ctb], Hao Zhu [ctb], Benjamin Soltoff [ctb], Zoe Wilkinson Saldana [ctb], Tyler Littlefield [ctb], Charles T. Gray [ctb], Shabbh E. Banks [ctb], Serina Robinson [ctb], Roger Bivand [ctb], Riinu Ots [ctb], Nicholas Williams [ctb], Nina Jakobsen [ctb], Michael Weylandt [ctb], Lisa Lendway [ctb], Karl Hailperin [ctb], Josue Rodriguez [ctb], Jenny Bryan [ctb], Chris Jarvis [ctb], Greg Macfarlane [ctb], Brian Mannakee [ctb], Drew Tyre [ctb], Shreyas Singh [ctb], Laurens Geffert [ctb], Hong Ooi [ctb], Henrik Bengtsson [ctb], Eduard Szocs [ctb], David Hugh-Jones [ctb], Matthieu Stigler [ctb], Hugo Tavares [ctb] (ORCID: ), R. Willem Vervoort [ctb], Brenton M. Wiernik [ctb], Josh Yamamoto [ctb], Jasme Lee [ctb], Taren Sanders [ctb] (ORCID: ), Ilaria Prosdocimi [ctb] (ORCID: ), Daniel D. Sjoberg [ctb] (ORCID: ), Alex Reinhart [ctb] (ORCID: )", + "Maintainer": "Emil Hvitfeldt ", + "Repository": "CRAN" + }, "bslib": { "Package": "bslib", - "Version": "0.9.0", + "Version": "0.11.0", "Source": "Repository", "Title": "Custom 'Bootstrap' 'Sass' Themes for 'shiny' and 'rmarkdown'", "Authors@R": "c( person(\"Carson\", \"Sievert\", , \"carson@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-4958-2844\")), person(\"Joe\", \"Cheng\", , \"joe@posit.co\", role = \"aut\"), person(\"Garrick\", \"Aden-Buie\", , \"garrick@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0002-7111-0077\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")), person(, \"Bootstrap contributors\", role = \"ctb\", comment = \"Bootstrap library\"), person(, \"Twitter, Inc\", role = \"cph\", comment = \"Bootstrap library\"), person(\"Javi\", \"Aguilar\", role = c(\"ctb\", \"cph\"), comment = \"Bootstrap colorpicker library\"), person(\"Thomas\", \"Park\", role = c(\"ctb\", \"cph\"), comment = \"Bootswatch library\"), person(, \"PayPal\", role = c(\"ctb\", \"cph\"), comment = \"Bootstrap accessibility plugin\") )", @@ -354,16 +658,18 @@ "sass (>= 0.4.9)" ], "Suggests": [ + "brand.yml", "bsicons", "curl", "fontawesome", "future", "ggplot2", "knitr", + "lattice", "magrittr", "rappdirs", "rmarkdown (>= 2.7)", - "shiny (> 1.8.1)", + "shiny (>= 1.11.1.9000)", "testthat", "thematic", "tools", @@ -374,14 +680,14 @@ "Config/Needs/deploy": "BH, chiflights22, colourpicker, commonmark, cpp11, cpsievert/chiflights22, cpsievert/histoslider, dplyr, DT, ggplot2, ggridges, gt, hexbin, histoslider, htmlwidgets, lattice, leaflet, lubridate, markdown, modelr, plotly, reactable, reshape2, rprojroot, rsconnect, rstudio/shiny, scales, styler, tibble", "Config/Needs/routine": "chromote, desc, renv", "Config/Needs/website": "brio, crosstalk, dplyr, DT, ggplot2, glue, htmlwidgets, leaflet, lorem, palmerpenguins, plotly, purrr, rprojroot, rstudio/htmltools, scales, stringr, tidyr, webshot2", + "Config/roxygen2/version": "8.0.0", "Config/testthat/edition": "3", "Config/testthat/parallel": "true", "Config/testthat/start-first": "zzzz-bs-sass, fonts, zzz-precompile, theme-*, rmd-*", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", - "Collate": "'accordion.R' 'breakpoints.R' 'bs-current-theme.R' 'bs-dependencies.R' 'bs-global.R' 'bs-remove.R' 'bs-theme-layers.R' 'bs-theme-preset-bootswatch.R' 'bs-theme-preset-brand.R' 'bs-theme-preset-builtin.R' 'bs-theme-preset.R' 'utils.R' 'bs-theme-preview.R' 'bs-theme-update.R' 'bs-theme.R' 'bslib-package.R' 'buttons.R' 'card.R' 'deprecated.R' 'files.R' 'fill.R' 'imports.R' 'input-dark-mode.R' 'input-switch.R' 'layout.R' 'nav-items.R' 'nav-update.R' 'navbar_options.R' 'navs-legacy.R' 'navs.R' 'onLoad.R' 'page.R' 'popover.R' 'precompiled.R' 'print.R' 'shiny-devmode.R' 'sidebar.R' 'staticimports.R' 'tooltip.R' 'utils-deps.R' 'utils-shiny.R' 'utils-tags.R' 'value-box.R' 'version-default.R' 'versions.R'", + "Collate": "'accordion.R' 'breakpoints.R' 'bs-current-theme.R' 'bs-dependencies.R' 'bs-global.R' 'bs-remove.R' 'bs-theme-layers.R' 'bs-theme-preset-bootswatch.R' 'bs-theme-preset-brand.R' 'bs-theme-preset-builtin.R' 'bs-theme-preset.R' 'utils.R' 'bs-theme-preview.R' 'bs-theme-update.R' 'bs-theme.R' 'bslib-package.R' 'buttons.R' 'card.R' 'deprecated.R' 'files.R' 'fill.R' 'imports.R' 'input-code-editor.R' 'input-dark-mode.R' 'input-submit.R' 'input-switch.R' 'layout.R' 'nav-items.R' 'nav-update.R' 'navbar_options.R' 'navs-legacy.R' 'navs.R' 'onLoad.R' 'page.R' 'popover.R' 'precompiled.R' 'print.R' 'shiny-devmode.R' 'sidebar.R' 'staticimports.R' 'toast.R' 'toolbar.R' 'tooltip.R' 'utils-deps.R' 'utils-shiny.R' 'utils-tags.R' 'value-box.R' 'version-default.R' 'versions.R'", "NeedsCompilation": "no", - "Author": "Carson Sievert [aut, cre] (), Joe Cheng [aut], Garrick Aden-Buie [aut] (), Posit Software, PBC [cph, fnd], Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Javi Aguilar [ctb, cph] (Bootstrap colorpicker library), Thomas Park [ctb, cph] (Bootswatch library), PayPal [ctb, cph] (Bootstrap accessibility plugin)", + "Author": "Carson Sievert [aut, cre] (ORCID: ), Joe Cheng [aut], Garrick Aden-Buie [aut] (ORCID: ), Posit Software, PBC [cph, fnd], Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Javi Aguilar [ctb, cph] (Bootstrap colorpicker library), Thomas Park [ctb, cph] (Bootswatch library), PayPal [ctb, cph] (Bootstrap accessibility plugin)", "Maintainer": "Carson Sievert ", "Repository": "CRAN" }, @@ -411,12 +717,82 @@ "Maintainer": "Winston Chang ", "Repository": "CRAN" }, + "callr": { + "Package": "callr", + "Version": "3.7.6", + "Source": "Repository", + "Title": "Call R from R", + "Authors@R": "c( person(\"Gábor\", \"Csárdi\", , \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\", \"cph\"), comment = c(ORCID = \"0000-0001-7098-9676\")), person(\"Winston\", \"Chang\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")), person(\"Ascent Digital Services\", role = c(\"cph\", \"fnd\")) )", + "Description": "It is sometimes useful to perform a computation in a separate R process, without affecting the current R process at all. This packages does exactly that.", + "License": "MIT + file LICENSE", + "URL": "https://callr.r-lib.org, https://github.com/r-lib/callr", + "BugReports": "https://github.com/r-lib/callr/issues", + "Depends": [ + "R (>= 3.4)" + ], + "Imports": [ + "processx (>= 3.6.1)", + "R6", + "utils" + ], + "Suggests": [ + "asciicast (>= 2.3.1)", + "cli (>= 1.1.0)", + "mockery", + "ps", + "rprojroot", + "spelling", + "testthat (>= 3.2.0)", + "withr (>= 2.3.0)" + ], + "Config/Needs/website": "r-lib/asciicast, glue, htmlwidgets, igraph, tibble, tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "Language": "en-US", + "RoxygenNote": "7.3.1.9000", + "NeedsCompilation": "no", + "Author": "Gábor Csárdi [aut, cre, cph] (), Winston Chang [aut], Posit Software, PBC [cph, fnd], Ascent Digital Services [cph, fnd]", + "Maintainer": "Gábor Csárdi ", + "Repository": "RSPM" + }, + "cellranger": { + "Package": "cellranger", + "Version": "1.1.0", + "Source": "Repository", + "Title": "Translate Spreadsheet Cell Ranges to Rows and Columns", + "Authors@R": "c( person(\"Jennifer\", \"Bryan\", , \"jenny@stat.ubc.ca\", c(\"cre\", \"aut\")), person(\"Hadley\", \"Wickham\", , \"hadley@rstudio.com\", \"ctb\") )", + "Description": "Helper functions to work with spreadsheets and the \"A1:D10\" style of cell range specification.", + "Depends": [ + "R (>= 3.0.0)" + ], + "License": "MIT + file LICENSE", + "LazyData": "true", + "URL": "https://github.com/rsheets/cellranger", + "BugReports": "https://github.com/rsheets/cellranger/issues", + "Suggests": [ + "covr", + "testthat (>= 1.0.0)", + "knitr", + "rmarkdown" + ], + "RoxygenNote": "5.0.1.9000", + "VignetteBuilder": "knitr", + "Imports": [ + "rematch", + "tibble" + ], + "NeedsCompilation": "no", + "Author": "Jennifer Bryan [cre, aut], Hadley Wickham [ctb]", + "Maintainer": "Jennifer Bryan ", + "Repository": "RSPM", + "Encoding": "UTF-8" + }, "cli": { "Package": "cli", - "Version": "3.6.4", + "Version": "3.6.6", "Source": "Repository", "Title": "Helpers for Developing Command Line Interfaces", - "Authors@R": "c( person(\"Gábor\", \"Csárdi\", , \"gabor@posit.co\", role = c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", role = \"ctb\"), person(\"Kirill\", \"Müller\", role = \"ctb\"), person(\"Salim\", \"Brüggemann\", , \"salim-b@pm.me\", role = \"ctb\", comment = c(ORCID = \"0000-0002-5329-5987\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Authors@R": "c( person(\"Gábor\", \"Csárdi\", , \"gabor@posit.co\", role = c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", role = \"ctb\"), person(\"Kirill\", \"Müller\", role = \"ctb\"), person(\"Salim\", \"Brüggemann\", , \"salim-b@pm.me\", role = \"ctb\", comment = c(ORCID = \"0000-0002-5329-5987\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", "Description": "A suite of tools to build attractive command line interfaces ('CLIs'), from semantic elements: headings, lists, alerts, paragraphs, etc. Supports custom themes via a 'CSS'-like language. It also contains a number of lower level 'CLI' elements: rules, boxes, trees, and 'Unicode' symbols with 'ASCII' alternatives. It support ANSI colors and text styles as well.", "License": "MIT + file LICENSE", "URL": "https://cli.r-lib.org, https://github.com/r-lib/cli", @@ -451,10 +827,11 @@ ], "Config/Needs/website": "r-lib/asciicast, bench, brio, cpp11, decor, desc, fansi, prettyunits, sessioninfo, tidyverse/tidytemplate, usethis, vctrs", "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-25", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", + "RoxygenNote": "7.3.2.9000", "NeedsCompilation": "yes", - "Author": "Gábor Csárdi [aut, cre], Hadley Wickham [ctb], Kirill Müller [ctb], Salim Brüggemann [ctb] (), Posit Software, PBC [cph, fnd]", + "Author": "Gábor Csárdi [aut, cre], Hadley Wickham [ctb], Kirill Müller [ctb], Salim Brüggemann [ctb] (ORCID: ), Posit Software, PBC [cph, fnd] (ROR: )", "Maintainer": "Gábor Csárdi ", "Repository": "CRAN" }, @@ -489,60 +866,6 @@ "Maintainer": "Matthew Lincoln ", "Repository": "CRAN" }, - "colorspace": { - "Package": "colorspace", - "Version": "2.1-1", - "Source": "Repository", - "Date": "2024-07-26", - "Title": "A Toolbox for Manipulating and Assessing Colors and Palettes", - "Authors@R": "c(person(given = \"Ross\", family = \"Ihaka\", role = \"aut\", email = \"ihaka@stat.auckland.ac.nz\"), person(given = \"Paul\", family = \"Murrell\", role = \"aut\", email = \"paul@stat.auckland.ac.nz\", comment = c(ORCID = \"0000-0002-3224-8858\")), person(given = \"Kurt\", family = \"Hornik\", role = \"aut\", email = \"Kurt.Hornik@R-project.org\", comment = c(ORCID = \"0000-0003-4198-9911\")), person(given = c(\"Jason\", \"C.\"), family = \"Fisher\", role = \"aut\", email = \"jfisher@usgs.gov\", comment = c(ORCID = \"0000-0001-9032-8912\")), person(given = \"Reto\", family = \"Stauffer\", role = \"aut\", email = \"Reto.Stauffer@uibk.ac.at\", comment = c(ORCID = \"0000-0002-3798-5507\")), person(given = c(\"Claus\", \"O.\"), family = \"Wilke\", role = \"aut\", email = \"wilke@austin.utexas.edu\", comment = c(ORCID = \"0000-0002-7470-9261\")), person(given = c(\"Claire\", \"D.\"), family = \"McWhite\", role = \"aut\", email = \"claire.mcwhite@utmail.utexas.edu\", comment = c(ORCID = \"0000-0001-7346-3047\")), person(given = \"Achim\", family = \"Zeileis\", role = c(\"aut\", \"cre\"), email = \"Achim.Zeileis@R-project.org\", comment = c(ORCID = \"0000-0003-0918-3766\")))", - "Description": "Carries out mapping between assorted color spaces including RGB, HSV, HLS, CIEXYZ, CIELUV, HCL (polar CIELUV), CIELAB, and polar CIELAB. Qualitative, sequential, and diverging color palettes based on HCL colors are provided along with corresponding ggplot2 color scales. Color palette choice is aided by an interactive app (with either a Tcl/Tk or a shiny graphical user interface) and shiny apps with an HCL color picker and a color vision deficiency emulator. Plotting functions for displaying and assessing palettes include color swatches, visualizations of the HCL space, and trajectories in HCL and/or RGB spectrum. Color manipulation functions include: desaturation, lightening/darkening, mixing, and simulation of color vision deficiencies (deutanomaly, protanomaly, tritanomaly). Details can be found on the project web page at and in the accompanying scientific paper: Zeileis et al. (2020, Journal of Statistical Software, ).", - "Depends": [ - "R (>= 3.0.0)", - "methods" - ], - "Imports": [ - "graphics", - "grDevices", - "stats" - ], - "Suggests": [ - "datasets", - "utils", - "KernSmooth", - "MASS", - "kernlab", - "mvtnorm", - "vcd", - "tcltk", - "shiny", - "shinyjs", - "ggplot2", - "dplyr", - "scales", - "grid", - "png", - "jpeg", - "knitr", - "rmarkdown", - "RColorBrewer", - "rcartocolor", - "scico", - "viridis", - "wesanderson" - ], - "VignetteBuilder": "knitr", - "License": "BSD_3_clause + file LICENSE", - "URL": "https://colorspace.R-Forge.R-project.org/, https://hclwizard.org/", - "BugReports": "https://colorspace.R-Forge.R-project.org/contact.html", - "LazyData": "yes", - "Encoding": "UTF-8", - "RoxygenNote": "7.3.1", - "NeedsCompilation": "yes", - "Author": "Ross Ihaka [aut], Paul Murrell [aut] (), Kurt Hornik [aut] (), Jason C. Fisher [aut] (), Reto Stauffer [aut] (), Claus O. Wilke [aut] (), Claire D. McWhite [aut] (), Achim Zeileis [aut, cre] ()", - "Maintainer": "Achim Zeileis ", - "Repository": "CRAN" - }, "commonmark": { "Package": "commonmark", "Version": "1.9.5", @@ -565,11 +888,48 @@ "NeedsCompilation": "yes", "Author": "Jeroen Ooms [aut, cre] (), John MacFarlane [cph] (Author of cmark)", "Maintainer": "Jeroen Ooms ", - "Repository": "CRAN" + "Repository": "RSPM" + }, + "conflicted": { + "Package": "conflicted", + "Version": "1.2.0", + "Source": "Repository", + "Title": "An Alternative Conflict Resolution Strategy", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@rstudio.com\", role = c(\"aut\", \"cre\")), person(\"RStudio\", role = c(\"cph\", \"fnd\")) )", + "Description": "R's default conflict management system gives the most recently loaded package precedence. This can make it hard to detect conflicts, particularly when they arise because a package update creates ambiguity that did not previously exist. 'conflicted' takes a different approach, making every conflict an error and forcing you to choose which function to use.", + "License": "MIT + file LICENSE", + "URL": "https://conflicted.r-lib.org/, https://github.com/r-lib/conflicted", + "BugReports": "https://github.com/r-lib/conflicted/issues", + "Depends": [ + "R (>= 3.2)" + ], + "Imports": [ + "cli (>= 3.4.0)", + "memoise", + "rlang (>= 1.0.0)" + ], + "Suggests": [ + "callr", + "covr", + "dplyr", + "Matrix", + "methods", + "pkgload", + "testthat (>= 3.0.0)", + "withr" + ], + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.2.3", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut, cre], RStudio [cph, fnd]", + "Maintainer": "Hadley Wickham ", + "Repository": "RSPM" }, "cpp11": { "Package": "cpp11", - "Version": "0.5.2", + "Version": "0.5.5", "Source": "Repository", "Title": "A C++11 Interface for R's C Interface", "Authors@R": "c( person(\"Davis\", \"Vaughan\", email = \"davis@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0003-4777-038X\")), person(\"Jim\",\"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Romain\", \"François\", role = \"aut\", comment = c(ORCID = \"0000-0002-2444-4226\")), person(\"Benjamin\", \"Kietzman\", role = \"ctb\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", @@ -608,9 +968,9 @@ "Config/testthat/edition": "3", "Config/Needs/cpp11/cpp_register": "brio, cli, decor, desc, glue, tibble, vctrs", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", + "RoxygenNote": "7.3.3", "NeedsCompilation": "no", - "Author": "Davis Vaughan [aut, cre] (), Jim Hester [aut] (), Romain François [aut] (), Benjamin Kietzman [ctb], Posit Software, PBC [cph, fnd]", + "Author": "Davis Vaughan [aut, cre] (ORCID: ), Jim Hester [aut] (ORCID: ), Romain François [aut] (ORCID: ), Benjamin Kietzman [ctb], Posit Software, PBC [cph, fnd]", "Maintainer": "Davis Vaughan ", "Repository": "CRAN" }, @@ -646,14 +1006,14 @@ }, "curl": { "Package": "curl", - "Version": "6.2.2", + "Version": "7.1.0", "Source": "Repository", "Type": "Package", "Title": "A Modern and Flexible Web Client for R", "Authors@R": "c( person(\"Jeroen\", \"Ooms\", role = c(\"aut\", \"cre\"), email = \"jeroenooms@gmail.com\", comment = c(ORCID = \"0000-0002-4035-0289\")), person(\"Hadley\", \"Wickham\", role = \"ctb\"), person(\"Posit Software, PBC\", role = \"cph\"))", "Description": "Bindings to 'libcurl' for performing fully configurable HTTP/FTP requests where responses can be processed in memory, on disk, or streaming via the callback or connection interfaces. Some knowledge of 'libcurl' is recommended; for a more-user-friendly web client see the 'httr2' package which builds on this package with http specific tools and logic.", "License": "MIT + file LICENSE", - "SystemRequirements": "libcurl (>= 7.62): libcurl-devel (rpm) or libcurl4-openssl-dev (deb)", + "SystemRequirements": "libcurl (>= 7.73): libcurl-devel (rpm) or libcurl4-openssl-dev (deb)", "URL": "https://jeroen.r-universe.dev/curl", "BugReports": "https://github.com/jeroen/curl/issues", "Suggests": [ @@ -670,45 +1030,224 @@ "Depends": [ "R (>= 3.0.0)" ], - "RoxygenNote": "7.3.2.9000", + "RoxygenNote": "7.3.2", "Encoding": "UTF-8", "Language": "en-US", "NeedsCompilation": "yes", - "Author": "Jeroen Ooms [aut, cre] (), Hadley Wickham [ctb], Posit Software, PBC [cph]", + "Author": "Jeroen Ooms [aut, cre] (ORCID: ), Hadley Wickham [ctb], Posit Software, PBC [cph]", "Maintainer": "Jeroen Ooms ", "Repository": "CRAN" }, - "digest": { - "Package": "digest", - "Version": "0.6.37", + "data.table": { + "Package": "data.table", + "Version": "1.18.4", "Source": "Repository", - "Authors@R": "c(person(\"Dirk\", \"Eddelbuettel\", role = c(\"aut\", \"cre\"), email = \"edd@debian.org\", comment = c(ORCID = \"0000-0001-6419-907X\")), person(\"Antoine\", \"Lucas\", role=\"ctb\"), person(\"Jarek\", \"Tuszynski\", role=\"ctb\"), person(\"Henrik\", \"Bengtsson\", role=\"ctb\", comment = c(ORCID = \"0000-0002-7579-5165\")), person(\"Simon\", \"Urbanek\", role=\"ctb\", comment = c(ORCID = \"0000-0003-2297-1732\")), person(\"Mario\", \"Frasca\", role=\"ctb\"), person(\"Bryan\", \"Lewis\", role=\"ctb\"), person(\"Murray\", \"Stokely\", role=\"ctb\"), person(\"Hannes\", \"Muehleisen\", role=\"ctb\"), person(\"Duncan\", \"Murdoch\", role=\"ctb\"), person(\"Jim\", \"Hester\", role=\"ctb\"), person(\"Wush\", \"Wu\", role=\"ctb\", comment = c(ORCID = \"0000-0001-5180-0567\")), person(\"Qiang\", \"Kou\", role=\"ctb\", comment = c(ORCID = \"0000-0001-6786-5453\")), person(\"Thierry\", \"Onkelinx\", role=\"ctb\", comment = c(ORCID = \"0000-0001-8804-4216\")), person(\"Michel\", \"Lang\", role=\"ctb\", comment = c(ORCID = \"0000-0001-9754-0393\")), person(\"Viliam\", \"Simko\", role=\"ctb\"), person(\"Kurt\", \"Hornik\", role=\"ctb\", comment = c(ORCID = \"0000-0003-4198-9911\")), person(\"Radford\", \"Neal\", role=\"ctb\", comment = c(ORCID = \"0000-0002-2473-3407\")), person(\"Kendon\", \"Bell\", role=\"ctb\", comment = c(ORCID = \"0000-0002-9093-8312\")), person(\"Matthew\", \"de Queljoe\", role=\"ctb\"), person(\"Dmitry\", \"Selivanov\", role=\"ctb\"), person(\"Ion\", \"Suruceanu\", role=\"ctb\"), person(\"Bill\", \"Denney\", role=\"ctb\"), person(\"Dirk\", \"Schumacher\", role=\"ctb\"), person(\"András\", \"Svraka\", role=\"ctb\"), person(\"Sergey\", \"Fedorov\", role=\"ctb\"), person(\"Will\", \"Landau\", role=\"ctb\", comment = c(ORCID = \"0000-0003-1878-3253\")), person(\"Floris\", \"Vanderhaeghe\", role=\"ctb\", comment = c(ORCID = \"0000-0002-6378-6229\")), person(\"Kevin\", \"Tappe\", role=\"ctb\"), person(\"Harris\", \"McGehee\", role=\"ctb\"), person(\"Tim\", \"Mastny\", role=\"ctb\"), person(\"Aaron\", \"Peikert\", role=\"ctb\", comment = c(ORCID = \"0000-0001-7813-818X\")), person(\"Mark\", \"van der Loo\", role=\"ctb\", comment = c(ORCID = \"0000-0002-9807-4686\")), person(\"Chris\", \"Muir\", role=\"ctb\", comment = c(ORCID = \"0000-0003-2555-3878\")), person(\"Moritz\", \"Beller\", role=\"ctb\", comment = c(ORCID = \"0000-0003-4852-0526\")), person(\"Sebastian\", \"Campbell\", role=\"ctb\"), person(\"Winston\", \"Chang\", role=\"ctb\", comment = c(ORCID = \"0000-0002-1576-2126\")), person(\"Dean\", \"Attali\", role=\"ctb\", comment = c(ORCID = \"0000-0002-5645-3493\")), person(\"Michael\", \"Chirico\", role=\"ctb\", comment = c(ORCID = \"0000-0003-0787-087X\")), person(\"Kevin\", \"Ushey\", role=\"ctb\"))", - "Date": "2024-08-19", - "Title": "Create Compact Hash Digests of R Objects", - "Description": "Implementation of a function 'digest()' for the creation of hash digests of arbitrary R objects (using the 'md5', 'sha-1', 'sha-256', 'crc32', 'xxhash', 'murmurhash', 'spookyhash', 'blake3', 'crc32c', 'xxh3_64', and 'xxh3_128' algorithms) permitting easy comparison of R language objects, as well as functions such as'hmac()' to create hash-based message authentication code. Please note that this package is not meant to be deployed for cryptographic purposes for which more comprehensive (and widely tested) libraries such as 'OpenSSL' should be used.", - "URL": "https://github.com/eddelbuettel/digest, https://dirk.eddelbuettel.com/code/digest.html", - "BugReports": "https://github.com/eddelbuettel/digest/issues", + "Title": "Extension of `data.frame`", "Depends": [ - "R (>= 3.3.0)" + "R (>= 3.4.0)" ], "Imports": [ - "utils" + "methods" ], - "License": "GPL (>= 2)", "Suggests": [ - "tinytest", - "simplermarkdown" + "bit64 (>= 4.0.0)", + "bit (>= 4.0.4)", + "R.utils (>= 2.13.0)", + "xts", + "zoo (>= 1.8-1)", + "yaml", + "knitr", + "markdown" + ], + "Description": "Fast aggregation of large data (e.g. 100GB in RAM), fast ordered joins, fast add/modify/delete of columns by group using no copies at all, list columns, friendly and fast character-separated-value read/write. Offers a natural and flexible syntax, for faster development.", + "License": "MPL-2.0 | file LICENSE", + "URL": "https://r-datatable.com, https://Rdatatable.gitlab.io/data.table, https://github.com/Rdatatable/data.table", + "BugReports": "https://github.com/Rdatatable/data.table/issues", + "VignetteBuilder": "knitr", + "Encoding": "UTF-8", + "ByteCompile": "TRUE", + "Authors@R": "c( person(\"Tyson\",\"Barrett\", role=c(\"aut\",\"cre\"), email=\"t.barrett88@gmail.com\", comment = c(ORCID=\"0000-0002-2137-1391\")), person(\"Matt\",\"Dowle\", role=\"aut\", email=\"mattjdowle@gmail.com\"), person(\"Arun\",\"Srinivasan\", role=\"aut\", email=\"asrini@pm.me\"), person(\"Jan\",\"Gorecki\", role=\"aut\", email=\"j.gorecki@wit.edu.pl\"), person(\"Michael\",\"Chirico\", role=\"aut\", email=\"michaelchirico4@gmail.com\", comment = c(ORCID=\"0000-0003-0787-087X\")), person(\"Toby\",\"Hocking\", role=\"aut\", email=\"toby.hocking@r-project.org\", comment = c(ORCID=\"0000-0002-3146-0865\")), person(\"Benjamin\",\"Schwendinger\",role=\"aut\", comment = c(ORCID=\"0000-0003-3315-8114\")), person(\"Ivan\", \"Krylov\", role=\"aut\", email=\"ikrylov@disroot.org\", comment = c(ORCID=\"0000-0002-0172-3812\")), person(\"Pasha\",\"Stetsenko\", role=\"ctb\"), person(\"Tom\",\"Short\", role=\"ctb\"), person(\"Steve\",\"Lianoglou\", role=\"ctb\"), person(\"Eduard\",\"Antonyan\", role=\"ctb\"), person(\"Markus\",\"Bonsch\", role=\"ctb\"), person(\"Hugh\",\"Parsonage\", role=\"ctb\"), person(\"Scott\",\"Ritchie\", role=\"ctb\"), person(\"Kun\",\"Ren\", role=\"ctb\"), person(\"Xianying\",\"Tan\", role=\"ctb\"), person(\"Rick\",\"Saporta\", role=\"ctb\"), person(\"Otto\",\"Seiskari\", role=\"ctb\"), person(\"Xianghui\",\"Dong\", role=\"ctb\"), person(\"Michel\",\"Lang\", role=\"ctb\"), person(\"Watal\",\"Iwasaki\", role=\"ctb\"), person(\"Seth\",\"Wenchel\", role=\"ctb\"), person(\"Karl\",\"Broman\", role=\"ctb\"), person(\"Tobias\",\"Schmidt\", role=\"ctb\"), person(\"David\",\"Arenburg\", role=\"ctb\"), person(\"Ethan\",\"Smith\", role=\"ctb\"), person(\"Francois\",\"Cocquemas\", role=\"ctb\"), person(\"Matthieu\",\"Gomez\", role=\"ctb\"), person(\"Philippe\",\"Chataignon\", role=\"ctb\"), person(\"Nello\",\"Blaser\", role=\"ctb\"), person(\"Dmitry\",\"Selivanov\", role=\"ctb\"), person(\"Andrey\",\"Riabushenko\", role=\"ctb\"), person(\"Cheng\",\"Lee\", role=\"ctb\"), person(\"Declan\",\"Groves\", role=\"ctb\"), person(\"Daniel\",\"Possenriede\", role=\"ctb\"), person(\"Felipe\",\"Parages\", role=\"ctb\"), person(\"Denes\",\"Toth\", role=\"ctb\"), person(\"Mus\",\"Yaramaz-David\", role=\"ctb\"), person(\"Ayappan\",\"Perumal\", role=\"ctb\"), person(\"James\",\"Sams\", role=\"ctb\"), person(\"Martin\",\"Morgan\", role=\"ctb\"), person(\"Michael\",\"Quinn\", role=\"ctb\"), person(given=\"@javrucebo\", role=\"ctb\", comment=\"GitHub user\"), person(\"Marc\",\"Halperin\", role=\"ctb\"), person(\"Roy\",\"Storey\", role=\"ctb\"), person(\"Manish\",\"Saraswat\", role=\"ctb\"), person(\"Morgan\",\"Jacob\", role=\"ctb\"), person(\"Michael\",\"Schubmehl\", role=\"ctb\"), person(\"Davis\",\"Vaughan\", role=\"ctb\"), person(\"Leonardo\",\"Silvestri\", role=\"ctb\"), person(\"Jim\",\"Hester\", role=\"ctb\"), person(\"Anthony\",\"Damico\", role=\"ctb\"), person(\"Sebastian\",\"Freundt\", role=\"ctb\"), person(\"David\",\"Simons\", role=\"ctb\"), person(\"Elliott\",\"Sales de Andrade\", role=\"ctb\"), person(\"Cole\",\"Miller\", role=\"ctb\"), person(\"Jens Peder\",\"Meldgaard\", role=\"ctb\"), person(\"Vaclav\",\"Tlapak\", role=\"ctb\"), person(\"Kevin\",\"Ushey\", role=\"ctb\"), person(\"Dirk\",\"Eddelbuettel\", role=\"ctb\"), person(\"Tony\",\"Fischetti\", role=\"ctb\"), person(\"Ofek\",\"Shilon\", role=\"ctb\"), person(\"Vadim\",\"Khotilovich\", role=\"ctb\"), person(\"Hadley\",\"Wickham\", role=\"ctb\"), person(\"Bennet\",\"Becker\", role=\"ctb\"), person(\"Kyle\",\"Haynes\", role=\"ctb\"), person(\"Boniface Christian\",\"Kamgang\", role=\"ctb\"), person(\"Olivier\",\"Delmarcell\", role=\"ctb\"), person(\"Josh\",\"O'Brien\", role=\"ctb\"), person(\"Dereck\",\"de Mezquita\", role=\"ctb\"), person(\"Michael\",\"Czekanski\", role=\"ctb\"), person(\"Dmitry\", \"Shemetov\", role=\"ctb\"), person(\"Nitish\", \"Jha\", role=\"ctb\"), person(\"Joshua\", \"Wu\", role=\"ctb\"), person(\"Iago\", \"Giné-Vázquez\", role=\"ctb\"), person(\"Anirban\", \"Chetia\", role=\"ctb\"), person(\"Doris\", \"Amoakohene\", role=\"ctb\"), person(\"Angel\", \"Feliz\", role=\"ctb\"), person(\"Michael\",\"Young\", role=\"ctb\"), person(\"Mark\", \"Seeto\", role=\"ctb\"), person(\"Philippe\", \"Grosjean\", role=\"ctb\"), person(\"Vincent\", \"Runge\", role=\"ctb\"), person(\"Christian\", \"Wia\", role=\"ctb\"), person(\"Elise\", \"Maigné\", role=\"ctb\"), person(\"Vincent\", \"Rocher\", role=\"ctb\"), person(\"Vijay\", \"Lulla\", role=\"ctb\"), person(\"Aljaž\", \"Sluga\", role=\"ctb\"), person(\"Bill\", \"Evans\", role=\"ctb\"), person(\"Reino\", \"Bruner\", role=\"ctb\"), person(given=\"@badasahog\", role=\"ctb\", comment=\"GitHub user\"), person(\"Vinit\", \"Thakur\", role=\"ctb\"), person(\"Mukul\", \"Kumar\", role=\"ctb\"), person(\"Ildikó\", \"Czeller\", role=\"ctb\"), person(\"Manmita\", \"Das\", role=\"ctb\"), person(\"Tarun\", \"Thammisetty\", role=\"ctb\") )", + "NeedsCompilation": "yes", + "Author": "Tyson Barrett [aut, cre] (ORCID: ), Matt Dowle [aut], Arun Srinivasan [aut], Jan Gorecki [aut], Michael Chirico [aut] (ORCID: ), Toby Hocking [aut] (ORCID: ), Benjamin Schwendinger [aut] (ORCID: ), Ivan Krylov [aut] (ORCID: ), Pasha Stetsenko [ctb], Tom Short [ctb], Steve Lianoglou [ctb], Eduard Antonyan [ctb], Markus Bonsch [ctb], Hugh Parsonage [ctb], Scott Ritchie [ctb], Kun Ren [ctb], Xianying Tan [ctb], Rick Saporta [ctb], Otto Seiskari [ctb], Xianghui Dong [ctb], Michel Lang [ctb], Watal Iwasaki [ctb], Seth Wenchel [ctb], Karl Broman [ctb], Tobias Schmidt [ctb], David Arenburg [ctb], Ethan Smith [ctb], Francois Cocquemas [ctb], Matthieu Gomez [ctb], Philippe Chataignon [ctb], Nello Blaser [ctb], Dmitry Selivanov [ctb], Andrey Riabushenko [ctb], Cheng Lee [ctb], Declan Groves [ctb], Daniel Possenriede [ctb], Felipe Parages [ctb], Denes Toth [ctb], Mus Yaramaz-David [ctb], Ayappan Perumal [ctb], James Sams [ctb], Martin Morgan [ctb], Michael Quinn [ctb], @javrucebo [ctb] (GitHub user), Marc Halperin [ctb], Roy Storey [ctb], Manish Saraswat [ctb], Morgan Jacob [ctb], Michael Schubmehl [ctb], Davis Vaughan [ctb], Leonardo Silvestri [ctb], Jim Hester [ctb], Anthony Damico [ctb], Sebastian Freundt [ctb], David Simons [ctb], Elliott Sales de Andrade [ctb], Cole Miller [ctb], Jens Peder Meldgaard [ctb], Vaclav Tlapak [ctb], Kevin Ushey [ctb], Dirk Eddelbuettel [ctb], Tony Fischetti [ctb], Ofek Shilon [ctb], Vadim Khotilovich [ctb], Hadley Wickham [ctb], Bennet Becker [ctb], Kyle Haynes [ctb], Boniface Christian Kamgang [ctb], Olivier Delmarcell [ctb], Josh O'Brien [ctb], Dereck de Mezquita [ctb], Michael Czekanski [ctb], Dmitry Shemetov [ctb], Nitish Jha [ctb], Joshua Wu [ctb], Iago Giné-Vázquez [ctb], Anirban Chetia [ctb], Doris Amoakohene [ctb], Angel Feliz [ctb], Michael Young [ctb], Mark Seeto [ctb], Philippe Grosjean [ctb], Vincent Runge [ctb], Christian Wia [ctb], Elise Maigné [ctb], Vincent Rocher [ctb], Vijay Lulla [ctb], Aljaž Sluga [ctb], Bill Evans [ctb], Reino Bruner [ctb], @badasahog [ctb] (GitHub user), Vinit Thakur [ctb], Mukul Kumar [ctb], Ildikó Czeller [ctb], Manmita Das [ctb], Tarun Thammisetty [ctb]", + "Maintainer": "Tyson Barrett ", + "Repository": "CRAN" + }, + "dbplyr": { + "Package": "dbplyr", + "Version": "2.5.2", + "Source": "Repository", + "Type": "Package", + "Title": "A 'dplyr' Back End for Databases", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Maximilian\", \"Girlich\", role = \"aut\"), person(\"Edgar\", \"Ruiz\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "A 'dplyr' back end for databases that allows you to work with remote database tables as if they are in-memory data frames. Basic features works with any database that has a 'DBI' back end; more advanced features require 'SQL' translation to be provided by the package author.", + "License": "MIT + file LICENSE", + "URL": "https://dbplyr.tidyverse.org/, https://github.com/tidyverse/dbplyr", + "BugReports": "https://github.com/tidyverse/dbplyr/issues", + "Depends": [ + "R (>= 3.6)" + ], + "Imports": [ + "blob (>= 1.2.0)", + "cli (>= 3.6.1)", + "DBI (>= 1.1.3)", + "dplyr (>= 1.1.2)", + "glue (>= 1.6.2)", + "lifecycle (>= 1.0.3)", + "magrittr", + "methods", + "pillar (>= 1.9.0)", + "purrr (>= 1.0.1)", + "R6 (>= 2.2.2)", + "rlang (>= 1.1.1)", + "tibble (>= 3.2.1)", + "tidyr (>= 1.3.0)", + "tidyselect (>= 1.2.1)", + "utils", + "vctrs (>= 0.6.3)", + "withr (>= 2.5.0)" + ], + "Suggests": [ + "bit64", + "covr", + "knitr", + "Lahman", + "nycflights13", + "odbc (>= 1.4.2)", + "RMariaDB (>= 1.2.2)", + "rmarkdown", + "RPostgres (>= 1.4.5)", + "RPostgreSQL", + "RSQLite (>= 2.3.8)", + "testthat (>= 3.1.10)" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/testthat/parallel": "TRUE", + "Encoding": "UTF-8", + "Language": "en-gb", + "RoxygenNote": "7.3.3", + "Collate": "'db-sql.R' 'utils-check.R' 'import-standalone-types-check.R' 'import-standalone-obj-type.R' 'utils.R' 'sql.R' 'escape.R' 'translate-sql-cut.R' 'translate-sql-quantile.R' 'translate-sql-string.R' 'translate-sql-paste.R' 'translate-sql-helpers.R' 'translate-sql-window.R' 'translate-sql-conditional.R' 'backend-.R' 'backend-access.R' 'backend-hana.R' 'backend-hive.R' 'backend-impala.R' 'verb-copy-to.R' 'backend-mssql.R' 'backend-mysql.R' 'backend-odbc.R' 'backend-oracle.R' 'backend-postgres.R' 'backend-postgres-old.R' 'backend-redshift.R' 'backend-snowflake.R' 'backend-spark-sql.R' 'backend-sqlite.R' 'backend-teradata.R' 'build-sql.R' 'data-cache.R' 'data-lahman.R' 'data-nycflights13.R' 'db-escape.R' 'db-io.R' 'db.R' 'dbplyr.R' 'explain.R' 'ident.R' 'import-standalone-s3-register.R' 'join-by-compat.R' 'join-cols-compat.R' 'lazy-join-query.R' 'lazy-ops.R' 'lazy-query.R' 'lazy-select-query.R' 'lazy-set-op-query.R' 'memdb.R' 'optimise-utils.R' 'pillar.R' 'progress.R' 'sql-build.R' 'query-join.R' 'query-select.R' 'query-semi-join.R' 'query-set-op.R' 'query.R' 'reexport.R' 'remote.R' 'rows.R' 'schema.R' 'simulate.R' 'sql-clause.R' 'sql-expr.R' 'src-sql.R' 'src_dbi.R' 'table-name.R' 'tbl-lazy.R' 'tbl-sql.R' 'test-frame.R' 'testthat.R' 'tidyeval-across.R' 'tidyeval.R' 'translate-sql.R' 'utils-format.R' 'verb-arrange.R' 'verb-compute.R' 'verb-count.R' 'verb-distinct.R' 'verb-do-query.R' 'verb-do.R' 'verb-expand.R' 'verb-fill.R' 'verb-filter.R' 'verb-group_by.R' 'verb-head.R' 'verb-joins.R' 'verb-mutate.R' 'verb-pivot-longer.R' 'verb-pivot-wider.R' 'verb-pull.R' 'verb-select.R' 'verb-set-ops.R' 'verb-slice.R' 'verb-summarise.R' 'verb-uncount.R' 'verb-window.R' 'zzz.R'", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut, cre], Maximilian Girlich [aut], Edgar Ruiz [aut], Posit Software, PBC [cph, fnd]", + "Maintainer": "Hadley Wickham ", + "Repository": "CRAN" + }, + "desc": { + "Package": "desc", + "Version": "1.4.3", + "Source": "Repository", + "Title": "Manipulate DESCRIPTION Files", + "Authors@R": "c( person(\"Gábor\", \"Csárdi\", , \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\")), person(\"Kirill\", \"Müller\", role = \"aut\"), person(\"Jim\", \"Hester\", , \"james.f.hester@gmail.com\", role = \"aut\"), person(\"Maëlle\", \"Salmon\", role = \"ctb\", comment = c(ORCID = \"0000-0002-2815-0399\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Maintainer": "Gábor Csárdi ", + "Description": "Tools to read, write, create, and manipulate DESCRIPTION files. It is intended for packages that create or manipulate other packages.", + "License": "MIT + file LICENSE", + "URL": "https://desc.r-lib.org/, https://github.com/r-lib/desc", + "BugReports": "https://github.com/r-lib/desc/issues", + "Depends": [ + "R (>= 3.4)" + ], + "Imports": [ + "cli", + "R6", + "utils" + ], + "Suggests": [ + "callr", + "covr", + "gh", + "spelling", + "testthat", + "whoami", + "withr" + ], + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "Language": "en-US", + "RoxygenNote": "7.2.3", + "Collate": "'assertions.R' 'authors-at-r.R' 'built.R' 'classes.R' 'collate.R' 'constants.R' 'deps.R' 'desc-package.R' 'description.R' 'encoding.R' 'find-package-root.R' 'latex.R' 'non-oo-api.R' 'package-archives.R' 'read.R' 'remotes.R' 'str.R' 'syntax_checks.R' 'urls.R' 'utils.R' 'validate.R' 'version.R'", + "NeedsCompilation": "no", + "Author": "Gábor Csárdi [aut, cre], Kirill Müller [aut], Jim Hester [aut], Maëlle Salmon [ctb] (), Posit Software, PBC [cph, fnd]", + "Repository": "RSPM" + }, + "digest": { + "Package": "digest", + "Version": "0.6.39", + "Source": "Repository", + "Authors@R": "c(person(\"Dirk\", \"Eddelbuettel\", role = c(\"aut\", \"cre\"), email = \"edd@debian.org\", comment = c(ORCID = \"0000-0001-6419-907X\")), person(\"Antoine\", \"Lucas\", role=\"ctb\", comment = c(ORCID = \"0000-0002-8059-9767\")), person(\"Jarek\", \"Tuszynski\", role=\"ctb\"), person(\"Henrik\", \"Bengtsson\", role=\"ctb\", comment = c(ORCID = \"0000-0002-7579-5165\")), person(\"Simon\", \"Urbanek\", role=\"ctb\", comment = c(ORCID = \"0000-0003-2297-1732\")), person(\"Mario\", \"Frasca\", role=\"ctb\"), person(\"Bryan\", \"Lewis\", role=\"ctb\"), person(\"Murray\", \"Stokely\", role=\"ctb\"), person(\"Hannes\", \"Muehleisen\", role=\"ctb\", comment = c(ORCID = \"0000-0001-8552-0029\")), person(\"Duncan\", \"Murdoch\", role=\"ctb\"), person(\"Jim\", \"Hester\", role=\"ctb\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Wush\", \"Wu\", role=\"ctb\", comment = c(ORCID = \"0000-0001-5180-0567\")), person(\"Qiang\", \"Kou\", role=\"ctb\", comment = c(ORCID = \"0000-0001-6786-5453\")), person(\"Thierry\", \"Onkelinx\", role=\"ctb\", comment = c(ORCID = \"0000-0001-8804-4216\")), person(\"Michel\", \"Lang\", role=\"ctb\", comment = c(ORCID = \"0000-0001-9754-0393\")), person(\"Viliam\", \"Simko\", role=\"ctb\"), person(\"Kurt\", \"Hornik\", role=\"ctb\", comment = c(ORCID = \"0000-0003-4198-9911\")), person(\"Radford\", \"Neal\", role=\"ctb\", comment = c(ORCID = \"0000-0002-2473-3407\")), person(\"Kendon\", \"Bell\", role=\"ctb\", comment = c(ORCID = \"0000-0002-9093-8312\")), person(\"Matthew\", \"de Queljoe\", role=\"ctb\"), person(\"Dmitry\", \"Selivanov\", role=\"ctb\", comment = c(ORCID = \"0000-0003-0492-6647\")), person(\"Ion\", \"Suruceanu\", role=\"ctb\", comment = c(ORCID = \"0009-0005-6446-4909\")), person(\"Bill\", \"Denney\", role=\"ctb\", comment = c(ORCID = \"0000-0002-5759-428X\")), person(\"Dirk\", \"Schumacher\", role=\"ctb\"), person(\"András\", \"Svraka\", role=\"ctb\", comment = c(ORCID = \"0009-0008-8480-1329\")), person(\"Sergey\", \"Fedorov\", role=\"ctb\", comment = c(ORCID = \"0000-0002-5970-7233\")), person(\"Will\", \"Landau\", role=\"ctb\", comment = c(ORCID = \"0000-0003-1878-3253\")), person(\"Floris\", \"Vanderhaeghe\", role=\"ctb\", comment = c(ORCID = \"0000-0002-6378-6229\")), person(\"Kevin\", \"Tappe\", role=\"ctb\"), person(\"Harris\", \"McGehee\", role=\"ctb\"), person(\"Tim\", \"Mastny\", role=\"ctb\"), person(\"Aaron\", \"Peikert\", role=\"ctb\", comment = c(ORCID = \"0000-0001-7813-818X\")), person(\"Mark\", \"van der Loo\", role=\"ctb\", comment = c(ORCID = \"0000-0002-9807-4686\")), person(\"Chris\", \"Muir\", role=\"ctb\", comment = c(ORCID = \"0000-0003-2555-3878\")), person(\"Moritz\", \"Beller\", role=\"ctb\", comment = c(ORCID = \"0000-0003-4852-0526\")), person(\"Sebastian\", \"Campbell\", role=\"ctb\", comment = c(ORCID = \"0009-0000-5948-4503\")), person(\"Winston\", \"Chang\", role=\"ctb\", comment = c(ORCID = \"0000-0002-1576-2126\")), person(\"Dean\", \"Attali\", role=\"ctb\", comment = c(ORCID = \"0000-0002-5645-3493\")), person(\"Michael\", \"Chirico\", role=\"ctb\", comment = c(ORCID = \"0000-0003-0787-087X\")), person(\"Kevin\", \"Ushey\", role=\"ctb\", comment = c(ORCID = \"0000-0003-2880-7407\")), person(\"Carl\", \"Pearson\", role=\"ctb\", comment = c(ORCID = \"0000-0003-0701-7860\")))", + "Date": "2025-11-19", + "Title": "Create Compact Hash Digests of R Objects", + "Description": "Implementation of a function 'digest()' for the creation of hash digests of arbitrary R objects (using the 'md5', 'sha-1', 'sha-256', 'crc32', 'xxhash', 'murmurhash', 'spookyhash', 'blake3', 'crc32c', 'xxh3_64', and 'xxh3_128' algorithms) permitting easy comparison of R language objects, as well as functions such as 'hmac()' to create hash-based message authentication code. Please note that this package is not meant to be deployed for cryptographic purposes for which more comprehensive (and widely tested) libraries such as 'OpenSSL' should be used.", + "URL": "https://github.com/eddelbuettel/digest, https://eddelbuettel.github.io/digest/, https://dirk.eddelbuettel.com/code/digest.html", + "BugReports": "https://github.com/eddelbuettel/digest/issues", + "Depends": [ + "R (>= 3.3.0)" + ], + "Imports": [ + "utils" + ], + "License": "GPL (>= 2)", + "Suggests": [ + "tinytest", + "simplermarkdown", + "rbenchmark" ], "VignetteBuilder": "simplermarkdown", "Encoding": "UTF-8", "NeedsCompilation": "yes", - "Author": "Dirk Eddelbuettel [aut, cre] (), Antoine Lucas [ctb], Jarek Tuszynski [ctb], Henrik Bengtsson [ctb] (), Simon Urbanek [ctb] (), Mario Frasca [ctb], Bryan Lewis [ctb], Murray Stokely [ctb], Hannes Muehleisen [ctb], Duncan Murdoch [ctb], Jim Hester [ctb], Wush Wu [ctb] (), Qiang Kou [ctb] (), Thierry Onkelinx [ctb] (), Michel Lang [ctb] (), Viliam Simko [ctb], Kurt Hornik [ctb] (), Radford Neal [ctb] (), Kendon Bell [ctb] (), Matthew de Queljoe [ctb], Dmitry Selivanov [ctb], Ion Suruceanu [ctb], Bill Denney [ctb], Dirk Schumacher [ctb], András Svraka [ctb], Sergey Fedorov [ctb], Will Landau [ctb] (), Floris Vanderhaeghe [ctb] (), Kevin Tappe [ctb], Harris McGehee [ctb], Tim Mastny [ctb], Aaron Peikert [ctb] (), Mark van der Loo [ctb] (), Chris Muir [ctb] (), Moritz Beller [ctb] (), Sebastian Campbell [ctb], Winston Chang [ctb] (), Dean Attali [ctb] (), Michael Chirico [ctb] (), Kevin Ushey [ctb]", + "Author": "Dirk Eddelbuettel [aut, cre] (ORCID: ), Antoine Lucas [ctb] (ORCID: ), Jarek Tuszynski [ctb], Henrik Bengtsson [ctb] (ORCID: ), Simon Urbanek [ctb] (ORCID: ), Mario Frasca [ctb], Bryan Lewis [ctb], Murray Stokely [ctb], Hannes Muehleisen [ctb] (ORCID: ), Duncan Murdoch [ctb], Jim Hester [ctb] (ORCID: ), Wush Wu [ctb] (ORCID: ), Qiang Kou [ctb] (ORCID: ), Thierry Onkelinx [ctb] (ORCID: ), Michel Lang [ctb] (ORCID: ), Viliam Simko [ctb], Kurt Hornik [ctb] (ORCID: ), Radford Neal [ctb] (ORCID: ), Kendon Bell [ctb] (ORCID: ), Matthew de Queljoe [ctb], Dmitry Selivanov [ctb] (ORCID: ), Ion Suruceanu [ctb] (ORCID: ), Bill Denney [ctb] (ORCID: ), Dirk Schumacher [ctb], András Svraka [ctb] (ORCID: ), Sergey Fedorov [ctb] (ORCID: ), Will Landau [ctb] (ORCID: ), Floris Vanderhaeghe [ctb] (ORCID: ), Kevin Tappe [ctb], Harris McGehee [ctb], Tim Mastny [ctb], Aaron Peikert [ctb] (ORCID: ), Mark van der Loo [ctb] (ORCID: ), Chris Muir [ctb] (ORCID: ), Moritz Beller [ctb] (ORCID: ), Sebastian Campbell [ctb] (ORCID: ), Winston Chang [ctb] (ORCID: ), Dean Attali [ctb] (ORCID: ), Michael Chirico [ctb] (ORCID: ), Kevin Ushey [ctb] (ORCID: ), Carl Pearson [ctb] (ORCID: )", "Maintainer": "Dirk Eddelbuettel ", - "Repository": "CRAN" + "Repository": "https://p3m.dev/cran/latest" + }, + "downlit": { + "Package": "downlit", + "Version": "0.4.4", + "Source": "Repository", + "Title": "Syntax Highlighting and Automatic Linking", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Syntax highlighting of R code, specifically designed for the needs of 'RMarkdown' packages like 'pkgdown', 'hugodown', and 'bookdown'. It includes linking of function calls to their documentation on the web, and automatic translation of ANSI escapes in output to the equivalent HTML.", + "License": "MIT + file LICENSE", + "URL": "https://downlit.r-lib.org/, https://github.com/r-lib/downlit", + "BugReports": "https://github.com/r-lib/downlit/issues", + "Depends": [ + "R (>= 4.0.0)" + ], + "Imports": [ + "brio", + "desc", + "digest", + "evaluate", + "fansi", + "memoise", + "rlang", + "vctrs", + "withr", + "yaml" + ], + "Suggests": [ + "covr", + "htmltools", + "jsonlite", + "MASS", + "MassSpecWavelet", + "pkgload", + "rmarkdown", + "testthat (>= 3.0.0)", + "xml2" + ], + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.1", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut, cre], Posit Software, PBC [cph, fnd]", + "Maintainer": "Hadley Wickham ", + "Repository": "RSPM" }, "dplyr": { "Package": "dplyr", - "Version": "1.1.4", + "Version": "1.2.1", "Source": "Repository", "Type": "Package", "Title": "A Grammar of Data Manipulation", @@ -718,27 +1257,25 @@ "URL": "https://dplyr.tidyverse.org, https://github.com/tidyverse/dplyr", "BugReports": "https://github.com/tidyverse/dplyr/issues", "Depends": [ - "R (>= 3.5.0)" + "R (>= 4.1.0)" ], "Imports": [ - "cli (>= 3.4.0)", + "cli (>= 3.6.2)", "generics", "glue (>= 1.3.2)", - "lifecycle (>= 1.0.3)", + "lifecycle (>= 1.0.5)", "magrittr (>= 1.5)", "methods", "pillar (>= 1.9.0)", "R6", - "rlang (>= 1.1.0)", + "rlang (>= 1.1.7)", "tibble (>= 3.2.0)", "tidyselect (>= 1.2.0)", "utils", - "vctrs (>= 0.6.4)" + "vctrs (>= 0.7.1)" ], "Suggests": [ - "bench", "broom", - "callr", "covr", "DBI", "dbplyr (>= 2.2.1)", @@ -746,12 +1283,9 @@ "knitr", "Lahman", "lobstr", - "microbenchmark", "nycflights13", "purrr", "rmarkdown", - "RMySQL", - "RPostgreSQL", "RSQLite", "stringi (>= 1.7.6)", "testthat (>= 3.1.5)", @@ -759,19 +1293,63 @@ "withr" ], "VignetteBuilder": "knitr", - "Config/Needs/website": "tidyverse, shiny, pkgdown, tidyverse/tidytemplate", + "Config/build/compilation-database": "true", + "Config/Needs/website": "tidyverse/tidytemplate", "Config/testthat/edition": "3", "Encoding": "UTF-8", "LazyData": "true", - "RoxygenNote": "7.2.3", + "RoxygenNote": "7.3.3", "NeedsCompilation": "yes", - "Author": "Hadley Wickham [aut, cre] (), Romain François [aut] (), Lionel Henry [aut], Kirill Müller [aut] (), Davis Vaughan [aut] (), Posit Software, PBC [cph, fnd]", + "Author": "Hadley Wickham [aut, cre] (ORCID: ), Romain François [aut] (ORCID: ), Lionel Henry [aut], Kirill Müller [aut] (ORCID: ), Davis Vaughan [aut] (ORCID: ), Posit Software, PBC [cph, fnd]", + "Maintainer": "Hadley Wickham ", + "Repository": "CRAN" + }, + "dtplyr": { + "Package": "dtplyr", + "Version": "1.3.3", + "Source": "Repository", + "Title": "Data Table Back-End for 'dplyr'", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"cre\", \"aut\")), person(\"Maximilian\", \"Girlich\", role = \"aut\"), person(\"Mark\", \"Fairbanks\", role = \"aut\"), person(\"Ryan\", \"Dickerson\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Provides a data.table backend for 'dplyr'. The goal of 'dtplyr' is to allow you to write 'dplyr' code that is automatically translated to the equivalent, but usually much faster, data.table code.", + "License": "MIT + file LICENSE", + "URL": "https://dtplyr.tidyverse.org, https://github.com/tidyverse/dtplyr", + "BugReports": "https://github.com/tidyverse/dtplyr/issues", + "Depends": [ + "R (>= 4.0)" + ], + "Imports": [ + "cli (>= 3.4.0)", + "data.table (>= 1.13.0)", + "dplyr (>= 1.1.0)", + "glue", + "lifecycle", + "rlang (>= 1.0.4)", + "tibble", + "tidyselect (>= 1.2.0)", + "vctrs (>= 0.4.1)" + ], + "Suggests": [ + "bench", + "covr", + "knitr", + "rmarkdown", + "testthat (>= 3.1.2)", + "tidyr (>= 1.1.0)", + "waldo (>= 0.3.1)" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [cre, aut], Maximilian Girlich [aut], Mark Fairbanks [aut], Ryan Dickerson [aut], Posit Software, PBC [cph, fnd]", "Maintainer": "Hadley Wickham ", "Repository": "CRAN" }, "evaluate": { "Package": "evaluate", - "Version": "1.0.3", + "Version": "1.0.5", "Source": "Repository", "Type": "Package", "Title": "Parsing and Evaluation Tools that Provide More Details than the Default", @@ -790,7 +1368,8 @@ "lattice", "methods", "pkgload", - "rlang", + "ragg (>= 1.4.0)", + "rlang (>= 1.1.5)", "knitr", "testthat (>= 3.0.0)", "withr" @@ -800,9 +1379,9 @@ "Encoding": "UTF-8", "RoxygenNote": "7.3.2", "NeedsCompilation": "no", - "Author": "Hadley Wickham [aut, cre], Yihui Xie [aut] (), Michael Lawrence [ctb], Thomas Kluyver [ctb], Jeroen Ooms [ctb], Barret Schloerke [ctb], Adam Ryczkowski [ctb], Hiroaki Yutani [ctb], Michel Lang [ctb], Karolis Koncevičius [ctb], Posit Software, PBC [cph, fnd]", + "Author": "Hadley Wickham [aut, cre], Yihui Xie [aut] (ORCID: ), Michael Lawrence [ctb], Thomas Kluyver [ctb], Jeroen Ooms [ctb], Barret Schloerke [ctb], Adam Ryczkowski [ctb], Hiroaki Yutani [ctb], Michel Lang [ctb], Karolis Koncevičius [ctb], Posit Software, PBC [cph, fnd]", "Maintainer": "Hadley Wickham ", - "Repository": "CRAN" + "Repository": "RSPM" }, "fansi": { "Package": "fansi", @@ -878,6 +1457,111 @@ "Maintainer": "Winston Chang ", "Repository": "CRAN" }, + "flextable": { + "Package": "flextable", + "Version": "0.9.11", + "Source": "Repository", + "Type": "Package", + "Title": "Functions for Tabular Reporting", + "Authors@R": "c( person(\"David\", \"Gohel\", , \"david.gohel@ardata.fr\", role = c(\"aut\", \"cre\")), person(\"ArData\", role = \"cph\"), person(\"Clementine\", \"Jager\", role = \"ctb\"), person(\"Eli\", \"Daniels\", role = \"ctb\"), person(\"Panagiotis\", \"Skintzos\", , \"panagiotis.skintzos@ardata.fr\", role = \"aut\"), person(\"Quentin\", \"Fazilleau\", role = \"ctb\"), person(\"Maxim\", \"Nazarov\", role = \"ctb\"), person(\"Titouan\", \"Robert\", role = \"ctb\"), person(\"Michael\", \"Barrowman\", role = \"ctb\"), person(\"Atsushi\", \"Yasumoto\", role = \"ctb\"), person(\"Paul\", \"Julian\", role = \"ctb\"), person(\"Sean\", \"Browning\", role = \"ctb\"), person(\"Rémi\", \"Thériault\", role = \"ctb\", comment = c(ORCID = \"0000-0003-4315-6788\")), person(\"Samuel\", \"Jobert\", role = \"ctb\"), person(\"Keith\", \"Newman\", role = \"ctb\") )", + "Description": "Use a grammar for creating and customizing pretty tables. The following formats are supported: 'HTML', 'PDF', 'RTF', 'Microsoft Word', 'Microsoft PowerPoint', R 'Grid Graphics' and 'patchwork'. 'R Markdown', 'Quarto' and the package 'officer' can be used to produce the result files. The syntax is the same for the user regardless of the type of output to be produced. A set of functions allows the creation, definition of cell arrangement, addition of headers or footers, formatting and definition of cell content with text and or images. The package also offers a set of high-level functions that allow tabular reporting of statistical models and the creation of complex cross tabulations.", + "License": "GPL-3", + "URL": "https://ardata-fr.github.io/flextable-book/, https://davidgohel.github.io/flextable/", + "BugReports": "https://github.com/davidgohel/flextable/issues", + "Imports": [ + "data.table (>= 1.13.0)", + "gdtools (>= 0.5.0)", + "graphics", + "grDevices", + "grid", + "htmltools", + "knitr", + "officer (>= 0.7.3)", + "ragg", + "rlang", + "rmarkdown (>= 2.0)", + "stats", + "utils", + "uuid (>= 0.1-4)", + "xml2" + ], + "Suggests": [ + "bookdown (>= 0.40)", + "broom", + "broom.mixed", + "chromote", + "cluster", + "commonmark", + "doconv (>= 0.3.0)", + "equatags", + "ggplot2", + "gtable", + "jsonlite", + "lme4", + "magick", + "mgcv", + "nlme", + "officedown", + "patchwork", + "pdftools", + "pkgdown (>= 2.0.0)", + "scales", + "svglite", + "tables (>= 0.9.17)", + "testthat (>= 3.0.0)", + "webshot2", + "withr", + "xtable" + ], + "VignetteBuilder": "knitr", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "no", + "Author": "David Gohel [aut, cre], ArData [cph], Clementine Jager [ctb], Eli Daniels [ctb], Panagiotis Skintzos [aut], Quentin Fazilleau [ctb], Maxim Nazarov [ctb], Titouan Robert [ctb], Michael Barrowman [ctb], Atsushi Yasumoto [ctb], Paul Julian [ctb], Sean Browning [ctb], Rémi Thériault [ctb] (ORCID: ), Samuel Jobert [ctb], Keith Newman [ctb]", + "Maintainer": "David Gohel ", + "Repository": "CRAN" + }, + "fontBitstreamVera": { + "Package": "fontBitstreamVera", + "Version": "0.1.1", + "Source": "Repository", + "Title": "Fonts with 'Bitstream Vera Fonts' License", + "Authors@R": "c( person(\"Lionel\", \"Henry\", , \"lionel.hry@gmail.com\", c(\"cre\", \"aut\")), person(\"Bitstream\", role = \"cph\"))", + "Description": "Provides fonts licensed under the 'Bitstream Vera Fonts' license for the 'fontquiver' package.", + "Depends": [ + "R (>= 3.0.0)" + ], + "License": "file LICENCE", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "5.0.1", + "NeedsCompilation": "no", + "Author": "Lionel Henry [cre, aut], Bitstream [cph]", + "Maintainer": "Lionel Henry ", + "License_is_FOSS": "yes", + "Repository": "CRAN" + }, + "fontLiberation": { + "Package": "fontLiberation", + "Version": "0.1.0", + "Source": "Repository", + "Title": "Liberation Fonts", + "Authors@R": "c( person(\"Lionel\", \"Henry\", , \"lionel@rstudio.com\", \"cre\"), person(\"Pravin Satpute\", role = \"aut\"), person(\"Steve Matteson\", role = \"aut\"), person(\"Red Hat, Inc\", role = \"cph\"), person(\"Google Corporation\", role = \"cph\"))", + "Description": "A placeholder for the Liberation fontset intended for the `fontquiver` package. This fontset covers the 12 combinations of families (sans, serif, mono) and faces (plain, bold, italic, bold italic) supported in R graphics devices.", + "Depends": [ + "R (>= 3.0)" + ], + "License": "file LICENSE", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "5.0.1", + "NeedsCompilation": "no", + "Author": "Lionel Henry [cre], Pravin Satpute [aut], Steve Matteson [aut], Red Hat, Inc [cph], Google Corporation [cph]", + "Maintainer": "Lionel Henry ", + "Repository": "CRAN", + "License_is_FOSS": "yes" + }, "fontawesome": { "Package": "fontawesome", "Version": "0.5.3", @@ -913,18 +1597,88 @@ "Maintainer": "Richard Iannone ", "Repository": "CRAN" }, + "fontquiver": { + "Package": "fontquiver", + "Version": "0.2.1", + "Source": "Repository", + "Title": "Set of Installed Fonts", + "Authors@R": "c( person(\"Lionel\", \"Henry\", , \"lionel@rstudio.com\", c(\"cre\", \"aut\")), person(\"RStudio\", role = \"cph\"), person(\"George Douros\", role = \"cph\", comment = \"Symbola font\"))", + "Description": "Provides a set of fonts with permissive licences. This is useful when you want to avoid system fonts to make sure your outputs are reproducible.", + "Depends": [ + "R (>= 3.0.0)" + ], + "Imports": [ + "fontBitstreamVera (>= 0.1.0)", + "fontLiberation (>= 0.1.0)" + ], + "Suggests": [ + "testthat", + "htmltools" + ], + "License": "GPL-3 | file LICENSE", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "5.0.1", + "Collate": "'font-getters.R' 'fontset.R' 'fontset-bitstream-vera.R' 'fontset-dejavu.R' 'fontset-liberation.R' 'fontset-symbola.R' 'html-dependency.R' 'utils.R'", + "NeedsCompilation": "no", + "Author": "Lionel Henry [cre, aut], RStudio [cph], George Douros [cph] (Symbola font)", + "Maintainer": "Lionel Henry ", + "Repository": "CRAN" + }, + "forcats": { + "Package": "forcats", + "Version": "1.0.1", + "Source": "Repository", + "Title": "Tools for Working with Categorical Variables (Factors)", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Description": "Helpers for reordering factor levels (including moving specified levels to front, ordering by first appearance, reversing, and randomly shuffling), and tools for modifying factor levels (including collapsing rare levels into other, 'anonymising', and manually 'recoding').", + "License": "MIT + file LICENSE", + "URL": "https://forcats.tidyverse.org/, https://github.com/tidyverse/forcats", + "BugReports": "https://github.com/tidyverse/forcats/issues", + "Depends": [ + "R (>= 4.1)" + ], + "Imports": [ + "cli (>= 3.4.0)", + "glue", + "lifecycle", + "magrittr", + "rlang (>= 1.0.0)", + "tibble" + ], + "Suggests": [ + "covr", + "dplyr", + "ggplot2", + "knitr", + "readr", + "rmarkdown", + "testthat (>= 3.0.0)", + "withr" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut, cre], Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Hadley Wickham ", + "Repository": "CRAN" + }, "fs": { "Package": "fs", - "Version": "1.6.5", + "Version": "2.1.0", "Source": "Repository", "Title": "Cross-Platform File System Operations Based on 'libuv'", - "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\"), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Gábor\", \"Csárdi\", , \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\")), person(\"libuv project contributors\", role = \"cph\", comment = \"libuv library\"), person(\"Joyent, Inc. and other Node contributors\", role = \"cph\", comment = \"libuv library\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\"), person(\"Hadley\", \"Wickham\", role = \"aut\"), person(\"Gábor\", \"Csárdi\", role = \"aut\"), person(\"Jeroen\", \"Ooms\", , \"jeroenooms@gmail.com\", role = \"cre\"), person(\"libuv project contributors\", role = \"cph\", comment = \"libuv library\"), person(\"Joyent, Inc. and other Node contributors\", role = \"cph\", comment = \"libuv library\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", "Description": "A cross-platform interface to file system operations, built on top of the 'libuv' C library.", "License": "MIT + file LICENSE", "URL": "https://fs.r-lib.org, https://github.com/r-lib/fs", "BugReports": "https://github.com/r-lib/fs/issues", "Depends": [ - "R (>= 3.6)" + "R (>= 4.1)" ], "Imports": [ "methods" @@ -942,31 +1696,117 @@ "withr" ], "VignetteBuilder": "knitr", - "ByteCompile": "true", + "SystemRequirements": "libuv: libuv-devel (rpm) or libuv1-dev (deb). Alternatively to build the vendored libuv 'cmake' is required. GNU make.", "Config/Needs/website": "tidyverse/tidytemplate", "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-23", "Copyright": "file COPYRIGHTS", "Encoding": "UTF-8", "Language": "en-US", - "RoxygenNote": "7.2.3", - "SystemRequirements": "GNU make", + "RoxygenNote": "7.3.3", "NeedsCompilation": "yes", - "Author": "Jim Hester [aut], Hadley Wickham [aut], Gábor Csárdi [aut, cre], libuv project contributors [cph] (libuv library), Joyent, Inc. and other Node contributors [cph] (libuv library), Posit Software, PBC [cph, fnd]", - "Maintainer": "Gábor Csárdi ", + "Author": "Jim Hester [aut], Hadley Wickham [aut], Gábor Csárdi [aut], Jeroen Ooms [cre], libuv project contributors [cph] (libuv library), Joyent, Inc. and other Node contributors [cph] (libuv library), Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Jeroen Ooms ", + "Repository": "CRAN" + }, + "gargle": { + "Package": "gargle", + "Version": "1.6.1", + "Source": "Repository", + "Title": "Utilities for Working with Google APIs", + "Authors@R": "c( person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Craig\", \"Citro\", , \"craigcitro@google.com\", role = \"aut\"), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Google Inc\", role = \"cph\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Provides utilities for working with Google APIs . This includes functions and classes for handling common credential types and for preparing, executing, and processing HTTP requests.", + "License": "MIT + file LICENSE", + "URL": "https://gargle.r-lib.org, https://github.com/r-lib/gargle", + "BugReports": "https://github.com/r-lib/gargle/issues", + "Depends": [ + "R (>= 4.1)" + ], + "Imports": [ + "cli (>= 3.0.1)", + "fs (>= 1.3.1)", + "glue (>= 1.3.0)", + "httr (>= 1.4.5)", + "jsonlite", + "lifecycle (>= 0.2.0)", + "openssl", + "rappdirs", + "rlang (>= 1.1.0)", + "stats", + "utils", + "withr" + ], + "Suggests": [ + "aws.ec2metadata", + "aws.signature", + "covr", + "httpuv", + "knitr", + "rmarkdown", + "sodium", + "spelling", + "testthat (>= 3.1.7)" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "Language": "en-US", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "no", + "Author": "Jennifer Bryan [aut, cre] (ORCID: ), Craig Citro [aut], Hadley Wickham [aut] (ORCID: ), Google Inc [cph], Posit Software, PBC [cph, fnd]", + "Maintainer": "Jennifer Bryan ", + "Repository": "CRAN" + }, + "gdtools": { + "Package": "gdtools", + "Version": "0.5.0", + "Source": "Repository", + "Title": "Font Metrics and Font Management Utilities for R Graphics", + "Authors@R": "c( person(\"David\", \"Gohel\", , \"david.gohel@ardata.fr\", role = c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", , \"hadley@rstudio.com\", role = \"aut\"), person(\"Lionel\", \"Henry\", , \"lionel@rstudio.com\", role = \"aut\"), person(\"Jeroen\", \"Ooms\", , \"jeroen@berkeley.edu\", role = \"aut\", comment = c(ORCID = \"0000-0002-4035-0289\")), person(\"Yixuan\", \"Qiu\", role = \"ctb\"), person(\"R Core Team\", role = \"cph\", comment = \"Cairo code from X11 device\"), person(\"ArData\", role = \"cph\"), person(\"RStudio\", role = \"cph\") )", + "Description": "Compute text metrics (width, ascent, descent) using 'Cairo' and 'FreeType', independently of the active graphic device. Font lookup is delegated to 'systemfonts'. Additional utilities let users register 'Google Fonts' or bundled 'Liberation' fonts, check font availability, and assemble 'htmlDependency' objects so that fonts are correctly embedded in 'Shiny' applications, 'R Markdown' documents, and 'htmlwidgets' outputs such as 'ggiraph'.", + "License": "GPL-3 | file LICENSE", + "URL": "https://davidgohel.github.io/gdtools/", + "BugReports": "https://github.com/davidgohel/gdtools/issues", + "Depends": [ + "R (>= 4.0.0)" + ], + "Imports": [ + "fontquiver (>= 0.2.0)", + "htmltools", + "Rcpp (>= 0.12.12)", + "systemfonts (>= 1.3.1)", + "tools" + ], + "Suggests": [ + "curl", + "gfonts", + "methods", + "testthat" + ], + "LinkingTo": [ + "Rcpp" + ], + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "SystemRequirements": "cairo, freetype2, fontconfig", + "NeedsCompilation": "yes", + "Author": "David Gohel [aut, cre], Hadley Wickham [aut], Lionel Henry [aut], Jeroen Ooms [aut] (ORCID: ), Yixuan Qiu [ctb], R Core Team [cph] (Cairo code from X11 device), ArData [cph], RStudio [cph]", + "Maintainer": "David Gohel ", "Repository": "CRAN" }, "generics": { "Package": "generics", - "Version": "0.1.3", + "Version": "0.1.4", "Source": "Repository", "Title": "Common S3 Generics not Provided by Base R Methods Related to Model Fitting", - "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@rstudio.com\", role = c(\"aut\", \"cre\")), person(\"Max\", \"Kuhn\", , \"max@rstudio.com\", role = \"aut\"), person(\"Davis\", \"Vaughan\", , \"davis@rstudio.com\", role = \"aut\"), person(\"RStudio\", role = \"cph\") )", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Max\", \"Kuhn\", , \"max@posit.co\", role = \"aut\"), person(\"Davis\", \"Vaughan\", , \"davis@posit.co\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"https://ror.org/03wc8by49\")) )", "Description": "In order to reduce potential package dependencies and conflicts, generics provides a number of commonly used S3 generics.", "License": "MIT + file LICENSE", "URL": "https://generics.r-lib.org, https://github.com/r-lib/generics", "BugReports": "https://github.com/r-lib/generics/issues", "Depends": [ - "R (>= 3.2)" + "R (>= 3.6)" ], "Imports": [ "methods" @@ -981,24 +1821,97 @@ "Config/Needs/website": "tidyverse/tidytemplate", "Config/testthat/edition": "3", "Encoding": "UTF-8", - "RoxygenNote": "7.2.0", + "RoxygenNote": "7.3.2", "NeedsCompilation": "no", - "Author": "Hadley Wickham [aut, cre], Max Kuhn [aut], Davis Vaughan [aut], RStudio [cph]", - "Maintainer": "Hadley Wickham ", + "Author": "Hadley Wickham [aut, cre] (ORCID: ), Max Kuhn [aut], Davis Vaughan [aut], Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Hadley Wickham ", + "Repository": "RSPM" + }, + "ggplot2": { + "Package": "ggplot2", + "Version": "4.0.3", + "Source": "Repository", + "Title": "Create Elegant Data Visualisations Using the Grammar of Graphics", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Winston\", \"Chang\", role = \"aut\", comment = c(ORCID = \"0000-0002-1576-2126\")), person(\"Lionel\", \"Henry\", role = \"aut\"), person(\"Thomas Lin\", \"Pedersen\", , \"thomas.pedersen@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-5147-4711\")), person(\"Kohske\", \"Takahashi\", role = \"aut\"), person(\"Claus\", \"Wilke\", role = \"aut\", comment = c(ORCID = \"0000-0002-7470-9261\")), person(\"Kara\", \"Woo\", role = \"aut\", comment = c(ORCID = \"0000-0002-5125-4188\")), person(\"Hiroaki\", \"Yutani\", role = \"aut\", comment = c(ORCID = \"0000-0002-3385-7233\")), person(\"Dewey\", \"Dunnington\", role = \"aut\", comment = c(ORCID = \"0000-0002-9415-4582\")), person(\"Teun\", \"van den Brand\", role = \"aut\", comment = c(ORCID = \"0000-0002-9335-7468\")), person(\"Posit, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Description": "A system for 'declaratively' creating graphics, based on \"The Grammar of Graphics\". You provide the data, tell 'ggplot2' how to map variables to aesthetics, what graphical primitives to use, and it takes care of the details.", + "License": "MIT + file LICENSE", + "URL": "https://ggplot2.tidyverse.org, https://github.com/tidyverse/ggplot2", + "BugReports": "https://github.com/tidyverse/ggplot2/issues", + "Depends": [ + "R (>= 4.1)" + ], + "Imports": [ + "cli", + "grDevices", + "grid", + "gtable (>= 0.3.6)", + "isoband", + "lifecycle (> 1.0.1)", + "rlang (>= 1.1.0)", + "S7", + "scales (>= 1.4.0)", + "stats", + "vctrs (>= 0.6.0)", + "withr (>= 2.5.0)" + ], + "Suggests": [ + "broom", + "covr", + "dplyr", + "ggplot2movies", + "hexbin", + "Hmisc", + "hms", + "knitr", + "mapproj", + "maps", + "MASS", + "mgcv", + "multcomp", + "munsell", + "nlme", + "profvis", + "quantreg", + "quarto", + "ragg (>= 1.2.6)", + "RColorBrewer", + "roxygen2", + "rpart", + "sf (>= 0.7-3)", + "svglite (>= 2.1.2)", + "testthat (>= 3.1.5)", + "tibble", + "vdiffr (>= 1.0.6)", + "xml2" + ], + "Enhances": [ + "sp" + ], + "VignetteBuilder": "quarto", + "Config/Needs/website": "ggtext, tidyr, forcats, tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-23", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "7.3.3", + "Collate": "'ggproto.R' 'ggplot-global.R' 'aaa-.R' 'aes-colour-fill-alpha.R' 'aes-evaluation.R' 'aes-group-order.R' 'aes-linetype-size-shape.R' 'aes-position.R' 'all-classes.R' 'compat-plyr.R' 'utilities.R' 'aes.R' 'annotation-borders.R' 'utilities-checks.R' 'legend-draw.R' 'geom-.R' 'annotation-custom.R' 'annotation-logticks.R' 'scale-type.R' 'layer.R' 'make-constructor.R' 'geom-polygon.R' 'geom-map.R' 'annotation-map.R' 'geom-raster.R' 'annotation-raster.R' 'annotation.R' 'autolayer.R' 'autoplot.R' 'axis-secondary.R' 'backports.R' 'bench.R' 'bin.R' 'coord-.R' 'coord-cartesian-.R' 'coord-fixed.R' 'coord-flip.R' 'coord-map.R' 'coord-munch.R' 'coord-polar.R' 'coord-quickmap.R' 'coord-radial.R' 'coord-sf.R' 'coord-transform.R' 'data.R' 'docs_layer.R' 'facet-.R' 'facet-grid-.R' 'facet-null.R' 'facet-wrap.R' 'fortify-map.R' 'fortify-models.R' 'fortify-spatial.R' 'fortify.R' 'stat-.R' 'geom-abline.R' 'geom-rect.R' 'geom-bar.R' 'geom-tile.R' 'geom-bin2d.R' 'geom-blank.R' 'geom-boxplot.R' 'geom-col.R' 'geom-path.R' 'geom-contour.R' 'geom-point.R' 'geom-count.R' 'geom-crossbar.R' 'geom-segment.R' 'geom-curve.R' 'geom-defaults.R' 'geom-ribbon.R' 'geom-density.R' 'geom-density2d.R' 'geom-dotplot.R' 'geom-errorbar.R' 'geom-freqpoly.R' 'geom-function.R' 'geom-hex.R' 'geom-histogram.R' 'geom-hline.R' 'geom-jitter.R' 'geom-label.R' 'geom-linerange.R' 'geom-pointrange.R' 'geom-quantile.R' 'geom-rug.R' 'geom-sf.R' 'geom-smooth.R' 'geom-spoke.R' 'geom-text.R' 'geom-violin.R' 'geom-vline.R' 'ggplot2-package.R' 'grob-absolute.R' 'grob-dotstack.R' 'grob-null.R' 'grouping.R' 'properties.R' 'margins.R' 'theme-elements.R' 'guide-.R' 'guide-axis.R' 'guide-axis-logticks.R' 'guide-axis-stack.R' 'guide-axis-theta.R' 'guide-legend.R' 'guide-bins.R' 'guide-colorbar.R' 'guide-colorsteps.R' 'guide-custom.R' 'guide-none.R' 'guide-old.R' 'guides-.R' 'guides-grid.R' 'hexbin.R' 'import-standalone-obj-type.R' 'import-standalone-types-check.R' 'labeller.R' 'labels.R' 'layer-sf.R' 'layout.R' 'limits.R' 'performance.R' 'plot-build.R' 'plot-construction.R' 'plot-last.R' 'plot.R' 'position-.R' 'position-collide.R' 'position-dodge.R' 'position-dodge2.R' 'position-identity.R' 'position-jitter.R' 'position-jitterdodge.R' 'position-nudge.R' 'position-stack.R' 'quick-plot.R' 'reshape-add-margins.R' 'save.R' 'scale-.R' 'scale-alpha.R' 'scale-binned.R' 'scale-brewer.R' 'scale-colour.R' 'scale-continuous.R' 'scale-date.R' 'scale-discrete-.R' 'scale-expansion.R' 'scale-gradient.R' 'scale-grey.R' 'scale-hue.R' 'scale-identity.R' 'scale-linetype.R' 'scale-linewidth.R' 'scale-manual.R' 'scale-shape.R' 'scale-size.R' 'scale-steps.R' 'scale-view.R' 'scale-viridis.R' 'scales-.R' 'stat-align.R' 'stat-bin.R' 'stat-summary-2d.R' 'stat-bin2d.R' 'stat-bindot.R' 'stat-binhex.R' 'stat-boxplot.R' 'stat-connect.R' 'stat-contour.R' 'stat-count.R' 'stat-density-2d.R' 'stat-density.R' 'stat-ecdf.R' 'stat-ellipse.R' 'stat-function.R' 'stat-identity.R' 'stat-manual.R' 'stat-qq-line.R' 'stat-qq.R' 'stat-quantilemethods.R' 'stat-sf-coordinates.R' 'stat-sf.R' 'stat-smooth-methods.R' 'stat-smooth.R' 'stat-sum.R' 'stat-summary-bin.R' 'stat-summary-hex.R' 'stat-summary.R' 'stat-unique.R' 'stat-ydensity.R' 'summarise-plot.R' 'summary.R' 'theme.R' 'theme-defaults.R' 'theme-current.R' 'theme-sub.R' 'utilities-break.R' 'utilities-grid.R' 'utilities-help.R' 'utilities-patterns.R' 'utilities-resolution.R' 'utilities-tidy-eval.R' 'zxx.R' 'zzz.R'", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut] (ORCID: ), Winston Chang [aut] (ORCID: ), Lionel Henry [aut], Thomas Lin Pedersen [aut, cre] (ORCID: ), Kohske Takahashi [aut], Claus Wilke [aut] (ORCID: ), Kara Woo [aut] (ORCID: ), Hiroaki Yutani [aut] (ORCID: ), Dewey Dunnington [aut] (ORCID: ), Teun van den Brand [aut] (ORCID: ), Posit, PBC [cph, fnd] (ROR: )", + "Maintainer": "Thomas Lin Pedersen ", "Repository": "CRAN" }, "glue": { "Package": "glue", - "Version": "1.8.0", + "Version": "1.8.1", "Source": "Repository", "Title": "Interpreted String Literals", - "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", "Description": "An implementation of interpreted string literals, inspired by Python's Literal String Interpolation and Docstrings and Julia's Triple-Quoted String Literals .", "License": "MIT + file LICENSE", "URL": "https://glue.tidyverse.org/, https://github.com/tidyverse/glue", "BugReports": "https://github.com/tidyverse/glue/issues", "Depends": [ - "R (>= 3.6)" + "R (>= 4.1)" ], "Imports": [ "methods" @@ -1008,7 +1921,6 @@ "DBI (>= 1.2.0)", "dplyr", "knitr", - "magrittr", "rlang", "rmarkdown", "RSQLite", @@ -1017,14 +1929,114 @@ "waldo (>= 0.5.3)", "withr" ], - "VignetteBuilder": "knitr", + "VignetteBuilder": "knitr", + "ByteCompile": "true", + "Config/Needs/website": "bench, forcats, ggbeeswarm, ggplot2, R.utils, rprintf, tidyr, tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2026-04-16", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "yes", + "Author": "Jim Hester [aut] (ORCID: ), Jennifer Bryan [aut, cre] (ORCID: ), Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Jennifer Bryan ", + "Repository": "CRAN" + }, + "googledrive": { + "Package": "googledrive", + "Version": "2.1.2", + "Source": "Repository", + "Title": "An Interface to Google Drive", + "Authors@R": "c( person(\"Lucy\", \"D'Agostino McGowan\", , role = \"aut\"), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Manage Google Drive files from R.", + "License": "MIT + file LICENSE", + "URL": "https://googledrive.tidyverse.org, https://github.com/tidyverse/googledrive", + "BugReports": "https://github.com/tidyverse/googledrive/issues", + "Depends": [ + "R (>= 4.1)" + ], + "Imports": [ + "cli (>= 3.0.0)", + "gargle (>= 1.6.0)", + "glue (>= 1.4.2)", + "httr", + "jsonlite", + "lifecycle", + "magrittr", + "pillar (>= 1.9.0)", + "purrr (>= 1.0.1)", + "rlang (>= 1.0.2)", + "tibble (>= 2.0.0)", + "utils", + "uuid", + "vctrs (>= 0.3.0)", + "withr" + ], + "Suggests": [ + "curl", + "dplyr (>= 1.0.0)", + "knitr", + "rmarkdown", + "spelling", + "testthat (>= 3.1.5)" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse, tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "Language": "en-US", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "no", + "Author": "Lucy D'Agostino McGowan [aut], Jennifer Bryan [aut, cre] (ORCID: ), Posit Software, PBC [cph, fnd]", + "Maintainer": "Jennifer Bryan ", + "Repository": "CRAN" + }, + "googlesheets4": { + "Package": "googlesheets4", + "Version": "1.1.2", + "Source": "Repository", + "Title": "Access Google Sheets using the Sheets API V4", + "Authors@R": "c( person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"cre\", \"aut\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Interact with Google Sheets through the Sheets API v4 . \"API\" is an acronym for \"application programming interface\"; the Sheets API allows users to interact with Google Sheets programmatically, instead of via a web browser. The \"v4\" refers to the fact that the Sheets API is currently at version 4. This package can read and write both the metadata and the cell data in a Sheet.", + "License": "MIT + file LICENSE", + "URL": "https://googlesheets4.tidyverse.org, https://github.com/tidyverse/googlesheets4", + "BugReports": "https://github.com/tidyverse/googlesheets4/issues", + "Depends": [ + "R (>= 3.6)" + ], + "Imports": [ + "cellranger", + "cli (>= 3.0.0)", + "curl", + "gargle (>= 1.6.0)", + "glue (>= 1.3.0)", + "googledrive (>= 2.1.0)", + "httr", + "ids", + "lifecycle", + "magrittr", + "methods", + "purrr", + "rematch2", + "rlang (>= 1.0.2)", + "tibble (>= 2.1.1)", + "utils", + "vctrs (>= 0.2.3)", + "withr" + ], + "Suggests": [ + "readr", + "rmarkdown", + "spelling", + "testthat (>= 3.1.7)" + ], "ByteCompile": "true", - "Config/Needs/website": "bench, forcats, ggbeeswarm, ggplot2, R.utils, rprintf, tidyr, tidyverse/tidytemplate", + "Config/Needs/website": "tidyverse, tidyverse/tidytemplate", "Config/testthat/edition": "3", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", - "NeedsCompilation": "yes", - "Author": "Jim Hester [aut] (), Jennifer Bryan [aut, cre] (), Posit Software, PBC [cph, fnd]", + "Language": "en-US", + "RoxygenNote": "7.3.2.9000", + "NeedsCompilation": "no", + "Author": "Jennifer Bryan [cre, aut] (ORCID: ), Posit Software, PBC [cph, fnd]", "Maintainer": "Jennifer Bryan ", "Repository": "CRAN" }, @@ -1098,9 +2110,98 @@ "Maintainer": "Richard Iannone ", "Repository": "CRAN" }, + "gtable": { + "Package": "gtable", + "Version": "0.3.6", + "Source": "Repository", + "Title": "Arrange 'Grobs' in Tables", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Thomas Lin\", \"Pedersen\", , \"thomas.pedersen@posit.co\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Tools to make it easier to work with \"tables\" of 'grobs'. The 'gtable' package defines a 'gtable' grob class that specifies a grid along with a list of grobs and their placement in the grid. Further the package makes it easy to manipulate and combine 'gtable' objects so that complex compositions can be built up sequentially.", + "License": "MIT + file LICENSE", + "URL": "https://gtable.r-lib.org, https://github.com/r-lib/gtable", + "BugReports": "https://github.com/r-lib/gtable/issues", + "Depends": [ + "R (>= 4.0)" + ], + "Imports": [ + "cli", + "glue", + "grid", + "lifecycle", + "rlang (>= 1.1.0)", + "stats" + ], + "Suggests": [ + "covr", + "ggplot2", + "knitr", + "profvis", + "rmarkdown", + "testthat (>= 3.0.0)" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2024-10-25", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut], Thomas Lin Pedersen [aut, cre], Posit Software, PBC [cph, fnd]", + "Maintainer": "Thomas Lin Pedersen ", + "Repository": "RSPM" + }, + "haven": { + "Package": "haven", + "Version": "2.5.5", + "Source": "Repository", + "Title": "Import and Export 'SPSS', 'Stata' and 'SAS' Files", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Evan\", \"Miller\", role = c(\"aut\", \"cph\"), comment = \"Author of included ReadStat code\"), person(\"Danny\", \"Smith\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Import foreign statistical formats into R via the embedded 'ReadStat' C library, .", + "License": "MIT + file LICENSE", + "URL": "https://haven.tidyverse.org, https://github.com/tidyverse/haven, https://github.com/WizardMac/ReadStat", + "BugReports": "https://github.com/tidyverse/haven/issues", + "Depends": [ + "R (>= 3.6)" + ], + "Imports": [ + "cli (>= 3.0.0)", + "forcats (>= 0.2.0)", + "hms", + "lifecycle", + "methods", + "readr (>= 0.1.0)", + "rlang (>= 0.4.0)", + "tibble", + "tidyselect", + "vctrs (>= 0.3.0)" + ], + "Suggests": [ + "covr", + "crayon", + "fs", + "knitr", + "pillar (>= 1.4.0)", + "rmarkdown", + "testthat (>= 3.0.0)", + "utf8" + ], + "LinkingTo": [ + "cpp11" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2", + "SystemRequirements": "GNU make, zlib: zlib1g-dev (deb), zlib-devel (rpm)", + "NeedsCompilation": "yes", + "Author": "Hadley Wickham [aut, cre], Evan Miller [aut, cph] (Author of included ReadStat code), Danny Smith [aut], Posit Software, PBC [cph, fnd]", + "Maintainer": "Hadley Wickham ", + "Repository": "RSPM" + }, "highr": { "Package": "highr", - "Version": "0.11", + "Version": "0.12", "Source": "Repository", "Type": "Package", "Title": "Syntax Highlighting for R Source Code", @@ -1122,21 +2223,25 @@ "BugReports": "https://github.com/yihui/highr/issues", "VignetteBuilder": "knitr", "Encoding": "UTF-8", - "RoxygenNote": "7.3.1", + "RoxygenNote": "7.3.3", "NeedsCompilation": "no", - "Author": "Yihui Xie [aut, cre] (), Yixuan Qiu [aut], Christopher Gandrud [ctb], Qiang Li [ctb]", + "Author": "Yihui Xie [aut, cre] (ORCID: ), Yixuan Qiu [aut], Christopher Gandrud [ctb], Qiang Li [ctb]", "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, "hms": { "Package": "hms", - "Version": "1.1.3", + "Version": "1.1.4", "Source": "Repository", "Title": "Pretty Time of Day", - "Date": "2023-03-21", - "Authors@R": "c( person(\"Kirill\", \"Müller\", role = c(\"aut\", \"cre\"), email = \"kirill@cynkra.com\", comment = c(ORCID = \"0000-0002-1416-3412\")), person(\"R Consortium\", role = \"fnd\"), person(\"RStudio\", role = \"fnd\") )", + "Date": "2025-10-11", + "Authors@R": "c( person(\"Kirill\", \"Müller\", , \"kirill@cynkra.com\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-1416-3412\")), person(\"R Consortium\", role = \"fnd\"), person(\"Posit Software, PBC\", role = \"fnd\", comment = c(ROR = \"03wc8by49\")) )", "Description": "Implements an S3 class for storing and formatting time-of-day values, based on the 'difftime' class.", + "License": "MIT + file LICENSE", + "URL": "https://hms.tidyverse.org/, https://github.com/tidyverse/hms", + "BugReports": "https://github.com/tidyverse/hms/issues", "Imports": [ + "cli", "lifecycle", "methods", "pkgconfig", @@ -1149,23 +2254,18 @@ "pillar (>= 1.1.0)", "testthat (>= 3.0.0)" ], - "License": "MIT + file LICENSE", - "Encoding": "UTF-8", - "URL": "https://hms.tidyverse.org/, https://github.com/tidyverse/hms", - "BugReports": "https://github.com/tidyverse/hms/issues", - "RoxygenNote": "7.2.3", - "Config/testthat/edition": "3", - "Config/autostyle/scope": "line_breaks", - "Config/autostyle/strict": "false", "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3.9000", "NeedsCompilation": "no", - "Author": "Kirill Müller [aut, cre] (), R Consortium [fnd], RStudio [fnd]", + "Author": "Kirill Müller [aut, cre] (ORCID: ), R Consortium [fnd], Posit Software, PBC [fnd] (ROR: )", "Maintainer": "Kirill Müller ", "Repository": "CRAN" }, "htmltools": { "Package": "htmltools", - "Version": "0.5.8.1", + "Version": "0.5.9", "Source": "Repository", "Type": "Package", "Title": "Tools for HTML", @@ -1199,12 +2299,12 @@ "Config/Needs/check": "knitr", "Config/Needs/website": "rstudio/quillt, bench", "Encoding": "UTF-8", - "RoxygenNote": "7.3.1", + "RoxygenNote": "7.3.3", "Collate": "'colors.R' 'fill.R' 'html_dependency.R' 'html_escape.R' 'html_print.R' 'htmltools-package.R' 'images.R' 'known_tags.R' 'selector.R' 'staticimports.R' 'tag_query.R' 'utils.R' 'tags.R' 'template.R'", "NeedsCompilation": "yes", - "Author": "Joe Cheng [aut], Carson Sievert [aut, cre] (), Barret Schloerke [aut] (), Winston Chang [aut] (), Yihui Xie [aut], Jeff Allen [aut], Posit Software, PBC [cph, fnd]", + "Author": "Joe Cheng [aut], Carson Sievert [aut, cre] (ORCID: ), Barret Schloerke [aut] (ORCID: ), Winston Chang [aut] (ORCID: ), Yihui Xie [aut], Jeff Allen [aut], Posit Software, PBC [cph, fnd]", "Maintainer": "Carson Sievert ", - "Repository": "CRAN" + "Repository": "https://p3m.dev/cran/latest" }, "htmlwidgets": { "Package": "htmlwidgets", @@ -1237,23 +2337,23 @@ "NeedsCompilation": "no", "Author": "Ramnath Vaidyanathan [aut, cph], Yihui Xie [aut], JJ Allaire [aut], Joe Cheng [aut], Carson Sievert [aut, cre] (), Kenton Russell [aut, cph], Ellis Hughes [ctb], Posit Software, PBC [cph, fnd]", "Maintainer": "Carson Sievert ", - "Repository": "CRAN" + "Repository": "RSPM" }, "httr": { "Package": "httr", - "Version": "1.4.7", + "Version": "1.4.8", "Source": "Repository", "Title": "Tools for Working with URLs and HTTP", - "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Posit, PBC\", role = c(\"cph\", \"fnd\")) )", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", "Description": "Useful tools for working with HTTP organised by HTTP verbs (GET(), POST(), etc). Configuration functions make it easy to control additional request components (authenticate(), add_headers() and so on).", "License": "MIT + file LICENSE", "URL": "https://httr.r-lib.org/, https://github.com/r-lib/httr", "BugReports": "https://github.com/r-lib/httr/issues", "Depends": [ - "R (>= 3.5)" + "R (>= 3.6)" ], "Imports": [ - "curl (>= 5.0.2)", + "curl (>= 5.1.0)", "jsonlite", "mime", "openssl (>= 0.8)", @@ -1273,12 +2373,82 @@ "VignetteBuilder": "knitr", "Config/Needs/website": "tidyverse/tidytemplate", "Encoding": "UTF-8", - "RoxygenNote": "7.2.3", + "RoxygenNote": "7.3.3", "NeedsCompilation": "no", - "Author": "Hadley Wickham [aut, cre], Posit, PBC [cph, fnd]", + "Author": "Hadley Wickham [aut, cre], Posit Software, PBC [cph, fnd]", "Maintainer": "Hadley Wickham ", "Repository": "CRAN" }, + "ids": { + "Package": "ids", + "Version": "1.0.1", + "Source": "Repository", + "Title": "Generate Random Identifiers", + "Authors@R": "person(\"Rich\", \"FitzJohn\", role = c(\"aut\", \"cre\"), email = \"rich.fitzjohn@gmail.com\")", + "Description": "Generate random or human readable and pronounceable identifiers.", + "License": "MIT + file LICENSE", + "URL": "https://github.com/richfitz/ids", + "BugReports": "https://github.com/richfitz/ids/issues", + "Imports": [ + "openssl", + "uuid" + ], + "Suggests": [ + "knitr", + "rcorpora", + "rmarkdown", + "testthat" + ], + "RoxygenNote": "6.0.1", + "VignetteBuilder": "knitr", + "NeedsCompilation": "no", + "Author": "Rich FitzJohn [aut, cre]", + "Maintainer": "Rich FitzJohn ", + "Repository": "RSPM", + "Encoding": "UTF-8" + }, + "isoband": { + "Package": "isoband", + "Version": "0.3.0", + "Source": "Repository", + "Title": "Generate Isolines and Isobands from Regularly Spaced Elevation Grids", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Claus O.\", \"Wilke\", , \"wilke@austin.utexas.edu\", role = \"aut\", comment = c(\"Original author\", ORCID = \"0000-0002-7470-9261\")), person(\"Thomas Lin\", \"Pedersen\", , \"thomas.pedersen@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-5147-4711\")), person(\"Posit, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Description": "A fast C++ implementation to generate contour lines (isolines) and contour polygons (isobands) from regularly spaced grids containing elevation data.", + "License": "MIT + file LICENSE", + "URL": "https://isoband.r-lib.org, https://github.com/r-lib/isoband", + "BugReports": "https://github.com/r-lib/isoband/issues", + "Imports": [ + "cli", + "grid", + "rlang", + "utils" + ], + "Suggests": [ + "covr", + "ggplot2", + "knitr", + "magick", + "bench", + "rmarkdown", + "sf", + "testthat (>= 3.0.0)", + "xml2" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-12-05", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "Config/build/compilation-database": "true", + "LinkingTo": [ + "cpp11" + ], + "NeedsCompilation": "yes", + "Author": "Hadley Wickham [aut] (ORCID: ), Claus O. Wilke [aut] (Original author, ORCID: ), Thomas Lin Pedersen [aut, cre] (ORCID: ), Posit, PBC [cph, fnd] (ROR: )", + "Maintainer": "Thomas Lin Pedersen ", + "Repository": "CRAN" + }, "jquerylib": { "Package": "jquerylib", "Version": "0.1.4", @@ -1303,7 +2473,7 @@ }, "jsonlite": { "Package": "jsonlite", - "Version": "1.9.1", + "Version": "2.0.0", "Source": "Repository", "Title": "A Simple and Robust JSON Parser and Generator for R", "License": "MIT + file LICENSE", @@ -1325,11 +2495,11 @@ "R.rsp", "sf" ], - "RoxygenNote": "7.2.3", + "RoxygenNote": "7.3.2", "Encoding": "UTF-8", "NeedsCompilation": "yes", "Author": "Jeroen Ooms [aut, cre] (), Duncan Temple Lang [ctb], Lloyd Hilaiel [cph] (author of bundled libyajl)", - "Repository": "CRAN" + "Repository": "RSPM" }, "juicyjuice": { "Package": "juicyjuice", @@ -1353,11 +2523,11 @@ "NeedsCompilation": "no", "Author": "Richard Iannone [aut, cre, cph] (), Automattic [cph] (juice library), juice contributors [ctb] (juice library)", "Maintainer": "Richard Iannone ", - "Repository": "CRAN" + "Repository": "RSPM" }, "knitr": { "Package": "knitr", - "Version": "1.50", + "Version": "1.51", "Source": "Repository", "Type": "Package", "Title": "A General-Purpose Package for Dynamic Report Generation in R", @@ -1371,12 +2541,11 @@ "highr (>= 0.11)", "methods", "tools", - "xfun (>= 0.51)", + "xfun (>= 0.52)", "yaml (>= 2.1.19)" ], "Suggests": [ "bslib", - "codetools", "DBI (>= 0.4-1)", "digest", "formatR", @@ -1388,6 +2557,8 @@ "magick", "litedown", "markdown (>= 1.3)", + "otel", + "otelsdk", "png", "ragg", "reticulate (>= 1.4)", @@ -1412,10 +2583,10 @@ "Encoding": "UTF-8", "VignetteBuilder": "litedown, knitr", "SystemRequirements": "Package vignettes based on R Markdown v2 or reStructuredText require Pandoc (http://pandoc.org). The function rst2pdf() requires rst2pdf (https://github.com/rst2pdf/rst2pdf).", - "Collate": "'block.R' 'cache.R' 'citation.R' 'hooks-html.R' 'plot.R' 'utils.R' 'defaults.R' 'concordance.R' 'engine.R' 'highlight.R' 'themes.R' 'header.R' 'hooks-asciidoc.R' 'hooks-chunk.R' 'hooks-extra.R' 'hooks-latex.R' 'hooks-md.R' 'hooks-rst.R' 'hooks-textile.R' 'hooks.R' 'output.R' 'package.R' 'pandoc.R' 'params.R' 'parser.R' 'pattern.R' 'rocco.R' 'spin.R' 'table.R' 'template.R' 'utils-conversion.R' 'utils-rd2html.R' 'utils-string.R' 'utils-sweave.R' 'utils-upload.R' 'utils-vignettes.R' 'zzz.R'", - "RoxygenNote": "7.3.2", + "Collate": "'block.R' 'cache.R' 'citation.R' 'hooks-html.R' 'plot.R' 'utils.R' 'defaults.R' 'concordance.R' 'engine.R' 'highlight.R' 'themes.R' 'header.R' 'hooks-asciidoc.R' 'hooks-chunk.R' 'hooks-extra.R' 'hooks-latex.R' 'hooks-md.R' 'hooks-rst.R' 'hooks-textile.R' 'hooks.R' 'otel.R' 'output.R' 'package.R' 'pandoc.R' 'params.R' 'parser.R' 'pattern.R' 'rocco.R' 'spin.R' 'table.R' 'template.R' 'utils-conversion.R' 'utils-rd2html.R' 'utils-string.R' 'utils-sweave.R' 'utils-upload.R' 'utils-vignettes.R' 'zzz.R'", + "RoxygenNote": "7.3.3", "NeedsCompilation": "no", - "Author": "Yihui Xie [aut, cre] (, https://yihui.org), Abhraneel Sarma [ctb], Adam Vogt [ctb], Alastair Andrew [ctb], Alex Zvoleff [ctb], Amar Al-Zubaidi [ctb], Andre Simon [ctb] (the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de), Aron Atkins [ctb], Aaron Wolen [ctb], Ashley Manton [ctb], Atsushi Yasumoto [ctb] (), Ben Baumer [ctb], Brian Diggs [ctb], Brian Zhang [ctb], Bulat Yapparov [ctb], Cassio Pereira [ctb], Christophe Dervieux [ctb], David Hall [ctb], David Hugh-Jones [ctb], David Robinson [ctb], Doug Hemken [ctb], Duncan Murdoch [ctb], Elio Campitelli [ctb], Ellis Hughes [ctb], Emily Riederer [ctb], Fabian Hirschmann [ctb], Fitch Simeon [ctb], Forest Fang [ctb], Frank E Harrell Jr [ctb] (the Sweavel package at inst/misc/Sweavel.sty), Garrick Aden-Buie [ctb], Gregoire Detrez [ctb], Hadley Wickham [ctb], Hao Zhu [ctb], Heewon Jeon [ctb], Henrik Bengtsson [ctb], Hiroaki Yutani [ctb], Ian Lyttle [ctb], Hodges Daniel [ctb], Jacob Bien [ctb], Jake Burkhead [ctb], James Manton [ctb], Jared Lander [ctb], Jason Punyon [ctb], Javier Luraschi [ctb], Jeff Arnold [ctb], Jenny Bryan [ctb], Jeremy Ashkenas [ctb, cph] (the CSS file at inst/misc/docco-classic.css), Jeremy Stephens [ctb], Jim Hester [ctb], Joe Cheng [ctb], Johannes Ranke [ctb], John Honaker [ctb], John Muschelli [ctb], Jonathan Keane [ctb], JJ Allaire [ctb], Johan Toloe [ctb], Jonathan Sidi [ctb], Joseph Larmarange [ctb], Julien Barnier [ctb], Kaiyin Zhong [ctb], Kamil Slowikowski [ctb], Karl Forner [ctb], Kevin K. Smith [ctb], Kirill Mueller [ctb], Kohske Takahashi [ctb], Lorenz Walthert [ctb], Lucas Gallindo [ctb], Marius Hofert [ctb], Martin Modrák [ctb], Michael Chirico [ctb], Michael Friendly [ctb], Michal Bojanowski [ctb], Michel Kuhlmann [ctb], Miller Patrick [ctb], Nacho Caballero [ctb], Nick Salkowski [ctb], Niels Richard Hansen [ctb], Noam Ross [ctb], Obada Mahdi [ctb], Pavel N. Krivitsky [ctb] (), Pedro Faria [ctb], Qiang Li [ctb], Ramnath Vaidyanathan [ctb], Richard Cotton [ctb], Robert Krzyzanowski [ctb], Rodrigo Copetti [ctb], Romain Francois [ctb], Ruaridh Williamson [ctb], Sagiru Mati [ctb] (), Scott Kostyshak [ctb], Sebastian Meyer [ctb], Sietse Brouwer [ctb], Simon de Bernard [ctb], Sylvain Rousseau [ctb], Taiyun Wei [ctb], Thibaut Assus [ctb], Thibaut Lamadon [ctb], Thomas Leeper [ctb], Tim Mastny [ctb], Tom Torsney-Weir [ctb], Trevor Davis [ctb], Viktoras Veitas [ctb], Weicheng Zhu [ctb], Wush Wu [ctb], Zachary Foster [ctb], Zhian N. Kamvar [ctb] (), Posit Software, PBC [cph, fnd]", + "Author": "Yihui Xie [aut, cre] (ORCID: , URL: https://yihui.org), Abhraneel Sarma [ctb], Adam Vogt [ctb], Alastair Andrew [ctb], Alex Zvoleff [ctb], Amar Al-Zubaidi [ctb], Andre Simon [ctb] (the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de), Aron Atkins [ctb], Aaron Wolen [ctb], Ashley Manton [ctb], Atsushi Yasumoto [ctb] (ORCID: ), Ben Baumer [ctb], Brian Diggs [ctb], Brian Zhang [ctb], Bulat Yapparov [ctb], Cassio Pereira [ctb], Christophe Dervieux [ctb], David Hall [ctb], David Hugh-Jones [ctb], David Robinson [ctb], Doug Hemken [ctb], Duncan Murdoch [ctb], Elio Campitelli [ctb], Ellis Hughes [ctb], Emily Riederer [ctb], Fabian Hirschmann [ctb], Fitch Simeon [ctb], Forest Fang [ctb], Frank E Harrell Jr [ctb] (the Sweavel package at inst/misc/Sweavel.sty), Garrick Aden-Buie [ctb], Gregoire Detrez [ctb], Hadley Wickham [ctb], Hao Zhu [ctb], Heewon Jeon [ctb], Henrik Bengtsson [ctb], Hiroaki Yutani [ctb], Ian Lyttle [ctb], Hodges Daniel [ctb], Jacob Bien [ctb], Jake Burkhead [ctb], James Manton [ctb], Jared Lander [ctb], Jason Punyon [ctb], Javier Luraschi [ctb], Jeff Arnold [ctb], Jenny Bryan [ctb], Jeremy Ashkenas [ctb, cph] (the CSS file at inst/misc/docco-classic.css), Jeremy Stephens [ctb], Jim Hester [ctb], Joe Cheng [ctb], Johannes Ranke [ctb], John Honaker [ctb], John Muschelli [ctb], Jonathan Keane [ctb], JJ Allaire [ctb], Johan Toloe [ctb], Jonathan Sidi [ctb], Joseph Larmarange [ctb], Julien Barnier [ctb], Kaiyin Zhong [ctb], Kamil Slowikowski [ctb], Karl Forner [ctb], Kevin K. Smith [ctb], Kirill Mueller [ctb], Kohske Takahashi [ctb], Lorenz Walthert [ctb], Lucas Gallindo [ctb], Marius Hofert [ctb], Martin Modrák [ctb], Michael Chirico [ctb], Michael Friendly [ctb], Michal Bojanowski [ctb], Michel Kuhlmann [ctb], Miller Patrick [ctb], Nacho Caballero [ctb], Nick Salkowski [ctb], Niels Richard Hansen [ctb], Noam Ross [ctb], Obada Mahdi [ctb], Pavel N. Krivitsky [ctb] (ORCID: ), Pedro Faria [ctb], Qiang Li [ctb], Ramnath Vaidyanathan [ctb], Richard Cotton [ctb], Robert Krzyzanowski [ctb], Rodrigo Copetti [ctb], Romain Francois [ctb], Ruaridh Williamson [ctb], Sagiru Mati [ctb] (ORCID: ), Scott Kostyshak [ctb], Sebastian Meyer [ctb], Sietse Brouwer [ctb], Simon de Bernard [ctb], Sylvain Rousseau [ctb], Taiyun Wei [ctb], Thibaut Assus [ctb], Thibaut Lamadon [ctb], Thomas Leeper [ctb], Tim Mastny [ctb], Tom Torsney-Weir [ctb], Trevor Davis [ctb], Viktoras Veitas [ctb], Weicheng Zhu [ctb], Wush Wu [ctb], Zachary Foster [ctb], Zhian N. Kamvar [ctb] (ORCID: ), Posit Software, PBC [cph, fnd]", "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, @@ -1436,11 +2607,12 @@ "stats", "graphics" ], - "Repository": "CRAN" + "Repository": "RSPM", + "Encoding": "UTF-8" }, "lifecycle": { "Package": "lifecycle", - "Version": "1.0.4", + "Version": "1.0.5", "Source": "Repository", "Title": "Manage the Life Cycle of your Package Functions", "Authors@R": "c( person(\"Lionel\", \"Henry\", , \"lionel@posit.co\", role = c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", @@ -1453,29 +2625,28 @@ ], "Imports": [ "cli (>= 3.4.0)", - "glue", "rlang (>= 1.1.0)" ], "Suggests": [ "covr", - "crayon", "knitr", - "lintr", + "lintr (>= 3.1.0)", "rmarkdown", "testthat (>= 3.0.1)", "tibble", "tidyverse", "tools", "vctrs", - "withr" + "withr", + "xml2" ], "VignetteBuilder": "knitr", "Config/Needs/website": "tidyverse/tidytemplate, usethis", "Config/testthat/edition": "3", "Encoding": "UTF-8", - "RoxygenNote": "7.2.1", + "RoxygenNote": "7.3.3", "NeedsCompilation": "no", - "Author": "Lionel Henry [aut, cre], Hadley Wickham [aut] (), Posit Software, PBC [cph, fnd]", + "Author": "Lionel Henry [aut, cre], Hadley Wickham [aut] (ORCID: ), Posit Software, PBC [cph, fnd]", "Maintainer": "Lionel Henry ", "Repository": "CRAN" }, @@ -1511,13 +2682,59 @@ "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, + "lubridate": { + "Package": "lubridate", + "Version": "1.9.5", + "Source": "Repository", + "Type": "Package", + "Title": "Make Dealing with Dates a Little Easier", + "Authors@R": "c( person(\"Vitalie\", \"Spinu\", , \"spinuvit@gmail.com\", role = c(\"aut\", \"cre\")), person(\"Garrett\", \"Grolemund\", role = \"aut\"), person(\"Hadley\", \"Wickham\", role = \"aut\"), person(\"Davis\", \"Vaughan\", role = \"ctb\"), person(\"Ian\", \"Lyttle\", role = \"ctb\"), person(\"Imanuel\", \"Costigan\", role = \"ctb\"), person(\"Jason\", \"Law\", role = \"ctb\"), person(\"Doug\", \"Mitarotonda\", role = \"ctb\"), person(\"Joseph\", \"Larmarange\", role = \"ctb\"), person(\"Jonathan\", \"Boiser\", role = \"ctb\"), person(\"Chel Hee\", \"Lee\", role = \"ctb\") )", + "Maintainer": "Vitalie Spinu ", + "Description": "Functions to work with date-times and time-spans: fast and user friendly parsing of date-time data, extraction and updating of components of a date-time (years, months, days, hours, minutes, and seconds), algebraic manipulation on date-time and time-span objects. The 'lubridate' package has a consistent and memorable syntax that makes working with dates easy and fun.", + "License": "MIT + file LICENSE", + "URL": "https://lubridate.tidyverse.org, https://github.com/tidyverse/lubridate", + "BugReports": "https://github.com/tidyverse/lubridate/issues", + "Depends": [ + "methods", + "R (>= 3.2)" + ], + "Imports": [ + "generics", + "timechange (>= 0.4.0)" + ], + "Suggests": [ + "covr", + "knitr", + "rmarkdown", + "testthat (>= 2.1.0)", + "vctrs (>= 0.6.5)" + ], + "Enhances": [ + "chron", + "data.table", + "timeDate", + "tis", + "zoo" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "7.3.3", + "SystemRequirements": "A system with zoneinfo data (e.g. /usr/share/zoneinfo). On Windows the zoneinfo included with R is used.", + "Collate": "'Dates.r' 'POSIXt.r' 'util.r' 'parse.r' 'timespans.r' 'intervals.r' 'difftimes.r' 'durations.r' 'periods.r' 'accessors-date.R' 'accessors-day.r' 'accessors-dst.r' 'accessors-hour.r' 'accessors-minute.r' 'accessors-month.r' 'accessors-quarter.r' 'accessors-second.r' 'accessors-tz.r' 'accessors-week.r' 'accessors-year.r' 'am-pm.r' 'time-zones.r' 'numeric.r' 'coercion.r' 'constants.r' 'cyclic_encoding.r' 'data.r' 'decimal-dates.r' 'deprecated.r' 'format_ISO8601.r' 'guess.r' 'hidden.r' 'instants.r' 'leap-years.r' 'ops-addition.r' 'ops-compare.r' 'ops-division.r' 'ops-integer-division.r' 'ops-m+.r' 'ops-modulo.r' 'ops-multiplication.r' 'ops-subtraction.r' 'package.r' 'pretty.r' 'round.r' 'stamp.r' 'tzdir.R' 'update.r' 'vctrs.R' 'zzz.R'", + "NeedsCompilation": "yes", + "Author": "Vitalie Spinu [aut, cre], Garrett Grolemund [aut], Hadley Wickham [aut], Davis Vaughan [ctb], Ian Lyttle [ctb], Imanuel Costigan [ctb], Jason Law [ctb], Doug Mitarotonda [ctb], Joseph Larmarange [ctb], Jonathan Boiser [ctb], Chel Hee Lee [ctb]", + "Repository": "CRAN" + }, "magrittr": { "Package": "magrittr", - "Version": "2.0.3", + "Version": "2.0.5", "Source": "Repository", "Type": "Package", "Title": "A Forward-Pipe Operator for R", - "Authors@R": "c( person(\"Stefan Milton\", \"Bache\", , \"stefan@stefanbache.dk\", role = c(\"aut\", \"cph\"), comment = \"Original author and creator of magrittr\"), person(\"Hadley\", \"Wickham\", , \"hadley@rstudio.com\", role = \"aut\"), person(\"Lionel\", \"Henry\", , \"lionel@rstudio.com\", role = \"cre\"), person(\"RStudio\", role = c(\"cph\", \"fnd\")) )", + "Authors@R": "c( person(\"Stefan Milton\", \"Bache\", , \"stefan@stefanbache.dk\", role = c(\"aut\", \"cph\"), comment = \"Original author and creator of magrittr\"), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Lionel\", \"Henry\", , \"lionel@posit.co\", role = \"cre\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", "Description": "Provides a mechanism for chaining commands with a new forward-pipe operator, %>%. This operator will forward a value, or the result of an expression, into the next function call/expression. There is flexible support for the type of right-hand side expressions. For more information, see package vignette. To quote Rene Magritte, \"Ceci n'est pas un pipe.\"", "License": "MIT + file LICENSE", "URL": "https://magrittr.tidyverse.org, https://github.com/tidyverse/magrittr", @@ -1536,10 +2753,10 @@ "ByteCompile": "Yes", "Config/Needs/website": "tidyverse/tidytemplate", "Encoding": "UTF-8", - "RoxygenNote": "7.1.2", + "RoxygenNote": "7.3.3", "NeedsCompilation": "yes", - "Author": "Stefan Milton Bache [aut, cph] (Original author and creator of magrittr), Hadley Wickham [aut], Lionel Henry [cre], RStudio [cph, fnd]", - "Maintainer": "Lionel Henry ", + "Author": "Stefan Milton Bache [aut, cph] (Original author and creator of magrittr), Hadley Wickham [aut], Lionel Henry [cre], Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Lionel Henry ", "Repository": "CRAN" }, "markdown": { @@ -1572,7 +2789,7 @@ "NeedsCompilation": "no", "Author": "Yihui Xie [aut, cre] (), JJ Allaire [aut], Jeffrey Horner [aut], Henrik Bengtsson [ctb], Jim Hester [ctb], Yixuan Qiu [ctb], Kohske Takahashi [ctb], Adam November [ctb], Nacho Caballero [ctb], Jeroen Ooms [ctb], Thomas Leeper [ctb], Joe Cheng [ctb], Andrzej Oles [ctb], Posit Software, PBC [cph, fnd]", "Maintainer": "Yihui Xie ", - "Repository": "CRAN" + "Repository": "RSPM" }, "memoise": { "Package": "memoise", @@ -1625,34 +2842,95 @@ "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, - "munsell": { - "Package": "munsell", - "Version": "0.5.1", + "modelr": { + "Package": "modelr", + "Version": "0.1.11", "Source": "Repository", - "Type": "Package", - "Title": "Utilities for Using Munsell Colours", - "Author": "Charlotte Wickham ", - "Maintainer": "Charlotte Wickham ", - "Description": "Provides easy access to, and manipulation of, the Munsell colours. Provides a mapping between Munsell's original notation (e.g. \"5R 5/10\") and hexadecimal strings suitable for use directly in R graphics. Also provides utilities to explore slices through the Munsell colour tree, to transform Munsell colours and display colour palettes.", + "Title": "Modelling Functions that Work with the Pipe", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Functions for modelling that help you seamlessly integrate modelling into a pipeline of data manipulation and visualisation.", + "License": "GPL-3", + "URL": "https://modelr.tidyverse.org, https://github.com/tidyverse/modelr", + "BugReports": "https://github.com/tidyverse/modelr/issues", + "Depends": [ + "R (>= 3.2)" + ], + "Imports": [ + "broom", + "magrittr", + "purrr (>= 0.2.2)", + "rlang (>= 1.0.6)", + "tibble", + "tidyr (>= 0.8.0)", + "tidyselect", + "vctrs" + ], "Suggests": [ + "compiler", + "covr", "ggplot2", - "testthat" + "testthat (>= 3.0.0)" ], + "Config/Needs/website": "tidyverse/tidytemplate", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "7.2.3", + "Config/testthat/edition": "3", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut, cre], Posit Software, PBC [cph, fnd]", + "Maintainer": "Hadley Wickham ", + "Repository": "RSPM" + }, + "officer": { + "Package": "officer", + "Version": "0.7.5", + "Source": "Repository", + "Type": "Package", + "Title": "Manipulation of Microsoft Word and PowerPoint Documents", + "Authors@R": "c( person(\"David\", \"Gohel\", , \"david.gohel@ardata.fr\", role = c(\"aut\", \"cre\")), person(\"Stefan\", \"Moog\", , \"moogs@gmx.de\", role = \"aut\"), person(\"Mark\", \"Heckmann\", , \"heckmann.mark@gmail.com\", role = \"aut\", comment = c(ORCID = \"0000-0002-0736-7417\")), person(\"ArData\", role = \"cph\"), person(\"Frank\", \"Hangler\", , \"frank@plotandscatter.com\", role = \"ctb\", comment = \"function body_replace_all_text\"), person(\"Liz\", \"Sander\", , \"lsander@civisanalytics.com\", role = \"ctb\", comment = \"several documentation fixes\"), person(\"Anton\", \"Victorson\", , \"anton@victorson.se\", role = \"ctb\", comment = \"fixes xml structures\"), person(\"Jon\", \"Calder\", , \"jonmcalder@gmail.com\", role = \"ctb\", comment = \"update vignettes\"), person(\"John\", \"Harrold\", , \"john.m.harrold@gmail.com\", role = \"ctb\", comment = \"function annotate_base\"), person(\"John\", \"Muschelli\", , \"muschellij2@gmail.com\", role = \"ctb\", comment = \"google doc compatibility\"), person(\"Bill\", \"Denney\", , \"wdenney@humanpredictions.com\", role = \"ctb\", comment = c(ORCID = \"0000-0002-5759-428X\", \"function as.matrix.rpptx\")), person(\"Nikolai\", \"Beck\", , \"beck.nikolai@gmail.com\", role = \"ctb\", comment = \"set speaker notes for .pptx documents\"), person(\"Greg\", \"Leleu\", , \"gregoire.leleu@gmail.com\", role = \"ctb\", comment = \"fields functionality in ppt\"), person(\"Majid\", \"Eismann\", role = \"ctb\"), person(\"Wahiduzzaman\", \"Khan\", role = \"ctb\", comment = \"vectorization of remove_slide\"), person(\"Hongyuan\", \"Jia\", , \"hongyuanjia@cqust.edu.cn\", role = \"ctb\", comment = c(ORCID = \"0000-0002-0075-8183\")), person(\"Michael\", \"Stackhouse\", , \"mike.stackhouse@atorusresearch.com\", role = \"ctb\") )", + "Description": "Access and manipulate 'Microsoft Word', 'RTF' and 'Microsoft PowerPoint' documents from R. The package focuses on tabular and graphical reporting from R; it also provides two functions that let users get document content into data objects. A set of functions lets add and remove images, tables and paragraphs of text in new or existing documents. The package does not require any installation of Microsoft products to be able to write Microsoft files.", + "License": "MIT + file LICENSE", + "URL": "https://ardata-fr.github.io/officeverse/, https://davidgohel.github.io/officer/", + "BugReports": "https://github.com/davidgohel/officer/issues", "Imports": [ - "colorspace", - "methods" + "cli", + "dplyr", + "graphics", + "grDevices", + "openssl", + "R6", + "ragg", + "stats", + "tidyr", + "utils", + "uuid", + "xml2 (>= 1.1.0)", + "zip (>= 2.1.0)" + ], + "Suggests": [ + "devEMF", + "doconv (>= 0.3.0)", + "gdtools", + "ggplot2", + "knitr", + "magick", + "rmarkdown", + "rsvg", + "mschart", + "testthat", + "withr" ], - "License": "MIT + file LICENSE", - "URL": "https://cran.r-project.org/package=munsell, https://github.com/cwickham/munsell/", - "RoxygenNote": "7.3.1", "Encoding": "UTF-8", - "BugReports": "https://github.com/cwickham/munsell/issues", + "Collate": "'core_properties.R' 'custom_properties.R' 'defunct.R' 'dev-utils.R' 'docx_add.R' 'docx_comments.R' 'docx_cursor.R' 'docx_embed_font.R' 'docx_part.R' 'docx_replace.R' 'docx_section.R' 'docx_settings.R' 'docx_styles.R' 'docx_utils_funs.R' 'empty_content.R' 'formatting_properties.R' 'fortify_docx.R' 'fortify_pptx.R' 'knitr_utils.R' 'officer.R' 'ooxml.R' 'ooxml_block_objects.R' 'ooxml_run_objects.R' 'openxml_content_type.R' 'openxml_document.R' 'pack_folder.R' 'ph_location.R' 'post-proc.R' 'ppt_class_dir_collection.R' 'ppt_classes.R' 'ppt_notes.R' 'ppt_ph_dedupe_layout.R' 'ppt_ph_manipulate.R' 'ppt_ph_rename_layout.R' 'ppt_ph_with_methods.R' 'pptx_informations.R' 'pptx_layout_helper.R' 'pptx_matrix.R' 'utils.R' 'pptx_slide_manip.R' 'read_docx.R' 'docx_write.R' 'read_docx_styles.R' 'read_pptx.R' 'read_xlsx.R' 'relationship.R' 'rtf.R' 'shape_properties.R' 'shorcuts.R' 'docx_append_context.R' 'utils-xml.R' 'deprecated.R' 'zzz.R'", + "Config/roxygen2/version": "8.0.0", "NeedsCompilation": "no", + "Author": "David Gohel [aut, cre], Stefan Moog [aut], Mark Heckmann [aut] (ORCID: ), ArData [cph], Frank Hangler [ctb] (function body_replace_all_text), Liz Sander [ctb] (several documentation fixes), Anton Victorson [ctb] (fixes xml structures), Jon Calder [ctb] (update vignettes), John Harrold [ctb] (function annotate_base), John Muschelli [ctb] (google doc compatibility), Bill Denney [ctb] (ORCID: , function as.matrix.rpptx), Nikolai Beck [ctb] (set speaker notes for .pptx documents), Greg Leleu [ctb] (fields functionality in ppt), Majid Eismann [ctb], Wahiduzzaman Khan [ctb] (vectorization of remove_slide), Hongyuan Jia [ctb] (ORCID: ), Michael Stackhouse [ctb]", + "Maintainer": "David Gohel ", "Repository": "CRAN" }, "openssl": { "Package": "openssl", - "Version": "2.3.2", + "Version": "2.4.1", "Source": "Repository", "Type": "Package", "Title": "Toolkit for Encryption, Signatures and Certificates Based on OpenSSL", @@ -1679,13 +2957,13 @@ "RoxygenNote": "7.3.2", "Encoding": "UTF-8", "NeedsCompilation": "yes", - "Author": "Jeroen Ooms [aut, cre] (), Oliver Keyes [ctb]", + "Author": "Jeroen Ooms [aut, cre] (ORCID: ), Oliver Keyes [ctb]", "Maintainer": "Jeroen Ooms ", "Repository": "CRAN" }, "pillar": { "Package": "pillar", - "Version": "1.10.1", + "Version": "1.11.1", "Source": "Repository", "Title": "Coloured Formatting for Columns", "Authors@R": "c(person(given = \"Kirill\", family = \"M\\u00fcller\", role = c(\"aut\", \"cre\"), email = \"kirill@cynkra.com\", comment = c(ORCID = \"0000-0002-1416-3412\")), person(given = \"Hadley\", family = \"Wickham\", role = \"aut\"), person(given = \"RStudio\", role = \"cph\"))", @@ -1727,16 +3005,16 @@ ], "VignetteBuilder": "knitr", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2.9000", + "RoxygenNote": "7.3.3.9000", "Config/testthat/edition": "3", "Config/testthat/parallel": "true", "Config/testthat/start-first": "format_multi_fuzz, format_multi_fuzz_2, format_multi, ctl_colonnade, ctl_colonnade_1, ctl_colonnade_2", "Config/autostyle/scope": "line_breaks", "Config/autostyle/strict": "true", - "Config/gha/extra-packages": "DiagrammeR=?ignore-before-r=3.5.0", + "Config/gha/extra-packages": "units=?ignore-before-r=4.3.0", "Config/Needs/website": "tidyverse/tidytemplate", "NeedsCompilation": "no", - "Author": "Kirill Müller [aut, cre] (), Hadley Wickham [aut], RStudio [cph]", + "Author": "Kirill Müller [aut, cre] (ORCID: ), Hadley Wickham [aut], RStudio [cph]", "Maintainer": "Kirill Müller ", "Repository": "CRAN" }, @@ -1789,6 +3067,47 @@ "Maintainer": "Gabor Csardi ", "Repository": "CRAN" }, + "processx": { + "Package": "processx", + "Version": "3.9.0", + "Source": "Repository", + "Title": "Execute and Control System Processes", + "Authors@R": "c( person(\"Gábor\", \"Csárdi\", , \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\", \"cph\"), comment = c(ORCID = \"0000-0001-7098-9676\")), person(\"Winston\", \"Chang\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")), person(\"Ascent Digital Services\", role = c(\"cph\", \"fnd\")) )", + "Description": "Tools to run system processes in the background. It can check if a background process is running; wait on a background process to finish; get the exit status of finished processes; kill background processes. It can read the standard output and error of the processes, using non-blocking connections. 'processx' can poll a process for standard output or error, with a timeout. It can also poll several processes at once.", + "License": "MIT + file LICENSE", + "URL": "https://processx.r-lib.org, https://github.com/r-lib/processx", + "BugReports": "https://github.com/r-lib/processx/issues", + "Depends": [ + "R (>= 3.4.0)" + ], + "Imports": [ + "ps (>= 1.9.3)", + "R6", + "utils" + ], + "Suggests": [ + "callr (>= 3.7.3)", + "cli (>= 3.3.0)", + "codetools", + "covr", + "curl", + "debugme", + "parallel", + "rlang (>= 1.0.2)", + "testthat (>= 3.0.0)", + "webfakes", + "withr" + ], + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-25", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "yes", + "Author": "Gábor Csárdi [aut, cre, cph] (ORCID: ), Winston Chang [aut], Posit Software, PBC [cph, fnd] (ROR: ), Ascent Digital Services [cph, fnd]", + "Maintainer": "Gábor Csárdi ", + "Repository": "CRAN" + }, "progress": { "Package": "progress", "Version": "1.2.3", @@ -1822,33 +3141,161 @@ "Maintainer": "Gábor Csárdi ", "Repository": "CRAN" }, + "ps": { + "Package": "ps", + "Version": "1.9.3", + "Source": "Repository", + "Title": "List, Query, Manipulate System Processes", + "Authors@R": "c( person(\"Jay\", \"Loden\", role = \"aut\"), person(\"Dave\", \"Daeschler\", role = \"aut\"), person(\"Giampaolo\", \"Rodola'\", role = \"aut\"), person(\"Gábor\", \"Csárdi\", , \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Description": "List, query and manipulate all system processes, on 'Windows', 'Linux' and 'macOS'.", + "License": "MIT + file LICENSE", + "URL": "https://github.com/r-lib/ps, https://ps.r-lib.org/", + "BugReports": "https://github.com/r-lib/ps/issues", + "Depends": [ + "R (>= 3.4)" + ], + "Imports": [ + "utils" + ], + "Suggests": [ + "callr", + "covr", + "curl", + "pillar", + "pingr", + "processx (>= 3.1.0)", + "R6", + "rlang", + "testthat (>= 3.0.0)", + "webfakes", + "withr" + ], + "Biarch": "true", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-28", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "yes", + "Author": "Jay Loden [aut], Dave Daeschler [aut], Giampaolo Rodola' [aut], Gábor Csárdi [aut, cre], Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Gábor Csárdi ", + "Repository": "CRAN" + }, + "purrr": { + "Package": "purrr", + "Version": "1.2.2", + "Source": "Repository", + "Title": "Functional Programming Tools", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Lionel\", \"Henry\", , \"lionel@posit.co\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"https://ror.org/03wc8by49\")) )", + "Description": "A complete and consistent functional programming toolkit for R.", + "License": "MIT + file LICENSE", + "URL": "https://purrr.tidyverse.org/, https://github.com/tidyverse/purrr", + "BugReports": "https://github.com/tidyverse/purrr/issues", + "Depends": [ + "R (>= 4.1)" + ], + "Imports": [ + "cli (>= 3.6.1)", + "lifecycle (>= 1.0.3)", + "magrittr (>= 1.5.0)", + "rlang (>= 1.1.1)", + "vctrs (>= 0.6.3)" + ], + "Suggests": [ + "carrier (>= 0.3.0)", + "covr", + "dplyr (>= 0.7.8)", + "httr", + "knitr", + "lubridate", + "mirai (>= 2.5.1)", + "rmarkdown", + "testthat (>= 3.0.0)", + "tibble", + "tidyselect" + ], + "LinkingTo": [ + "cli" + ], + "VignetteBuilder": "knitr", + "Biarch": "true", + "Config/build/compilation-database": "true", + "Config/Needs/website": "tidyverse/tidytemplate, tidyr", + "Config/testthat/edition": "3", + "Config/testthat/parallel": "TRUE", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "yes", + "Author": "Hadley Wickham [aut, cre] (ORCID: ), Lionel Henry [aut], Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Hadley Wickham ", + "Repository": "CRAN" + }, + "ragg": { + "Package": "ragg", + "Version": "1.5.2", + "Source": "Repository", + "Type": "Package", + "Title": "Graphic Devices Based on AGG", + "Authors@R": "c( person(\"Thomas Lin\", \"Pedersen\", , \"thomas.pedersen@posit.co\", role = c(\"cre\", \"aut\"), comment = c(ORCID = \"0000-0002-5147-4711\")), person(\"Maxim\", \"Shemanarev\", role = c(\"aut\", \"cph\"), comment = \"Author of AGG\"), person(\"Tony\", \"Juricic\", , \"tonygeek@yahoo.com\", role = c(\"ctb\", \"cph\"), comment = \"Contributor to AGG\"), person(\"Milan\", \"Marusinec\", , \"milan@marusinec.sk\", role = c(\"ctb\", \"cph\"), comment = \"Contributor to AGG\"), person(\"Spencer\", \"Garrett\", role = \"ctb\", comment = \"Contributor to AGG\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Maintainer": "Thomas Lin Pedersen ", + "Description": "Anti-Grain Geometry (AGG) is a high-quality and high-performance 2D drawing library. The 'ragg' package provides a set of graphic devices based on AGG to use as alternative to the raster devices provided through the 'grDevices' package.", + "License": "MIT + file LICENSE", + "URL": "https://ragg.r-lib.org, https://github.com/r-lib/ragg", + "BugReports": "https://github.com/r-lib/ragg/issues", + "Imports": [ + "systemfonts (>= 1.0.3)", + "textshaping (>= 0.3.0)" + ], + "Suggests": [ + "covr", + "graphics", + "grid", + "testthat (>= 3.0.0)" + ], + "LinkingTo": [ + "systemfonts", + "textshaping" + ], + "Config/build/compilation-database": "true", + "Config/Needs/website": "ggplot2, devoid, magick, bench, tidyr, ggridges, hexbin, sessioninfo, pkgdown, tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-25", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "SystemRequirements": "freetype2, libpng, libtiff, libjpeg, libwebp, libwebpmux", + "NeedsCompilation": "yes", + "Author": "Thomas Lin Pedersen [cre, aut] (ORCID: ), Maxim Shemanarev [aut, cph] (Author of AGG), Tony Juricic [ctb, cph] (Contributor to AGG), Milan Marusinec [ctb, cph] (Contributor to AGG), Spencer Garrett [ctb] (Contributor to AGG), Posit Software, PBC [cph, fnd] (ROR: )", + "Repository": "CRAN" + }, "rappdirs": { "Package": "rappdirs", - "Version": "0.3.3", + "Version": "0.3.4", "Source": "Repository", "Type": "Package", "Title": "Application Directories: Determine Where to Save Data, Caches, and Logs", - "Authors@R": "c(person(given = \"Hadley\", family = \"Wickham\", role = c(\"trl\", \"cre\", \"cph\"), email = \"hadley@rstudio.com\"), person(given = \"RStudio\", role = \"cph\"), person(given = \"Sridhar\", family = \"Ratnakumar\", role = \"aut\"), person(given = \"Trent\", family = \"Mick\", role = \"aut\"), person(given = \"ActiveState\", role = \"cph\", comment = \"R/appdir.r, R/cache.r, R/data.r, R/log.r translated from appdirs\"), person(given = \"Eddy\", family = \"Petrisor\", role = \"ctb\"), person(given = \"Trevor\", family = \"Davis\", role = c(\"trl\", \"aut\")), person(given = \"Gabor\", family = \"Csardi\", role = \"ctb\"), person(given = \"Gregory\", family = \"Jefferis\", role = \"ctb\"))", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"trl\", \"cre\", \"cph\")), person(\"Sridhar\", \"Ratnakumar\", role = \"aut\"), person(\"Trent\", \"Mick\", role = \"aut\"), person(\"ActiveState\", role = \"cph\", comment = \"R/appdir.r, R/cache.r, R/data.r, R/log.r translated from appdirs\"), person(\"Eddy\", \"Petrisor\", role = \"ctb\"), person(\"Trevor\", \"Davis\", role = c(\"trl\", \"aut\"), comment = c(ORCID = \"0000-0001-6341-4639\")), person(\"Gabor\", \"Csardi\", role = \"ctb\"), person(\"Gregory\", \"Jefferis\", role = \"ctb\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", "Description": "An easy way to determine which directories on the users computer you should use to save data, caches and logs. A port of Python's 'Appdirs' () to R.", "License": "MIT + file LICENSE", "URL": "https://rappdirs.r-lib.org, https://github.com/r-lib/rappdirs", "BugReports": "https://github.com/r-lib/rappdirs/issues", "Depends": [ - "R (>= 3.2)" + "R (>= 4.1)" ], "Suggests": [ - "roxygen2", - "testthat (>= 3.0.0)", "covr", + "roxygen2", + "testthat (>= 3.2.0)", "withr" ], - "Copyright": "Original python appdirs module copyright (c) 2010 ActiveState Software Inc. R port copyright Hadley Wickham, RStudio. See file LICENSE for details.", - "Encoding": "UTF-8", - "RoxygenNote": "7.1.1", + "Config/Needs/website": "tidyverse/tidytemplate", "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-05-05", + "Copyright": "Original python appdirs module copyright (c) 2010 ActiveState Software Inc. R port copyright Hadley Wickham, Posit, PBC. See file LICENSE for details.", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", "NeedsCompilation": "yes", - "Author": "Hadley Wickham [trl, cre, cph], RStudio [cph], Sridhar Ratnakumar [aut], Trent Mick [aut], ActiveState [cph] (R/appdir.r, R/cache.r, R/data.r, R/log.r translated from appdirs), Eddy Petrisor [ctb], Trevor Davis [trl, aut], Gabor Csardi [ctb], Gregory Jefferis [ctb]", - "Maintainer": "Hadley Wickham ", + "Author": "Hadley Wickham [trl, cre, cph], Sridhar Ratnakumar [aut], Trent Mick [aut], ActiveState [cph] (R/appdir.r, R/cache.r, R/data.r, R/log.r translated from appdirs), Eddy Petrisor [ctb], Trevor Davis [trl, aut] (ORCID: ), Gabor Csardi [ctb], Gregory Jefferis [ctb], Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Hadley Wickham ", "Repository": "CRAN" }, "reactR": { @@ -1881,7 +3328,7 @@ "VignetteBuilder": "knitr", "NeedsCompilation": "no", "Author": "Facebook Inc [aut, cph] (React library in lib, https://reactjs.org/; see AUTHORS for full list of contributors), Michel Weststrate [aut, cph] (mobx library in lib, https://github.com/mobxjs), Kent Russell [aut, cre] (R interface), Alan Dipert [aut] (R interface), Greg Lin [aut] (R interface)", - "Repository": "CRAN" + "Repository": "RSPM" }, "reactable": { "Package": "reactable", @@ -1925,33 +3372,35 @@ "NeedsCompilation": "no", "Author": "Greg Lin [aut, cre], Tanner Linsley [ctb, cph] (React Table library), Emotion team and other contributors [ctb, cph] (Emotion library), Kent Russell [ctb, cph] (reactR package), Ramnath Vaidyanathan [ctb, cph] (htmlwidgets package), Joe Cheng [ctb, cph] (htmlwidgets package), JJ Allaire [ctb, cph] (htmlwidgets package), Yihui Xie [ctb, cph] (htmlwidgets package), Kenton Russell [ctb, cph] (htmlwidgets package), Facebook, Inc. and its affiliates [ctb, cph] (React library), FormatJS [ctb, cph] (FormatJS libraries), Feross Aboukhadijeh, and other contributors [ctb, cph] (buffer library), Roman Shtylman [ctb, cph] (process library), James Halliday [ctb, cph] (stream-browserify library), Posit Software, PBC [fnd, cph]", "Maintainer": "Greg Lin ", - "Repository": "CRAN" + "Repository": "RSPM" }, "readr": { "Package": "readr", - "Version": "2.1.5", + "Version": "2.2.0", "Source": "Repository", "Title": "Read Rectangular Text Data", - "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Jim\", \"Hester\", role = \"aut\"), person(\"Romain\", \"Francois\", role = \"ctb\"), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Shelby\", \"Bearrows\", role = \"ctb\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")), person(\"https://github.com/mandreyel/\", role = \"cph\", comment = \"mio library\"), person(\"Jukka\", \"Jylänki\", role = c(\"ctb\", \"cph\"), comment = \"grisu3 implementation\"), person(\"Mikkel\", \"Jørgensen\", role = c(\"ctb\", \"cph\"), comment = \"grisu3 implementation\") )", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Jim\", \"Hester\", role = \"aut\"), person(\"Romain\", \"Francois\", role = \"ctb\"), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Shelby\", \"Bearrows\", role = \"ctb\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")), person(\"https://github.com/mandreyel/\", role = \"cph\", comment = \"mio library\"), person(\"Jukka\", \"Jylänki\", role = c(\"ctb\", \"cph\"), comment = \"grisu3 implementation\"), person(\"Mikkel\", \"Jørgensen\", role = c(\"ctb\", \"cph\"), comment = \"grisu3 implementation\") )", "Description": "The goal of 'readr' is to provide a fast and friendly way to read rectangular data (like 'csv', 'tsv', and 'fwf'). It is designed to flexibly parse many types of data found in the wild, while still cleanly failing when data unexpectedly changes.", "License": "MIT + file LICENSE", "URL": "https://readr.tidyverse.org, https://github.com/tidyverse/readr", "BugReports": "https://github.com/tidyverse/readr/issues", "Depends": [ - "R (>= 3.6)" + "R (>= 4.1)" ], "Imports": [ - "cli (>= 3.2.0)", + "cli", "clipr", "crayon", + "glue", "hms (>= 0.4.1)", - "lifecycle (>= 0.2.0)", + "lifecycle", "methods", "R6", "rlang", "tibble", "utils", - "vroom (>= 1.6.0)" + "vroom (>= 1.7.0)", + "withr" ], "Suggests": [ "covr", @@ -1964,7 +3413,6 @@ "testthat (>= 3.2.0)", "tzdb (>= 0.1.1)", "waldo", - "withr", "xml2" ], "LinkingTo": [ @@ -1975,14 +3423,101 @@ "Config/Needs/website": "tidyverse, tidyverse/tidytemplate", "Config/testthat/edition": "3", "Config/testthat/parallel": "false", + "Config/usethis/last-upkeep": "2025-11-14", "Encoding": "UTF-8", "Language": "en-US", - "RoxygenNote": "7.2.3", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "yes", + "Author": "Hadley Wickham [aut], Jim Hester [aut], Romain Francois [ctb], Jennifer Bryan [aut, cre] (ORCID: ), Shelby Bearrows [ctb], Posit Software, PBC [cph, fnd] (ROR: ), https://github.com/mandreyel/ [cph] (mio library), Jukka Jylänki [ctb, cph] (grisu3 implementation), Mikkel Jørgensen [ctb, cph] (grisu3 implementation)", + "Maintainer": "Jennifer Bryan ", + "Repository": "CRAN" + }, + "readxl": { + "Package": "readxl", + "Version": "1.5.0", + "Source": "Repository", + "Title": "Read Excel Files", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Posit, PBC\", role = c(\"cph\", \"fnd\"), comment = \"Copyright holder of all R code and all C/C++ code without explicit copyright attribution\"), person(\"Marcin\", \"Kalicinski\", role = c(\"ctb\", \"cph\"), comment = \"Author of included RapidXML code\"), person(\"Komarov Valery\", role = c(\"ctb\", \"cph\"), comment = \"Author of included libxls code\"), person(\"Christophe Leitienne\", role = c(\"ctb\", \"cph\"), comment = \"Author of included libxls code\"), person(\"Bob Colbert\", role = c(\"ctb\", \"cph\"), comment = \"Author of included libxls code\"), person(\"David Hoerl\", role = c(\"ctb\", \"cph\"), comment = \"Author of included libxls code\"), person(\"Evan Miller\", role = c(\"ctb\", \"cph\"), comment = \"Author of included libxls code\") )", + "Description": "Import excel files into R. Supports '.xls' via the embedded 'libxls' C library and '.xlsx' via the embedded 'RapidXML' C++ library . Works on Windows, Mac and Linux without external dependencies.", + "License": "MIT + file LICENSE", + "URL": "https://readxl.tidyverse.org, https://github.com/tidyverse/readxl", + "BugReports": "https://github.com/tidyverse/readxl/issues", + "Depends": [ + "R (>= 4.1)" + ], + "Imports": [ + "cellranger", + "tibble (>= 2.0.1)", + "utils" + ], + "Suggests": [ + "covr", + "knitr", + "rmarkdown", + "testthat (>= 3.1.6)", + "withr" + ], + "LinkingTo": [ + "cpp11 (>= 0.5.5)", + "progress" + ], + "VignetteBuilder": "knitr", + "Config/build/compilation-database": "true", + "Config/Needs/website": "tidyverse/tidytemplate, tidyverse", + "Config/roxygen2/version": "8.0.0", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "Note": "libxls v1.6.3 c199d13", "NeedsCompilation": "yes", - "Author": "Hadley Wickham [aut], Jim Hester [aut], Romain Francois [ctb], Jennifer Bryan [aut, cre] (), Shelby Bearrows [ctb], Posit Software, PBC [cph, fnd], https://github.com/mandreyel/ [cph] (mio library), Jukka Jylänki [ctb, cph] (grisu3 implementation), Mikkel Jørgensen [ctb, cph] (grisu3 implementation)", + "Author": "Hadley Wickham [aut] (ORCID: ), Jennifer Bryan [aut, cre] (ORCID: ), Posit, PBC [cph, fnd] (Copyright holder of all R code and all C/C++ code without explicit copyright attribution), Marcin Kalicinski [ctb, cph] (Author of included RapidXML code), Komarov Valery [ctb, cph] (Author of included libxls code), Christophe Leitienne [ctb, cph] (Author of included libxls code), Bob Colbert [ctb, cph] (Author of included libxls code), David Hoerl [ctb, cph] (Author of included libxls code), Evan Miller [ctb, cph] (Author of included libxls code)", "Maintainer": "Jennifer Bryan ", "Repository": "CRAN" }, + "rematch": { + "Package": "rematch", + "Version": "2.0.0", + "Source": "Repository", + "Title": "Match Regular Expressions with a Nicer 'API'", + "Author": "Gabor Csardi", + "Maintainer": "Gabor Csardi ", + "Description": "A small wrapper on 'regexpr' to extract the matches and captured groups from the match of a regular expression to a character vector.", + "License": "MIT + file LICENSE", + "URL": "https://github.com/gaborcsardi/rematch", + "BugReports": "https://github.com/gaborcsardi/rematch/issues", + "RoxygenNote": "5.0.1.9000", + "Suggests": [ + "covr", + "testthat" + ], + "Encoding": "UTF-8", + "NeedsCompilation": "no", + "Repository": "RSPM" + }, + "rematch2": { + "Package": "rematch2", + "Version": "2.1.2", + "Source": "Repository", + "Title": "Tidy Output from Regular Expression Matching", + "Authors@R": "c( person(\"Gábor\", \"Csárdi\", email = \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\")), person(\"Matthew\", \"Lincoln\", email = \"matthew.d.lincoln@gmail.com\", role = c(\"ctb\")))", + "Description": "Wrappers on 'regexpr' and 'gregexpr' to return the match results in tidy data frames.", + "License": "MIT + file LICENSE", + "LazyData": "true", + "URL": "https://github.com/r-lib/rematch2#readme", + "BugReports": "https://github.com/r-lib/rematch2/issues", + "RoxygenNote": "7.1.0", + "Imports": [ + "tibble" + ], + "Suggests": [ + "covr", + "testthat" + ], + "Encoding": "UTF-8", + "NeedsCompilation": "no", + "Author": "Gábor Csárdi [aut, cre], Matthew Lincoln [ctb]", + "Maintainer": "Gábor Csárdi ", + "Repository": "RSPM" + }, "renv": { "Package": "renv", "Version": "1.1.4", @@ -2036,18 +3571,70 @@ "Maintainer": "Kevin Ushey ", "Repository": "CRAN" }, + "reprex": { + "Package": "reprex", + "Version": "2.1.1", + "Source": "Repository", + "Title": "Prepare Reproducible Example Code via the Clipboard", + "Authors@R": "c( person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Jim\", \"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"David\", \"Robinson\", , \"admiral.david@gmail.com\", role = \"aut\"), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Christophe\", \"Dervieux\", , \"cderv@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4474-2498\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Convenience wrapper that uses the 'rmarkdown' package to render small snippets of code to target formats that include both code and output. The goal is to encourage the sharing of small, reproducible, and runnable examples on code-oriented websites, such as and , or in email. The user's clipboard is the default source of input code and the default target for rendered output. 'reprex' also extracts clean, runnable R code from various common formats, such as copy/paste from an R session.", + "License": "MIT + file LICENSE", + "URL": "https://reprex.tidyverse.org, https://github.com/tidyverse/reprex", + "BugReports": "https://github.com/tidyverse/reprex/issues", + "Depends": [ + "R (>= 3.6)" + ], + "Imports": [ + "callr (>= 3.6.0)", + "cli (>= 3.2.0)", + "clipr (>= 0.4.0)", + "fs", + "glue", + "knitr (>= 1.23)", + "lifecycle", + "rlang (>= 1.0.0)", + "rmarkdown", + "rstudioapi", + "utils", + "withr (>= 2.3.0)" + ], + "Suggests": [ + "covr", + "fortunes", + "miniUI", + "rprojroot", + "sessioninfo", + "shiny", + "spelling", + "styler (>= 1.2.0)", + "testthat (>= 3.2.1)" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "dplyr, tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/testthat/parallel": "TRUE", + "Config/testthat/start-first": "knitr-options, venues, reprex", + "Encoding": "UTF-8", + "Language": "en-US", + "RoxygenNote": "7.3.2", + "SystemRequirements": "pandoc (>= 2.0) - https://pandoc.org/", + "NeedsCompilation": "no", + "Author": "Jennifer Bryan [aut, cre] (), Jim Hester [aut] (), David Robinson [aut], Hadley Wickham [aut] (), Christophe Dervieux [aut] (), Posit Software, PBC [cph, fnd]", + "Maintainer": "Jennifer Bryan ", + "Repository": "RSPM" + }, "rlang": { "Package": "rlang", - "Version": "1.1.5", + "Version": "1.3.0", "Source": "Repository", "Title": "Functions for Base Types and Core R and 'Tidyverse' Features", + "Authors@R": "c( person(\"Lionel\", \"Henry\", , \"lionel@posit.co\", role = c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"mikefc\", , , \"mikefc@coolbutuseless.com\", role = \"cph\", comment = \"Hash implementation based on Mike's xxhashlite\"), person(\"Yann\", \"Collet\", role = \"cph\", comment = \"Author of the embedded xxHash library\"), person(\"Posit, PBC\", role = c(\"cph\", \"fnd\")) )", "Description": "A toolbox for working with base types, core R features like the condition system, and core 'Tidyverse' features like tidy evaluation.", - "Authors@R": "c( person(\"Lionel\", \"Henry\", ,\"lionel@posit.co\", c(\"aut\", \"cre\")), person(\"Hadley\", \"Wickham\", ,\"hadley@posit.co\", \"aut\"), person(given = \"mikefc\", email = \"mikefc@coolbutuseless.com\", role = \"cph\", comment = \"Hash implementation based on Mike's xxhashlite\"), person(given = \"Yann\", family = \"Collet\", role = \"cph\", comment = \"Author of the embedded xxHash library\"), person(given = \"Posit, PBC\", role = c(\"cph\", \"fnd\")) )", "License": "MIT + file LICENSE", - "ByteCompile": "true", - "Biarch": "true", + "URL": "https://rlang.r-lib.org, https://github.com/r-lib/rlang", + "BugReports": "https://github.com/r-lib/rlang/issues", "Depends": [ - "R (>= 3.5.0)" + "R (>= 4.0.0)" ], "Imports": [ "utils" @@ -2056,15 +3643,17 @@ "cli (>= 3.1.0)", "covr", "crayon", + "desc", "fs", "glue", "knitr", "magrittr", "methods", "pillar", + "pkgload", "rmarkdown", "stats", - "testthat (>= 3.0.0)", + "testthat (>= 3.3.2)", "tibble", "usethis", "vctrs (>= 0.2.3)", @@ -2073,20 +3662,22 @@ "Enhances": [ "winch" ], - "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", - "URL": "https://rlang.r-lib.org, https://github.com/r-lib/rlang", - "BugReports": "https://github.com/r-lib/rlang/issues", - "Config/testthat/edition": "3", + "Biarch": "true", + "ByteCompile": "true", + "Config/build/compilation-database": "true", "Config/Needs/website": "dplyr, tidyverse/tidytemplate", + "Config/roxygen2/version": "8.0.0", + "Config/testthat/edition": "3", + "Config/testthat/parallel": "true", + "Encoding": "UTF-8", "NeedsCompilation": "yes", "Author": "Lionel Henry [aut, cre], Hadley Wickham [aut], mikefc [cph] (Hash implementation based on Mike's xxhashlite), Yann Collet [cph] (Author of the embedded xxHash library), Posit, PBC [cph, fnd]", "Maintainer": "Lionel Henry ", - "Repository": "CRAN" + "Repository": "RSPM" }, "rmarkdown": { "Package": "rmarkdown", - "Version": "2.29", + "Version": "2.31", "Source": "Repository", "Type": "Package", "Title": "Dynamic Documents for R", @@ -2133,16 +3724,95 @@ "Config/Needs/website": "rstudio/quillt, pkgdown", "Config/testthat/edition": "3", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", + "RoxygenNote": "7.3.3", "SystemRequirements": "pandoc (>= 1.14) - http://pandoc.org", "NeedsCompilation": "no", - "Author": "JJ Allaire [aut], Yihui Xie [aut, cre] (), Christophe Dervieux [aut] (), Jonathan McPherson [aut], Javier Luraschi [aut], Kevin Ushey [aut], Aron Atkins [aut], Hadley Wickham [aut], Joe Cheng [aut], Winston Chang [aut], Richard Iannone [aut] (), Andrew Dunning [ctb] (), Atsushi Yasumoto [ctb, cph] (, Number sections Lua filter), Barret Schloerke [ctb], Carson Sievert [ctb] (), Devon Ryan [ctb] (), Frederik Aust [ctb] (), Jeff Allen [ctb], JooYoung Seo [ctb] (), Malcolm Barrett [ctb], Rob Hyndman [ctb], Romain Lesur [ctb], Roy Storey [ctb], Ruben Arslan [ctb], Sergio Oller [ctb], Posit Software, PBC [cph, fnd], jQuery UI contributors [ctb, cph] (jQuery UI library; authors listed in inst/rmd/h/jqueryui/AUTHORS.txt), Mark Otto [ctb] (Bootstrap library), Jacob Thornton [ctb] (Bootstrap library), Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Alexander Farkas [ctb, cph] (html5shiv library), Scott Jehl [ctb, cph] (Respond.js library), Ivan Sagalaev [ctb, cph] (highlight.js library), Greg Franko [ctb, cph] (tocify library), John MacFarlane [ctb, cph] (Pandoc templates), Google, Inc. [ctb, cph] (ioslides library), Dave Raggett [ctb] (slidy library), W3C [cph] (slidy library), Dave Gandy [ctb, cph] (Font-Awesome), Ben Sperry [ctb] (Ionicons), Drifty [cph] (Ionicons), Aidan Lister [ctb, cph] (jQuery StickyTabs), Benct Philip Jonsson [ctb, cph] (pagebreak Lua filter), Albert Krewinkel [ctb, cph] (pagebreak Lua filter)", + "Author": "JJ Allaire [aut], Yihui Xie [aut, cre] (ORCID: ), Christophe Dervieux [aut] (ORCID: ), Jonathan McPherson [aut], Javier Luraschi [aut], Kevin Ushey [aut], Aron Atkins [aut], Hadley Wickham [aut], Joe Cheng [aut], Winston Chang [aut], Richard Iannone [aut] (ORCID: ), Andrew Dunning [ctb] (ORCID: ), Atsushi Yasumoto [ctb, cph] (ORCID: , cph: Number sections Lua filter), Barret Schloerke [ctb], Carson Sievert [ctb] (ORCID: ), Devon Ryan [ctb] (ORCID: ), Frederik Aust [ctb] (ORCID: ), Jeff Allen [ctb], JooYoung Seo [ctb] (ORCID: ), Malcolm Barrett [ctb], Rob Hyndman [ctb], Romain Lesur [ctb], Roy Storey [ctb], Ruben Arslan [ctb], Sergio Oller [ctb], Posit Software, PBC [cph, fnd], jQuery UI contributors [ctb, cph] (jQuery UI library; authors listed in inst/rmd/h/jqueryui/AUTHORS.txt), Mark Otto [ctb] (Bootstrap library), Jacob Thornton [ctb] (Bootstrap library), Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Alexander Farkas [ctb, cph] (html5shiv library), Scott Jehl [ctb, cph] (Respond.js library), Ivan Sagalaev [ctb, cph] (highlight.js library), Greg Franko [ctb, cph] (tocify library), John MacFarlane [ctb, cph] (Pandoc templates), Google, Inc. [ctb, cph] (ioslides library), Dave Raggett [ctb] (slidy library), W3C [cph] (slidy library), Dave Gandy [ctb, cph] (Font-Awesome), Ben Sperry [ctb] (Ionicons), Drifty [cph] (Ionicons), Aidan Lister [ctb, cph] (jQuery StickyTabs), Benct Philip Jonsson [ctb, cph] (pagebreak Lua filter), Albert Krewinkel [ctb, cph] (pagebreak Lua filter)", "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, + "rstudioapi": { + "Package": "rstudioapi", + "Version": "0.18.0", + "Source": "Repository", + "Title": "Safely Access the RStudio API", + "Description": "Access the RStudio API (if available) and provide informative error messages when it's not.", + "Authors@R": "c( person(\"Kevin\", \"Ushey\", role = c(\"aut\", \"cre\"), email = \"kevin@rstudio.com\"), person(\"JJ\", \"Allaire\", role = c(\"aut\"), email = \"jj@posit.co\"), person(\"Hadley\", \"Wickham\", role = c(\"aut\"), email = \"hadley@posit.co\"), person(\"Gary\", \"Ritchie\", role = c(\"aut\"), email = \"gary@posit.co\"), person(family = \"RStudio\", role = \"cph\") )", + "Maintainer": "Kevin Ushey ", + "License": "MIT + file LICENSE", + "URL": "https://rstudio.github.io/rstudioapi/, https://github.com/rstudio/rstudioapi", + "BugReports": "https://github.com/rstudio/rstudioapi/issues", + "RoxygenNote": "7.3.3", + "Suggests": [ + "testthat", + "knitr", + "rmarkdown", + "clipr", + "covr", + "curl", + "jsonlite", + "withr" + ], + "VignetteBuilder": "knitr", + "Encoding": "UTF-8", + "NeedsCompilation": "no", + "Author": "Kevin Ushey [aut, cre], JJ Allaire [aut], Hadley Wickham [aut], Gary Ritchie [aut], RStudio [cph]", + "Repository": "CRAN" + }, + "rvest": { + "Package": "rvest", + "Version": "1.0.5", + "Source": "Repository", + "Title": "Easily Harvest (Scrape) Web Pages", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Description": "Wrappers around the 'xml2' and 'httr' packages to make it easy to download, then manipulate, HTML and XML.", + "License": "MIT + file LICENSE", + "URL": "https://rvest.tidyverse.org/, https://github.com/tidyverse/rvest", + "BugReports": "https://github.com/tidyverse/rvest/issues", + "Depends": [ + "R (>= 4.1)" + ], + "Imports": [ + "cli", + "glue", + "httr (>= 0.5)", + "lifecycle (>= 1.0.3)", + "magrittr", + "rlang (>= 1.1.0)", + "selectr", + "tibble", + "xml2 (>= 1.4.0)" + ], + "Suggests": [ + "chromote", + "covr", + "knitr", + "purrr", + "R6", + "readr", + "repurrrsive", + "rmarkdown", + "spelling", + "stringi (>= 0.3.1)", + "testthat (>= 3.0.2)", + "tidyr", + "webfakes" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/testthat/parallel": "true", + "Encoding": "UTF-8", + "Language": "en-US", + "RoxygenNote": "7.3.2", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut, cre], Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Hadley Wickham ", + "Repository": "RSPM" + }, "sass": { "Package": "sass", - "Version": "0.4.9", + "Version": "0.4.10", "Source": "Repository", "Type": "Package", "Title": "Syntactically Awesome Style Sheets ('Sass')", @@ -2152,7 +3822,7 @@ "URL": "https://rstudio.github.io/sass/, https://github.com/rstudio/sass", "BugReports": "https://github.com/rstudio/sass/issues", "Encoding": "UTF-8", - "RoxygenNote": "7.3.1", + "RoxygenNote": "7.3.2", "SystemRequirements": "GNU make", "Imports": [ "fs (>= 1.2.4)", @@ -2174,20 +3844,20 @@ "NeedsCompilation": "yes", "Author": "Joe Cheng [aut], Timothy Mastny [aut], Richard Iannone [aut] (), Barret Schloerke [aut] (), Carson Sievert [aut, cre] (), Christophe Dervieux [ctb] (), RStudio [cph, fnd], Sass Open Source Foundation [ctb, cph] (LibSass library), Greter Marcel [ctb, cph] (LibSass library), Mifsud Michael [ctb, cph] (LibSass library), Hampton Catlin [ctb, cph] (LibSass library), Natalie Weizenbaum [ctb, cph] (LibSass library), Chris Eppstein [ctb, cph] (LibSass library), Adams Joseph [ctb, cph] (json.cpp), Trifunovic Nemanja [ctb, cph] (utf8.h)", "Maintainer": "Carson Sievert ", - "Repository": "CRAN" + "Repository": "RSPM" }, "scales": { "Package": "scales", - "Version": "1.3.0", + "Version": "1.4.0", "Source": "Repository", "Title": "Scale Functions for Visualization", - "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\")), person(\"Thomas Lin\", \"Pedersen\", , \"thomas.pedersen@posit.co\", role = c(\"cre\", \"aut\"), comment = c(ORCID = \"0000-0002-5147-4711\")), person(\"Dana\", \"Seidel\", role = \"aut\"), person(\"Posit, PBC\", role = c(\"cph\", \"fnd\")) )", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Thomas Lin\", \"Pedersen\", , \"thomas.pedersen@posit.co\", role = c(\"cre\", \"aut\"), comment = c(ORCID = \"0000-0002-5147-4711\")), person(\"Dana\", \"Seidel\", role = \"aut\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", "Description": "Graphical scales map data to aesthetics, and provide methods for automatically determining breaks and labels for axes and legends.", "License": "MIT + file LICENSE", "URL": "https://scales.r-lib.org, https://github.com/r-lib/scales", "BugReports": "https://github.com/r-lib/scales/issues", "Depends": [ - "R (>= 3.6)" + "R (>= 4.1)" ], "Imports": [ "cli", @@ -2195,10 +3865,9 @@ "glue", "labeling", "lifecycle", - "munsell (>= 0.5)", "R6", "RColorBrewer", - "rlang (>= 1.0.0)", + "rlang (>= 1.1.0)", "viridisLite" ], "Suggests": [ @@ -2212,12 +3881,117 @@ ], "Config/Needs/website": "tidyverse/tidytemplate", "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-23", "Encoding": "UTF-8", "LazyLoad": "yes", - "RoxygenNote": "7.2.3", - "NeedsCompilation": "yes", - "Author": "Hadley Wickham [aut], Thomas Lin Pedersen [cre, aut] (), Dana Seidel [aut], Posit, PBC [cph, fnd]", + "RoxygenNote": "7.3.2", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut], Thomas Lin Pedersen [cre, aut] (), Dana Seidel [aut], Posit Software, PBC [cph, fnd] (03wc8by49)", "Maintainer": "Thomas Lin Pedersen ", + "Repository": "RSPM" + }, + "selectr": { + "Package": "selectr", + "Version": "0.5-1", + "Source": "Repository", + "Type": "Package", + "Title": "Translate CSS Selectors to XPath Expressions", + "Authors@R": "c(person(\"Simon\", \"Potter\", role = c(\"aut\", \"trl\", \"cre\"), email = \"simon@sjp.co.nz\"), person(\"Simon\", \"Sapin\", role = \"aut\"), person(\"Ian\", \"Bicking\", role = \"aut\"))", + "License": "BSD_3_clause + file LICENCE", + "Depends": [ + "R (>= 3.0)" + ], + "Imports": [ + "methods", + "stringr", + "R6" + ], + "Suggests": [ + "testthat", + "XML", + "xml2" + ], + "URL": "https://sjp.co.nz/projects/selectr/", + "BugReports": "https://github.com/sjp/selectr/issues", + "Description": "Translates a CSS selector into an equivalent XPath expression. This allows us to use CSS selectors when working with the XML package as it can only evaluate XPath expressions. Also provided are convenience functions useful for using CSS selectors on XML nodes. This package is a port of the Python package 'cssselect' ().", + "NeedsCompilation": "no", + "Author": "Simon Potter [aut, trl, cre], Simon Sapin [aut], Ian Bicking [aut]", + "Maintainer": "Simon Potter ", + "Repository": "CRAN" + }, + "stringi": { + "Package": "stringi", + "Version": "1.8.7", + "Source": "Repository", + "Date": "2025-03-27", + "Title": "Fast and Portable Character String Processing Facilities", + "Description": "A collection of character string/text/natural language processing tools for pattern searching (e.g., with 'Java'-like regular expressions or the 'Unicode' collation algorithm), random string generation, case mapping, string transliteration, concatenation, sorting, padding, wrapping, Unicode normalisation, date-time formatting and parsing, and many more. They are fast, consistent, convenient, and - thanks to 'ICU' (International Components for Unicode) - portable across all locales and platforms. Documentation about 'stringi' is provided via its website at and the paper by Gagolewski (2022, ).", + "URL": "https://stringi.gagolewski.com/, https://github.com/gagolews/stringi, https://icu.unicode.org/", + "BugReports": "https://github.com/gagolews/stringi/issues", + "SystemRequirements": "ICU4C (>= 61, optional)", + "Type": "Package", + "Depends": [ + "R (>= 3.4)" + ], + "Imports": [ + "tools", + "utils", + "stats" + ], + "Biarch": "TRUE", + "License": "file LICENSE", + "Authors@R": "c(person(given = \"Marek\", family = \"Gagolewski\", role = c(\"aut\", \"cre\", \"cph\"), email = \"marek@gagolewski.com\", comment = c(ORCID = \"0000-0003-0637-6028\")), person(given = \"Bartek\", family = \"Tartanus\", role = \"ctb\"), person(\"Unicode, Inc. and others\", role=\"ctb\", comment = \"ICU4C source code, Unicode Character Database\") )", + "RoxygenNote": "7.3.2", + "Encoding": "UTF-8", + "NeedsCompilation": "yes", + "Author": "Marek Gagolewski [aut, cre, cph] (), Bartek Tartanus [ctb], Unicode, Inc. and others [ctb] (ICU4C source code, Unicode Character Database)", + "Maintainer": "Marek Gagolewski ", + "License_is_FOSS": "yes", + "Repository": "RSPM" + }, + "stringr": { + "Package": "stringr", + "Version": "1.6.0", + "Source": "Repository", + "Title": "Simple, Consistent Wrappers for Common String Operations", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\", \"cph\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "A consistent, simple and easy to use set of wrappers around the fantastic 'stringi' package. All function and argument names (and positions) are consistent, all functions deal with \"NA\"'s and zero length vectors in the same way, and the output from one function is easy to feed into the input of another.", + "License": "MIT + file LICENSE", + "URL": "https://stringr.tidyverse.org, https://github.com/tidyverse/stringr", + "BugReports": "https://github.com/tidyverse/stringr/issues", + "Depends": [ + "R (>= 4.1.0)" + ], + "Imports": [ + "cli", + "glue (>= 1.6.1)", + "lifecycle (>= 1.0.3)", + "magrittr", + "rlang (>= 1.0.0)", + "stringi (>= 1.5.3)", + "vctrs (>= 0.4.0)" + ], + "Suggests": [ + "covr", + "dplyr", + "gt", + "htmltools", + "htmlwidgets", + "knitr", + "rmarkdown", + "testthat (>= 3.0.0)", + "tibble" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/potools/style": "explicit", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut, cre, cph], Posit Software, PBC [cph, fnd]", + "Maintainer": "Hadley Wickham ", "Repository": "CRAN" }, "sys": { @@ -2244,12 +4018,104 @@ "Maintainer": "Jeroen Ooms ", "Repository": "CRAN" }, + "systemfonts": { + "Package": "systemfonts", + "Version": "1.3.2", + "Source": "Repository", + "Type": "Package", + "Title": "System Native Font Finding", + "Authors@R": "c( person(\"Thomas Lin\", \"Pedersen\", , \"thomas.pedersen@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-5147-4711\")), person(\"Jeroen\", \"Ooms\", , \"jeroen@berkeley.edu\", role = \"aut\", comment = c(ORCID = \"0000-0002-4035-0289\")), person(\"Devon\", \"Govett\", role = \"aut\", comment = \"Author of font-manager\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Description": "Provides system native access to the font catalogue. As font handling varies between systems it is difficult to correctly locate installed fonts across different operating systems. The 'systemfonts' package provides bindings to the native libraries on Windows, macOS and Linux for finding font files that can then be used further by e.g. graphic devices. The main use is intended to be from compiled code but 'systemfonts' also provides access from R.", + "License": "MIT + file LICENSE", + "URL": "https://github.com/r-lib/systemfonts, https://systemfonts.r-lib.org", + "BugReports": "https://github.com/r-lib/systemfonts/issues", + "Depends": [ + "R (>= 3.2.0)" + ], + "Imports": [ + "base64enc", + "grid", + "jsonlite", + "lifecycle", + "tools", + "utils" + ], + "Suggests": [ + "covr", + "farver", + "ggplot2", + "graphics", + "knitr", + "ragg", + "rmarkdown", + "svglite", + "testthat (>= 2.1.0)" + ], + "LinkingTo": [ + "cpp11 (>= 0.2.1)" + ], + "VignetteBuilder": "knitr", + "Config/build/compilation-database": "true", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/usethis/last-upkeep": "2025-04-23", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2", + "SystemRequirements": "fontconfig, freetype2", + "NeedsCompilation": "yes", + "Author": "Thomas Lin Pedersen [aut, cre] (ORCID: ), Jeroen Ooms [aut] (ORCID: ), Devon Govett [aut] (Author of font-manager), Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Thomas Lin Pedersen ", + "Repository": "CRAN" + }, + "textshaping": { + "Package": "textshaping", + "Version": "1.0.5", + "Source": "Repository", + "Title": "Bindings to the 'HarfBuzz' and 'Fribidi' Libraries for Text Shaping", + "Authors@R": "c( person(\"Thomas Lin\", \"Pedersen\", , \"thomas.pedersen@posit.co\", role = c(\"cre\", \"aut\"), comment = c(ORCID = \"0000-0002-5147-4711\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Description": "Provides access to the text shaping functionality in the 'HarfBuzz' library and the bidirectional algorithm in the 'Fribidi' library. 'textshaping' is a low-level utility package mainly for graphic devices that expands upon the font tool-set provided by the 'systemfonts' package.", + "License": "MIT + file LICENSE", + "URL": "https://github.com/r-lib/textshaping", + "BugReports": "https://github.com/r-lib/textshaping/issues", + "Depends": [ + "R (>= 3.2.0)" + ], + "Imports": [ + "lifecycle", + "stats", + "stringi", + "systemfonts (>= 1.3.0)", + "utils" + ], + "Suggests": [ + "covr", + "grDevices", + "grid", + "knitr", + "rmarkdown", + "testthat (>= 3.0.0)" + ], + "LinkingTo": [ + "cpp11 (>= 0.2.1)", + "systemfonts (>= 1.0.0)" + ], + "VignetteBuilder": "knitr", + "Config/build/compilation-database": "true", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-04-23", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2", + "SystemRequirements": "freetype2, harfbuzz, fribidi", + "NeedsCompilation": "yes", + "Author": "Thomas Lin Pedersen [cre, aut] (ORCID: ), Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Thomas Lin Pedersen ", + "Repository": "CRAN" + }, "tibble": { "Package": "tibble", - "Version": "3.2.1", + "Version": "3.3.1", "Source": "Repository", "Title": "Simple Data Frames", - "Authors@R": "c(person(given = \"Kirill\", family = \"M\\u00fcller\", role = c(\"aut\", \"cre\"), email = \"kirill@cynkra.com\", comment = c(ORCID = \"0000-0002-1416-3412\")), person(given = \"Hadley\", family = \"Wickham\", role = \"aut\", email = \"hadley@rstudio.com\"), person(given = \"Romain\", family = \"Francois\", role = \"ctb\", email = \"romain@r-enthusiasts.com\"), person(given = \"Jennifer\", family = \"Bryan\", role = \"ctb\", email = \"jenny@rstudio.com\"), person(given = \"RStudio\", role = c(\"cph\", \"fnd\")))", + "Authors@R": "c( person(\"Kirill\", \"Müller\", , \"kirill@cynkra.com\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-1416-3412\")), person(\"Hadley\", \"Wickham\", , \"hadley@rstudio.com\", role = \"aut\"), person(\"Romain\", \"Francois\", , \"romain@r-enthusiasts.com\", role = \"ctb\"), person(\"Jennifer\", \"Bryan\", , \"jenny@rstudio.com\", role = \"ctb\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", "Description": "Provides a 'tbl_df' class (the 'tibble') with stricter checking and better formatting than the traditional data frame.", "License": "MIT + file LICENSE", "URL": "https://tibble.tidyverse.org/, https://github.com/tidyverse/tibble", @@ -2258,7 +4124,7 @@ "R (>= 3.4.0)" ], "Imports": [ - "fansi (>= 0.4.0)", + "cli", "lifecycle (>= 1.0.0)", "magrittr", "methods", @@ -2266,7 +4132,7 @@ "pkgconfig", "rlang (>= 1.0.2)", "utils", - "vctrs (>= 0.4.2)" + "vctrs (>= 0.5.0)" ], "Suggests": [ "bench", @@ -2274,9 +4140,6 @@ "blob", "brio", "callr", - "cli", - "covr", - "crayon (>= 1.3.4)", "DiagrammeR", "dplyr", "evaluate", @@ -2287,9 +4150,7 @@ "htmltools", "knitr", "lubridate", - "mockr", "nycflights13", - "pkgbuild", "pkgload", "purrr", "rmarkdown", @@ -2299,20 +4160,72 @@ "withr" ], "VignetteBuilder": "knitr", - "Encoding": "UTF-8", - "RoxygenNote": "7.2.3", - "Config/testthat/edition": "3", - "Config/testthat/parallel": "true", - "Config/testthat/start-first": "vignette-formats, as_tibble, add, invariants", + "Config/autostyle/rmd": "false", "Config/autostyle/scope": "line_breaks", "Config/autostyle/strict": "true", - "Config/autostyle/rmd": "false", "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/testthat/parallel": "true", + "Config/testthat/start-first": "vignette-formats, as_tibble, add, invariants", + "Config/usethis/last-upkeep": "2025-06-07", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3.9000", "NeedsCompilation": "yes", - "Author": "Kirill Müller [aut, cre] (), Hadley Wickham [aut], Romain Francois [ctb], Jennifer Bryan [ctb], RStudio [cph, fnd]", + "Author": "Kirill Müller [aut, cre] (ORCID: ), Hadley Wickham [aut], Romain Francois [ctb], Jennifer Bryan [ctb], Posit Software, PBC [cph, fnd] (ROR: )", "Maintainer": "Kirill Müller ", "Repository": "CRAN" }, + "tidyr": { + "Package": "tidyr", + "Version": "1.3.2", + "Source": "Repository", + "Title": "Tidy Messy Data", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = c(\"aut\", \"cre\")), person(\"Davis\", \"Vaughan\", , \"davis@posit.co\", role = \"aut\"), person(\"Maximilian\", \"Girlich\", role = \"aut\"), person(\"Kevin\", \"Ushey\", , \"kevin@posit.co\", role = \"ctb\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Description": "Tools to help to create tidy data, where each column is a variable, each row is an observation, and each cell contains a single value. 'tidyr' contains tools for changing the shape (pivoting) and hierarchy (nesting and 'unnesting') of a dataset, turning deeply nested lists into rectangular data frames ('rectangling'), and extracting values out of string columns. It also includes tools for working with missing values (both implicit and explicit).", + "License": "MIT + file LICENSE", + "URL": "https://tidyr.tidyverse.org, https://github.com/tidyverse/tidyr", + "BugReports": "https://github.com/tidyverse/tidyr/issues", + "Depends": [ + "R (>= 4.1.0)" + ], + "Imports": [ + "cli (>= 3.4.1)", + "dplyr (>= 1.1.0)", + "glue", + "lifecycle (>= 1.0.3)", + "magrittr", + "purrr (>= 1.0.1)", + "rlang (>= 1.1.1)", + "stringr (>= 1.5.0)", + "tibble (>= 2.1.1)", + "tidyselect (>= 1.2.1)", + "utils", + "vctrs (>= 0.5.2)" + ], + "Suggests": [ + "covr", + "data.table", + "knitr", + "readr", + "repurrrsive (>= 1.1.0)", + "rmarkdown", + "testthat (>= 3.0.0)" + ], + "LinkingTo": [ + "cpp11 (>= 0.4.0)" + ], + "VignetteBuilder": "knitr", + "Config/build/compilation-database": "true", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "LazyData": "true", + "RoxygenNote": "7.3.3", + "NeedsCompilation": "yes", + "Author": "Hadley Wickham [aut, cre], Davis Vaughan [aut], Maximilian Girlich [aut], Kevin Ushey [ctb], Posit Software, PBC [cph, fnd]", + "Maintainer": "Hadley Wickham ", + "Repository": "CRAN" + }, "tidyselect": { "Package": "tidyselect", "Version": "1.2.1", @@ -2356,9 +4269,101 @@ "Maintainer": "Lionel Henry ", "Repository": "CRAN" }, + "tidyverse": { + "Package": "tidyverse", + "Version": "2.0.0", + "Source": "Repository", + "Title": "Easily Install and Load the 'Tidyverse'", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@rstudio.com\", role = c(\"aut\", \"cre\")), person(\"RStudio\", role = c(\"cph\", \"fnd\")) )", + "Description": "The 'tidyverse' is a set of packages that work in harmony because they share common data representations and 'API' design. This package is designed to make it easy to install and load multiple 'tidyverse' packages in a single step. Learn more about the 'tidyverse' at .", + "License": "MIT + file LICENSE", + "URL": "https://tidyverse.tidyverse.org, https://github.com/tidyverse/tidyverse", + "BugReports": "https://github.com/tidyverse/tidyverse/issues", + "Depends": [ + "R (>= 3.3)" + ], + "Imports": [ + "broom (>= 1.0.3)", + "conflicted (>= 1.2.0)", + "cli (>= 3.6.0)", + "dbplyr (>= 2.3.0)", + "dplyr (>= 1.1.0)", + "dtplyr (>= 1.2.2)", + "forcats (>= 1.0.0)", + "ggplot2 (>= 3.4.1)", + "googledrive (>= 2.0.0)", + "googlesheets4 (>= 1.0.1)", + "haven (>= 2.5.1)", + "hms (>= 1.1.2)", + "httr (>= 1.4.4)", + "jsonlite (>= 1.8.4)", + "lubridate (>= 1.9.2)", + "magrittr (>= 2.0.3)", + "modelr (>= 0.1.10)", + "pillar (>= 1.8.1)", + "purrr (>= 1.0.1)", + "ragg (>= 1.2.5)", + "readr (>= 2.1.4)", + "readxl (>= 1.4.2)", + "reprex (>= 2.0.2)", + "rlang (>= 1.0.6)", + "rstudioapi (>= 0.14)", + "rvest (>= 1.0.3)", + "stringr (>= 1.5.0)", + "tibble (>= 3.1.8)", + "tidyr (>= 1.3.0)", + "xml2 (>= 1.3.3)" + ], + "Suggests": [ + "covr (>= 3.6.1)", + "feather (>= 0.3.5)", + "glue (>= 1.6.2)", + "mockr (>= 0.2.0)", + "knitr (>= 1.41)", + "rmarkdown (>= 2.20)", + "testthat (>= 3.1.6)" + ], + "VignetteBuilder": "knitr", + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Encoding": "UTF-8", + "RoxygenNote": "7.2.3", + "NeedsCompilation": "no", + "Author": "Hadley Wickham [aut, cre], RStudio [cph, fnd]", + "Maintainer": "Hadley Wickham ", + "Repository": "RSPM" + }, + "timechange": { + "Package": "timechange", + "Version": "0.4.0", + "Source": "Repository", + "Title": "Efficient Manipulation of Date-Times", + "Authors@R": "c(person(\"Vitalie\", \"Spinu\", email = \"spinuvit@gmail.com\", role = c(\"aut\", \"cre\")), person(\"Google Inc.\", role = c(\"ctb\", \"cph\")))", + "Description": "Efficient routines for manipulation of date-time objects while accounting for time-zones and daylight saving times. The package includes utilities for updating of date-time components (year, month, day etc.), modification of time-zones, rounding of date-times, period addition and subtraction etc. Parts of the 'CCTZ' source code, released under the Apache 2.0 License, are included in this package. See for more details.", + "Depends": [ + "R (>= 3.3)" + ], + "License": "GPL (>= 3)", + "Encoding": "UTF-8", + "LinkingTo": [ + "cpp11 (>= 0.2.7)" + ], + "Suggests": [ + "testthat (>= 0.7.1.99)", + "knitr" + ], + "SystemRequirements": "A system with zoneinfo data (e.g. /usr/share/zoneinfo). On Windows the zoneinfo included with R is used.", + "BugReports": "https://github.com/vspinu/timechange/issues", + "URL": "https://github.com/vspinu/timechange/", + "RoxygenNote": "7.2.1", + "NeedsCompilation": "yes", + "Author": "Vitalie Spinu [aut, cre], Google Inc. [ctb, cph]", + "Maintainer": "Vitalie Spinu ", + "Repository": "CRAN" + }, "tinytex": { "Package": "tinytex", - "Version": "0.56", + "Version": "0.59", "Source": "Repository", "Type": "Package", "Title": "Helper Functions to Install and Maintain TeX Live, and Compile LaTeX Documents", @@ -2375,9 +4380,9 @@ "URL": "https://github.com/rstudio/tinytex", "BugReports": "https://github.com/rstudio/tinytex/issues", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", + "RoxygenNote": "7.3.3", "NeedsCompilation": "no", - "Author": "Yihui Xie [aut, cre, cph] (), Posit Software, PBC [cph, fnd], Christophe Dervieux [ctb] (), Devon Ryan [ctb] (), Ethan Heinzen [ctb], Fernando Cagua [ctb]", + "Author": "Yihui Xie [aut, cre, cph] (ORCID: ), Posit Software, PBC [cph, fnd], Christophe Dervieux [ctb] (ORCID: ), Devon Ryan [ctb] (ORCID: ), Ethan Heinzen [ctb], Fernando Cagua [ctb]", "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, @@ -2413,14 +4418,14 @@ }, "utf8": { "Package": "utf8", - "Version": "1.2.4", + "Version": "1.2.6", "Source": "Repository", "Title": "Unicode Text Processing", - "Authors@R": "c(person(given = c(\"Patrick\", \"O.\"), family = \"Perry\", role = c(\"aut\", \"cph\")), person(given = \"Kirill\", family = \"M\\u00fcller\", role = \"cre\", email = \"kirill@cynkra.com\"), person(given = \"Unicode, Inc.\", role = c(\"cph\", \"dtc\"), comment = \"Unicode Character Database\"))", + "Authors@R": "c(person(given = c(\"Patrick\", \"O.\"), family = \"Perry\", role = c(\"aut\", \"cph\")), person(given = \"Kirill\", family = \"M\\u00fcller\", role = \"cre\", email = \"kirill@cynkra.com\", comment = c(ORCID = \"0000-0002-1416-3412\")), person(given = \"Unicode, Inc.\", role = c(\"cph\", \"dtc\"), comment = \"Unicode Character Database\"))", "Description": "Process and print 'UTF-8' encoded international text (Unicode). Input, validate, normalize, encode, format, and display.", "License": "Apache License (== 2.0) | file LICENSE", - "URL": "https://ptrckprry.com/r-utf8/, https://github.com/patperry/r-utf8", - "BugReports": "https://github.com/patperry/r-utf8/issues", + "URL": "https://krlmlr.github.io/utf8/, https://github.com/krlmlr/utf8", + "BugReports": "https://github.com/krlmlr/utf8/issues", "Depends": [ "R (>= 2.10)" ], @@ -2436,15 +4441,33 @@ "VignetteBuilder": "knitr, rmarkdown", "Config/testthat/edition": "3", "Encoding": "UTF-8", - "RoxygenNote": "7.2.3", + "RoxygenNote": "7.3.2.9000", "NeedsCompilation": "yes", - "Author": "Patrick O. Perry [aut, cph], Kirill Müller [cre], Unicode, Inc. [cph, dtc] (Unicode Character Database)", + "Author": "Patrick O. Perry [aut, cph], Kirill Müller [cre] (ORCID: ), Unicode, Inc. [cph, dtc] (Unicode Character Database)", "Maintainer": "Kirill Müller ", + "Repository": "RSPM" + }, + "uuid": { + "Package": "uuid", + "Version": "1.2-2", + "Source": "Repository", + "Title": "Tools for Generating and Handling of UUIDs", + "Author": "Simon Urbanek [aut, cre, cph] (https://urbanek.org, ORCID: ), Theodore Ts'o [aut, cph] (libuuid)", + "Maintainer": "Simon Urbanek ", + "Authors@R": "c(person(\"Simon\", \"Urbanek\", role=c(\"aut\",\"cre\",\"cph\"), email=\"Simon.Urbanek@r-project.org\", comment=c(\"https://urbanek.org\", ORCID=\"0000-0003-2297-1732\")), person(\"Theodore\",\"Ts'o\", email=\"tytso@thunk.org\", role=c(\"aut\",\"cph\"), comment=\"libuuid\"))", + "Depends": [ + "R (>= 2.9.0)" + ], + "Description": "Tools for generating and handling of UUIDs (Universally Unique Identifiers).", + "License": "MIT + file LICENSE", + "URL": "https://www.rforge.net/uuid", + "BugReports": "https://github.com/s-u/uuid/issues", + "NeedsCompilation": "yes", "Repository": "CRAN" }, "vctrs": { "Package": "vctrs", - "Version": "0.6.5", + "Version": "0.7.3", "Source": "Repository", "Title": "Vector Helpers", "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\"), person(\"Lionel\", \"Henry\", , \"lionel@posit.co\", role = \"aut\"), person(\"Davis\", \"Vaughan\", , \"davis@posit.co\", role = c(\"aut\", \"cre\")), person(\"data.table team\", role = \"cph\", comment = \"Radix sort based on data.table's forder() and their contribution to R's order()\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", @@ -2453,13 +4476,13 @@ "URL": "https://vctrs.r-lib.org/, https://github.com/r-lib/vctrs", "BugReports": "https://github.com/r-lib/vctrs/issues", "Depends": [ - "R (>= 3.5.0)" + "R (>= 4.0.0)" ], "Imports": [ "cli (>= 3.4.0)", "glue", "lifecycle (>= 1.0.3)", - "rlang (>= 1.1.0)" + "rlang (>= 1.1.7)" ], "Suggests": [ "bit64", @@ -2479,11 +4502,14 @@ "zeallot" ], "VignetteBuilder": "knitr", + "Config/build/compilation-database": "true", "Config/Needs/website": "tidyverse/tidytemplate", "Config/testthat/edition": "3", + "Config/testthat/parallel": "true", "Encoding": "UTF-8", + "KeepSource": "true", "Language": "en-GB", - "RoxygenNote": "7.2.3", + "RoxygenNote": "7.3.3", "NeedsCompilation": "yes", "Author": "Hadley Wickham [aut], Lionel Henry [aut], Davis Vaughan [aut, cre], data.table team [cph] (Radix sort based on data.table's forder() and their contribution to R's order()), Posit Software, PBC [cph, fnd]", "Maintainer": "Davis Vaughan ", @@ -2491,11 +4517,11 @@ }, "viridisLite": { "Package": "viridisLite", - "Version": "0.4.2", + "Version": "0.4.3", "Source": "Repository", "Type": "Package", "Title": "Colorblind-Friendly Color Maps (Lite Version)", - "Date": "2023-05-02", + "Date": "2026-02-03", "Authors@R": "c( person(\"Simon\", \"Garnier\", email = \"garnier@njit.edu\", role = c(\"aut\", \"cre\")), person(\"Noam\", \"Ross\", email = \"noam.ross@gmail.com\", role = c(\"ctb\", \"cph\")), person(\"Bob\", \"Rudis\", email = \"bob@rud.is\", role = c(\"ctb\", \"cph\")), person(\"Marco\", \"Sciaini\", email = \"sciaini.marco@gmail.com\", role = c(\"ctb\", \"cph\")), person(\"Antônio Pedro\", \"Camargo\", role = c(\"ctb\", \"cph\")), person(\"Cédric\", \"Scherer\", email = \"scherer@izw-berlin.de\", role = c(\"ctb\", \"cph\")) )", "Maintainer": "Simon Garnier ", "Description": "Color maps designed to improve graph readability for readers with common forms of color blindness and/or color vision deficiency. The color maps are also perceptually-uniform, both in regular form and also when converted to black-and-white for printing. This is the 'lite' version of the 'viridis' package that also contains 'ggplot2' bindings for discrete and continuous color and fill scales and can be found at .", @@ -2512,23 +4538,23 @@ ], "URL": "https://sjmgarnier.github.io/viridisLite/, https://github.com/sjmgarnier/viridisLite/", "BugReports": "https://github.com/sjmgarnier/viridisLite/issues/", - "RoxygenNote": "7.2.3", + "RoxygenNote": "7.3.3", "NeedsCompilation": "no", "Author": "Simon Garnier [aut, cre], Noam Ross [ctb, cph], Bob Rudis [ctb, cph], Marco Sciaini [ctb, cph], Antônio Pedro Camargo [ctb, cph], Cédric Scherer [ctb, cph]", "Repository": "CRAN" }, "vroom": { "Package": "vroom", - "Version": "1.6.5", + "Version": "1.7.1", "Source": "Repository", "Title": "Read and Write Rectangular Text Data Quickly", - "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Shelby\", \"Bearrows\", role = \"ctb\"), person(\"https://github.com/mandreyel/\", role = \"cph\", comment = \"mio library\"), person(\"Jukka\", \"Jylänki\", role = \"cph\", comment = \"grisu3 implementation\"), person(\"Mikkel\", \"Jørgensen\", role = \"cph\", comment = \"grisu3 implementation\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Authors@R": "c( person(\"Jim\", \"Hester\", role = \"aut\", comment = c(ORCID = \"0000-0002-2739-7082\")), person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"aut\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Jennifer\", \"Bryan\", , \"jenny@posit.co\", role = c(\"aut\", \"cre\"), comment = c(ORCID = \"0000-0002-6983-2759\")), person(\"Shelby\", \"Bearrows\", role = \"ctb\"), person(\"https://github.com/mandreyel/\", role = \"cph\", comment = \"mio library\"), person(\"Jukka\", \"Jylänki\", role = \"cph\", comment = \"grisu3 implementation\"), person(\"Mikkel\", \"Jørgensen\", role = \"cph\", comment = \"grisu3 implementation\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", "Description": "The goal of 'vroom' is to read and write data (like 'csv', 'tsv' and 'fwf') quickly. When reading it uses a quick initial indexing step, then reads the values lazily , so only the data you actually use needs to be read. The writer formats the data in parallel and writes to disk asynchronously from formatting.", "License": "MIT + file LICENSE", - "URL": "https://vroom.r-lib.org, https://github.com/tidyverse/vroom", + "URL": "https://vroom.tidyverse.org, https://github.com/tidyverse/vroom", "BugReports": "https://github.com/tidyverse/vroom/issues", "Depends": [ - "R (>= 3.6)" + "R (>= 4.1)" ], "Imports": [ "bit64", @@ -2538,7 +4564,7 @@ "hms", "lifecycle (>= 1.0.3)", "methods", - "rlang (>= 0.4.2)", + "rlang (>= 1.1.0)", "stats", "tibble (>= 2.0.0)", "tidyselect", @@ -2571,19 +4597,21 @@ ], "LinkingTo": [ "cpp11 (>= 0.2.0)", - "progress (>= 1.2.1)", + "progress (>= 1.2.3)", "tzdb (>= 0.1.1)" ], "VignetteBuilder": "knitr", "Config/Needs/website": "nycflights13, tidyverse/tidytemplate", "Config/testthat/edition": "3", "Config/testthat/parallel": "false", + "Config/usethis/last-upkeep": "2025-11-25", "Copyright": "file COPYRIGHTS", "Encoding": "UTF-8", "Language": "en-US", - "RoxygenNote": "7.2.3.9000", + "RoxygenNote": "7.3.3", + "Config/build/compilation-database": "true", "NeedsCompilation": "yes", - "Author": "Jim Hester [aut] (), Hadley Wickham [aut] (), Jennifer Bryan [aut, cre] (), Shelby Bearrows [ctb], https://github.com/mandreyel/ [cph] (mio library), Jukka Jylänki [cph] (grisu3 implementation), Mikkel Jørgensen [cph] (grisu3 implementation), Posit Software, PBC [cph, fnd]", + "Author": "Jim Hester [aut] (ORCID: ), Hadley Wickham [aut] (ORCID: ), Jennifer Bryan [aut, cre] (ORCID: ), Shelby Bearrows [ctb], https://github.com/mandreyel/ [cph] (mio library), Jukka Jylänki [cph] (grisu3 implementation), Mikkel Jørgensen [cph] (grisu3 implementation), Posit Software, PBC [cph, fnd] (ROR: )", "Maintainer": "Jennifer Bryan ", "Repository": "CRAN" }, @@ -2627,7 +4655,7 @@ }, "xfun": { "Package": "xfun", - "Version": "0.51", + "Version": "0.57", "Source": "Repository", "Type": "Package", "Title": "Supporting Functions for Packages Maintained by 'Yihui Xie'", @@ -2649,35 +4677,33 @@ "rstudioapi", "tinytex (>= 0.30)", "mime", - "litedown (>= 0.4)", + "litedown (>= 0.6)", "commonmark", - "knitr (>= 1.47)", + "knitr (>= 1.50)", "remotes", "pak", - "rhub", - "renv", "curl", "xml2", "jsonlite", "magick", "yaml", - "qs", - "rmarkdown" + "data.table", + "qs2" ], "License": "MIT + file LICENSE", "URL": "https://github.com/yihui/xfun", "BugReports": "https://github.com/yihui/xfun/issues", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", + "RoxygenNote": "7.3.3", "VignetteBuilder": "litedown", "NeedsCompilation": "yes", - "Author": "Yihui Xie [aut, cre, cph] (, https://yihui.org), Wush Wu [ctb], Daijiang Li [ctb], Xianying Tan [ctb], Salim Brüggemann [ctb] (), Christophe Dervieux [ctb]", + "Author": "Yihui Xie [aut, cre, cph] (ORCID: , URL: https://yihui.org), Wush Wu [ctb], Daijiang Li [ctb], Xianying Tan [ctb], Salim Brüggemann [ctb] (ORCID: ), Christophe Dervieux [ctb]", "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, "xml2": { "Package": "xml2", - "Version": "1.3.8", + "Version": "1.5.2", "Source": "Repository", "Title": "Parse XML", "Authors@R": "c( person(\"Hadley\", \"Wickham\", role = \"aut\"), person(\"Jim\", \"Hester\", role = \"aut\"), person(\"Jeroen\", \"Ooms\", email = \"jeroenooms@gmail.com\", role = c(\"aut\", \"cre\")), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\")), person(\"R Foundation\", role = \"ctb\", comment = \"Copy of R-project homepage cached as example\") )", @@ -2698,7 +4724,6 @@ "curl", "httr", "knitr", - "magrittr", "mockery", "rmarkdown", "testthat (>= 3.2.0)", @@ -2707,7 +4732,7 @@ "VignetteBuilder": "knitr", "Config/Needs/website": "tidyverse/tidytemplate", "Encoding": "UTF-8", - "RoxygenNote": "7.2.3", + "RoxygenNote": "7.3.3", "SystemRequirements": "libxml2: libxml2-dev (deb), libxml2-devel (rpm)", "Collate": "'S4.R' 'as_list.R' 'xml_parse.R' 'as_xml_document.R' 'classes.R' 'format.R' 'import-standalone-obj-type.R' 'import-standalone-purrr.R' 'import-standalone-types-check.R' 'init.R' 'nodeset_apply.R' 'paths.R' 'utils.R' 'xml2-package.R' 'xml_attr.R' 'xml_children.R' 'xml_document.R' 'xml_find.R' 'xml_missing.R' 'xml_modify.R' 'xml_name.R' 'xml_namespaces.R' 'xml_node.R' 'xml_nodeset.R' 'xml_path.R' 'xml_schema.R' 'xml_serialize.R' 'xml_structure.R' 'xml_text.R' 'xml_type.R' 'xml_url.R' 'xml_write.R' 'zzz.R'", "Config/testthat/edition": "3", @@ -2718,22 +4743,57 @@ }, "yaml": { "Package": "yaml", - "Version": "2.3.10", + "Version": "2.3.12", "Source": "Repository", "Type": "Package", "Title": "Methods to Convert R Data to YAML and Back", - "Date": "2024-07-22", + "Authors@R": "c( person(\"Hadley\", \"Wickham\", , \"hadley@posit.co\", role = \"cre\", comment = c(ORCID = \"0000-0003-4757-117X\")), person(\"Shawn\", \"Garbett\", , \"shawn.garbett@vumc.org\", role = \"ctb\", comment = c(ORCID = \"0000-0003-4079-5621\")), person(\"Jeremy\", \"Stephens\", role = c(\"aut\", \"ctb\")), person(\"Kirill\", \"Simonov\", role = \"aut\"), person(\"Yihui\", \"Xie\", role = \"ctb\", comment = c(ORCID = \"0000-0003-0645-5666\")), person(\"Zhuoer\", \"Dong\", role = \"ctb\"), person(\"Jeffrey\", \"Horner\", role = \"ctb\"), person(\"reikoch\", role = \"ctb\"), person(\"Will\", \"Beasley\", role = \"ctb\", comment = c(ORCID = \"0000-0002-5613-5006\")), person(\"Brendan\", \"O'Connor\", role = \"ctb\"), person(\"Michael\", \"Quinn\", role = \"ctb\"), person(\"Charlie\", \"Gao\", role = \"ctb\"), person(c(\"Gregory\", \"R.\"), \"Warnes\", role = \"ctb\"), person(c(\"Zhian\", \"N.\"), \"Kamvar\", role = \"ctb\") )", + "Description": "Implements the 'libyaml' 'YAML' 1.1 parser and emitter () for R.", + "License": "BSD_3_clause + file LICENSE", + "URL": "https://yaml.r-lib.org, https://github.com/r-lib/yaml/", + "BugReports": "https://github.com/r-lib/yaml/issues", "Suggests": [ - "RUnit" + "knitr", + "rmarkdown", + "testthat (>= 3.0.0)" ], - "Author": "Shawn P Garbett [aut], Jeremy Stephens [aut, cre], Kirill Simonov [aut], Yihui Xie [ctb], Zhuoer Dong [ctb], Hadley Wickham [ctb], Jeffrey Horner [ctb], reikoch [ctb], Will Beasley [ctb], Brendan O'Connor [ctb], Gregory R. Warnes [ctb], Michael Quinn [ctb], Zhian N. Kamvar [ctb], Charlie Gao [ctb]", - "Maintainer": "Shawn Garbett ", - "License": "BSD_3_clause + file LICENSE", - "Description": "Implements the 'libyaml' 'YAML' 1.1 parser and emitter () for R.", - "URL": "https://github.com/vubiostat/r-yaml/", - "BugReports": "https://github.com/vubiostat/r-yaml/issues", + "Config/testthat/edition": "3", + "Config/Needs/website": "tidyverse/tidytemplate", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.3", + "VignetteBuilder": "knitr", "NeedsCompilation": "yes", + "Author": "Hadley Wickham [cre] (ORCID: ), Shawn Garbett [ctb] (ORCID: ), Jeremy Stephens [aut, ctb], Kirill Simonov [aut], Yihui Xie [ctb] (ORCID: ), Zhuoer Dong [ctb], Jeffrey Horner [ctb], reikoch [ctb], Will Beasley [ctb] (ORCID: ), Brendan O'Connor [ctb], Michael Quinn [ctb], Charlie Gao [ctb], Gregory R. Warnes [ctb], Zhian N. Kamvar [ctb]", + "Maintainer": "Hadley Wickham ", "Repository": "CRAN" + }, + "zip": { + "Package": "zip", + "Version": "2.3.3", + "Source": "Repository", + "Title": "Cross-Platform 'zip' Compression", + "Authors@R": "c( person(\"Gábor\", \"Csárdi\", , \"csardi.gabor@gmail.com\", role = c(\"aut\", \"cre\")), person(\"Kuba\", \"Podgórski\", role = \"ctb\"), person(\"Rich\", \"Geldreich\", role = \"ctb\"), person(\"Posit Software, PBC\", role = c(\"cph\", \"fnd\"), comment = c(ROR = \"03wc8by49\")) )", + "Description": "Cross-Platform 'zip' Compression Library. A replacement for the 'zip' function, that does not require any additional external tools on any platform.", + "License": "MIT + file LICENSE", + "URL": "https://github.com/r-lib/zip, https://r-lib.github.io/zip/", + "BugReports": "https://github.com/r-lib/zip/issues", + "Suggests": [ + "covr", + "pillar", + "processx", + "R6", + "testthat", + "withr" + ], + "Config/Needs/website": "tidyverse/tidytemplate", + "Config/testthat/edition": "3", + "Config/usethis/last-upkeep": "2025-05-07", + "Encoding": "UTF-8", + "RoxygenNote": "7.3.2.9000", + "NeedsCompilation": "yes", + "Author": "Gábor Csárdi [aut, cre], Kuba Podgórski [ctb], Rich Geldreich [ctb], Posit Software, PBC [cph, fnd] (ROR: )", + "Maintainer": "Gábor Csárdi ", + "Repository": "RSPM" } } } diff --git a/tests/test_course_project.py b/tests/test_course_project.py new file mode 100644 index 0000000..84aac83 --- /dev/null +++ b/tests/test_course_project.py @@ -0,0 +1,163 @@ +from __future__ import annotations + +import importlib.util +import json +from pathlib import Path +import subprocess +import tempfile +import unittest +from unittest import mock + + +ROOT = Path(__file__).resolve().parents[1] +SPEC = importlib.util.spec_from_file_location( + "create_course_project", ROOT / "bin" / "create_course_project.py" +) +assert SPEC and SPEC.loader +course_project = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(course_project) + + +def git(target: Path, *args: str, check: bool = True) -> subprocess.CompletedProcess[str]: + return subprocess.run( + ["git", *args], + cwd=target, + check=check, + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + + +class CourseProjectTest(unittest.TestCase): + def setUp(self) -> None: + self.temporary = tempfile.TemporaryDirectory() + self.root = Path(self.temporary.name) + + def tearDown(self) -> None: + self.temporary.cleanup() + + def make(self, state: str) -> Path: + target = self.root / state + course_project.copy_starter(target) + course_project.build_local_state(target, state) + return target + + def test_starter_matches_manifest_and_has_no_commits(self) -> None: + target = self.make("starter") + expected = json.loads(course_project.MANIFEST.read_text(encoding="utf-8")) + actual = { + item.relative_to(target).as_posix() + for item in target.rglob("*") + if item.is_file() and ".git" not in item.relative_to(target).parts + } + self.assertEqual(set(expected), actual) + self.assertNotEqual(git(target, "rev-parse", "--verify", "HEAD", check=False).returncode, 0) + self.assertIn("?? analysis.qmd", git(target, "status", "--short").stdout) + self.assertTrue((target / "penguins.R").exists()) + self.assertTrue((target / "tables.qmd").exists()) + + def test_clean_states_have_expected_branch_and_history(self) -> None: + expected = { + "baseline": ("main", 1), + "paper": ("main", 2), + "histogram": ("main", 3), + "boxplot-branch": ("boxplot", 4), + "merged": ("main", 6), + } + for state, (branch, commits) in expected.items(): + with self.subTest(state=state): + target = self.make(state) + self.assertEqual(git(target, "branch", "--show-current").stdout.strip(), branch) + self.assertEqual(int(git(target, "rev-list", "--count", "--all").stdout), commits) + self.assertEqual(git(target, "status", "--porcelain").stdout, "") + + def test_paper_uses_quarto_data_path_and_base_pipe(self) -> None: + target = self.make("histogram") + paper = (target / "paper.qmd").read_text(encoding="utf-8") + self.assertIn('read.csv("data/penguins.csv")', paper) + self.assertIn("|>", paper) + self.assertNotIn("%>%", paper) + self.assertFalse((target / "paper.R").exists()) + + def test_dirty_main_contains_only_uncommitted_paper_change(self) -> None: + target = self.make("dirty-main") + self.assertEqual(git(target, "branch", "--show-current").stdout.strip(), "main") + self.assertEqual(git(target, "status", "--short").stdout, " M paper.qmd\n") + + def test_conflict_is_an_unfinished_merge_in_paper(self) -> None: + target = self.make("conflict") + self.assertTrue((target / ".git" / "MERGE_HEAD").exists()) + self.assertIn("UU paper.qmd", git(target, "status", "--short").stdout) + paper = (target / "paper.qmd").read_text(encoding="utf-8") + self.assertIn("<<<<<<< HEAD", paper) + self.assertIn(">>>>>>> boxplot", paper) + + def test_merged_state_has_merge_commit(self) -> None: + target = self.make("merged") + parents = git(target, "show", "-s", "--format=%P", "HEAD").stdout.split() + self.assertEqual(len(parents), 2) + self.assertIn('boxplot(x, ylab = "Bill length, mm")', (target / "paper.qmd").read_text()) + + def test_webhook_request_uses_pull_request_event(self) -> None: + with mock.patch.object(course_project, "run") as mocked_run: + course_project.add_webhook("owner/repo", "https://example.test/hook", "secret") + command = mocked_run.call_args.args[0] + self.assertIn("repos/owner/repo/hooks", command) + self.assertIn("events[]=pull_request", command) + self.assertIn("config[secret]=secret", command) + + def test_github_login_uses_browser_when_status_fails(self) -> None: + failed = subprocess.CompletedProcess([], 1) + passed = subprocess.CompletedProcess([], 0) + with mock.patch.object(course_project.shutil, "which", return_value="/usr/bin/gh"), mock.patch.object( + course_project, "run", side_effect=(failed, passed, passed) + ) as mocked_run, mock.patch("builtins.print"): + course_project.ensure_gh_auth() + self.assertEqual( + mocked_run.call_args_list[1].args[0], + ["gh", "auth", "login", "--web", "-h", "github.com", "-p", "https"], + ) + + def test_publish_starts_remote_from_main_and_restores_branch(self) -> None: + target = self.make("merged") + git(target, "switch", "-c", "adjust-by-sex") + completed = subprocess.CompletedProcess([], 0, stdout="adjust-by-sex\n", stderr="") + with mock.patch.object(course_project, "run", wraps=course_project.run) as mocked_run: + mocked_run.side_effect = [ + completed, + subprocess.CompletedProcess([], 0, stdout="", stderr=""), + subprocess.CompletedProcess([], 0, stdout="", stderr=""), + subprocess.CompletedProcess([], 0, stdout="", stderr=""), + subprocess.CompletedProcess([], 0, stdout="", stderr=""), + ] + course_project.publish_repository(target, "owner/repo", "private") + commands = [call.args[0] for call in mocked_run.call_args_list] + self.assertEqual(commands[1], ["git", "switch", "main"]) + self.assertIn(["git", "switch", "adjust-by-sex"], commands) + + def test_remote_preflight_distinguishes_missing_from_network_error(self) -> None: + missing = subprocess.CompletedProcess([], 1, stdout="", stderr="GraphQL: Could not resolve to a Repository") + offline = subprocess.CompletedProcess([], 1, stdout="", stderr="network is unreachable") + with mock.patch.object(course_project, "run", return_value=missing): + course_project.ensure_remote_absent("owner/missing") + with mock.patch.object(course_project, "run", return_value=offline): + with self.assertRaises(course_project.CourseProjectError): + course_project.ensure_remote_absent("owner/unknown") + + def test_github_webhook_requires_url_before_authentication(self) -> None: + with mock.patch.object(course_project, "ensure_gh_auth") as auth: + result = course_project.main( + [str(self.root / "webhook"), "--state", "github-webhook", "--repo", "owner/repo"] + ) + self.assertEqual(result, 1) + auth.assert_not_called() + + def test_refuses_existing_target(self) -> None: + target = self.root / "existing" + target.mkdir() + self.assertEqual(course_project.main([str(target), "--state", "starter"]), 1) + + +if __name__ == "__main__": + unittest.main() From be7f58e1a34d5315a29166ce9da22bae71355744 Mon Sep 17 00:00:00 2001 From: Kirill Voronin Date: Wed, 26 Aug 2026 15:37:18 +0300 Subject: [PATCH 02/24] =?UTF-8?q?=D0=92=D0=B5=D1=80=D0=BD=D1=83=D0=BB=20?= =?UTF-8?q?=D0=B8=D1=81=D1=85=D0=BE=D0=B4=D0=BD=D1=8B=D0=B9=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D1=81=D1=82=20=D0=BA=D1=83=D1=80=D1=81=D0=B0=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20Positron?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 01-01-about.Rmd | 61 +++-- 01-02-install.Rmd | 62 +++-- 01-03-shell.Rmd | 40 +++- 02-01-init.Rmd | 53 ++-- 02-02-commit.Rmd | 55 +++-- 02-03-practice.Rmd | 126 ++++++++-- 02-04-log-n-diff.Rmd | 44 ++-- 03-01-branches.Rmd | 65 ++++- 03-02-checkout.Rmd | 38 +-- 03-03-merge.Rmd | 98 ++++++-- 03-04-conclusion.Rmd | 65 +++-- 04-01-github.Rmd | 30 ++- 04-02-remote.Rmd | 38 +-- 04-03-push-pull.Rmd | 77 ++++-- 04-04-pull-request.Rmd | 50 ++-- 04-05-clone.Rmd | 30 ++- 04-06-conclusion.Rmd | 23 +- 05-01-faq.Rmd | 60 +++-- 05-02-references.Rmd | 29 +-- 05-03-webhooks.Rmd | 32 +-- bin/check_course.py | 12 +- docs/01-01-about.md | 49 ++-- docs/01-02-install.md | 62 +++-- docs/01-03-shell.md | 40 +++- docs/02-01-init.md | 53 ++-- docs/02-02-commit.md | 51 ++-- docs/02-03-practice.md | 115 +++++++-- docs/02-04-log-n-diff.md | 39 +-- docs/03-01-branches.md | 62 ++++- docs/03-02-checkout.md | 39 +-- docs/03-03-merge.md | 93 +++++-- docs/03-04-conclusion.md | 65 +++-- docs/04-01-github.md | 30 ++- docs/04-02-remote.md | 33 +-- docs/04-03-push-pull.md | 73 ++++-- docs/04-04-pull-request.md | 50 ++-- docs/04-05-clone.md | 30 ++- docs/04-06-conclusion.md | 23 +- docs/05-01-faq.md | 60 +++-- docs/05-02-references.md | 29 +-- docs/05-03-webhooks.md | 32 +-- docs/404.html | 47 ++-- docs/about-git.html | 142 ----------- docs/about.html | 139 +++++++++++ docs/branch.html | 135 +++++++++++ docs/branches-conclusion.html | 134 ----------- docs/branches.html | 134 ----------- docs/clone-repository.html | 129 ---------- docs/commit-workflow.html | 166 ------------- docs/faq.html | 147 ++++++------ docs/first-commit.html | 152 ------------ docs/git-branch.html | 150 ++++++++++++ docs/git-checkout.html | 144 +++++++++++ docs/git-clone.html | 135 +++++++++++ docs/git-commit.html | 152 ++++++++++++ docs/git-commit2.html | 226 ++++++++++++++++++ docs/git-identity.html | 126 ---------- docs/git-init.html | 152 ++++++++++++ docs/git-log.html | 145 +++++++++++ docs/git-merge.html | 187 +++++++++++++++ docs/git-push-pull.html | 167 +++++++++++++ docs/git-remote.html | 136 +++++++++++ docs/github-conclusion.html | 128 ---------- docs/github-part.html | 134 ----------- docs/github.html | 145 +++++++++++ docs/history-diff.html | 159 ------------ docs/index.html | 103 ++++---- docs/index.md | 57 +++-- docs/install-git.html | 147 ------------ docs/install.html | 166 +++++++++++++ docs/merge-conflict.html | 149 ------------ docs/open-project.html | 140 ----------- docs/pr.html | 165 +++++++++++++ docs/publish-github.html | 132 ---------- docs/pull-request.html | 167 ------------- docs/reference-keys.txt | 82 +++---- docs/references.html | 129 ++++------ docs/search.json | 2 +- docs/setup.html | 140 +++++++++++ docs/switch-branches.html | 137 ----------- docs/sync-remote.html | 162 ------------- docs/webhooks.html | 103 ++++---- ...07\320\265\320\275\320\270\320\265-1.html" | 131 ++++++++++ ...\207\320\265\320\275\320\270\320\265.html" | 176 ++++++++++++++ index.Rmd | 67 ++++-- packages.bib | 10 +- 86 files changed, 4672 insertions(+), 3420 deletions(-) delete mode 100644 docs/about-git.html create mode 100644 docs/about.html create mode 100644 docs/branch.html delete mode 100644 docs/branches-conclusion.html delete mode 100644 docs/branches.html delete mode 100644 docs/clone-repository.html delete mode 100644 docs/commit-workflow.html delete mode 100644 docs/first-commit.html create mode 100644 docs/git-branch.html create mode 100644 docs/git-checkout.html create mode 100644 docs/git-clone.html create mode 100644 docs/git-commit.html create mode 100644 docs/git-commit2.html delete mode 100644 docs/git-identity.html create mode 100644 docs/git-init.html create mode 100644 docs/git-log.html create mode 100644 docs/git-merge.html create mode 100644 docs/git-push-pull.html create mode 100644 docs/git-remote.html delete mode 100644 docs/github-conclusion.html delete mode 100644 docs/github-part.html create mode 100644 docs/github.html delete mode 100644 docs/history-diff.html delete mode 100644 docs/install-git.html create mode 100644 docs/install.html delete mode 100644 docs/merge-conflict.html delete mode 100644 docs/open-project.html create mode 100644 docs/pr.html delete mode 100644 docs/publish-github.html delete mode 100644 docs/pull-request.html create mode 100644 docs/setup.html delete mode 100644 docs/switch-branches.html delete mode 100644 docs/sync-remote.html create mode 100644 "docs/\320\267\320\260\320\272\320\273\321\216\321\207\320\265\320\275\320\270\320\265-1.html" create mode 100644 "docs/\320\267\320\260\320\272\320\273\321\216\321\207\320\265\320\275\320\270\320\265.html" diff --git a/01-01-about.Rmd b/01-01-about.Rmd index f62ddb2..ef95fa7 100644 --- a/01-01-about.Rmd +++ b/01-01-about.Rmd @@ -1,28 +1,57 @@ -# (PART) Подготовка {-} +# (PART) Введение {-} -# Зачем проекту Git {#about-git} +# Что такое Git {#about} -В проекте анализа данных меняются код, текст отчёта и графики. Копии с названиями `final`, `final-2` и `really-final` сохраняют файлы, но не объясняют, кто и зачем их менял. +**Git** --- это программа, выполняющая функции **Системы Контроля Версий (VCS, Version Control System)**. +Многие применяют простую систему контроля версий, вручную копируя файлы и добавляя дату в названия. +Git автоматически отслеживает изменения во время редактирования файлов, позволяет фиксировать состояние файлов в версии, хранить и переключаться между ними. +Вы сможете оценить, какие изменения внесли, а также посмотреть историю изменений --- когда, кем и с какой целью они были сделаны. -Git хранит **коммиты** — снимки выбранных изменений с коротким пояснением. Из них складывается история проекта. По ней можно: +```{r, include=FALSE} +# Очевидно ли, зачем оценивать какие изменения внесли или нужно расписать, +# что работать надо над конкретной задачей, а не хаотично редактировать код. +``` -- сравнить текущую работу с предыдущей версией; -- вернуть исправный вариант; -- вести несколько вариантов анализа в ветках; -- объединять изменения разных участников. +::: {.text-center} +![Пример ручного хранения нескольких версий одного файла](./img/notFinal.gif){width=400px style="border: 1px solid #ddd"} +::: -Git работает локально. Для коммитов не нужны интернет и аккаунт. GitHub понадобится позже как удалённое место для общей истории и обсуждения изменений. +Важная особенность Git в том, что участники могут работать и создавать версии независимо друг от друга на своих компьютерах. Каждый может работать над своей задачей, не мешая другим, даже если все редактируют один и тот же файл. Git поможет объединить изменения в одну общую версию. -## Что уже есть в проекте +```{r, include=FALSE} +# Особенность звучит так себе, но ветки это реально основная фича Git. +# Должно быть согласовано с этим же тезисом в предыдущей главе. +``` -Откройте папку `r-course`, созданную в предыдущем курсе. Не создавайте новый учебный проект и не переносите файлы. +Проект Git можно загрузить на сервер для надежного хранения и передачи файлов, совместной работы и публикации. +Самым популярным сервисом для этого является GitHub. +Он похож на облачные хранилища, такие как Google Drive или Dropbox, но с более продвинутым отслеживанием и объединением изменений, а также другими полезными функциями. +Вместо GitHub можно использовать другой сервер, например корпоративный во внутренней сети организации или использовать Git оффлайн --- только на своем компьютере. -В проекте могут оставаться `.R`-скрипты, `report.qmd`, `analysis.qmd`, другие документы, папки `data` и `out`. Это ожидаемое состояние. Git умеет отслеживать любые файлы; расширение не нужно менять ради Git. +```{r, include=FALSE} +# Расписать "другими полезными функциями". +``` -Новый код этого курса будем писать в `paper.qmd`. Так текст, команды R и результат останутся в одном воспроизводимом документе Quarto. +Если это всё ещё не убедило вас начать использовать Git, вот несколько примеров, когда он будет полезен: -## Репозиторий +```{r, include=FALSE} +# Два раза "использовать Git". +``` -**Репозиторий** — папка проекта вместе со скрытой служебной папкой `.git`. В `.git` находится история, ветки и настройки связи с удалённым репозиторием. -Шаблон R Project в Positron создаёт `.git` и `.gitignore` автоматически. Поэтому проект из R-курса уже должен быть репозиторием, хотя в нём пока нет коммитов. В главе \@ref(open-project) мы это проверим. +- Возможно, вы оказывались в следующей ситуации. Вы вносите изменения в работающую программу или файл. Оцениваете результат и решаете отменить изменения. Вот только у вас нет копии оригинального файла, а вернуть прежнее состояние почему-то не получается --- программа никак не работает или работает иначе. С Git это делается одной командой, а экспериментальную версию можно сохранить и вернуться к ней позже. + +- Если вам понадобилась помощь, вы можете одной командой загрузить сделанные изменения на GitHub. Другой участник увидит, что вы пытаетесь сделать, и может загрузить решение проблемы, а вы так же одной командой получите исправленную версию. + +Благодаря последовательному внесению и отслеживанию изменений Git помогает организовать процесс анализа данных, обеспечивает воспроизводимость и упрощает совместную работу над проектом. + +```{r, include=FALSE} +# Как-будто из текста выше этого все еще не следует. +``` + +::: {.callout .callout-info} + +Существуют другие системы контроля версий, например Mercurial и Subversion и вероятно, в будущем появятся новые. +Но благодаря простоте, эффективности и приобретенной популярности в основном используется Git. + +::: diff --git a/01-02-install.Rmd b/01-02-install.Rmd index 6ca85eb..94160e6 100644 --- a/01-02-install.Rmd +++ b/01-02-install.Rmd @@ -1,27 +1,59 @@ -# Установка Git {#install-git} +# Установка {#install} -Positron предоставляет интерфейс Source Control, но использует Git, установленный в операционной системе. Если Git не найден, Source Control покажет предложение его установить. Такое поведение описано в официальной главе [Git Version Control](https://positron.posit.co/git.html). +## Проверьте наличие Git {#terminal} -## Проверка +В комплекте с дистрибутивом Git устанавливается программа для терминала. +Чтобы открыть терминал в Positron, вызовите палитру команд и выберите **Terminal: Create New Terminal**. +В появившемся окне терминала введите команду `git` и нажмите клавишу Enter. -Откройте встроенный терминал командой **Terminal: Create New Terminal** из палитры команд и выполните: +Если вы видите результат как на скриншоте ниже, то Git установлен. +Иначе нужно его установить --- см. инструкцию для вашей операционной системы ниже. +После установки перезапустите Positron и повторите проверку. + +![Терминал Positron после команды git: показана справка с доступными командами. Чтобы получить состояние, выполните git в новом терминале]() + +## Windows + +Загрузите инсталлятор по ссылке [git-scm.com/downloads/win](https://git-scm.com/downloads/win) +(используйте **Standalone**, а не **Portable** версию, если в этом нет необходимости), запустите и следуйте инструкциям на экране, можете везде оставить опции, выбранные по умолчанию. + +## Mac OS + +**Вариант 1.** Git входит в инструменты разработчика от Apple, которые предоставляются бесплатно. Для установки введите в терминал следующую команду: ```sh -git --version +xcode-select --install ``` -Если команда вывела строку вида `git version 2.45.2`, установка готова. Конкретный номер может отличаться. +В появившемся окне нажмите кнопку **Install**. -![Терминал Positron после проверки версии Git: видна строка с установленной версией]() +**Вариант 2.** Последнюю версию Git можно установить используя сторонний менеджер программ [Homebrew](https://brew.sh). Если он у вас установлен, введите в терминал следующую команду: -## Если Git не установлен +```sh +brew install git +``` + +## Linux -- **Windows:** установите [Git for Windows](https://git-scm.com/download/win), оставив параметры установщика по умолчанию. -- **macOS:** установите [Xcode Command Line Tools](https://developer.apple.com/xcode/resources/) по предложению системы после команды `git --version` или установите Git с [официальной страницы](https://git-scm.com/download/mac). -- **Linux:** используйте менеджер пакетов своего дистрибутива; команды приведены в [официальной инструкции Git](https://git-scm.com/download/linux). +Используйте в терминале одну из следующих команд, в зависимости от вашего дистрибутива Linux. -После установки полностью перезапустите Positron и снова выполните `git --version`. +**Ubuntu или Debian** + +```sh +sudo apt-get update +sudo apt-get install git +``` + +**Fedora** + +```sh +sudo dnf install git +``` + +**Arch Linux** + +```sh +sudo pacman -S git +``` -::: {.callout .callout-warning} -Не скачивайте отдельные графические клиенты Git для прохождения курса. Они могут пригодиться позже, но названия действий и расположение элементов будут отличаться от Positron. -::: +Для других дистрибутивов см. [git-scm.com/downloads/linux](https://git-scm.com/downloads/linux). Не забудьте, что команды нужно запускать с правами администратора, т.е. начав с `sudo`, как в примере выше. diff --git a/01-03-shell.Rmd b/01-03-shell.Rmd index 8bc0e63..e7d8ff0 100644 --- a/01-03-shell.Rmd +++ b/01-03-shell.Rmd @@ -1,21 +1,41 @@ -# Имя автора {#git-identity} +# Настройка {#setup} -Каждый коммит хранит имя и электронную почту автора. При первом коммите Positron может попросить их настроить. Укажите имя, по которому коллеги вас узнают, и почту, связанную с GitHub. +Основной способ работы с Git --- это команда `git`, которую мы выполнили в предыдущей главе. +Команды для терминала вы встретите в документации и в интернете, ими легко поделиться и использовать в скриптах. +Кроме терминала есть много других способов и их даже можно использовать одновременно. -Если интерфейс показал ошибку `Please tell me who you are`, откройте терминал и выполните две команды, заменив значения своими: +Графические интерфейсы --- все они имеют ограничения и реализуют только часть возможностей Git, но достаточны для решения большинства задач. Это может быть интерфейс, встроенный в другие программы (например [Positron](https://positron.posit.co/git.html), [Pycharm](https://www.jetbrains.com/help/pycharm/using-git-integration.html), [VS Code](https://code.visualstudio.com/docs/sourcecontrol/overview)) или самостоятельная программа (например [GitHub Desktop](https://github.com/apps/desktop), [GitKraken](https://www.gitkraken.com) [и многие другие](https://git-scm.com/downloads/guis)); + +Веб-интерфейсы --- прямо на сайте GitHub можно редактировать отдельные файлы, а также выполнять некоторые команды. + +В этом курсе мы будем работать с Git одновременно в интерфейсе Positron и в терминале, как это делает большинство пользователей R каждый день, а также через GitHub. +Поэтому запомните, как запустить терминал в Positron --- +в палитре команд выберите **Terminal: Create New Terminal** ([см. скриншот в предыдущей главе](#terminal)). + +Перед началом работы необходимо сделать несколько настроек. +Укажите свое имя и адрес электронной почты, чтобы Git верно записывал информацию об авторе изменений. +В терминале выполните следующие команды, заменив **Your Name** на свое имя и **your@email.com** на свой email, не стирая кавычки. + +```sh +git config --global user.name "Your Name" +git config --global user.email "your@email.com" +``` + +Если вы уже использовали Git, то чтобы вывести в терминале текущее значение настроек выполните эти же команды, но не указывая новых значений. ```sh -git config --global user.name "Ivan Ivanov" -git config --global user.email "ivan@example.org" +git config --global user.name +git config --global user.email ``` -Проверьте результат: +Также заранее настроим способ объединения изменений, чтобы не возвращаться к этому позже. ```sh -git config --global --get user.name -git config --global --get user.email +git config --global pull.rebase false ``` -Настройка `--global` применяется ко всем будущим проектам этого пользователя. Если рабочий проект требует другую почту, откройте его папку и повторите команды без `--global`: значение сохранится только в этом репозитории. +Опция `--global` означает, что эти настройки будут использованы для всех проектов на компьютере и их достаточно сделать один раз. +Чтобы изменить настройки для отдельного проекта, выполните в нем эти же команды без опции `--global`. Например, иногда требуется указать корпоративный email для рабочего проекта на персональном компьютере. -Пароль GitHub здесь не нужен. Вход в GitHub выполним в браузере в части \@ref(github-part). +Это все настройки, которые понадобятся для курса. +Всего через команду `git config` их доступно более 800. diff --git a/02-01-init.Rmd b/02-01-init.Rmd index 108ea5b..dbc0f0b 100644 --- a/02-01-init.Rmd +++ b/02-01-init.Rmd @@ -1,25 +1,50 @@ -# (PART) Коммиты {-} +# (PART) Основы {-} -# Открытие проекта {#open-project} +# Создание репозитория {#git-init} -На экране Welcome в Positron выберите **Open Folder** и откройте папку `r-course`. Убедитесь, что в Explorer видны накопленные файлы R-курса, в том числе папка `data`. +Git может отслеживать изменения в любой папке на вашем компьютере. +Для этого нужно инициализировать в ней Git репозиторий. +**Репозиторий** --- это скрытая подпапка `.git`, в которой хранятся версии проекта и информация об изменениях. +Всё необходимое для работы Git содержится непосредственно в ней. -Откройте **Source Control** на панели активности слева. У изменённых файлов стоят обозначения состояния: `U` у ещё не отслеживаемых и `M` у изменённых. +Проект для этого курса уже создан в конце курса R. Откройте Positron и на экране Welcome выберите [Open Folder]{.figtext}, затем укажите папку проекта `r-course`. +Не создавайте новый проект, не переносите и не переименовывайте накопленные файлы. -![Окно Positron с открытым проектом r-course: в Explorer видны накопленные файлы, а в Source Control перечислены незафиксированные изменения]() +Убедитесь в том, что проект загружен: в панели [Explorer]{.figtext} должна быть открыта папка с файлами проекта, в том числе с папкой `data`. +Откройте [Source Control]{.figtext} на панели активности. Если там уже перечислены файлы проекта, репозиторий готов. -Если Source Control уже показывает файлы, репозиторий готов. Не нажимайте **Initialize Repository** повторно и не удаляйте `.git`. +![Окно Positron с открытой папкой r-course: в Explorer видны накопленные файлы и папка data, а в Source Control перечислены незафиксированные файлы. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-starter --state starter]() -## Если репозитория нет +Когда в Positron открыта папка проекта, R и Git ищут файлы в ней --- это так называемая **рабочая папка или рабочая область**. -В старой версии R-курса проект мог быть создан без Git. Тогда Source Control покажет кнопку **Initialize Repository**. Нажмите её один раз. Positron создаст `.git` и начнёт показывать изменения. +
Подробнее про поиск и адреса файлов. +На разных компьютерах, например у разных участников, проект может находиться в разных местах. +У пользователя с именем `mjordan` это может быть `/Users/mjordan/penguins`, +а у пользователя `scruz` допустим +`C:\Users\scruz\penguins`. -Официальная документация Positron описывает те же шаги: открыть папку, перейти в Source Control и выбрать **Initialize Repository**. +Если в документе использовать полный адрес файла, например: -## Что сейчас видит Git +```r +read.csv("/Users/mjordan/r-course/data/penguins.csv") +``` -Все накопленные файлы ещё не входят ни в один коммит. Это не ошибка и не повод чистить проект. В следующей главе сделаем один исходный коммит, который станет точкой отсчёта для новой работы. +то он будет работать только у пользователя `mjordan`. +У других полный адрес будет отличаться, и код «сломается». +Чтобы он работал у всех, нужно указывать адрес файла относительно рабочей папки. -::: {.callout .callout-warning} -Не переводите старые `.R`-файлы в `.qmd`, не удаляйте дополнительные данные и не заменяйте результаты. Исходный коммит должен быть точной фиксацией конца R-курса. -::: +```r +read.csv("data/penguins.csv") +``` +
+ +Рассмотрим служебные файлы проекта: + +- `.gitignore` --- содержит список файлов, которые Git не будет отслеживать; о том, зачем это нужно и как настроить [смотри в отдельном разделе](#gitignore) +- `.git` --- репозиторий; это скрытая папка, в которой Git будет хранить версии проекта + +Если вместо списка файлов Source Control показывает кнопку [Initialize Repository]{.figtext}, нажмите её один раз. Positron создаст репозиторий в уже существующей папке, не меняя остальные файлы. + +Итак, у нас есть проект --- папка, в которой мы будем работать, и +внутри нее Git репозиторий --- скрытая папка, в которой будут храниться версии проекта. +Приступим к созданию первой версии. diff --git a/02-02-commit.Rmd b/02-02-commit.Rmd index ecef4c4..75fe0ce 100644 --- a/02-02-commit.Rmd +++ b/02-02-commit.Rmd @@ -1,35 +1,44 @@ -# Первый коммит {#first-commit} +# Отслеживание изменений {#git-commit} -Коммит состоит из снимка выбранных файлов, автора, времени и сообщения. Сначала файлы попадают в **индекс** (staging area), затем Git записывает из индекса коммит. +Git отслеживает изменения в файлах, находящихся в рабочей папке. +Но не все подряд, как это делают Блокнот или Word при помощи команд «Отменить» и «Повторить», +а при помощи версий --- или, в терминах Git, **коммитов (commit)**. +Коммиты нужно создавать вручную, выбирая, какие файлы вы хотите зафиксировать, добавив в версию. -## Проверка изменений +Откройте в Positron панель с названием [Source Control]{.figtext}. +В отличие от списка файлов, на ней выводятся только те файлы, которые были изменены по сравнению с последней версией (коммитом). +Так как мы еще не создали ни одной версии, то в списке выводятся все файлы, накопленные к концу курса R. -В Source Control выберите любой текстовый файл. Откроется редактор различий (diff). Для нового файла одна сторона сравнения пуста, а весь текст отмечен как добавленный. +![Панель Source Control в Positron до первого коммита: в разделе Changes перечислены все накопленные файлы проекта. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-first-commit --state starter]() -Бинарные файлы, например `.png`, `.xlsx` и `.rds`, Git сохранит, но не покажет построчное сравнение. Перед коммитом откройте их обычным способом и убедитесь, что это нужные файлы. +
Нет панели Git? +Значит, репозиторий не был создан или Git не установлен. +[Проверьте наличие Git](#install), затем вернитесь к [созданию репозитория](#git-init). +
-![Редактор различий Positron для нового текстового файла из проекта r-course и список Changes в Source Control]() +Чтобы создать коммит (версию), нажмите `+` напротив заголовка [Changes]{.figtext}. +После этого файлы окажутся в разделе [Staged Changes]{.figtext}, то есть будут добавлены в **индекс (staging)** --- +промежуточную область для выбора файлов, которые будут зафиксированы. +Файлы, оставшиеся в разделе [Changes]{.figtext}, будут находиться в рабочей папке, но в коммит не попадут. +Вы можете добавить их в следующую версию позже или отменить изменения. -## Добавление в индекс +![Source Control после добавления файлов в индекс: все файлы находятся в разделе Staged Changes. Подготовьте состояние starter и нажмите Stage All Changes]() -Наведите указатель на заголовок **Changes** и нажмите `+` (**Stage All Changes**). Файлы переместятся в раздел **Staged Changes**. +Перед фиксацией выберите несколько текстовых файлов и посмотрите, что изменилось в них. +Для нового файла Positron покажет весь текст как добавленный. +Введите краткое описание в поле сообщения коммита. +В нашем примере мы закончили курс R, это и будет подходящим описанием: `Зафиксировал результат курса R`. +Нажмите кнопку [Commit]{.figtext}. -Проверьте список ещё раз. В первый коммит должны войти все накопленные файлы проекта, кроме уже скрытых правилами `.gitignore`. +![Source Control перед первым коммитом: проверен diff, введено сообщение Зафиксировал результат курса R. Подготовьте состояние starter, добавьте все файлы в индекс и введите сообщение]() -## Запись коммита +Обратите внимание, теперь панель [Source Control]{.figtext} со списком измененных файлов пуста --- +это значит, что изменений по сравнению с последней версией, которую мы только что создали, нет. -Введите сообщение: +![Source Control сразу после первого коммита: разделы Changes и Staged Changes пусты. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-baseline --state baseline]() -```text -Зафиксировал результат курса R -``` - -Нажмите **Commit**. Если Positron попросит настроить автора, вернитесь к главе \@ref(git-identity). - -![Source Control сразу после исходного коммита: разделы Changes и Staged Changes пусты, в Graph виден один коммит]() +Теперь у нас есть версия проекта, к которой можно вернуться в любой момент и начать работу с этого места. -Пустой список изменений означает, что рабочая папка совпадает с последним коммитом. Старые файлы никуда не переместились: Git только записал их состояние. - -::: {.callout .callout-info} -Сообщение коммита отвечает на вопрос «что сделал этот шаг?». Короткая форма с глаголом помогает читать историю: «Добавил импорт данных», «Исправил подпись оси». -::: +```{r, include=FALSE} +# Заменить название главы на «Создание коммита» +``` diff --git a/02-03-practice.Rmd b/02-03-practice.Rmd index 8e34b76..07357dd 100644 --- a/02-03-practice.Rmd +++ b/02-03-practice.Rmd @@ -1,18 +1,36 @@ -# Рабочий цикл {#commit-workflow} +# Рабочий процесс {#git-commit2} -Теперь начнём отдельный анализ для Git-курса. Каждая небольшая законченная задача станет коммитом: +В предыдущей главе мы научились создавать коммиты (версии). +Работая с Git, это нужно делать регулярно --- +обычно после выполнения задачи или её части, +после внесения исправлений или просто чтобы зафиксировать изменения. +Коммит сохраняет «стабильную» версию проекта, к которой можно вернуться или сравнить с ней сделанные изменения. -1. изменить и сохранить файл; -2. открыть diff и проверить изменение; -3. добавить нужные файлы в индекс; -4. записать коммит; -5. убедиться, что Source Control снова пуст. +Рассмотрим процесс работы над проектом подробнее: -## Документ Quarto +1. Мы создали коммит, и с тех пор в рабочей папке не было изменений. +2. Выполняем задачу и добавляем нужные для ее решения изменения в индекс, а лишние, например код для отладки или временные файлы, удаляем. +3. Перед созданием коммита обязательно проверяем изменения, которые в него попадут. + Начинающие пользователи часто либо добавляют ненужный код, не относящийся к задаче, либо забывают добавить код, без которого не будет работать остальная часть проекта. +4. Создаём коммит и получаем чистую рабочую папку --- без изменений относительно нового коммита. + Можно переходить к следующей задаче. -Создайте в корне проекта файл `paper.qmd`. Накопленные `.R`-скрипты остаются без изменений, но весь новый код пишем в Quarto. +![Рабочий цикл Git: чистая рабочая папка, изменения, индекс, проверка и новый коммит](./img/02-02-06-workflow.png){width=540px} -Добавьте настройки и первый блок R: +Такой процесс помогает упорядочить внесение изменений и сделать результат воспроизводимым. +Он хорошо подходит для анализа данных, потому что его легко разделить на задачи, из которых получатся коммиты. +Попробуем сделать это на практике и продолжим анализ длины клюва антарктических пингвинов. +Каждая подглава этой главы соответствует одной задаче и завершается одним коммитом. + +## Импорт данных + +Данные уже находятся в файле `data/penguins.csv`, который вошёл в первый коммит. Не скачивайте и не переносите его. + +Создайте документ Quarto для анализа. В Positron выберите [New → New File]{.figtext}, затем [Quarto Document]{.figtext} и сохраните файл под названием `paper.qmd` в корне проекта. + +![Диалог New File в Positron с выбранным типом Quarto Document и открытый файл paper.qmd. Подготовьте состояние baseline и выполните New → New File → Quarto Document]() + +Добавьте в начало документа заголовок: ```yaml --- @@ -21,23 +39,58 @@ format: html --- ``` +Скопируйте следующий код для импорта данных в блок R и сохраните документ. +Выполните блок в Positron. +Если импорт данных работает, в консоли появится вектор из чисел. + ```{r, eval=FALSE} data <- read.csv("data/penguins.csv") x <- data$bill_len |> na.omit() x ``` -Путь начинается от корня проекта. Данные уже находятся в `data`, поэтому ничего скачивать и перекладывать не нужно. В новом коде используем базовую трубу `|>`. +Убедитесь, что файл `paper.qmd` появился на панели [Source Control]{.figtext}. +Добавьте его в индекс и создайте коммит с описанием «Добавил импорт данных в paper.qmd». +Перед коммитом обязательно проверьте содержимое `paper.qmd`, +так как часто пользователи забывают сохранить файл перед добавлением в индекс. + +![Source Control перед коммитом импорта: в Staged Changes находится paper.qmd и открыт его diff. Подготовьте состояние baseline, создайте paper.qmd по заданию и добавьте его в индекс]() + +После создания коммита список измененных файлов на панели [Source Control]{.figtext} должен быть пуст. -Выполните блок в текущей R-сессии. Positron передаст код из документа Quarto в Console. Убедитесь, что вектор `x` создан без ошибки. +## Визуализация -![Открытый paper.qmd после выполнения блока: в Console виден результат импорта data/penguins.csv]() +Анализ новых данных полезно начинать с исследования распределения. +Для этого присвоим данные с длиной клюва переменной `x` и построим несколько вариантов гистограммы с разной шириной столбца. +Сохраните приведённый ниже код в тот же файл, запустите и посмотрите графики. + +```{r, eval=FALSE} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() + +hist(x, breaks = seq(30, 60, 4)) +hist(x, breaks = seq(30, 60, 2)) +hist(x, breaks = seq(30, 60, 1)) +``` -Сохраните файл, проверьте diff и создайте коммит `Добавил импорт данных в paper.qmd`. +После сохранения файл `paper.qmd` снова появился в списке изменений на панели [Source Control]{.figtext}. +Добавьте его в индекс и проверьте изменения в окне коммита. -## Гистограмма +Вы уже могли заметить, что новые строки выделяются зеленым цветом. +Красным цветом выделяются удаленные строки, а неизмененные остаются белыми. +Такой формат записи изменений называется **«дифф» (diff)**. +Обратите внимание, что по умолчанию Git анализирует строки, а не отдельные слова или символы. +Поэтому получился следующий дифф: старая вторая строка была удалена, новая вторая строка добавлена (см. номера строк слева), хотя мы всего лишь добавили присвоение `x <- ` в начало строки. -Замените блок кода на следующий: +![Diff файла paper.qmd: добавлены присвоение x и три варианта гистограммы, новые строки выделены зелёным. Подготовьте состояние paper и замените блок R кодом из раздела «Гистограмма»]() + +Убедитесь, что сделанные изменения соответствуют диффу на скриншоте выше, и создайте новый коммит с описанием «Добавили гистограммы для длины клюва». + +## Экспорт + +Гистограмма с шириной столбца 2 выглядит наиболее информативно. +Такой график можно и опубликовать. +Чтобы экспортировать изображение, замените блок R в `paper.qmd` следующим кодом и выполните его. ```{r, eval=FALSE} data <- read.csv("data/penguins.csv") @@ -48,10 +101,43 @@ hist(x, breaks = seq(30, 60, 2)) dev.off() ``` -Выполните блок. В папке `out` появится `penguins-hist.png`. +После этого в списке изменений на панели [Source Control]{.figtext}, кроме файла `paper.qmd`, появился файл с изображением `out/penguins-hist.png`. +Его мы тоже добавим в коммит. +Во-первых, так другие участники, загрузив проект, сразу увидят результат без необходимости выполнять документ. +Во-вторых, если вы измените ширину столбца или другие настройки графика, будет удобно сравнить старую и новую версии. + +Добавьте оба файла в индекс, проверьте изменения, изучив дифф, и создайте коммит с описанием «Сохранил гистограмму длины клюва». + +На этом остановимся и посмотрим историю версий в журнале Git. + +::: {.callout .callout-info} +Делайте коммиты часто и не придавайте слишком большое значение планированию. +Коммит это не концептуально новая версия проекта, а просто шаг или изменения, которые вы хотите зафиксировать. + +```{r, include=FALSE} +# При необходимости можно объединить несколько коммитов в один +# ([см. в разделе с решением частых задач](#faq)). +``` +::: + +::: {.callout .callout-info} +Не обязательно добавлять в коммит все изменения сразу или их отменять --- они могут оставаться в рабочей папке сколько угодно. +Тем не менее старайтесь не копить изменения, потому что тогда версия в репозитории будет отличаться от версии, с которой вы работаете, а значит, теряется смысл системы контроля версий и возникают ошибки. -В Source Control выберите `paper.qmd` и проверьте добавленные строки. Затем добавьте в индекс `paper.qmd` и `out/penguins-hist.png`, но не остальные случайные изменения. Создайте коммит `Сохранил гистограмму длины клюва`. +```{r, include=FALSE} +# Сказать, что можно отменить. +# Сказать про ветки. +``` +::: -![Source Control перед коммитом гистограммы: в Staged Changes находятся только paper.qmd и out/penguins-hist.png]() +```{r, include=FALSE} +# Показать как отменить изменения. +``` -Теперь у проекта есть исходная версия, импорт данных и готовый график в трёх отдельных коммитах. +```{r, include=FALSE} +# Как писать сообщение коммита. +``` + +```{r, include=FALSE} +# Заменить название главы на «Практика» или «Отслеживание изменений» +``` diff --git a/02-04-log-n-diff.Rmd b/02-04-log-n-diff.Rmd index 8dd7692..abb5b27 100644 --- a/02-04-log-n-diff.Rmd +++ b/02-04-log-n-diff.Rmd @@ -1,25 +1,37 @@ -# История и различия {#history-diff} +# Просмотр истории {#git-log} -Разверните **Source Control Graph** в Source Control. В нём видны коммиты текущей ветки `main`. +До этого мы просматривали изменения только по сравнению с последней версией в момент создания коммита. Предыдущие коммиты можно посмотреть в **журнале (log)**. -Выберите коммит `Сохранил гистограмму длины клюва`. Под ним появится список изменённых файлов. Выберите `paper.qmd`, чтобы открыть diff именно для этого коммита. +Журнал позволяет изучить изменения от других участников или вспомнить свои собственные, и зачем они сделаны. +Поэтому так важно писать ясные и содержательные описания коммитов. +Используя журнал, можно найти, когда сделаны изменения, приведшие к ошибке, и вернуть проект к предыдущему состоянию. +В конце концов, его можно использовать для отчетности и бизнесс-аналитики по проекту. -![Source Control Graph с тремя учебными коммитами и открытым diff файла paper.qmd для коммита с гистограммой]() +Чтобы открыть журнал, разверните [Source Control Graph]{.figtext} на панели [Source Control]{.figtext}. +В открывшемся окне выводится список коммитов в обратном порядке --- последние коммиты находятся вверху. +В списке выводится краткая информация о коммите, а под списком подробная информация по выделенному коммиту. -В diff удалённые строки отмечены красным, добавленные — зелёным. Git сравнивает строки, поэтому даже изменение одного символа может выглядеть как удаление старой строки и добавление новой. +![Source Control Graph в Positron: показана последовательность учебных коммитов и сведения о выбранном коммите. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-histogram --state histogram]() -Для истории одного файла откройте `paper.qmd`, затем разверните **Timeline** в Explorer. Там можно выбрать прежний коммит и посмотреть, как менялся только этот файл. +- SHA --- так называемый хэш коммита, который является его уникальным идентификатором в репозитории +- Author --- автор коммита \, [которые были указаны в настройках](#setup) +- Date --- дата и время создания коммита +- Subject --- описание коммита +- Parent --- хэш (идентификатор) предыдущего коммита -## Рабочая папка, индекс и коммит +Под выбранным коммитом показаны изменённые файлы. Выберите текстовый файл, чтобы открыть дифф --- изменения, сделанные в этом коммите по сравнению с предыдущим. +Для больших файлов выводятся только те строки, которые поменялись, а также несколько строк выше и ниже, чтобы был понятен контекст. +Чтобы посмотреть историю только одного файла, выберите его в [Explorer]{.figtext} и откройте представление [Timeline]{.figtext}. -Эти три состояния полезно различать: +Даже если вы работаете в одиночку, полезно иметь под рукой историю изменений. +Но по настоящему эта функция полезна, +когда приходится работать с несколькими версиями одновременно, +например при работе в команде. +[Об этом далее](#git-branch). -| Состояние | Что содержит | -|---|---| -| Рабочая папка | Сохранённые на диске файлы, включая незаконченные изменения | -| Индекс | Только изменения, выбранные для следующего коммита | -| Последний коммит | Уже записанный снимок проекта | +```{r, include=F} +# Название главы что-то типа «Журнал (log)»? -Кнопка `+` переносит изменение из рабочей папки в индекс. Кнопка `−` у **Staged Changes** убирает его из индекса, но не удаляет из файла. **Commit** записывает содержимое индекса в историю. - -Официальное руководство [Staging and committing changes](https://code.visualstudio.com/docs/sourcecontrol/staging-commits) использует эту же модель. +# примеры? код ревью, просто посмотреть кто, когда и зачем. +# рассказать почему в списке выводится только первые 8 символов sha? +``` diff --git a/03-01-branches.Rmd b/03-01-branches.Rmd index 54eb928..246588e 100644 --- a/03-01-branches.Rmd +++ b/03-01-branches.Rmd @@ -1,18 +1,54 @@ # (PART) Ветки {-} -# Альтернативный график {#branches} +```{r, include=FALSE} +# Ветка отражает состояние проекта во времени. +# Ветки можно делать от веток. +``` + +# Введение {#branch} + +До этого мы создавали версии только последовательно, +чтобы записывать историю изменений. +Git позволяет создавать параллельные версии. +Это могут быть как версии различных участников (collaborators) с различных устройств, +так и несколько альтернативных версий на одном и том же компьютере. +Таким образом участники могут создавать и обмениваться различными вариантами изменений. +Git позволяет эффективно объединять эти изменения, делая совместную работу комфортной, +чего, к слову, не умеют облачные сервисы вроде Google Drive. + +Для этого используются так называемые ветки (branch). +Почему ветки? Потому что начиная с выбранного коммита история изменений разветвляется. + +По умолчанию, мы работаем в ветке `main` +(ранее ветка по умолчанию называлась `master`, будьте готовы встретить и такое название). +Ее можно сравнить со стволом дерева --- вот он слева на изображении. +В нашем проекте с пингвинами в ветке `main` 4 коммита, последний из которых содержит гистограмму для публикации. + +![Source Control Graph: последовательные коммиты ветки main, последний содержит гистограмму. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-branches --state histogram]() -Ветка — указатель на последовательность коммитов. Она позволяет экспериментировать, не меняя основную линию `main`. +Представим ситуацию --- из журнала приходит ответ Рецензента 2, в котором он просит заменить гистограмму на ящик с усами. +С одной стороны, можно податься в журнал, где знают, что такое гистограмма, +с другой, можно хотя бы попробовать удовлетворить пожелания рецензента и, +если нам не понравится новая диаграмма, просто удалить изменения. -Представим, что рецензент попросил заменить гистограмму на ящик с усами. Сделаем вариант в отдельной ветке. +# Создание ветки {#git-branch} -Убедитесь, что Source Control пуст. Нажмите название `main` в строке состояния и выберите **Create new branch…**. То же действие доступно из палитры команд как **Git: Create Branch**. +Чтобы спокойно поэкспериментировать создадим новую ветку. +Так будет проще удалить изменения и они не будут мешать, если мы захотим поправить что-то действительно важное в основной ветке `main`. -Введите название `boxplot` и выберите `main` как исходную ветку. Positron сразу переключится на новую ветку; её имя появится в строке состояния. +В Positron нажмите название текущей ветки `main` в строке состояния и выберите [Create new branch…]{.figtext}. -![Positron после создания ветки boxplot: имя ветки видно в строке состояния, Source Control пуст]() +![Меню веток Positron с выбранным действием Create new branch. Подготовьте состояние histogram и нажмите название main в строке состояния]() -Замените код графика в `paper.qmd`: +В появившемся поле введите название, например `boxplot`, и подтвердите создание. +Positron переключится на ветку `boxplot`. + +![Positron после создания ветки boxplot: название новой ветки видно в строке состояния. Подготовьте состояние histogram и создайте ветку boxplot]() + +Обратите внимание, что название ветки в строке состояния поменялось с `main` на `boxplot`. + +Вернемся к пингвинам. +Замените блок R в документе `paper.qmd` на следующий: ```{r, eval=FALSE} data <- read.csv("data/penguins.csv") @@ -23,8 +59,17 @@ boxplot(x) dev.off() ``` -Выполните код. Удалите `out/penguins-hist.png`: в этой версии проекта он больше не нужен. Добавьте в индекс изменение `paper.qmd`, удаление гистограммы и новый `out/penguins-boxplot.png`. +Сохраните файл и выполните блок. +Обратите внмание, что мы поменяли название файла. +Старый файл `out/penguins-hist.png` в этой версии нам не нужен и его необходимо удалить. +Не переживайте, благодаря Git, в основной ветке `main` он останется. +В [Explorer]{.figtext} нажмите правой кнопкой на файл `out/penguins-hist.png` и выберите [Delete]{.figtext}. + +![Explorer в Positron перед удалением файла out/penguins-hist.png. Подготовьте состояние histogram, создайте ветку boxplot и выполните блок с boxplot]() + +Отметьте все изменения для фиксации и создайте коммит. +Обратите внимание, что удаление файла это тоже изменение, которое надо отметить. -Создайте коммит `Заменил гистограмму на ящик с усами`. +![Source Control перед коммитом в ветке boxplot: изменён paper.qmd, удалена гистограмма и добавлен новый боксплот. Подготовьте состояние boxplot-branch и выполните git reset --soft HEAD^]() -![Source Control Graph после коммита в boxplot: main указывает на гистограмму, boxplot — на новый коммит с ящиком с усами]() +Теперь отложим эксперименты и вернемся к прежней версии. diff --git a/03-02-checkout.Rmd b/03-02-checkout.Rmd index 729bc33..cf28156 100644 --- a/03-02-checkout.Rmd +++ b/03-02-checkout.Rmd @@ -1,25 +1,35 @@ -# Переключение веток {#switch-branches} +# Переключение веток {#git-checkout} -Нажмите `boxplot` в строке состояния и выберите `main`. Эта операция называется переключением, а в терминах Git — checkout или switch. +Для переключения ветки нажмите на название текущей ветки в строке состояния Positron. +В выпадающем списке выберите ветку на которую хотите переключиться (`main`). -Откройте `paper.qmd` и папку `out`. В `main` снова должна быть гистограмма и не должно быть нового боксплота. Git привёл рабочую папку к коммиту выбранной ветки. +![Меню веток Positron: для переключения выбрана ветка main. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-checkout --state boxplot-branch]() -![Ветка main после переключения: paper.qmd содержит hist(), в out виден penguins-hist.png]() +Убедитесь, что код документа `paper.qmd` вернулся к прежнему состоянию и строит гистограмму, +а в списке файлов находится файл с гистограммой `out/penguins-hist.png` и нету файла `out/penguins-boxplot.png`. -## Защита незаписанной работы +![Ветка main после переключения: paper.qmd снова содержит гистограмму, а в папке out находится penguins-hist.png. Подготовьте состояние boxplot-branch и выполните git switch main]() -В `paper.qmd` добавьте подпись оси: +Это было просто. +Но есть один случай, когда +Git откажется переключать ветку --- если это приведет к потере данных. -```r -hist(x, breaks = seq(30, 60, 2), xlab = "Bill length, mm") -``` +Например, замените блок R в `paper.qmd` на следующий (добавилась подпись оси X): -Сохраните файл, но пока не создавайте коммит. Попробуйте переключиться на `boxplot`. +```{r, eval=FALSE} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -Если переключение перезапишет изменённые строки, Git остановит операцию и предложит сначала сохранить работу. Это защитное поведение: незакоммиченные изменения не потеряны, вы по-прежнему на `main`. +png("out/penguins-hist.png") +hist(x, breaks = seq(30, 60, 2), xlab = "Bill length, mm") +dev.off() +``` -![Уведомление Positron об отказе переключить ветку из-за незакоммиченных изменений в paper.qmd]() +Сохраните файл и попробуйте переключиться на ветку `boxplot`. +Вы получите сообщение как на скриншоте ниже. +Если бы Git переключил ветку, ему бы пришлось перезаписать файл `paper.qmd`, в который мы внесли изменения, но не зафиксировали. +Поэтому, чтобы не потерять изменения при переключении, сначала необходимо их зафиксировать создав коммит. -Вернитесь в Source Control, проверьте diff и создайте коммит `Добавил подпись оси гистограммы`. После этого переключитесь на `boxplot` и обратно на `main`, чтобы проверить обе версии. +![Сообщение Positron об отказе переключить ветку из-за незафиксированных изменений в paper.qmd. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-dirty-main --state dirty-main; затем выберите boxplot]() -Если нужно временно убрать незаконченные изменения без коммита, используйте **Git: Stash (Include Untracked)**. Для основного упражнения stash не нужен. +Создайте коммит и попробуйте переключиться на ветку `boxplot` и обратно на ветку `main`. diff --git a/03-03-merge.Rmd b/03-03-merge.Rmd index 372762b..6d0a25b 100644 --- a/03-03-merge.Rmd +++ b/03-03-merge.Rmd @@ -1,35 +1,99 @@ -# Слияние и конфликт {#merge-conflict} +# Слияние веток {#git-merge} -Сейчас `main` и `boxplot` по-разному изменили одну строку `paper.qmd`. Объединим ветки и разрешим конфликт осознанно. +[Откройте журнал](#git-log) и разверните [Source Control Graph]{.figtext}, чтобы посмотреть все ветки. +На диграмме наглядно видно почему это называется веткой. -Переключитесь на `main`. Откройте палитру команд, выполните **Git: Merge Branch** и выберите `boxplot`. +![Source Control Graph перед слиянием: ветки main и boxplot расходятся от общего коммита. Подготовьте состояние conflict и выполните git merge --abort]() -Git автоматически объединит независимые изменения, но остановится на `paper.qmd`: обе ветки изменили код графика, и программа не знает, какой вариант нужен. +Если мы или другой участник проекта, решим принять эти изменения в основную ветку `main`, +нам нужно выполнить операцию «слияния» (merge). +Выполним слияние в терминале. +Команда совсем не сложная. -В Source Control файл появится в разделе **Merge Changes** с предупреждением. Это незавершённое слияние, а не повреждение проекта. +Для начала переключитесь на ветку, в которую будут вливаться изменения --- +в нашем случае это `main` ([см. переключение веток](#git-checkout)). +Откройте терминал ^[В палитре команд Positron выберите **Terminal: Create New Terminal**] и введите команду для слияния с веткой `boxplot`. -![Source Control после Git: Merge Branch: paper.qmd находится в Merge Changes, слияние ожидает решения]() +```sh +git merge boxplot -## Редактор слияний +``` + +Git попытается автоматически объединить изменения из обеих веток и создать новый коммит. +В большинстве случаев этого достаточно, +но любая совместная работа может приводить к конфликтам --- +когда в обеих ветках была изменена одна и та же строка, но разным образом. +Какую версию предпочтет Git? +Git предпочтет выдать ошибку и попросит вас разрешить конфликт. + +В списке изменений мы видим, +что Git автоматически выбрал изменения связанные с новым и старым файлом для графика +`out/penguins-hist.png` и `out/penguins-boxplot.png`, +но лишь частично для документа `paper.qmd`. + +![Source Control после команды git merge boxplot: файлы графиков объединены автоматически, а paper.qmd отмечен как конфликтующий. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-conflict --state conflict]() -Нажмите `paper.qmd` правой кнопкой и выберите **Open in Merge Editor**. Редактор показывает три области: +Причина в том, что мы вносили изменения в код графика в ветке `main` после того как изменили его в ветке `boxplot`. +Откройте файл `paper.qmd`. +Git любезно оставил для нас обе версии кода разделив специальными символами. +После строки `<<< HEAD` идет версия из текущей ветки, +строка `===` отделяет две версии друг от друга, +а строка `>>> boxplot` завершает версию из ветки `boxplot`. -- **Incoming** — изменение из `boxplot`; -- **Current** — изменение из `main`; -- **Result** — итог, который будет записан. +![Файл paper.qmd с маркерами конфликта: показаны версии кода из main и boxplot. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-conflict-file --state conflict]() -В Result оставьте боксплот из Incoming и добавьте к нему подпись из Current: +Наша задача переписать выделенный участок (строки 4-12) в одну версию и убрать спецсимволы. +Важно понимать, что Git просто вставил в документ кусок текста, +но это всё ещё обычный текст документа Quarto и мы должны привести его в рабочее состояние. + +Нам нужна версия из ветки `boxplot`, но мы хотим добавить в нее подпись оси, как это было сделано в ветке `main`. +Для этого оставим нижнюю версию (строки 9-11) и удалим лишние строки (4-8 и 12) +и добавим подпись, только для ящика с усами это должна быть подпись оси Y. +В итоге должен получиться следующий код. + +```{r, eval=FALSE} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -```r png("out/penguins-boxplot.png") boxplot(x, ylab = "Bill length, mm") dev.off() ``` -Нажмите **Complete Merge**. Убедитесь, что в Result нет строк `<<<<<<<`, `=======` и `>>>>>>>`, а `paper.qmd` находится в **Staged Changes**. +Сохраните файл и выполните блок. +Создайте коммит и +не забудьте добавить в индекс внесенные изменения, +в том числе обновившийся файл `out/penguins-boxplot.png`, который теперь содержит подпись оси. +Обычно сообщение коммита о слиянии веток содержит следующий текст «Merge branch название-ветки», но можете придумать свое. + +![Source Control перед коммитом слияния: paper.qmd и обновлённый out/penguins-boxplot.png добавлены в индекс. Подготовьте состояние conflict, разрешите конфликт по заданию и добавьте файлы в индекс]() -![Редактор слияний Positron: Incoming содержит boxplot, Current — hist с подписью, Result — boxplot с ylab]() +Итак, мы успешно слили изменения из ветки `boxplot` в основную ветку `main`. +Теперь можно продолжить работу в основной ветке. +Еще лучше будет создать очередную ветку для новых изменений, выполнить работу в ней и точно так же слить в основную. -Обновите `out/penguins-boxplot.png`, добавьте его в индекс и создайте коммит `Слил ветку boxplot`. +![Source Control Graph после слияния: ветки boxplot и main соединены коммитом слияния. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-merged --state merged]() -Если нужно отказаться от всего слияния, выполните **Git: Abort Merge** из палитры команд. Git вернёт проект к состоянию до попытки merge. +
Как удалить ветку? +Слитую ветку можно удалить. +Выполните в терминале команду: + +```sh +git branch -d boxplot +``` + +Если ветка не была слита, Git откажется ее удалять, ведь могут быть потеряны сделанные в ней изменения. +Если вы действительно уверены, что они вам не нужны и вы хотите удалить не слитую ветку, выполните команду: + +```sh +git branch -D boxplot +``` +
+ +```{r, include=FALSE} +# Советуем немного попрактиковаться и создать пару веток, +# переключиться между ними, от них создать еще и слить их, +# пока не освоитесь. +# +# Да не, ту мач и репозиторий выйдет из под контроля. +``` diff --git a/03-04-conclusion.Rmd b/03-04-conclusion.Rmd index e8d027e..7afd073 100644 --- a/03-04-conclusion.Rmd +++ b/03-04-conclusion.Rmd @@ -1,21 +1,58 @@ -# Итог работы с ветками {#branches-conclusion} +# Заключение -Разверните Source Control Graph. От общего коммита расходятся `main` и `boxplot`, а коммит слияния снова соединяет линии. +Теперь вы умеете создавать и объединять ветки --- +это одни из ключевых функций Git, особенно при совместной работе. +Благодаря простоте работы с ветками, рекомендуется создавать их чаще. +Чем меньше в ветке изменений, тем проще ее слить, и тем ниже вероятность конфликтов из-за одновременных правок одной и той же части проекта. Это отражает известную идею, что при работе в команде лучше синхронизироваться чаще. -![Source Control Graph после слияния: видны расхождение main и boxplot и merge-коммит в main]() +Рассмотрим продвинутые способы использования веток, а также для чего их использовать не стоит. -Теперь вы умеете: +Для начала уточним, что можно создать ветку от любой другой, а не только от основной ветки `main`. Уровень вложенности и количество веток не ограничены. +После слияния ветки она не прекращает свое существование --- в ней можно продолжить работу, а после слить еще раз. +На практике вам вряд ли понадобится больше 3-х уровней вложенности, а ветки лучше периодически удалять, чтобы не запутаться. -- создавать ветку командой **Git: Create Branch**; -- переключаться через индикатор ветки или **Git: Checkout to**; -- объединять ветки командой **Git: Merge Branch**; -- разрешать конфликт в трёхстороннем редакторе; -- отменять незавершённое слияние командой **Git: Abort Merge**. +## Тематические ветки (feature branch) -После проверки слитую локальную ветку можно удалить: переключитесь на `main`, выполните **Git: Delete Branch** и выберите `boxplot`. +Тематическая ветка содержит изменения, связанные с конкретной задачей или направлением работы. +Это может быть новый этап анализа или изменения в уже сделанные этапы, например: -::: {.callout .callout-warning} -Не удаляйте ветку, пока её изменения не слиты и не стали ненужными. Удаление несохранённой линии истории сложнее отменить, чем обычное редактирование файла. -::: +- ветка в которой мы визуализировали данные при помощи графиков, может называться `visualize` или `plot`; +- ветка в которой добавляются модели, может называться `model` или, если это более специфическая модель, например нелинейная, то `model-nle`; +- ветка в которой обновлены данные для уже выполненного анализа `update-data`; +- в нашем репозитории, когда мы заменили график на ящик с усами, ветка называлась `boxplot`. -В следующей части вынесем репозиторий на GitHub и повторим этот процесс как предложение изменений для коллег. +Если в проекте используется трекер задач или ошибок, +то зачастую работа выполняется в отдельной ветке с названием соответствующим номеру из трекера, +например `issue42` или `ticket58`. + +Это самый частый способ использования веток, применяемый независимо от размеров проекта и количества участников. + +## Долгоживущие ветки (long-running branches) + +Этот подход часто применяется для крупных проектов, когда нужно обеспечить высокую стабильность продукта, как правило при разработке программного обеспечения. + +Ветка `main` содержит стабильную версию. +От нее создается ветка `develop` в которой ведется разработка. +Тематические ветки создаются от ветки `develop` и вливаются в нее. +Когда разработка очередной версии завершилась, +изменения из ветки `develop` стабилизируются --- проходят тестирование и ревью, +после чего вливаются в стабильную ветку `main`. + +Далее цикл повторяется --- разработка следующей версии продолжается в ветке `develop` с использованием тематических веток, после чего она снова сливается с веткой `main`. + +## Когда не стоит использовать ветки + +Выше описаны лишь некоторые наиболее часто используемые процессы работы построенные вокруг веток. +Существует и можно придумать много других, подходящих для вас или вашей команды. + +Но у всех применений веток есть общая черта --- это способ организации внесения изменений в проект и рано или поздно эти изменения должны быть слиты или удалены. + +Ветки это не способ структурирования самого анализа или программы. +Например, если у вас есть несколько моделей и вы собираетесь поддерживать их все, то вероятно они должны быть в одной ветке, а не в отдельных. +Иначе потребуется следить за тем, чтобы изменения вносились в каждую ветку --- это утомительно и чревато ошибками. +Для работы с несколькими моделями одновременно придется переключаться и работать с несколькими ветками, что противоречит большинству способов их использования, например описанных выше. + +Другая частая ошибка --- участники создают ветки с собственным именем (`ivan`, `masha-work`) и используют их как личные папки для хранения своих файлов не связанных с файлами других участников. +Ветки предназначены для внесения изменений в один общий проект. Следует либо интегрировать эти файлы в проект, возможно отдельной веткой, либо хранить в другом месте. + +В следующей части мы посмотрим как организовать совместную работу при помощи «удаленных» (remote) веток и сервиса GitHub. diff --git a/04-01-github.Rmd b/04-01-github.Rmd index 3622ec6..1fdadf6 100644 --- a/04-01-github.Rmd +++ b/04-01-github.Rmd @@ -1,23 +1,29 @@ # (PART) GitHub {-} -# Аккаунт и вход {#github-part} +# Настройка {#github} -Git хранит историю на вашем компьютере. GitHub хранит копию репозитория на сервере, поэтому проект можно открыть с другого устройства, показать преподавателю и обсудить изменения с коллегами. +GitHub --- это веб-сервис для хранения Git репозиториев и совместной работы. +Ваши файлы размещаются на удаленном сервере и доступны публично или приватно для загрузки другими пользователями. В некотором смысле это аналог Dropbox или Google Drive для Git. +Помимо хранения репозиториев, GitHub предоставляет другие инструменты: отслеживание задач, обсуждение изменений, запуск тестов и сборок и многое другое. -Создайте аккаунт на [github.com](https://github.com/signup), если его ещё нет. Имя пользователя станет частью адресов репозиториев, поэтому лучше использовать короткое имя латиницей. +Для работы с GitHub вам понадобится зарегистрировать учетную запись и войти в неё из Positron. -Positron включает расширения **GitHub** и **GitHub Pull Requests and Issues**. При первой публикации или отправке изменений редактор предложит войти. Выберите **Sign in with GitHub**, подтвердите открытие браузера и разрешите доступ. +## Регистрация на GitHub -![Positron показывает запрос Sign in with GitHub перед первой публикацией репозитория]() +Перейдите на сайт github.com и зарегистрируйте учетную запись нажав на кнопку [Sign up]{.figtext} в верхнем правом углу или войдите в существующую учетную запись нажав [Sign in]{.figtext}. -После подтверждения вернитесь в Positron. Не создавайте classic personal access token для этого упражнения: обычный путь входа проходит через браузер. +E-mail при регистрации не обязательно должен совпадать с указанным при настройке Git в [Главе 1](#setup). Дополнительные e-mail адреса можно добавить после регистрации [на странице настроек](https://github.com/settings/emails). +Это рекоммендуется сделать, чтобы GitHub мог ассоциировать сделанные на компьютере коммиты с вашей учетной записью онлайн. -::: {.callout .callout-warning} -Никому не отправляйте пароли, токены, приватные ключи и секреты webhook. Не добавляйте их в `.qmd`, `.R`, `.env` или другие файлы репозитория. -::: +## Вход из Positron -## Git и GitHub — разные системы +Positron включает интеграцию с GitHub. При первой публикации репозитория редактор предложит войти в учётную запись. +Выберите [Sign in with GitHub]{.figtext}, подтвердите открытие браузера и разрешите доступ. +После входа вернитесь в Positron. -Коммит, ветка и слияние работают в Git без GitHub. GitHub добавляет удалённый репозиторий, права доступа, pull request, обсуждения и автоматические проверки. +![Positron предлагает войти в GitHub перед первой публикацией репозитория. Чтобы получить состояние, выйдите из GitHub в Positron и выберите Publish to GitHub]() -Если сайт GitHub недоступен, локальные коммиты продолжают работать. Когда связь восстановится, их можно отправить на сервер. +Отдельный Personal Access Token для этого упражнения создавать не нужно. +Никому не отправляйте пароль, токен или приватный ключ и не сохраняйте их в файлах проекта. + +Теперь мы готовы опубликовать наш репозиторий на GitHub. diff --git a/04-02-remote.Rmd b/04-02-remote.Rmd index ce54fac..3dcdb42 100644 --- a/04-02-remote.Rmd +++ b/04-02-remote.Rmd @@ -1,25 +1,33 @@ -# Публикация репозитория {#publish-github} +# Удаленный репозиторий {#git-remote} -Убедитесь, что выбрана ветка `main`, Source Control пуст и последний коммит — `Слил ветку boxplot`. +```{r, include=FALSE} +# Рассказать про видимость репозиториев +``` -В Source Control нажмите **Publish to GitHub**. Если кнопка не видна, откройте палитру команд и найдите **Publish to GitHub**. +Для загрузки репозитория с вашего компьютера (он называется локальный репозиторий) на GitHub необходимо создать удаленный репозиторий на сайте. +Positron может создать его и сразу связать с локальным. -Выберите имя репозитория, например `r-course`, и доступ **Private repository**. Для учебного проекта приватный режим безопаснее: открыть репозиторий позже можно в настройках GitHub. +Откройте [Source Control]{.figtext} и нажмите [Publish to GitHub]{.figtext}. +Если Positron предложит войти, выполните действия из [предыдущей главы](#github). +Введите название репозитория, например `r-course`, и выберите [Publish to GitHub public repository]{.figtext}. -Если Positron предложит выбрать файлы, оставьте все уже отслеживаемые файлы. В проекте не должно быть секретов. +![Диалог публикации Positron: указано имя r-course и выбран публичный репозиторий GitHub. Подготовьте состояние merged и выберите Publish to GitHub]() -![Диалог Publish to GitHub с именем r-course и выбранным вариантом Private repository]() +Настройка доступа определяет, кто может видеть файлы: -Positron выполнит три связанных действия: +- Public --- кто угодно сможет просматривать ваши файлы, но только отдельно добавленные пользователи смогут их изменять +- Private --- только отдельно добавленные пользователи смогут просматривать и изменять файлы -1. создаст репозиторий на GitHub; -2. добавит его как удалённый репозиторий `origin`; -3. отправит коммиты ветки `main`. +Не публикуйте проект, если в нём есть пароли, токены, персональные данные или другие секреты. -После публикации откройте созданный репозиторий на GitHub и сравните список файлов с Explorer. Убедитесь, что на сайте есть `paper.qmd`, папка `data` и история коммитов. +```{r, include=FALSE} +#
В чем разница между HTTPS и SSH? +#
+``` -**Удалённый репозиторий** (remote) — адрес другой копии проекта. Имя `origin` условное, но Git назначает его основной удалённой копии при публикации и клонировании. +Positron связал наш локальный репозиторий с удаленным при помощи операции **remote add** --- это необходимо было сделать один раз. +И выполнил операцию **push** --- отправил сделанные фиксации в удаленный репозиторий. Это необходимо делать регулярно, и соответствующее действие доступно на панели [Source Control]{.figtext}. +Если команды выполнились успешно, файлы были загружены на GitHub. +Обновите страницу репозитория и проверьте содержимое файлов. -::: {.callout .callout-info} -GitHub не выполняет код Quarto при обычной отправке. Файлы и история появятся на сервере, но готовый сайт требует отдельной настройки публикации. -::: +![Страница опубликованного репозитория r-course на GitHub: видны файлы проекта и история коммитов. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-published --state github-published --repo OWNER/NAME --visibility public]() diff --git a/04-03-push-pull.Rmd b/04-03-push-pull.Rmd index 67379ee..245e255 100644 --- a/04-03-push-pull.Rmd +++ b/04-03-push-pull.Rmd @@ -1,27 +1,72 @@ -# Push, pull и синхронизация {#sync-remote} +# Загрузка изменений {#git-push-pull} -Локальная и удалённая копии меняются независимо. Три операции поддерживают их в согласованном состоянии. +```{r, include=FALSE} +# Рассмотреть пример ситуации - push с конфликтом (надо сначала сделать pull). +# Для этого надо создать изменения на GitHub, +# потом в репозитории, сделать push и только потом pull. +# Это не последовательно и запутает, оставить для практики. +``` -| Действие | Результат | -|---|---| -| **Push** | Отправляет локальные коммиты на GitHub | -| **Pull** | Загружает удалённые коммиты и объединяет их с текущей веткой | -| **Sync Changes** | Сначала выполняет pull, затем push | +На предыдущем шаге мы загрузили изменения из нашего локального репозитория в удаленный репозиторий на GitHub при помощи операции `push`, которую выполнил Positron. -Эти определения соответствуют официальной документации [Working with repositories and remotes](https://code.visualstudio.com/docs/sourcecontrol/repos-remotes). +Git не синхронизирует изменения автоматически, это необходимо делать вручную, используя команду push или действие [Push]{.figtext} на панели [Source Control]{.figtext} в Positron. -## Небольшая проверка +Создадим и загрузим еще один коммит. Например, добавим небольшой комментарий к коду, чтобы человеку открывшему его впервые было легче разобраться. -Добавьте после заголовка `paper.qmd` одно предложение о цели анализа. Сохраните файл, проверьте diff и создайте коммит `Уточнил цель анализа`. +```{r, eval=FALSE} +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -В строке состояния появится исходящий коммит `↑1`. Нажмите **Sync Changes**. После синхронизации счётчик исчезнет, а коммит появится на GitHub. +# Ящик с усами для длины клюва -![Source Control перед Sync Changes: локальная main опережает origin/main на один коммит, в строке состояния показано ↑1]() +png("out/penguins-boxplot.png") +boxplot(x, ylab = "Bill length, mm") +dev.off() +``` -## Перед началом работы +Сохраните и закомитьте файл `paper.qmd`. +После чего выберите [Push]{.figtext} на панели [Source Control]{.figtext}. -В совместном проекте начинайте с **Pull**, а заканчивайте **Push**. Так вы раньше увидите чужие изменения и реже столкнётесь с конфликтом. +![Source Control перед Push: локальная ветка main содержит новый коммит с комментарием к коду. Подготовьте опубликованный репозиторий и создайте коммит по заданию, не выполняя Push]() -**Sync Changes** удобно, когда вы понимаете обе половины операции. Если нужно отдельно проверить входящие коммиты, выполните **Fetch**, посмотрите их в Source Control Graph и только затем нажмите **Pull**. +Перейдите на страницу репозитория на GitHub и убедитесь, что коммит был загружен. +Это можно понять по тексту сообщения над списком файлов и по тексту и времени изменения напротив файла `paper.qmd`. -Если push отклонён, обычно удалённая ветка содержит новые коммиты. Не применяйте force push. Сначала выполните Pull, разрешите возможный конфликт и повторите Push. +![Страница GitHub после Push: над списком файлов показано сообщение нового коммита, а у paper.qmd обновлено время. Чтобы получить состояние, выполните Push после предыдущего снимка]() + +GitHub позволяет вносить изменения в репозиторий из веб-интерфейса. +Эта функция используется редко, потому что код необходимо запускать и проверять на компьютере, но она полезна для небольших правок или загрузки файлов. +Создадим при помощи нее новый файл. +Файл README --- это файл, который отображается на главной странице репозитория для краткого описания проекта. Обычно он включает описание данных и кода, как начать работу с проектом и тому подобное. + +Нажмите кнопку [Add a README]{.figtext}. В открывшемся файле введите текст в формате Markdown^[в документе Quarto используется тот же синтаксис разметки, но README не выполняет код на R] (используйте или измените текст ниже) +и нажмите кнопку [Commit changes]{.figtext} в верхнем правом углу. +Откроется окно создания коммита, оставьте текст по умолчанию и подтвердите создание коммита нажатием кнопки [Commit changes]{.figtext} + +![Редактор README.md на GitHub: введено описание проекта и доступна кнопка Commit changes. Чтобы получить состояние, нажмите Add a README в опубликованном репозитории]() + +```md +# Пингвины «Палмер» 🐧 + +Этот репозиторий был создан в рамках курса от [Института биоинформатики](bioinf.me/education/stat), +чтобы познакомиться с основами Git — фиксацией изменений, ветвлением и работой с GitHub. + +В качестве примера использованы данные о длине клюва пингвинов, +собранные доктором Кристен Горман на станции «Палмер» в Антарктиде. + +Содержимое репозитория: + +- out/penguins-boxplot.png — диаграмма ящик с усами, показывающая распределение длины клюва +- paper.qmd — документ Quarto с кодом для построения диаграммы +- data/penguins.csv — данные +``` + +Чтобы загрузить изменения из удаленного репозитория на компьютер используется команда **pull**. + +Вернитесь в Positron и выберите [Pull]{.figtext} на панели [Source Control]{.figtext}. +Если команда выполнилась успешно, в списке файлов появится файл `README.md`, +а в журнале --- коммит созданный через GitHub. + +Как и в случае с переключением веток, Git откажется загружать изменения и выдаст ошибку, если в рабочей папке имеются незафиксированные изменения, которые конфликтуют с загружаемыми. + +Теперь вы умеете загружать изменения в удалённый репозиторий и из него. Рекомендуем делать это регулярно, чтобы синхронизироваться с другими участниками проекта, по крайней мере, в конце рабочего дня или рабочей сессии. diff --git a/04-04-pull-request.Rmd b/04-04-pull-request.Rmd index 5fbfb19..5a86cbb 100644 --- a/04-04-pull-request.Rmd +++ b/04-04-pull-request.Rmd @@ -1,10 +1,14 @@ -# Pull request {#pull-request} +# Pull Request {#pr} -Pull request — предложение объединить одну ветку с другой на GitHub. Перед слиянием коллеги могут посмотреть diff, обсудить решение и запустить проверки. +Pull Request --- это механизм GitHub для слияния веток загруженных в удаленный репозиторий, позволяющий просмотреть, обсудить и проверить предлагаемые изменения перед слиянием. Похожий механизм существует и на других платформах. -## Изменение в ветке +Орнитолог проходящий мимо нашего репозитория обратит внимание, что длину клюва пингвина лучше рассматривать в зависимости от пола. Он даже может предложить необходимые изменения при помощи Pull Request. -Создайте от актуальной `main` ветку `adjust-by-sex`. В `paper.qmd` замените блок кода: +Создайте ветку с названием `adjust-by-sex`: нажмите название текущей ветки в строке состояния Positron и выберите [Create new branch…]{.figtext}. Убедитесь, что вместо названия ветки по умолчанию `main` выводится название созданной ветки `adjust-by-sex`. + +![Строка состояния Positron после создания ветки: показано название adjust-by-sex. Подготовьте опубликованное состояние merged и создайте ветку adjust-by-sex]() + +Отредактируйте документ `paper.qmd`, добавив пол в код для построения ящика с усами. Код приведен ниже, не забывайте, что вы можете сравнить изменения по сравнению с оригиналом, выбрав файл на панели [Source Control]{.figtext}. ```{r, eval=FALSE} data <- read.csv("data/penguins.csv") @@ -16,33 +20,37 @@ boxplot(x ~ g, xlab = "Sex", ylab = "Bill length, mm") dev.off() ``` -Соберите документ, проверьте обновлённый график и создайте коммит `Сгруппировал пингвинов по полу`. +Сохраните документ и выполните блок R. +Создайте коммит, включив в него `paper.qmd` и обновленную диаграмму `out/penguins-boxplot.png`. -Нажмите **Publish Branch**. Это создаст `adjust-by-sex` в `origin` и свяжет локальную ветку с удалённой. +![Source Control перед коммитом в adjust-by-sex: изменены paper.qmd и out/penguins-boxplot.png. Подготовьте ветку adjust-by-sex, внесите изменения по заданию и добавьте оба файла в индекс]() -![Ветка adjust-by-sex после Publish Branch: Source Control Graph показывает локальную и удалённую ветки на одном коммите]() +После создания коммита выберите [Publish Branch]{.figtext} на панели [Source Control]{.figtext}. Так как у вас полные права на редактирование репозитория, то новая ветка будет загружена на GitHub. Прохожему орнитологу пришлось бы создать свою копию репозитория или просить дать доступ средствами GitHub. -## Создание предложения +Перейдите на страницу репозитория в GitHub и убедитесь, что ветка была загружена и содержит сделанные измнения, для этого выберите ее в выпадающем меню появляющемся при нажатии кнопки с названием ветки [main]{.figtext}. -Откройте представление **Pull Requests** на панели активности. Нажмите **Create Pull Request** или выполните команду **GitHub Pull Requests: Create Pull Request**. +![Страница GitHub с выбранной веткой adjust-by-sex и обновлённым графиком. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-pr --state github-pr --repo OWNER/NAME --visibility public]() -Выберите: +При просмотре ветки отличной от основной, GitHub предложит создать из нее **Pull Request** --- предложение автору репозитория слить изменения из этой ветки. Нажмите кнопку [Contribute]{.figtext} и в выпадающем меню выберите [Open pull request]{.figtext}. -- базовый репозиторий — ваш `r-course`; -- базовую ветку — `main`; -- ветку с изменением — `adjust-by-sex`; -- заголовок — `Сгруппировал пингвинов по полу`. +![Меню Contribute на GitHub с действием Open pull request. Подготовьте состояние github-pr и откройте ветку adjust-by-sex на GitHub]() -В описании объясните причину: распределение длины клюва теперь показано отдельно для каждого пола. Перед созданием откройте список файлов и проверьте diff. +GitHub предложит ввести заголовок и описание предлагаемых изменений, правило хорошего тона кратко описать причину изменений и суть предлагаемого решения. А также, прокрутите страницу создания Pull Request и проверьте изменения, которые вы предлагаете, после чего нажмите кнопку [Create pull Request]{.figtext} под полем с описанием. -![Форма Create Pull Request в Positron: base main, compare adjust-by-sex, заполнены заголовок и описание]() +![Форма создания pull request на GitHub: заполнены заголовок и описание, ниже показан diff. В состоянии github-pr выберите Contribute → Open pull request]() -Нажмите **Create**. Откроется режим просмотра pull request. Здесь можно оставить комментарий к строке, запросить проверку и увидеть обсуждение. +На странице Pull Request владельцу репозитория доступна опция слить предложенные изменения. +Нажмите кнопку [Merge pull request]{.figtext} внизу страницы. +В открывшемся окне GitHub предложить ввести текст коммита, как если бы мы делали слияние ветки в терминале. Оставьте или измените текст и нажмите кнопку [Confirm merge]{.figtext} +После успешного слияния ветку можно удалить. -## Слияние +![Страница pull request перед слиянием: доступна кнопка Merge pull request. Создайте pull request из состояния github-pr и откройте его страницу]() -Нажмите **Merge** только после проверки файлов. Выберите обычное создание merge-коммита, затем подтвердите операцию. После успешного слияния удалите ветку, когда Positron предложит это сделать. +![Подтверждение merge-коммита на GitHub. На странице pull request нажмите Merge pull request]() -Переключитесь на локальную `main` и выполните **Pull**. Убедитесь, что `paper.qmd` содержит группировку по полу, а Source Control Graph — коммит слияния с GitHub. +![Pull request после успешного слияния и предложение удалить ветку. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-github-merged --state github-merged --repo OWNER/NAME --visibility public]() -![Локальная main после Pull: в paper.qmd код boxplot по sex, в Graph виден слитый pull request]() +Вернемся к нашему проекту в Positron. +Слияние было выполнено онлайн на GitHub, а значит необходимо загрузить изменения в наш локальный репозиторий, т.е. сделать pull. +Переключитесь на ветку `main` при помощи строки состояния и выберите [Pull]{.figtext} на панели [Source Control]{.figtext}. +Убедитесь, что теперь ветка `main` содержит актуальные изменения в файлах `paper.qmd` и `out/penguins-boxplot.png`. diff --git a/04-05-clone.Rmd b/04-05-clone.Rmd index ed665d5..f023465 100644 --- a/04-05-clone.Rmd +++ b/04-05-clone.Rmd @@ -1,19 +1,23 @@ -# Клонирование {#clone-repository} +# Клонирование репозитория {#git-clone} -**Клонирование** создаёт новую локальную папку из удалённого репозитория. Вместе с файлами загружаются коммиты и ветки, а Git автоматически добавляет remote `origin`. +Сейчас репозиторий доступен публично и +чтобы поделиться проектом достаточно скопировать ссылку из адресной строки браузера. +Отличная идея приложить ее к тексту публикации, если репозиторий содержит данные и код для воспроизведения результатов. +Используйте GitHub чтобы делиться примерами кода. Например, если просите помощи, так другим будет легче понять проблему и предложить решение. -Не клонируйте репозиторий внутрь уже открытого `r-course`. Для проверки используйте другую родительскую папку. +Чтобы загрузить удаленный репозиторий на компьютер выполните команду **клонирования (clone)**. +Для этого понадобится адрес репозитория. +Нажмите кнопку [Code]{.figtext} на странице репозитория, +убедитесь что выбрана опция **HTTPS** и скопируйте адрес. -1. Откройте новое окно Positron без проекта. -2. Выполните **Workspaces: New Folder from Git…** из палитры команд. -3. Выберите **Clone from GitHub** и свой репозиторий `r-course`. -4. Укажите родительскую папку, например `projects-copy`. -5. После загрузки нажмите **Open**. +![Меню Code на GitHub: выбрана вкладка HTTPS и показан адрес репозитория. Откройте опубликованный репозиторий и нажмите Code]() -![Окно Workspaces: New Folder from Git со списком репозиториев GitHub и выбранным r-course]() +Создадим копию проекта в Positron. +Откройте новое окно без проекта и в палитре команд выберите [Workspaces: New Folder from Git…]{.figtext}. +Выберите [Clone from GitHub]{.figtext} и свой репозиторий `r-course` или вставьте скопированный адрес. +Укажите другую родительскую папку, чтобы новая копия не оказалась внутри уже открытого проекта. +После загрузки нажмите [Open]{.figtext}. -Откройте Source Control Graph и `paper.qmd`. История и код должны совпадать с первым проектом. +![Окно Workspaces: New Folder from Git в Positron: выбран репозиторий r-course и папка для новой копии. Выполните Workspaces: New Folder from Git… в новом окне Positron]() -Не редактируйте обе копии одновременно без необходимости. Это два независимых рабочих каталога: изменения попадут друг к другу только через Push и Pull. - -Если Positron спрашивает, доверяете ли вы содержимому, подтверждайте доверие только для своего репозитория или известного источника. Открытие чужого проекта ещё не запускает код, но дальнейшее выполнение файлов может это сделать. +Мы склонировали удаленный репозиторий на компьютер и теперь можем работать с ним как с оригинальным проектом --- делать коммиты, загружать изменения в удаленный репозиторий (push) и из него (pull). diff --git a/04-06-conclusion.Rmd b/04-06-conclusion.Rmd index 5b0ed71..74990b2 100644 --- a/04-06-conclusion.Rmd +++ b/04-06-conclusion.Rmd @@ -1,14 +1,17 @@ -# Итог работы с GitHub {#github-conclusion} +# Заключение -Теперь вы умеете: +Теперь у вас есть аккаунт на GitHub и вы умеете синхронизировать изменения с удаленным репозиторием, +пользоваться веб-интерфейсом и создавать Pull Request. +Этого достаточно для командной работы на курсе и в большинстве проектов. -- публиковать локальный репозиторий через **Publish to GitHub**; -- входить в GitHub через браузер; -- различать Push, Pull, Fetch и Sync Changes; -- публиковать отдельную ветку; -- создавать, проверять и сливать pull request; -- клонировать проект командой **Workspaces: New Folder from Git…**. +Диаграмма ниже поможет запомнить как соотносятся действия, которые мы изучили: +[1) создание коммитов](#git-commit), [2) работа с ветками](#branch) и [3) синхронизация с удаленным репозиторием](#git-push-pull). -Для обычной работы достаточно короткого цикла: Pull → новая ветка → небольшие коммиты → Push → pull request → проверка → merge. +![Связь коммитов, веток и синхронизации с удалённым репозиторием](./img/04-06-sequence.png){width=100%} -GitHub — не резервная копия незакоммиченных файлов. Пока изменение не вошло в коммит и не отправлено, оно существует только в вашей рабочей папке. +Рекомендуем использовать Git в своих проектах и не бояться экспериментировать с ветками. +Это помогает структурировать рабочий процесс, делает анализ данных воспроизводимым и облегчает командную работу. +Даже если вы работаете в одиночку, история изменений, возможность вернуться к предыдущим версиям и ветвление значительно упрощают развитие проекта. +А со временем вы сможете применять более продвинутые возможности, такие как автоматизация, интеграция с другими сервисами и управление проектами. + +Удачи в прохождении курса! diff --git a/05-01-faq.Rmd b/05-01-faq.Rmd index 0bf9008..e3b9840 100644 --- a/05-01-faq.Rmd +++ b/05-01-faq.Rmd @@ -1,41 +1,57 @@ -# (PART) Дополнительно {-} +# (PART) Дополнительные материалы {-} -# Частые ситуации {#faq} +# Best practices {#faq} -## Source Control не показывает проект +## .gitignore {#gitignore} -Убедитесь, что в Positron открыта именно папка `r-course`, а не отдельный файл. Затем выполните **Developer: Reload Window**. Если репозитория действительно нет, появится **Initialize Repository**. +## Feature бранчи {#feature-branch} -Для диагностики откройте **Git: Show Git Output**. Последняя строка обычно содержит команду и причину ошибки. Перед отправкой лога удалите из него токены и приватные адреса. +Хорошая практика каждое изменение делать в свой ветке. -## Коммит не содержит файл +Не всегда это удобно, особенно когда работаешь один. +Чтобы перенести уже сделанные коммиты в отдельную ветку воспользуйтесь [этим рецептом](#commits-to-branch). -Коммит получает только **Staged Changes**. Найдите файл в **Changes**, нажмите `+`, проверьте diff и создайте новый коммит. Не нужно удалять предыдущий коммит ради пропущенного файла. +## Комитьте и пушьте чаще -## В коммит попал лишний файл +Так меньше проблем при слиянии -Если коммит ещё не отправлен и вы работаете один, откройте в Source Control меню **More Actions (…) → Commit → Undo Last Commit**. Изменения останутся в **Staged Changes**. Исправьте индекс и создайте коммит снова. +## Принудительный push {#force-push} -Если коммит уже отправлен или его могли скачать коллеги, не переписывайте историю. Сделайте новый коммит, который удаляет или исправляет лишнее. +Это может привести к потери изменений загруженных на сервер ранее, например вашим коллегой. +Никогда не делайте так в команде, не уточнив у других. -## Нужно временно переключиться +## Как перенести коммиты в ветку {#commits-to-branch} -Сохраните законченную часть коммитом. Для незаконченной используйте **Git: Stash (Include Untracked)**, затем переключитесь. Вернуть выбранный stash можно командой **Git: Pop Stash...**. +Идея рецепта в том, +что мы создаем новую ветку из текущего набора коммитов, +переключаемся на оригинальную и в ней ненужные коммиты отменяем. -## Конфликт возник при Pull +::: {.alert .alert-warning} +Этот подход не сработает если вы загрузили коммиты на сервер, +потому что отмена коммитов переписывает историю. +Это потребует выполнения команды `git push --force`. +[Почему это плохо?](#force-push) +::: -Это то же слияние, что в главе \@ref(merge-conflict). Откройте файлы из **Merge Changes**, соберите осмысленный Result, нажмите **Complete Merge** и создайте коммит. После этого повторите Push. +Создайте новую ветку - она будет содержать набор коммитов, который вы имеете сейчас, +при помощи Positron или командой ниже. -## Опасные операции +```sh +git branch some +``` -Команды force push, hard reset, удаление неслитой ветки и переписывание опубликованной истории могут стереть доступ к чужим коммитам. +Важно! Убедитесь в том, что создали ветку. Для этого посмотрите журнал или команду `git log` и найдите напротив текущего коммита надпись с названием созданной ветки. -::: {.callout .callout-warning} -Не используйте **Force Push**, `git reset --hard` и удаление неслитых веток в командном проекте без явного согласования. Сначала создайте резервную ветку или попросите преподавателя помочь. -::: +Вернитесь на оригинальную ветку, как правило это `main`, при помощи Positron или команды ниже. -## Данные и секреты +```sh +git checkout main +``` -Git хорошо подходит для кода и небольших учебных данных. Большие файлы быстро раздувают историю, а удалённый из последнего коммита секрет может сохраниться в старых версиях. +Отмените нужное количество комитов, скажем `3`. +Опция `--hard` удалит все изменения. +Ничего страшного, ведь они остались в ветке, созданной на предыдущем шаге. -Перед первым коммитом добавляйте в `.gitignore` временные файлы, локальные настройки и секреты. Если секрет уже отправлен, сначала отзовите его у провайдера; одного удаления файла недостаточно. +```sh +git reset --hard HEAD~3 +``` diff --git a/05-02-references.Rmd b/05-02-references.Rmd index 4e63d99..4d30e57 100644 --- a/05-02-references.Rmd +++ b/05-02-references.Rmd @@ -1,25 +1,8 @@ # Ссылки {#references} -## Positron - -- [Welcome to Positron](https://positron.posit.co/welcome.html) — исходная точка официальной документации. -- [Git Version Control](https://positron.posit.co/git.html) — Git, Source Control, ветки и конфликты в Positron. -- [Command Palette](https://positron.posit.co/command-palette.html) — поиск и запуск команд. -- [Quarto](https://positron.posit.co/quarto.html) — выполнение и предпросмотр `.qmd`. -- [Folder Templates](https://positron.posit.co/folder-templates.html) — состав проекта, включая `.git` и `.gitignore`. - -## Git и Source Control - -- [Source Control overview](https://code.visualstudio.com/docs/sourcecontrol/overview). -- [Staging and committing changes](https://code.visualstudio.com/docs/sourcecontrol/staging-commits). -- [Source Control history](https://code.visualstudio.com/docs/sourcecontrol/history). -- [Branches and worktrees](https://code.visualstudio.com/docs/sourcecontrol/branches-worktrees). -- [Merge conflicts](https://code.visualstudio.com/docs/sourcecontrol/merge-conflicts). -- [Repositories and remotes](https://code.visualstudio.com/docs/sourcecontrol/repos-remotes). -- [GitHub in Source Control](https://code.visualstudio.com/docs/sourcecontrol/github). -- [Pro Git](https://git-scm.com/book/ru/v2) — подробная бесплатная книга. - -## Практика - -- [Learn Git Branching](https://learngitbranching.js.org/?locale=ru_RU) — интерактивные упражнения с ветками. -- [Happy Git and GitHub for the useR](https://happygitwithr.com/) — Git для проектов анализа данных. +- [Документация Positron](https://positron.posit.co/welcome.html) --- официальное руководство по интерфейсу Positron. +- [Git Version Control](https://positron.posit.co/git.html) --- работа с Git в Positron. +- [Quarto](https://positron.posit.co/quarto.html) --- работа с документами `.qmd` в Positron. +- [Pro Git](https://git-scm.com/book/en/v2) --- небольшая книга рекомендованная разработчиками Git. Из нее вы узнаете о внутреннем устройстве Git и научитесь работать с командой `git` в терминале. Пригодятся главы 1-3 и глава 6. +- [Happy Git and GitHub for the useR](https://happygitwithr.com/) --- материалы практического курса по Git с конференции Posit. +- [Git Cheatsheet](https://ndpsoftware.com/git-cheatsheet.html#loc=local_repo;) - интерактивная шпаргалка. diff --git a/05-03-webhooks.Rmd b/05-03-webhooks.Rmd index 09ee9cd..b44fa5a 100644 --- a/05-03-webhooks.Rmd +++ b/05-03-webhooks.Rmd @@ -1,23 +1,25 @@ # Webhooks {#webhooks} -Webhook позволяет GitHub отправить HTTP-запрос внешнему сервису после события: push, создания pull request или слияния. Так запускают уведомления и автоматические проверки. +Webhooks — это механизм GitHub для реагирования на события в репозитории. +Когда что-то происходит (например, кто-то сделал push или создал Pull Request), +GitHub отправит информацию о событии на указанный в настройках адрес. -Для настройки нужен готовый HTTPS-адрес сервиса. Не указывайте случайный сайт: содержимое запроса может включать имена репозитория, веток и участников. +Для обработки событий по указанному адресу должна работать программа (веб-сервер). +Многие сервисы, например Slack или Microsoft Teams, поддерживают таким образом отправку уведомлений в рабочий чат. +Для Telegram можно воспользоваться ботом [\@octo8bot](https://t.me/octo8bot). -1. Откройте репозиторий на GitHub. -2. Перейдите **Settings → Webhooks → Add webhook**. -3. Вставьте адрес в **Payload URL**. -4. Выберите `application/json`. -5. Добавьте отдельный случайный **Secret**, если принимающий сервис умеет проверять подпись. -6. Выберите **Let me select individual events** и оставьте **Pull requests**. -7. Нажмите **Add webhook**. +Добавьте бота в чат и скопируйте присланный им адрес. -![Страница GitHub Add webhook: заполнен Payload URL, content type application/json, выбран Pull requests, секрет скрыт]() +![Чат с ботом: после добавления показан адрес webhook, который нужно скопировать. Чтобы получить состояние, добавьте \@octo8bot в учебный чат]() -В разделе **Recent Deliveries** откройте тестовую доставку. Код `2xx` означает, что сервис принял запрос. Код `4xx` обычно указывает на неверный адрес или авторизацию, `5xx` — на ошибку принимающего сервиса. +Откройте репозиторий на Github и выберите **Settings → Webhooks → Add webhook**. +Вставьте адрес в поле **Payload URL** и заполните форму как на скриншоте ниже. +Нажмите **Add webhook**. -::: {.callout .callout-warning} -Webhook может запускать действия во внешней системе. Проверяйте адрес и минимально необходимый набор событий. Не записывайте secret в репозиторий и не показывайте его на скриншоте. -::: +![Форма Add webhook на GitHub: заполнен Payload URL и выбраны события pull request. Откройте Settings → Webhooks → Add webhook и заполните форму по заданию]() -Для преподавателя генератор проекта умеет создать такой webhook через `gh` в состоянии `github-webhook`; студенту достаточно один раз пройти настройку в интерфейсе и проверить доставку. +Если webhook настроен правильно, в чат придет сообщение с текстом «Successfully installed». + +Когда создаётся новый Pull Request, в него вносятся изменения или он сливается (merge), бот пришлет уведомление с ссылкой на этот Pull Request. + +![Уведомления бота о создании, изменении и слиянии pull request. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-webhook --state github-webhook --repo OWNER/NAME --webhook-url URL]() diff --git a/bin/check_course.py b/bin/check_course.py index 8ec0125..bba7178 100644 --- a/bin/check_course.py +++ b/bin/check_course.py @@ -12,8 +12,12 @@ ROOT = Path(__file__).resolve().parents[1] SOURCES = sorted(ROOT.glob("*.Rmd")) -PRACTICE_SOURCES = sorted((ROOT / "practice").rglob("*.qmd")) + sorted( - (ROOT / "practice").glob("*.patch") +PRACTICE_MIGRATED = (ROOT / "practice" / "workshop_notebook.qmd").exists() +PRACTICE_SOURCES = ( + sorted((ROOT / "practice").rglob("*.qmd")) + + sorted((ROOT / "practice").glob("*.patch")) + if PRACTICE_MIGRATED + else [] ) @@ -49,7 +53,9 @@ def main() -> int: if not alt.strip(): fail(f"{source.name}: у изображения нет описания", failures) if target.strip(): - fail(f"{source.name}: скриншот должен иметь пустой адрес: {target}", failures) + image_path = (source.parent / unquote(target.strip())).resolve() + if not image_path.exists(): + fail(f"{source.name}: не найдено изображение {target}", failures) for source in PRACTICE_SOURCES: text = source.read_text(encoding="utf-8") diff --git a/docs/01-01-about.md b/docs/01-01-about.md index f62ddb2..88b859a 100644 --- a/docs/01-01-about.md +++ b/docs/01-01-about.md @@ -1,28 +1,45 @@ -# (PART) Подготовка {-} +# (PART) Введение {-} -# Зачем проекту Git {#about-git} +# Что такое Git {#about} -В проекте анализа данных меняются код, текст отчёта и графики. Копии с названиями `final`, `final-2` и `really-final` сохраняют файлы, но не объясняют, кто и зачем их менял. +**Git** --- это программа, выполняющая функции **Системы Контроля Версий (VCS, Version Control System)**. +Многие применяют простую систему контроля версий, вручную копируя файлы и добавляя дату в названия. +Git автоматически отслеживает изменения во время редактирования файлов, позволяет фиксировать состояние файлов в версии, хранить и переключаться между ними. +Вы сможете оценить, какие изменения внесли, а также посмотреть историю изменений --- когда, кем и с какой целью они были сделаны. -Git хранит **коммиты** — снимки выбранных изменений с коротким пояснением. Из них складывается история проекта. По ней можно: -- сравнить текущую работу с предыдущей версией; -- вернуть исправный вариант; -- вести несколько вариантов анализа в ветках; -- объединять изменения разных участников. -Git работает локально. Для коммитов не нужны интернет и аккаунт. GitHub понадобится позже как удалённое место для общей истории и обсуждения изменений. +::: {.text-center} +![Пример ручного хранения нескольких версий одного файла](./img/notFinal.gif){width=400px style="border: 1px solid #ddd"} +::: -## Что уже есть в проекте +Важная особенность Git в том, что участники могут работать и создавать версии независимо друг от друга на своих компьютерах. Каждый может работать над своей задачей, не мешая другим, даже если все редактируют один и тот же файл. Git поможет объединить изменения в одну общую версию. -Откройте папку `r-course`, созданную в предыдущем курсе. Не создавайте новый учебный проект и не переносите файлы. -В проекте могут оставаться `.R`-скрипты, `report.qmd`, `analysis.qmd`, другие документы, папки `data` и `out`. Это ожидаемое состояние. Git умеет отслеживать любые файлы; расширение не нужно менять ради Git. -Новый код этого курса будем писать в `paper.qmd`. Так текст, команды R и результат останутся в одном воспроизводимом документе Quarto. +Проект Git можно загрузить на сервер для надежного хранения и передачи файлов, совместной работы и публикации. +Самым популярным сервисом для этого является GitHub. +Он похож на облачные хранилища, такие как Google Drive или Dropbox, но с более продвинутым отслеживанием и объединением изменений, а также другими полезными функциями. +Вместо GitHub можно использовать другой сервер, например корпоративный во внутренней сети организации или использовать Git оффлайн --- только на своем компьютере. -## Репозиторий -**Репозиторий** — папка проекта вместе со скрытой служебной папкой `.git`. В `.git` находится история, ветки и настройки связи с удалённым репозиторием. -Шаблон R Project в Positron создаёт `.git` и `.gitignore` автоматически. Поэтому проект из R-курса уже должен быть репозиторием, хотя в нём пока нет коммитов. В главе \@ref(open-project) мы это проверим. +Если это всё ещё не убедило вас начать использовать Git, вот несколько примеров, когда он будет полезен: + + + + +- Возможно, вы оказывались в следующей ситуации. Вы вносите изменения в работающую программу или файл. Оцениваете результат и решаете отменить изменения. Вот только у вас нет копии оригинального файла, а вернуть прежнее состояние почему-то не получается --- программа никак не работает или работает иначе. С Git это делается одной командой, а экспериментальную версию можно сохранить и вернуться к ней позже. + +- Если вам понадобилась помощь, вы можете одной командой загрузить сделанные изменения на GitHub. Другой участник увидит, что вы пытаетесь сделать, и может загрузить решение проблемы, а вы так же одной командой получите исправленную версию. + +Благодаря последовательному внесению и отслеживанию изменений Git помогает организовать процесс анализа данных, обеспечивает воспроизводимость и упрощает совместную работу над проектом. + + + +::: {.callout .callout-info} + +Существуют другие системы контроля версий, например Mercurial и Subversion и вероятно, в будущем появятся новые. +Но благодаря простоте, эффективности и приобретенной популярности в основном используется Git. + +::: diff --git a/docs/01-02-install.md b/docs/01-02-install.md index 6ca85eb..94160e6 100644 --- a/docs/01-02-install.md +++ b/docs/01-02-install.md @@ -1,27 +1,59 @@ -# Установка Git {#install-git} +# Установка {#install} -Positron предоставляет интерфейс Source Control, но использует Git, установленный в операционной системе. Если Git не найден, Source Control покажет предложение его установить. Такое поведение описано в официальной главе [Git Version Control](https://positron.posit.co/git.html). +## Проверьте наличие Git {#terminal} -## Проверка +В комплекте с дистрибутивом Git устанавливается программа для терминала. +Чтобы открыть терминал в Positron, вызовите палитру команд и выберите **Terminal: Create New Terminal**. +В появившемся окне терминала введите команду `git` и нажмите клавишу Enter. -Откройте встроенный терминал командой **Terminal: Create New Terminal** из палитры команд и выполните: +Если вы видите результат как на скриншоте ниже, то Git установлен. +Иначе нужно его установить --- см. инструкцию для вашей операционной системы ниже. +После установки перезапустите Positron и повторите проверку. + +![Терминал Positron после команды git: показана справка с доступными командами. Чтобы получить состояние, выполните git в новом терминале]() + +## Windows + +Загрузите инсталлятор по ссылке [git-scm.com/downloads/win](https://git-scm.com/downloads/win) +(используйте **Standalone**, а не **Portable** версию, если в этом нет необходимости), запустите и следуйте инструкциям на экране, можете везде оставить опции, выбранные по умолчанию. + +## Mac OS + +**Вариант 1.** Git входит в инструменты разработчика от Apple, которые предоставляются бесплатно. Для установки введите в терминал следующую команду: ```sh -git --version +xcode-select --install ``` -Если команда вывела строку вида `git version 2.45.2`, установка готова. Конкретный номер может отличаться. +В появившемся окне нажмите кнопку **Install**. -![Терминал Positron после проверки версии Git: видна строка с установленной версией]() +**Вариант 2.** Последнюю версию Git можно установить используя сторонний менеджер программ [Homebrew](https://brew.sh). Если он у вас установлен, введите в терминал следующую команду: -## Если Git не установлен +```sh +brew install git +``` + +## Linux -- **Windows:** установите [Git for Windows](https://git-scm.com/download/win), оставив параметры установщика по умолчанию. -- **macOS:** установите [Xcode Command Line Tools](https://developer.apple.com/xcode/resources/) по предложению системы после команды `git --version` или установите Git с [официальной страницы](https://git-scm.com/download/mac). -- **Linux:** используйте менеджер пакетов своего дистрибутива; команды приведены в [официальной инструкции Git](https://git-scm.com/download/linux). +Используйте в терминале одну из следующих команд, в зависимости от вашего дистрибутива Linux. -После установки полностью перезапустите Positron и снова выполните `git --version`. +**Ubuntu или Debian** + +```sh +sudo apt-get update +sudo apt-get install git +``` + +**Fedora** + +```sh +sudo dnf install git +``` + +**Arch Linux** + +```sh +sudo pacman -S git +``` -::: {.callout .callout-warning} -Не скачивайте отдельные графические клиенты Git для прохождения курса. Они могут пригодиться позже, но названия действий и расположение элементов будут отличаться от Positron. -::: +Для других дистрибутивов см. [git-scm.com/downloads/linux](https://git-scm.com/downloads/linux). Не забудьте, что команды нужно запускать с правами администратора, т.е. начав с `sudo`, как в примере выше. diff --git a/docs/01-03-shell.md b/docs/01-03-shell.md index 8bc0e63..e7d8ff0 100644 --- a/docs/01-03-shell.md +++ b/docs/01-03-shell.md @@ -1,21 +1,41 @@ -# Имя автора {#git-identity} +# Настройка {#setup} -Каждый коммит хранит имя и электронную почту автора. При первом коммите Positron может попросить их настроить. Укажите имя, по которому коллеги вас узнают, и почту, связанную с GitHub. +Основной способ работы с Git --- это команда `git`, которую мы выполнили в предыдущей главе. +Команды для терминала вы встретите в документации и в интернете, ими легко поделиться и использовать в скриптах. +Кроме терминала есть много других способов и их даже можно использовать одновременно. -Если интерфейс показал ошибку `Please tell me who you are`, откройте терминал и выполните две команды, заменив значения своими: +Графические интерфейсы --- все они имеют ограничения и реализуют только часть возможностей Git, но достаточны для решения большинства задач. Это может быть интерфейс, встроенный в другие программы (например [Positron](https://positron.posit.co/git.html), [Pycharm](https://www.jetbrains.com/help/pycharm/using-git-integration.html), [VS Code](https://code.visualstudio.com/docs/sourcecontrol/overview)) или самостоятельная программа (например [GitHub Desktop](https://github.com/apps/desktop), [GitKraken](https://www.gitkraken.com) [и многие другие](https://git-scm.com/downloads/guis)); + +Веб-интерфейсы --- прямо на сайте GitHub можно редактировать отдельные файлы, а также выполнять некоторые команды. + +В этом курсе мы будем работать с Git одновременно в интерфейсе Positron и в терминале, как это делает большинство пользователей R каждый день, а также через GitHub. +Поэтому запомните, как запустить терминал в Positron --- +в палитре команд выберите **Terminal: Create New Terminal** ([см. скриншот в предыдущей главе](#terminal)). + +Перед началом работы необходимо сделать несколько настроек. +Укажите свое имя и адрес электронной почты, чтобы Git верно записывал информацию об авторе изменений. +В терминале выполните следующие команды, заменив **Your Name** на свое имя и **your@email.com** на свой email, не стирая кавычки. + +```sh +git config --global user.name "Your Name" +git config --global user.email "your@email.com" +``` + +Если вы уже использовали Git, то чтобы вывести в терминале текущее значение настроек выполните эти же команды, но не указывая новых значений. ```sh -git config --global user.name "Ivan Ivanov" -git config --global user.email "ivan@example.org" +git config --global user.name +git config --global user.email ``` -Проверьте результат: +Также заранее настроим способ объединения изменений, чтобы не возвращаться к этому позже. ```sh -git config --global --get user.name -git config --global --get user.email +git config --global pull.rebase false ``` -Настройка `--global` применяется ко всем будущим проектам этого пользователя. Если рабочий проект требует другую почту, откройте его папку и повторите команды без `--global`: значение сохранится только в этом репозитории. +Опция `--global` означает, что эти настройки будут использованы для всех проектов на компьютере и их достаточно сделать один раз. +Чтобы изменить настройки для отдельного проекта, выполните в нем эти же команды без опции `--global`. Например, иногда требуется указать корпоративный email для рабочего проекта на персональном компьютере. -Пароль GitHub здесь не нужен. Вход в GitHub выполним в браузере в части \@ref(github-part). +Это все настройки, которые понадобятся для курса. +Всего через команду `git config` их доступно более 800. diff --git a/docs/02-01-init.md b/docs/02-01-init.md index 108ea5b..dbc0f0b 100644 --- a/docs/02-01-init.md +++ b/docs/02-01-init.md @@ -1,25 +1,50 @@ -# (PART) Коммиты {-} +# (PART) Основы {-} -# Открытие проекта {#open-project} +# Создание репозитория {#git-init} -На экране Welcome в Positron выберите **Open Folder** и откройте папку `r-course`. Убедитесь, что в Explorer видны накопленные файлы R-курса, в том числе папка `data`. +Git может отслеживать изменения в любой папке на вашем компьютере. +Для этого нужно инициализировать в ней Git репозиторий. +**Репозиторий** --- это скрытая подпапка `.git`, в которой хранятся версии проекта и информация об изменениях. +Всё необходимое для работы Git содержится непосредственно в ней. -Откройте **Source Control** на панели активности слева. У изменённых файлов стоят обозначения состояния: `U` у ещё не отслеживаемых и `M` у изменённых. +Проект для этого курса уже создан в конце курса R. Откройте Positron и на экране Welcome выберите [Open Folder]{.figtext}, затем укажите папку проекта `r-course`. +Не создавайте новый проект, не переносите и не переименовывайте накопленные файлы. -![Окно Positron с открытым проектом r-course: в Explorer видны накопленные файлы, а в Source Control перечислены незафиксированные изменения]() +Убедитесь в том, что проект загружен: в панели [Explorer]{.figtext} должна быть открыта папка с файлами проекта, в том числе с папкой `data`. +Откройте [Source Control]{.figtext} на панели активности. Если там уже перечислены файлы проекта, репозиторий готов. -Если Source Control уже показывает файлы, репозиторий готов. Не нажимайте **Initialize Repository** повторно и не удаляйте `.git`. +![Окно Positron с открытой папкой r-course: в Explorer видны накопленные файлы и папка data, а в Source Control перечислены незафиксированные файлы. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-starter --state starter]() -## Если репозитория нет +Когда в Positron открыта папка проекта, R и Git ищут файлы в ней --- это так называемая **рабочая папка или рабочая область**. -В старой версии R-курса проект мог быть создан без Git. Тогда Source Control покажет кнопку **Initialize Repository**. Нажмите её один раз. Positron создаст `.git` и начнёт показывать изменения. +
Подробнее про поиск и адреса файлов. +На разных компьютерах, например у разных участников, проект может находиться в разных местах. +У пользователя с именем `mjordan` это может быть `/Users/mjordan/penguins`, +а у пользователя `scruz` допустим +`C:\Users\scruz\penguins`. -Официальная документация Positron описывает те же шаги: открыть папку, перейти в Source Control и выбрать **Initialize Repository**. +Если в документе использовать полный адрес файла, например: -## Что сейчас видит Git +```r +read.csv("/Users/mjordan/r-course/data/penguins.csv") +``` -Все накопленные файлы ещё не входят ни в один коммит. Это не ошибка и не повод чистить проект. В следующей главе сделаем один исходный коммит, который станет точкой отсчёта для новой работы. +то он будет работать только у пользователя `mjordan`. +У других полный адрес будет отличаться, и код «сломается». +Чтобы он работал у всех, нужно указывать адрес файла относительно рабочей папки. -::: {.callout .callout-warning} -Не переводите старые `.R`-файлы в `.qmd`, не удаляйте дополнительные данные и не заменяйте результаты. Исходный коммит должен быть точной фиксацией конца R-курса. -::: +```r +read.csv("data/penguins.csv") +``` +
+ +Рассмотрим служебные файлы проекта: + +- `.gitignore` --- содержит список файлов, которые Git не будет отслеживать; о том, зачем это нужно и как настроить [смотри в отдельном разделе](#gitignore) +- `.git` --- репозиторий; это скрытая папка, в которой Git будет хранить версии проекта + +Если вместо списка файлов Source Control показывает кнопку [Initialize Repository]{.figtext}, нажмите её один раз. Positron создаст репозиторий в уже существующей папке, не меняя остальные файлы. + +Итак, у нас есть проект --- папка, в которой мы будем работать, и +внутри нее Git репозиторий --- скрытая папка, в которой будут храниться версии проекта. +Приступим к созданию первой версии. diff --git a/docs/02-02-commit.md b/docs/02-02-commit.md index ecef4c4..1721e29 100644 --- a/docs/02-02-commit.md +++ b/docs/02-02-commit.md @@ -1,35 +1,42 @@ -# Первый коммит {#first-commit} +# Отслеживание изменений {#git-commit} -Коммит состоит из снимка выбранных файлов, автора, времени и сообщения. Сначала файлы попадают в **индекс** (staging area), затем Git записывает из индекса коммит. +Git отслеживает изменения в файлах, находящихся в рабочей папке. +Но не все подряд, как это делают Блокнот или Word при помощи команд «Отменить» и «Повторить», +а при помощи версий --- или, в терминах Git, **коммитов (commit)**. +Коммиты нужно создавать вручную, выбирая, какие файлы вы хотите зафиксировать, добавив в версию. -## Проверка изменений +Откройте в Positron панель с названием [Source Control]{.figtext}. +В отличие от списка файлов, на ней выводятся только те файлы, которые были изменены по сравнению с последней версией (коммитом). +Так как мы еще не создали ни одной версии, то в списке выводятся все файлы, накопленные к концу курса R. -В Source Control выберите любой текстовый файл. Откроется редактор различий (diff). Для нового файла одна сторона сравнения пуста, а весь текст отмечен как добавленный. +![Панель Source Control в Positron до первого коммита: в разделе Changes перечислены все накопленные файлы проекта. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-first-commit --state starter]() -Бинарные файлы, например `.png`, `.xlsx` и `.rds`, Git сохранит, но не покажет построчное сравнение. Перед коммитом откройте их обычным способом и убедитесь, что это нужные файлы. +
Нет панели Git? +Значит, репозиторий не был создан или Git не установлен. +[Проверьте наличие Git](#install), затем вернитесь к [созданию репозитория](#git-init). +
-![Редактор различий Positron для нового текстового файла из проекта r-course и список Changes в Source Control]() +Чтобы создать коммит (версию), нажмите `+` напротив заголовка [Changes]{.figtext}. +После этого файлы окажутся в разделе [Staged Changes]{.figtext}, то есть будут добавлены в **индекс (staging)** --- +промежуточную область для выбора файлов, которые будут зафиксированы. +Файлы, оставшиеся в разделе [Changes]{.figtext}, будут находиться в рабочей папке, но в коммит не попадут. +Вы можете добавить их в следующую версию позже или отменить изменения. -## Добавление в индекс +![Source Control после добавления файлов в индекс: все файлы находятся в разделе Staged Changes. Подготовьте состояние starter и нажмите Stage All Changes]() -Наведите указатель на заголовок **Changes** и нажмите `+` (**Stage All Changes**). Файлы переместятся в раздел **Staged Changes**. +Перед фиксацией выберите несколько текстовых файлов и посмотрите, что изменилось в них. +Для нового файла Positron покажет весь текст как добавленный. +Введите краткое описание в поле сообщения коммита. +В нашем примере мы закончили курс R, это и будет подходящим описанием: `Зафиксировал результат курса R`. +Нажмите кнопку [Commit]{.figtext}. -Проверьте список ещё раз. В первый коммит должны войти все накопленные файлы проекта, кроме уже скрытых правилами `.gitignore`. +![Source Control перед первым коммитом: проверен diff, введено сообщение Зафиксировал результат курса R. Подготовьте состояние starter, добавьте все файлы в индекс и введите сообщение]() -## Запись коммита +Обратите внимание, теперь панель [Source Control]{.figtext} со списком измененных файлов пуста --- +это значит, что изменений по сравнению с последней версией, которую мы только что создали, нет. -Введите сообщение: +![Source Control сразу после первого коммита: разделы Changes и Staged Changes пусты. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-baseline --state baseline]() -```text -Зафиксировал результат курса R -``` +Теперь у нас есть версия проекта, к которой можно вернуться в любой момент и начать работу с этого места. -Нажмите **Commit**. Если Positron попросит настроить автора, вернитесь к главе \@ref(git-identity). -![Source Control сразу после исходного коммита: разделы Changes и Staged Changes пусты, в Graph виден один коммит]() - -Пустой список изменений означает, что рабочая папка совпадает с последним коммитом. Старые файлы никуда не переместились: Git только записал их состояние. - -::: {.callout .callout-info} -Сообщение коммита отвечает на вопрос «что сделал этот шаг?». Короткая форма с глаголом помогает читать историю: «Добавил импорт данных», «Исправил подпись оси». -::: diff --git a/docs/02-03-practice.md b/docs/02-03-practice.md index 9799a07..db7fb00 100644 --- a/docs/02-03-practice.md +++ b/docs/02-03-practice.md @@ -1,18 +1,36 @@ -# Рабочий цикл {#commit-workflow} +# Рабочий процесс {#git-commit2} -Теперь начнём отдельный анализ для Git-курса. Каждая небольшая законченная задача станет коммитом: +В предыдущей главе мы научились создавать коммиты (версии). +Работая с Git, это нужно делать регулярно --- +обычно после выполнения задачи или её части, +после внесения исправлений или просто чтобы зафиксировать изменения. +Коммит сохраняет «стабильную» версию проекта, к которой можно вернуться или сравнить с ней сделанные изменения. -1. изменить и сохранить файл; -2. открыть diff и проверить изменение; -3. добавить нужные файлы в индекс; -4. записать коммит; -5. убедиться, что Source Control снова пуст. +Рассмотрим процесс работы над проектом подробнее: -## Документ Quarto +1. Мы создали коммит, и с тех пор в рабочей папке не было изменений. +2. Выполняем задачу и добавляем нужные для ее решения изменения в индекс, а лишние, например код для отладки или временные файлы, удаляем. +3. Перед созданием коммита обязательно проверяем изменения, которые в него попадут. + Начинающие пользователи часто либо добавляют ненужный код, не относящийся к задаче, либо забывают добавить код, без которого не будет работать остальная часть проекта. +4. Создаём коммит и получаем чистую рабочую папку --- без изменений относительно нового коммита. + Можно переходить к следующей задаче. -Создайте в корне проекта файл `paper.qmd`. Накопленные `.R`-скрипты остаются без изменений, но весь новый код пишем в Quarto. +![Рабочий цикл Git: чистая рабочая папка, изменения, индекс, проверка и новый коммит](./img/02-02-06-workflow.png){width=540px} -Добавьте настройки и первый блок R: +Такой процесс помогает упорядочить внесение изменений и сделать результат воспроизводимым. +Он хорошо подходит для анализа данных, потому что его легко разделить на задачи, из которых получатся коммиты. +Попробуем сделать это на практике и продолжим анализ длины клюва антарктических пингвинов. +Каждая подглава этой главы соответствует одной задаче и завершается одним коммитом. + +## Импорт данных + +Данные уже находятся в файле `data/penguins.csv`, который вошёл в первый коммит. Не скачивайте и не переносите его. + +Создайте документ Quarto для анализа. В Positron выберите [New → New File]{.figtext}, затем [Quarto Document]{.figtext} и сохраните файл под названием `paper.qmd` в корне проекта. + +![Диалог New File в Positron с выбранным типом Quarto Document и открытый файл paper.qmd. Подготовьте состояние baseline и выполните New → New File → Quarto Document]() + +Добавьте в начало документа заголовок: ```yaml --- @@ -21,6 +39,10 @@ format: html --- ``` +Скопируйте следующий код для импорта данных в блок R и сохраните документ. +Выполните блок в Positron. +Если импорт данных работает, в консоли появится вектор из чисел. + ``` r data <- read.csv("data/penguins.csv") @@ -28,17 +50,49 @@ x <- data$bill_len |> na.omit() x ``` -Путь начинается от корня проекта. Данные уже находятся в `data`, поэтому ничего скачивать и перекладывать не нужно. В новом коде используем базовую трубу `|>`. +Убедитесь, что файл `paper.qmd` появился на панели [Source Control]{.figtext}. +Добавьте его в индекс и создайте коммит с описанием «Добавил импорт данных в paper.qmd». +Перед коммитом обязательно проверьте содержимое `paper.qmd`, +так как часто пользователи забывают сохранить файл перед добавлением в индекс. + +![Source Control перед коммитом импорта: в Staged Changes находится paper.qmd и открыт его diff. Подготовьте состояние baseline, создайте paper.qmd по заданию и добавьте его в индекс]() + +После создания коммита список измененных файлов на панели [Source Control]{.figtext} должен быть пуст. + +## Визуализация + +Анализ новых данных полезно начинать с исследования распределения. +Для этого присвоим данные с длиной клюва переменной `x` и построим несколько вариантов гистограммы с разной шириной столбца. +Сохраните приведённый ниже код в тот же файл, запустите и посмотрите графики. + + +``` r +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() + +hist(x, breaks = seq(30, 60, 4)) +hist(x, breaks = seq(30, 60, 2)) +hist(x, breaks = seq(30, 60, 1)) +``` + +После сохранения файл `paper.qmd` снова появился в списке изменений на панели [Source Control]{.figtext}. +Добавьте его в индекс и проверьте изменения в окне коммита. -Выполните блок в текущей R-сессии. Positron передаст код из документа Quarto в Console. Убедитесь, что вектор `x` создан без ошибки. +Вы уже могли заметить, что новые строки выделяются зеленым цветом. +Красным цветом выделяются удаленные строки, а неизмененные остаются белыми. +Такой формат записи изменений называется **«дифф» (diff)**. +Обратите внимание, что по умолчанию Git анализирует строки, а не отдельные слова или символы. +Поэтому получился следующий дифф: старая вторая строка была удалена, новая вторая строка добавлена (см. номера строк слева), хотя мы всего лишь добавили присвоение `x <- ` в начало строки. -![Открытый paper.qmd после выполнения блока: в Console виден результат импорта data/penguins.csv]() +![Diff файла paper.qmd: добавлены присвоение x и три варианта гистограммы, новые строки выделены зелёным. Подготовьте состояние paper и замените блок R кодом из раздела «Гистограмма»]() -Сохраните файл, проверьте diff и создайте коммит `Добавил импорт данных в paper.qmd`. +Убедитесь, что сделанные изменения соответствуют диффу на скриншоте выше, и создайте новый коммит с описанием «Добавили гистограммы для длины клюва». -## Гистограмма +## Экспорт -Замените блок кода на следующий: +Гистограмма с шириной столбца 2 выглядит наиболее информативно. +Такой график можно и опубликовать. +Чтобы экспортировать изображение, замените блок R в `paper.qmd` следующим кодом и выполните его. ``` r @@ -50,10 +104,31 @@ hist(x, breaks = seq(30, 60, 2)) dev.off() ``` -Выполните блок. В папке `out` появится `penguins-hist.png`. +После этого в списке изменений на панели [Source Control]{.figtext}, кроме файла `paper.qmd`, появился файл с изображением `out/penguins-hist.png`. +Его мы тоже добавим в коммит. +Во-первых, так другие участники, загрузив проект, сразу увидят результат без необходимости выполнять документ. +Во-вторых, если вы измените ширину столбца или другие настройки графика, будет удобно сравнить старую и новую версии. + +Добавьте оба файла в индекс, проверьте изменения, изучив дифф, и создайте коммит с описанием «Сохранил гистограмму длины клюва». + +На этом остановимся и посмотрим историю версий в журнале Git. + +::: {.callout .callout-info} +Делайте коммиты часто и не придавайте слишком большое значение планированию. +Коммит это не концептуально новая версия проекта, а просто шаг или изменения, которые вы хотите зафиксировать. + + +::: + +::: {.callout .callout-info} +Не обязательно добавлять в коммит все изменения сразу или их отменять --- они могут оставаться в рабочей папке сколько угодно. +Тем не менее старайтесь не копить изменения, потому что тогда версия в репозитории будет отличаться от версии, с которой вы работаете, а значит, теряется смысл системы контроля версий и возникают ошибки. + + +::: + + + -В Source Control выберите `paper.qmd` и проверьте добавленные строки. Затем добавьте в индекс `paper.qmd` и `out/penguins-hist.png`, но не остальные случайные изменения. Создайте коммит `Сохранил гистограмму длины клюва`. -![Source Control перед коммитом гистограммы: в Staged Changes находятся только paper.qmd и out/penguins-hist.png]() -Теперь у проекта есть исходная версия, импорт данных и готовый график в трёх отдельных коммитах. diff --git a/docs/02-04-log-n-diff.md b/docs/02-04-log-n-diff.md index 8dd7692..8deda40 100644 --- a/docs/02-04-log-n-diff.md +++ b/docs/02-04-log-n-diff.md @@ -1,25 +1,32 @@ -# История и различия {#history-diff} +# Просмотр истории {#git-log} -Разверните **Source Control Graph** в Source Control. В нём видны коммиты текущей ветки `main`. +До этого мы просматривали изменения только по сравнению с последней версией в момент создания коммита. Предыдущие коммиты можно посмотреть в **журнале (log)**. -Выберите коммит `Сохранил гистограмму длины клюва`. Под ним появится список изменённых файлов. Выберите `paper.qmd`, чтобы открыть diff именно для этого коммита. +Журнал позволяет изучить изменения от других участников или вспомнить свои собственные, и зачем они сделаны. +Поэтому так важно писать ясные и содержательные описания коммитов. +Используя журнал, можно найти, когда сделаны изменения, приведшие к ошибке, и вернуть проект к предыдущему состоянию. +В конце концов, его можно использовать для отчетности и бизнесс-аналитики по проекту. -![Source Control Graph с тремя учебными коммитами и открытым diff файла paper.qmd для коммита с гистограммой]() +Чтобы открыть журнал, разверните [Source Control Graph]{.figtext} на панели [Source Control]{.figtext}. +В открывшемся окне выводится список коммитов в обратном порядке --- последние коммиты находятся вверху. +В списке выводится краткая информация о коммите, а под списком подробная информация по выделенному коммиту. -В diff удалённые строки отмечены красным, добавленные — зелёным. Git сравнивает строки, поэтому даже изменение одного символа может выглядеть как удаление старой строки и добавление новой. +![Source Control Graph в Positron: показана последовательность учебных коммитов и сведения о выбранном коммите. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-histogram --state histogram]() -Для истории одного файла откройте `paper.qmd`, затем разверните **Timeline** в Explorer. Там можно выбрать прежний коммит и посмотреть, как менялся только этот файл. +- SHA --- так называемый хэш коммита, который является его уникальным идентификатором в репозитории +- Author --- автор коммита \, [которые были указаны в настройках](#setup) +- Date --- дата и время создания коммита +- Subject --- описание коммита +- Parent --- хэш (идентификатор) предыдущего коммита -## Рабочая папка, индекс и коммит +Под выбранным коммитом показаны изменённые файлы. Выберите текстовый файл, чтобы открыть дифф --- изменения, сделанные в этом коммите по сравнению с предыдущим. +Для больших файлов выводятся только те строки, которые поменялись, а также несколько строк выше и ниже, чтобы был понятен контекст. +Чтобы посмотреть историю только одного файла, выберите его в [Explorer]{.figtext} и откройте представление [Timeline]{.figtext}. -Эти три состояния полезно различать: +Даже если вы работаете в одиночку, полезно иметь под рукой историю изменений. +Но по настоящему эта функция полезна, +когда приходится работать с несколькими версиями одновременно, +например при работе в команде. +[Об этом далее](#git-branch). -| Состояние | Что содержит | -|---|---| -| Рабочая папка | Сохранённые на диске файлы, включая незаконченные изменения | -| Индекс | Только изменения, выбранные для следующего коммита | -| Последний коммит | Уже записанный снимок проекта | -Кнопка `+` переносит изменение из рабочей папки в индекс. Кнопка `−` у **Staged Changes** убирает его из индекса, но не удаляет из файла. **Commit** записывает содержимое индекса в историю. - -Официальное руководство [Staging and committing changes](https://code.visualstudio.com/docs/sourcecontrol/staging-commits) использует эту же модель. diff --git a/docs/03-01-branches.md b/docs/03-01-branches.md index e0832dc..fa2ba32 100644 --- a/docs/03-01-branches.md +++ b/docs/03-01-branches.md @@ -1,18 +1,51 @@ # (PART) Ветки {-} -# Альтернативный график {#branches} -Ветка — указатель на последовательность коммитов. Она позволяет экспериментировать, не меняя основную линию `main`. -Представим, что рецензент попросил заменить гистограмму на ящик с усами. Сделаем вариант в отдельной ветке. +# Введение {#branch} -Убедитесь, что Source Control пуст. Нажмите название `main` в строке состояния и выберите **Create new branch…**. То же действие доступно из палитры команд как **Git: Create Branch**. +До этого мы создавали версии только последовательно, +чтобы записывать историю изменений. +Git позволяет создавать параллельные версии. +Это могут быть как версии различных участников (collaborators) с различных устройств, +так и несколько альтернативных версий на одном и том же компьютере. +Таким образом участники могут создавать и обмениваться различными вариантами изменений. +Git позволяет эффективно объединять эти изменения, делая совместную работу комфортной, +чего, к слову, не умеют облачные сервисы вроде Google Drive. -Введите название `boxplot` и выберите `main` как исходную ветку. Positron сразу переключится на новую ветку; её имя появится в строке состояния. +Для этого используются так называемые ветки (branch). +Почему ветки? Потому что начиная с выбранного коммита история изменений разветвляется. -![Positron после создания ветки boxplot: имя ветки видно в строке состояния, Source Control пуст]() +По умолчанию, мы работаем в ветке `main` +(ранее ветка по умолчанию называлась `master`, будьте готовы встретить и такое название). +Ее можно сравнить со стволом дерева --- вот он слева на изображении. +В нашем проекте с пингвинами в ветке `main` 4 коммита, последний из которых содержит гистограмму для публикации. -Замените код графика в `paper.qmd`: +![Source Control Graph: последовательные коммиты ветки main, последний содержит гистограмму. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-branches --state histogram]() + +Представим ситуацию --- из журнала приходит ответ Рецензента 2, в котором он просит заменить гистограмму на ящик с усами. +С одной стороны, можно податься в журнал, где знают, что такое гистограмма, +с другой, можно хотя бы попробовать удовлетворить пожелания рецензента и, +если нам не понравится новая диаграмма, просто удалить изменения. + +# Создание ветки {#git-branch} + +Чтобы спокойно поэкспериментировать создадим новую ветку. +Так будет проще удалить изменения и они не будут мешать, если мы захотим поправить что-то действительно важное в основной ветке `main`. + +В Positron нажмите название текущей ветки `main` в строке состояния и выберите [Create new branch…]{.figtext}. + +![Меню веток Positron с выбранным действием Create new branch. Подготовьте состояние histogram и нажмите название main в строке состояния]() + +В появившемся поле введите название, например `boxplot`, и подтвердите создание. +Positron переключится на ветку `boxplot`. + +![Positron после создания ветки boxplot: название новой ветки видно в строке состояния. Подготовьте состояние histogram и создайте ветку boxplot]() + +Обратите внимание, что название ветки в строке состояния поменялось с `main` на `boxplot`. + +Вернемся к пингвинам. +Замените блок R в документе `paper.qmd` на следующий: ``` r @@ -24,8 +57,17 @@ boxplot(x) dev.off() ``` -Выполните код. Удалите `out/penguins-hist.png`: в этой версии проекта он больше не нужен. Добавьте в индекс изменение `paper.qmd`, удаление гистограммы и новый `out/penguins-boxplot.png`. +Сохраните файл и выполните блок. +Обратите внмание, что мы поменяли название файла. +Старый файл `out/penguins-hist.png` в этой версии нам не нужен и его необходимо удалить. +Не переживайте, благодаря Git, в основной ветке `main` он останется. +В [Explorer]{.figtext} нажмите правой кнопкой на файл `out/penguins-hist.png` и выберите [Delete]{.figtext}. + +![Explorer в Positron перед удалением файла out/penguins-hist.png. Подготовьте состояние histogram, создайте ветку boxplot и выполните блок с boxplot]() + +Отметьте все изменения для фиксации и создайте коммит. +Обратите внимание, что удаление файла это тоже изменение, которое надо отметить. -Создайте коммит `Заменил гистограмму на ящик с усами`. +![Source Control перед коммитом в ветке boxplot: изменён paper.qmd, удалена гистограмма и добавлен новый боксплот. Подготовьте состояние boxplot-branch и выполните git reset --soft HEAD^]() -![Source Control Graph после коммита в boxplot: main указывает на гистограмму, boxplot — на новый коммит с ящиком с усами]() +Теперь отложим эксперименты и вернемся к прежней версии. diff --git a/docs/03-02-checkout.md b/docs/03-02-checkout.md index 729bc33..acc27d6 100644 --- a/docs/03-02-checkout.md +++ b/docs/03-02-checkout.md @@ -1,25 +1,36 @@ -# Переключение веток {#switch-branches} +# Переключение веток {#git-checkout} -Нажмите `boxplot` в строке состояния и выберите `main`. Эта операция называется переключением, а в терминах Git — checkout или switch. +Для переключения ветки нажмите на название текущей ветки в строке состояния Positron. +В выпадающем списке выберите ветку на которую хотите переключиться (`main`). -Откройте `paper.qmd` и папку `out`. В `main` снова должна быть гистограмма и не должно быть нового боксплота. Git привёл рабочую папку к коммиту выбранной ветки. +![Меню веток Positron: для переключения выбрана ветка main. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-checkout --state boxplot-branch]() -![Ветка main после переключения: paper.qmd содержит hist(), в out виден penguins-hist.png]() +Убедитесь, что код документа `paper.qmd` вернулся к прежнему состоянию и строит гистограмму, +а в списке файлов находится файл с гистограммой `out/penguins-hist.png` и нету файла `out/penguins-boxplot.png`. -## Защита незаписанной работы +![Ветка main после переключения: paper.qmd снова содержит гистограмму, а в папке out находится penguins-hist.png. Подготовьте состояние boxplot-branch и выполните git switch main]() -В `paper.qmd` добавьте подпись оси: +Это было просто. +Но есть один случай, когда +Git откажется переключать ветку --- если это приведет к потере данных. + +Например, замените блок R в `paper.qmd` на следующий (добавилась подпись оси X): -```r -hist(x, breaks = seq(30, 60, 2), xlab = "Bill length, mm") -``` -Сохраните файл, но пока не создавайте коммит. Попробуйте переключиться на `boxplot`. +``` r +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -Если переключение перезапишет изменённые строки, Git остановит операцию и предложит сначала сохранить работу. Это защитное поведение: незакоммиченные изменения не потеряны, вы по-прежнему на `main`. +png("out/penguins-hist.png") +hist(x, breaks = seq(30, 60, 2), xlab = "Bill length, mm") +dev.off() +``` -![Уведомление Positron об отказе переключить ветку из-за незакоммиченных изменений в paper.qmd]() +Сохраните файл и попробуйте переключиться на ветку `boxplot`. +Вы получите сообщение как на скриншоте ниже. +Если бы Git переключил ветку, ему бы пришлось перезаписать файл `paper.qmd`, в который мы внесли изменения, но не зафиксировали. +Поэтому, чтобы не потерять изменения при переключении, сначала необходимо их зафиксировать создав коммит. -Вернитесь в Source Control, проверьте diff и создайте коммит `Добавил подпись оси гистограммы`. После этого переключитесь на `boxplot` и обратно на `main`, чтобы проверить обе версии. +![Сообщение Positron об отказе переключить ветку из-за незафиксированных изменений в paper.qmd. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-dirty-main --state dirty-main; затем выберите boxplot]() -Если нужно временно убрать незаконченные изменения без коммита, используйте **Git: Stash (Include Untracked)**. Для основного упражнения stash не нужен. +Создайте коммит и попробуйте переключиться на ветку `boxplot` и обратно на ветку `main`. diff --git a/docs/03-03-merge.md b/docs/03-03-merge.md index 372762b..52923e8 100644 --- a/docs/03-03-merge.md +++ b/docs/03-03-merge.md @@ -1,35 +1,94 @@ -# Слияние и конфликт {#merge-conflict} +# Слияние веток {#git-merge} -Сейчас `main` и `boxplot` по-разному изменили одну строку `paper.qmd`. Объединим ветки и разрешим конфликт осознанно. +[Откройте журнал](#git-log) и разверните [Source Control Graph]{.figtext}, чтобы посмотреть все ветки. +На диграмме наглядно видно почему это называется веткой. -Переключитесь на `main`. Откройте палитру команд, выполните **Git: Merge Branch** и выберите `boxplot`. +![Source Control Graph перед слиянием: ветки main и boxplot расходятся от общего коммита. Подготовьте состояние conflict и выполните git merge --abort]() -Git автоматически объединит независимые изменения, но остановится на `paper.qmd`: обе ветки изменили код графика, и программа не знает, какой вариант нужен. +Если мы или другой участник проекта, решим принять эти изменения в основную ветку `main`, +нам нужно выполнить операцию «слияния» (merge). +Выполним слияние в терминале. +Команда совсем не сложная. -В Source Control файл появится в разделе **Merge Changes** с предупреждением. Это незавершённое слияние, а не повреждение проекта. +Для начала переключитесь на ветку, в которую будут вливаться изменения --- +в нашем случае это `main` ([см. переключение веток](#git-checkout)). +Откройте терминал ^[В палитре команд Positron выберите **Terminal: Create New Terminal**] и введите команду для слияния с веткой `boxplot`. -![Source Control после Git: Merge Branch: paper.qmd находится в Merge Changes, слияние ожидает решения]() +```sh +git merge boxplot -## Редактор слияний +``` + +Git попытается автоматически объединить изменения из обеих веток и создать новый коммит. +В большинстве случаев этого достаточно, +но любая совместная работа может приводить к конфликтам --- +когда в обеих ветках была изменена одна и та же строка, но разным образом. +Какую версию предпочтет Git? +Git предпочтет выдать ошибку и попросит вас разрешить конфликт. + +В списке изменений мы видим, +что Git автоматически выбрал изменения связанные с новым и старым файлом для графика +`out/penguins-hist.png` и `out/penguins-boxplot.png`, +но лишь частично для документа `paper.qmd`. + +![Source Control после команды git merge boxplot: файлы графиков объединены автоматически, а paper.qmd отмечен как конфликтующий. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-conflict --state conflict]() -Нажмите `paper.qmd` правой кнопкой и выберите **Open in Merge Editor**. Редактор показывает три области: +Причина в том, что мы вносили изменения в код графика в ветке `main` после того как изменили его в ветке `boxplot`. +Откройте файл `paper.qmd`. +Git любезно оставил для нас обе версии кода разделив специальными символами. +После строки `<<< HEAD` идет версия из текущей ветки, +строка `===` отделяет две версии друг от друга, +а строка `>>> boxplot` завершает версию из ветки `boxplot`. -- **Incoming** — изменение из `boxplot`; -- **Current** — изменение из `main`; -- **Result** — итог, который будет записан. +![Файл paper.qmd с маркерами конфликта: показаны версии кода из main и boxplot. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-conflict-file --state conflict]() -В Result оставьте боксплот из Incoming и добавьте к нему подпись из Current: +Наша задача переписать выделенный участок (строки 4-12) в одну версию и убрать спецсимволы. +Важно понимать, что Git просто вставил в документ кусок текста, +но это всё ещё обычный текст документа Quarto и мы должны привести его в рабочее состояние. + +Нам нужна версия из ветки `boxplot`, но мы хотим добавить в нее подпись оси, как это было сделано в ветке `main`. +Для этого оставим нижнюю версию (строки 9-11) и удалим лишние строки (4-8 и 12) +и добавим подпись, только для ящика с усами это должна быть подпись оси Y. +В итоге должен получиться следующий код. + + +``` r +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -```r png("out/penguins-boxplot.png") boxplot(x, ylab = "Bill length, mm") dev.off() ``` -Нажмите **Complete Merge**. Убедитесь, что в Result нет строк `<<<<<<<`, `=======` и `>>>>>>>`, а `paper.qmd` находится в **Staged Changes**. +Сохраните файл и выполните блок. +Создайте коммит и +не забудьте добавить в индекс внесенные изменения, +в том числе обновившийся файл `out/penguins-boxplot.png`, который теперь содержит подпись оси. +Обычно сообщение коммита о слиянии веток содержит следующий текст «Merge branch название-ветки», но можете придумать свое. + +![Source Control перед коммитом слияния: paper.qmd и обновлённый out/penguins-boxplot.png добавлены в индекс. Подготовьте состояние conflict, разрешите конфликт по заданию и добавьте файлы в индекс]() -![Редактор слияний Positron: Incoming содержит boxplot, Current — hist с подписью, Result — boxplot с ylab]() +Итак, мы успешно слили изменения из ветки `boxplot` в основную ветку `main`. +Теперь можно продолжить работу в основной ветке. +Еще лучше будет создать очередную ветку для новых изменений, выполнить работу в ней и точно так же слить в основную. + +![Source Control Graph после слияния: ветки boxplot и main соединены коммитом слияния. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-merged --state merged]() + +
Как удалить ветку? +Слитую ветку можно удалить. +Выполните в терминале команду: + +```sh +git branch -d boxplot +``` + +Если ветка не была слита, Git откажется ее удалять, ведь могут быть потеряны сделанные в ней изменения. +Если вы действительно уверены, что они вам не нужны и вы хотите удалить не слитую ветку, выполните команду: + +```sh +git branch -D boxplot +``` +
-Обновите `out/penguins-boxplot.png`, добавьте его в индекс и создайте коммит `Слил ветку boxplot`. -Если нужно отказаться от всего слияния, выполните **Git: Abort Merge** из палитры команд. Git вернёт проект к состоянию до попытки merge. diff --git a/docs/03-04-conclusion.md b/docs/03-04-conclusion.md index e8d027e..7afd073 100644 --- a/docs/03-04-conclusion.md +++ b/docs/03-04-conclusion.md @@ -1,21 +1,58 @@ -# Итог работы с ветками {#branches-conclusion} +# Заключение -Разверните Source Control Graph. От общего коммита расходятся `main` и `boxplot`, а коммит слияния снова соединяет линии. +Теперь вы умеете создавать и объединять ветки --- +это одни из ключевых функций Git, особенно при совместной работе. +Благодаря простоте работы с ветками, рекомендуется создавать их чаще. +Чем меньше в ветке изменений, тем проще ее слить, и тем ниже вероятность конфликтов из-за одновременных правок одной и той же части проекта. Это отражает известную идею, что при работе в команде лучше синхронизироваться чаще. -![Source Control Graph после слияния: видны расхождение main и boxplot и merge-коммит в main]() +Рассмотрим продвинутые способы использования веток, а также для чего их использовать не стоит. -Теперь вы умеете: +Для начала уточним, что можно создать ветку от любой другой, а не только от основной ветки `main`. Уровень вложенности и количество веток не ограничены. +После слияния ветки она не прекращает свое существование --- в ней можно продолжить работу, а после слить еще раз. +На практике вам вряд ли понадобится больше 3-х уровней вложенности, а ветки лучше периодически удалять, чтобы не запутаться. -- создавать ветку командой **Git: Create Branch**; -- переключаться через индикатор ветки или **Git: Checkout to**; -- объединять ветки командой **Git: Merge Branch**; -- разрешать конфликт в трёхстороннем редакторе; -- отменять незавершённое слияние командой **Git: Abort Merge**. +## Тематические ветки (feature branch) -После проверки слитую локальную ветку можно удалить: переключитесь на `main`, выполните **Git: Delete Branch** и выберите `boxplot`. +Тематическая ветка содержит изменения, связанные с конкретной задачей или направлением работы. +Это может быть новый этап анализа или изменения в уже сделанные этапы, например: -::: {.callout .callout-warning} -Не удаляйте ветку, пока её изменения не слиты и не стали ненужными. Удаление несохранённой линии истории сложнее отменить, чем обычное редактирование файла. -::: +- ветка в которой мы визуализировали данные при помощи графиков, может называться `visualize` или `plot`; +- ветка в которой добавляются модели, может называться `model` или, если это более специфическая модель, например нелинейная, то `model-nle`; +- ветка в которой обновлены данные для уже выполненного анализа `update-data`; +- в нашем репозитории, когда мы заменили график на ящик с усами, ветка называлась `boxplot`. -В следующей части вынесем репозиторий на GitHub и повторим этот процесс как предложение изменений для коллег. +Если в проекте используется трекер задач или ошибок, +то зачастую работа выполняется в отдельной ветке с названием соответствующим номеру из трекера, +например `issue42` или `ticket58`. + +Это самый частый способ использования веток, применяемый независимо от размеров проекта и количества участников. + +## Долгоживущие ветки (long-running branches) + +Этот подход часто применяется для крупных проектов, когда нужно обеспечить высокую стабильность продукта, как правило при разработке программного обеспечения. + +Ветка `main` содержит стабильную версию. +От нее создается ветка `develop` в которой ведется разработка. +Тематические ветки создаются от ветки `develop` и вливаются в нее. +Когда разработка очередной версии завершилась, +изменения из ветки `develop` стабилизируются --- проходят тестирование и ревью, +после чего вливаются в стабильную ветку `main`. + +Далее цикл повторяется --- разработка следующей версии продолжается в ветке `develop` с использованием тематических веток, после чего она снова сливается с веткой `main`. + +## Когда не стоит использовать ветки + +Выше описаны лишь некоторые наиболее часто используемые процессы работы построенные вокруг веток. +Существует и можно придумать много других, подходящих для вас или вашей команды. + +Но у всех применений веток есть общая черта --- это способ организации внесения изменений в проект и рано или поздно эти изменения должны быть слиты или удалены. + +Ветки это не способ структурирования самого анализа или программы. +Например, если у вас есть несколько моделей и вы собираетесь поддерживать их все, то вероятно они должны быть в одной ветке, а не в отдельных. +Иначе потребуется следить за тем, чтобы изменения вносились в каждую ветку --- это утомительно и чревато ошибками. +Для работы с несколькими моделями одновременно придется переключаться и работать с несколькими ветками, что противоречит большинству способов их использования, например описанных выше. + +Другая частая ошибка --- участники создают ветки с собственным именем (`ivan`, `masha-work`) и используют их как личные папки для хранения своих файлов не связанных с файлами других участников. +Ветки предназначены для внесения изменений в один общий проект. Следует либо интегрировать эти файлы в проект, возможно отдельной веткой, либо хранить в другом месте. + +В следующей части мы посмотрим как организовать совместную работу при помощи «удаленных» (remote) веток и сервиса GitHub. diff --git a/docs/04-01-github.md b/docs/04-01-github.md index 3622ec6..1fdadf6 100644 --- a/docs/04-01-github.md +++ b/docs/04-01-github.md @@ -1,23 +1,29 @@ # (PART) GitHub {-} -# Аккаунт и вход {#github-part} +# Настройка {#github} -Git хранит историю на вашем компьютере. GitHub хранит копию репозитория на сервере, поэтому проект можно открыть с другого устройства, показать преподавателю и обсудить изменения с коллегами. +GitHub --- это веб-сервис для хранения Git репозиториев и совместной работы. +Ваши файлы размещаются на удаленном сервере и доступны публично или приватно для загрузки другими пользователями. В некотором смысле это аналог Dropbox или Google Drive для Git. +Помимо хранения репозиториев, GitHub предоставляет другие инструменты: отслеживание задач, обсуждение изменений, запуск тестов и сборок и многое другое. -Создайте аккаунт на [github.com](https://github.com/signup), если его ещё нет. Имя пользователя станет частью адресов репозиториев, поэтому лучше использовать короткое имя латиницей. +Для работы с GitHub вам понадобится зарегистрировать учетную запись и войти в неё из Positron. -Positron включает расширения **GitHub** и **GitHub Pull Requests and Issues**. При первой публикации или отправке изменений редактор предложит войти. Выберите **Sign in with GitHub**, подтвердите открытие браузера и разрешите доступ. +## Регистрация на GitHub -![Positron показывает запрос Sign in with GitHub перед первой публикацией репозитория]() +Перейдите на сайт github.com и зарегистрируйте учетную запись нажав на кнопку [Sign up]{.figtext} в верхнем правом углу или войдите в существующую учетную запись нажав [Sign in]{.figtext}. -После подтверждения вернитесь в Positron. Не создавайте classic personal access token для этого упражнения: обычный путь входа проходит через браузер. +E-mail при регистрации не обязательно должен совпадать с указанным при настройке Git в [Главе 1](#setup). Дополнительные e-mail адреса можно добавить после регистрации [на странице настроек](https://github.com/settings/emails). +Это рекоммендуется сделать, чтобы GitHub мог ассоциировать сделанные на компьютере коммиты с вашей учетной записью онлайн. -::: {.callout .callout-warning} -Никому не отправляйте пароли, токены, приватные ключи и секреты webhook. Не добавляйте их в `.qmd`, `.R`, `.env` или другие файлы репозитория. -::: +## Вход из Positron -## Git и GitHub — разные системы +Positron включает интеграцию с GitHub. При первой публикации репозитория редактор предложит войти в учётную запись. +Выберите [Sign in with GitHub]{.figtext}, подтвердите открытие браузера и разрешите доступ. +После входа вернитесь в Positron. -Коммит, ветка и слияние работают в Git без GitHub. GitHub добавляет удалённый репозиторий, права доступа, pull request, обсуждения и автоматические проверки. +![Positron предлагает войти в GitHub перед первой публикацией репозитория. Чтобы получить состояние, выйдите из GitHub в Positron и выберите Publish to GitHub]() -Если сайт GitHub недоступен, локальные коммиты продолжают работать. Когда связь восстановится, их можно отправить на сервер. +Отдельный Personal Access Token для этого упражнения создавать не нужно. +Никому не отправляйте пароль, токен или приватный ключ и не сохраняйте их в файлах проекта. + +Теперь мы готовы опубликовать наш репозиторий на GitHub. diff --git a/docs/04-02-remote.md b/docs/04-02-remote.md index ce54fac..7f7ac24 100644 --- a/docs/04-02-remote.md +++ b/docs/04-02-remote.md @@ -1,25 +1,28 @@ -# Публикация репозитория {#publish-github} +# Удаленный репозиторий {#git-remote} -Убедитесь, что выбрана ветка `main`, Source Control пуст и последний коммит — `Слил ветку boxplot`. -В Source Control нажмите **Publish to GitHub**. Если кнопка не видна, откройте палитру команд и найдите **Publish to GitHub**. -Выберите имя репозитория, например `r-course`, и доступ **Private repository**. Для учебного проекта приватный режим безопаснее: открыть репозиторий позже можно в настройках GitHub. +Для загрузки репозитория с вашего компьютера (он называется локальный репозиторий) на GitHub необходимо создать удаленный репозиторий на сайте. +Positron может создать его и сразу связать с локальным. -Если Positron предложит выбрать файлы, оставьте все уже отслеживаемые файлы. В проекте не должно быть секретов. +Откройте [Source Control]{.figtext} и нажмите [Publish to GitHub]{.figtext}. +Если Positron предложит войти, выполните действия из [предыдущей главы](#github). +Введите название репозитория, например `r-course`, и выберите [Publish to GitHub public repository]{.figtext}. -![Диалог Publish to GitHub с именем r-course и выбранным вариантом Private repository]() +![Диалог публикации Positron: указано имя r-course и выбран публичный репозиторий GitHub. Подготовьте состояние merged и выберите Publish to GitHub]() -Positron выполнит три связанных действия: +Настройка доступа определяет, кто может видеть файлы: -1. создаст репозиторий на GitHub; -2. добавит его как удалённый репозиторий `origin`; -3. отправит коммиты ветки `main`. +- Public --- кто угодно сможет просматривать ваши файлы, но только отдельно добавленные пользователи смогут их изменять +- Private --- только отдельно добавленные пользователи смогут просматривать и изменять файлы -После публикации откройте созданный репозиторий на GitHub и сравните список файлов с Explorer. Убедитесь, что на сайте есть `paper.qmd`, папка `data` и история коммитов. +Не публикуйте проект, если в нём есть пароли, токены, персональные данные или другие секреты. -**Удалённый репозиторий** (remote) — адрес другой копии проекта. Имя `origin` условное, но Git назначает его основной удалённой копии при публикации и клонировании. -::: {.callout .callout-info} -GitHub не выполняет код Quarto при обычной отправке. Файлы и история появятся на сервере, но готовый сайт требует отдельной настройки публикации. -::: + +Positron связал наш локальный репозиторий с удаленным при помощи операции **remote add** --- это необходимо было сделать один раз. +И выполнил операцию **push** --- отправил сделанные фиксации в удаленный репозиторий. Это необходимо делать регулярно, и соответствующее действие доступно на панели [Source Control]{.figtext}. +Если команды выполнились успешно, файлы были загружены на GitHub. +Обновите страницу репозитория и проверьте содержимое файлов. + +![Страница опубликованного репозитория r-course на GitHub: видны файлы проекта и история коммитов. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-published --state github-published --repo OWNER/NAME --visibility public]() diff --git a/docs/04-03-push-pull.md b/docs/04-03-push-pull.md index 67379ee..4860d83 100644 --- a/docs/04-03-push-pull.md +++ b/docs/04-03-push-pull.md @@ -1,27 +1,68 @@ -# Push, pull и синхронизация {#sync-remote} +# Загрузка изменений {#git-push-pull} -Локальная и удалённая копии меняются независимо. Три операции поддерживают их в согласованном состоянии. -| Действие | Результат | -|---|---| -| **Push** | Отправляет локальные коммиты на GitHub | -| **Pull** | Загружает удалённые коммиты и объединяет их с текущей веткой | -| **Sync Changes** | Сначала выполняет pull, затем push | -Эти определения соответствуют официальной документации [Working with repositories and remotes](https://code.visualstudio.com/docs/sourcecontrol/repos-remotes). +На предыдущем шаге мы загрузили изменения из нашего локального репозитория в удаленный репозиторий на GitHub при помощи операции `push`, которую выполнил Positron. -## Небольшая проверка +Git не синхронизирует изменения автоматически, это необходимо делать вручную, используя команду push или действие [Push]{.figtext} на панели [Source Control]{.figtext} в Positron. -Добавьте после заголовка `paper.qmd` одно предложение о цели анализа. Сохраните файл, проверьте diff и создайте коммит `Уточнил цель анализа`. +Создадим и загрузим еще один коммит. Например, добавим небольшой комментарий к коду, чтобы человеку открывшему его впервые было легче разобраться. -В строке состояния появится исходящий коммит `↑1`. Нажмите **Sync Changes**. После синхронизации счётчик исчезнет, а коммит появится на GitHub. -![Source Control перед Sync Changes: локальная main опережает origin/main на один коммит, в строке состояния показано ↑1]() +``` r +data <- read.csv("data/penguins.csv") +x <- data$bill_len |> na.omit() -## Перед началом работы +# Ящик с усами для длины клюва -В совместном проекте начинайте с **Pull**, а заканчивайте **Push**. Так вы раньше увидите чужие изменения и реже столкнётесь с конфликтом. +png("out/penguins-boxplot.png") +boxplot(x, ylab = "Bill length, mm") +dev.off() +``` -**Sync Changes** удобно, когда вы понимаете обе половины операции. Если нужно отдельно проверить входящие коммиты, выполните **Fetch**, посмотрите их в Source Control Graph и только затем нажмите **Pull**. +Сохраните и закомитьте файл `paper.qmd`. +После чего выберите [Push]{.figtext} на панели [Source Control]{.figtext}. -Если push отклонён, обычно удалённая ветка содержит новые коммиты. Не применяйте force push. Сначала выполните Pull, разрешите возможный конфликт и повторите Push. +![Source Control перед Push: локальная ветка main содержит новый коммит с комментарием к коду. Подготовьте опубликованный репозиторий и создайте коммит по заданию, не выполняя Push]() + +Перейдите на страницу репозитория на GitHub и убедитесь, что коммит был загружен. +Это можно понять по тексту сообщения над списком файлов и по тексту и времени изменения напротив файла `paper.qmd`. + +![Страница GitHub после Push: над списком файлов показано сообщение нового коммита, а у paper.qmd обновлено время. Чтобы получить состояние, выполните Push после предыдущего снимка]() + +GitHub позволяет вносить изменения в репозиторий из веб-интерфейса. +Эта функция используется редко, потому что код необходимо запускать и проверять на компьютере, но она полезна для небольших правок или загрузки файлов. +Создадим при помощи нее новый файл. +Файл README --- это файл, который отображается на главной странице репозитория для краткого описания проекта. Обычно он включает описание данных и кода, как начать работу с проектом и тому подобное. + +Нажмите кнопку [Add a README]{.figtext}. В открывшемся файле введите текст в формате Markdown^[в документе Quarto используется тот же синтаксис разметки, но README не выполняет код на R] (используйте или измените текст ниже) +и нажмите кнопку [Commit changes]{.figtext} в верхнем правом углу. +Откроется окно создания коммита, оставьте текст по умолчанию и подтвердите создание коммита нажатием кнопки [Commit changes]{.figtext} + +![Редактор README.md на GitHub: введено описание проекта и доступна кнопка Commit changes. Чтобы получить состояние, нажмите Add a README в опубликованном репозитории]() + +```md +# Пингвины «Палмер» 🐧 + +Этот репозиторий был создан в рамках курса от [Института биоинформатики](bioinf.me/education/stat), +чтобы познакомиться с основами Git — фиксацией изменений, ветвлением и работой с GitHub. + +В качестве примера использованы данные о длине клюва пингвинов, +собранные доктором Кристен Горман на станции «Палмер» в Антарктиде. + +Содержимое репозитория: + +- out/penguins-boxplot.png — диаграмма ящик с усами, показывающая распределение длины клюва +- paper.qmd — документ Quarto с кодом для построения диаграммы +- data/penguins.csv — данные +``` + +Чтобы загрузить изменения из удаленного репозитория на компьютер используется команда **pull**. + +Вернитесь в Positron и выберите [Pull]{.figtext} на панели [Source Control]{.figtext}. +Если команда выполнилась успешно, в списке файлов появится файл `README.md`, +а в журнале --- коммит созданный через GitHub. + +Как и в случае с переключением веток, Git откажется загружать изменения и выдаст ошибку, если в рабочей папке имеются незафиксированные изменения, которые конфликтуют с загружаемыми. + +Теперь вы умеете загружать изменения в удалённый репозиторий и из него. Рекомендуем делать это регулярно, чтобы синхронизироваться с другими участниками проекта, по крайней мере, в конце рабочего дня или рабочей сессии. diff --git a/docs/04-04-pull-request.md b/docs/04-04-pull-request.md index a5bc728..d0c780a 100644 --- a/docs/04-04-pull-request.md +++ b/docs/04-04-pull-request.md @@ -1,10 +1,14 @@ -# Pull request {#pull-request} +# Pull Request {#pr} -Pull request — предложение объединить одну ветку с другой на GitHub. Перед слиянием коллеги могут посмотреть diff, обсудить решение и запустить проверки. +Pull Request --- это механизм GitHub для слияния веток загруженных в удаленный репозиторий, позволяющий просмотреть, обсудить и проверить предлагаемые изменения перед слиянием. Похожий механизм существует и на других платформах. -## Изменение в ветке +Орнитолог проходящий мимо нашего репозитория обратит внимание, что длину клюва пингвина лучше рассматривать в зависимости от пола. Он даже может предложить необходимые изменения при помощи Pull Request. -Создайте от актуальной `main` ветку `adjust-by-sex`. В `paper.qmd` замените блок кода: +Создайте ветку с названием `adjust-by-sex`: нажмите название текущей ветки в строке состояния Positron и выберите [Create new branch…]{.figtext}. Убедитесь, что вместо названия ветки по умолчанию `main` выводится название созданной ветки `adjust-by-sex`. + +![Строка состояния Positron после создания ветки: показано название adjust-by-sex. Подготовьте опубликованное состояние merged и создайте ветку adjust-by-sex]() + +Отредактируйте документ `paper.qmd`, добавив пол в код для построения ящика с усами. Код приведен ниже, не забывайте, что вы можете сравнить изменения по сравнению с оригиналом, выбрав файл на панели [Source Control]{.figtext}. ``` r @@ -17,33 +21,37 @@ boxplot(x ~ g, xlab = "Sex", ylab = "Bill length, mm") dev.off() ``` -Соберите документ, проверьте обновлённый график и создайте коммит `Сгруппировал пингвинов по полу`. +Сохраните документ и выполните блок R. +Создайте коммит, включив в него `paper.qmd` и обновленную диаграмму `out/penguins-boxplot.png`. -Нажмите **Publish Branch**. Это создаст `adjust-by-sex` в `origin` и свяжет локальную ветку с удалённой. +![Source Control перед коммитом в adjust-by-sex: изменены paper.qmd и out/penguins-boxplot.png. Подготовьте ветку adjust-by-sex, внесите изменения по заданию и добавьте оба файла в индекс]() -![Ветка adjust-by-sex после Publish Branch: Source Control Graph показывает локальную и удалённую ветки на одном коммите]() +После создания коммита выберите [Publish Branch]{.figtext} на панели [Source Control]{.figtext}. Так как у вас полные права на редактирование репозитория, то новая ветка будет загружена на GitHub. Прохожему орнитологу пришлось бы создать свою копию репозитория или просить дать доступ средствами GitHub. -## Создание предложения +Перейдите на страницу репозитория в GitHub и убедитесь, что ветка была загружена и содержит сделанные измнения, для этого выберите ее в выпадающем меню появляющемся при нажатии кнопки с названием ветки [main]{.figtext}. -Откройте представление **Pull Requests** на панели активности. Нажмите **Create Pull Request** или выполните команду **GitHub Pull Requests: Create Pull Request**. +![Страница GitHub с выбранной веткой adjust-by-sex и обновлённым графиком. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-pr --state github-pr --repo OWNER/NAME --visibility public]() -Выберите: +При просмотре ветки отличной от основной, GitHub предложит создать из нее **Pull Request** --- предложение автору репозитория слить изменения из этой ветки. Нажмите кнопку [Contribute]{.figtext} и в выпадающем меню выберите [Open pull request]{.figtext}. -- базовый репозиторий — ваш `r-course`; -- базовую ветку — `main`; -- ветку с изменением — `adjust-by-sex`; -- заголовок — `Сгруппировал пингвинов по полу`. +![Меню Contribute на GitHub с действием Open pull request. Подготовьте состояние github-pr и откройте ветку adjust-by-sex на GitHub]() -В описании объясните причину: распределение длины клюва теперь показано отдельно для каждого пола. Перед созданием откройте список файлов и проверьте diff. +GitHub предложит ввести заголовок и описание предлагаемых изменений, правило хорошего тона кратко описать причину изменений и суть предлагаемого решения. А также, прокрутите страницу создания Pull Request и проверьте изменения, которые вы предлагаете, после чего нажмите кнопку [Create pull Request]{.figtext} под полем с описанием. -![Форма Create Pull Request в Positron: base main, compare adjust-by-sex, заполнены заголовок и описание]() +![Форма создания pull request на GitHub: заполнены заголовок и описание, ниже показан diff. В состоянии github-pr выберите Contribute → Open pull request]() -Нажмите **Create**. Откроется режим просмотра pull request. Здесь можно оставить комментарий к строке, запросить проверку и увидеть обсуждение. +На странице Pull Request владельцу репозитория доступна опция слить предложенные изменения. +Нажмите кнопку [Merge pull request]{.figtext} внизу страницы. +В открывшемся окне GitHub предложить ввести текст коммита, как если бы мы делали слияние ветки в терминале. Оставьте или измените текст и нажмите кнопку [Confirm merge]{.figtext} +После успешного слияния ветку можно удалить. -## Слияние +![Страница pull request перед слиянием: доступна кнопка Merge pull request. Создайте pull request из состояния github-pr и откройте его страницу]() -Нажмите **Merge** только после проверки файлов. Выберите обычное создание merge-коммита, затем подтвердите операцию. После успешного слияния удалите ветку, когда Positron предложит это сделать. +![Подтверждение merge-коммита на GitHub. На странице pull request нажмите Merge pull request]() -Переключитесь на локальную `main` и выполните **Pull**. Убедитесь, что `paper.qmd` содержит группировку по полу, а Source Control Graph — коммит слияния с GitHub. +![Pull request после успешного слияния и предложение удалить ветку. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-github-merged --state github-merged --repo OWNER/NAME --visibility public]() -![Локальная main после Pull: в paper.qmd код boxplot по sex, в Graph виден слитый pull request]() +Вернемся к нашему проекту в Positron. +Слияние было выполнено онлайн на GitHub, а значит необходимо загрузить изменения в наш локальный репозиторий, т.е. сделать pull. +Переключитесь на ветку `main` при помощи строки состояния и выберите [Pull]{.figtext} на панели [Source Control]{.figtext}. +Убедитесь, что теперь ветка `main` содержит актуальные изменения в файлах `paper.qmd` и `out/penguins-boxplot.png`. diff --git a/docs/04-05-clone.md b/docs/04-05-clone.md index ed665d5..f023465 100644 --- a/docs/04-05-clone.md +++ b/docs/04-05-clone.md @@ -1,19 +1,23 @@ -# Клонирование {#clone-repository} +# Клонирование репозитория {#git-clone} -**Клонирование** создаёт новую локальную папку из удалённого репозитория. Вместе с файлами загружаются коммиты и ветки, а Git автоматически добавляет remote `origin`. +Сейчас репозиторий доступен публично и +чтобы поделиться проектом достаточно скопировать ссылку из адресной строки браузера. +Отличная идея приложить ее к тексту публикации, если репозиторий содержит данные и код для воспроизведения результатов. +Используйте GitHub чтобы делиться примерами кода. Например, если просите помощи, так другим будет легче понять проблему и предложить решение. -Не клонируйте репозиторий внутрь уже открытого `r-course`. Для проверки используйте другую родительскую папку. +Чтобы загрузить удаленный репозиторий на компьютер выполните команду **клонирования (clone)**. +Для этого понадобится адрес репозитория. +Нажмите кнопку [Code]{.figtext} на странице репозитория, +убедитесь что выбрана опция **HTTPS** и скопируйте адрес. -1. Откройте новое окно Positron без проекта. -2. Выполните **Workspaces: New Folder from Git…** из палитры команд. -3. Выберите **Clone from GitHub** и свой репозиторий `r-course`. -4. Укажите родительскую папку, например `projects-copy`. -5. После загрузки нажмите **Open**. +![Меню Code на GitHub: выбрана вкладка HTTPS и показан адрес репозитория. Откройте опубликованный репозиторий и нажмите Code]() -![Окно Workspaces: New Folder from Git со списком репозиториев GitHub и выбранным r-course]() +Создадим копию проекта в Positron. +Откройте новое окно без проекта и в палитре команд выберите [Workspaces: New Folder from Git…]{.figtext}. +Выберите [Clone from GitHub]{.figtext} и свой репозиторий `r-course` или вставьте скопированный адрес. +Укажите другую родительскую папку, чтобы новая копия не оказалась внутри уже открытого проекта. +После загрузки нажмите [Open]{.figtext}. -Откройте Source Control Graph и `paper.qmd`. История и код должны совпадать с первым проектом. +![Окно Workspaces: New Folder from Git в Positron: выбран репозиторий r-course и папка для новой копии. Выполните Workspaces: New Folder from Git… в новом окне Positron]() -Не редактируйте обе копии одновременно без необходимости. Это два независимых рабочих каталога: изменения попадут друг к другу только через Push и Pull. - -Если Positron спрашивает, доверяете ли вы содержимому, подтверждайте доверие только для своего репозитория или известного источника. Открытие чужого проекта ещё не запускает код, но дальнейшее выполнение файлов может это сделать. +Мы склонировали удаленный репозиторий на компьютер и теперь можем работать с ним как с оригинальным проектом --- делать коммиты, загружать изменения в удаленный репозиторий (push) и из него (pull). diff --git a/docs/04-06-conclusion.md b/docs/04-06-conclusion.md index 5b0ed71..74990b2 100644 --- a/docs/04-06-conclusion.md +++ b/docs/04-06-conclusion.md @@ -1,14 +1,17 @@ -# Итог работы с GitHub {#github-conclusion} +# Заключение -Теперь вы умеете: +Теперь у вас есть аккаунт на GitHub и вы умеете синхронизировать изменения с удаленным репозиторием, +пользоваться веб-интерфейсом и создавать Pull Request. +Этого достаточно для командной работы на курсе и в большинстве проектов. -- публиковать локальный репозиторий через **Publish to GitHub**; -- входить в GitHub через браузер; -- различать Push, Pull, Fetch и Sync Changes; -- публиковать отдельную ветку; -- создавать, проверять и сливать pull request; -- клонировать проект командой **Workspaces: New Folder from Git…**. +Диаграмма ниже поможет запомнить как соотносятся действия, которые мы изучили: +[1) создание коммитов](#git-commit), [2) работа с ветками](#branch) и [3) синхронизация с удаленным репозиторием](#git-push-pull). -Для обычной работы достаточно короткого цикла: Pull → новая ветка → небольшие коммиты → Push → pull request → проверка → merge. +![Связь коммитов, веток и синхронизации с удалённым репозиторием](./img/04-06-sequence.png){width=100%} -GitHub — не резервная копия незакоммиченных файлов. Пока изменение не вошло в коммит и не отправлено, оно существует только в вашей рабочей папке. +Рекомендуем использовать Git в своих проектах и не бояться экспериментировать с ветками. +Это помогает структурировать рабочий процесс, делает анализ данных воспроизводимым и облегчает командную работу. +Даже если вы работаете в одиночку, история изменений, возможность вернуться к предыдущим версиям и ветвление значительно упрощают развитие проекта. +А со временем вы сможете применять более продвинутые возможности, такие как автоматизация, интеграция с другими сервисами и управление проектами. + +Удачи в прохождении курса! diff --git a/docs/05-01-faq.md b/docs/05-01-faq.md index 0bf9008..e3b9840 100644 --- a/docs/05-01-faq.md +++ b/docs/05-01-faq.md @@ -1,41 +1,57 @@ -# (PART) Дополнительно {-} +# (PART) Дополнительные материалы {-} -# Частые ситуации {#faq} +# Best practices {#faq} -## Source Control не показывает проект +## .gitignore {#gitignore} -Убедитесь, что в Positron открыта именно папка `r-course`, а не отдельный файл. Затем выполните **Developer: Reload Window**. Если репозитория действительно нет, появится **Initialize Repository**. +## Feature бранчи {#feature-branch} -Для диагностики откройте **Git: Show Git Output**. Последняя строка обычно содержит команду и причину ошибки. Перед отправкой лога удалите из него токены и приватные адреса. +Хорошая практика каждое изменение делать в свой ветке. -## Коммит не содержит файл +Не всегда это удобно, особенно когда работаешь один. +Чтобы перенести уже сделанные коммиты в отдельную ветку воспользуйтесь [этим рецептом](#commits-to-branch). -Коммит получает только **Staged Changes**. Найдите файл в **Changes**, нажмите `+`, проверьте diff и создайте новый коммит. Не нужно удалять предыдущий коммит ради пропущенного файла. +## Комитьте и пушьте чаще -## В коммит попал лишний файл +Так меньше проблем при слиянии -Если коммит ещё не отправлен и вы работаете один, откройте в Source Control меню **More Actions (…) → Commit → Undo Last Commit**. Изменения останутся в **Staged Changes**. Исправьте индекс и создайте коммит снова. +## Принудительный push {#force-push} -Если коммит уже отправлен или его могли скачать коллеги, не переписывайте историю. Сделайте новый коммит, который удаляет или исправляет лишнее. +Это может привести к потери изменений загруженных на сервер ранее, например вашим коллегой. +Никогда не делайте так в команде, не уточнив у других. -## Нужно временно переключиться +## Как перенести коммиты в ветку {#commits-to-branch} -Сохраните законченную часть коммитом. Для незаконченной используйте **Git: Stash (Include Untracked)**, затем переключитесь. Вернуть выбранный stash можно командой **Git: Pop Stash...**. +Идея рецепта в том, +что мы создаем новую ветку из текущего набора коммитов, +переключаемся на оригинальную и в ней ненужные коммиты отменяем. -## Конфликт возник при Pull +::: {.alert .alert-warning} +Этот подход не сработает если вы загрузили коммиты на сервер, +потому что отмена коммитов переписывает историю. +Это потребует выполнения команды `git push --force`. +[Почему это плохо?](#force-push) +::: -Это то же слияние, что в главе \@ref(merge-conflict). Откройте файлы из **Merge Changes**, соберите осмысленный Result, нажмите **Complete Merge** и создайте коммит. После этого повторите Push. +Создайте новую ветку - она будет содержать набор коммитов, который вы имеете сейчас, +при помощи Positron или командой ниже. -## Опасные операции +```sh +git branch some +``` -Команды force push, hard reset, удаление неслитой ветки и переписывание опубликованной истории могут стереть доступ к чужим коммитам. +Важно! Убедитесь в том, что создали ветку. Для этого посмотрите журнал или команду `git log` и найдите напротив текущего коммита надпись с названием созданной ветки. -::: {.callout .callout-warning} -Не используйте **Force Push**, `git reset --hard` и удаление неслитых веток в командном проекте без явного согласования. Сначала создайте резервную ветку или попросите преподавателя помочь. -::: +Вернитесь на оригинальную ветку, как правило это `main`, при помощи Positron или команды ниже. -## Данные и секреты +```sh +git checkout main +``` -Git хорошо подходит для кода и небольших учебных данных. Большие файлы быстро раздувают историю, а удалённый из последнего коммита секрет может сохраниться в старых версиях. +Отмените нужное количество комитов, скажем `3`. +Опция `--hard` удалит все изменения. +Ничего страшного, ведь они остались в ветке, созданной на предыдущем шаге. -Перед первым коммитом добавляйте в `.gitignore` временные файлы, локальные настройки и секреты. Если секрет уже отправлен, сначала отзовите его у провайдера; одного удаления файла недостаточно. +```sh +git reset --hard HEAD~3 +``` diff --git a/docs/05-02-references.md b/docs/05-02-references.md index 4e63d99..4d30e57 100644 --- a/docs/05-02-references.md +++ b/docs/05-02-references.md @@ -1,25 +1,8 @@ # Ссылки {#references} -## Positron - -- [Welcome to Positron](https://positron.posit.co/welcome.html) — исходная точка официальной документации. -- [Git Version Control](https://positron.posit.co/git.html) — Git, Source Control, ветки и конфликты в Positron. -- [Command Palette](https://positron.posit.co/command-palette.html) — поиск и запуск команд. -- [Quarto](https://positron.posit.co/quarto.html) — выполнение и предпросмотр `.qmd`. -- [Folder Templates](https://positron.posit.co/folder-templates.html) — состав проекта, включая `.git` и `.gitignore`. - -## Git и Source Control - -- [Source Control overview](https://code.visualstudio.com/docs/sourcecontrol/overview). -- [Staging and committing changes](https://code.visualstudio.com/docs/sourcecontrol/staging-commits). -- [Source Control history](https://code.visualstudio.com/docs/sourcecontrol/history). -- [Branches and worktrees](https://code.visualstudio.com/docs/sourcecontrol/branches-worktrees). -- [Merge conflicts](https://code.visualstudio.com/docs/sourcecontrol/merge-conflicts). -- [Repositories and remotes](https://code.visualstudio.com/docs/sourcecontrol/repos-remotes). -- [GitHub in Source Control](https://code.visualstudio.com/docs/sourcecontrol/github). -- [Pro Git](https://git-scm.com/book/ru/v2) — подробная бесплатная книга. - -## Практика - -- [Learn Git Branching](https://learngitbranching.js.org/?locale=ru_RU) — интерактивные упражнения с ветками. -- [Happy Git and GitHub for the useR](https://happygitwithr.com/) — Git для проектов анализа данных. +- [Документация Positron](https://positron.posit.co/welcome.html) --- официальное руководство по интерфейсу Positron. +- [Git Version Control](https://positron.posit.co/git.html) --- работа с Git в Positron. +- [Quarto](https://positron.posit.co/quarto.html) --- работа с документами `.qmd` в Positron. +- [Pro Git](https://git-scm.com/book/en/v2) --- небольшая книга рекомендованная разработчиками Git. Из нее вы узнаете о внутреннем устройстве Git и научитесь работать с командой `git` в терминале. Пригодятся главы 1-3 и глава 6. +- [Happy Git and GitHub for the useR](https://happygitwithr.com/) --- материалы практического курса по Git с конференции Posit. +- [Git Cheatsheet](https://ndpsoftware.com/git-cheatsheet.html#loc=local_repo;) - интерактивная шпаргалка. diff --git a/docs/05-03-webhooks.md b/docs/05-03-webhooks.md index 09ee9cd..b44fa5a 100644 --- a/docs/05-03-webhooks.md +++ b/docs/05-03-webhooks.md @@ -1,23 +1,25 @@ # Webhooks {#webhooks} -Webhook позволяет GitHub отправить HTTP-запрос внешнему сервису после события: push, создания pull request или слияния. Так запускают уведомления и автоматические проверки. +Webhooks — это механизм GitHub для реагирования на события в репозитории. +Когда что-то происходит (например, кто-то сделал push или создал Pull Request), +GitHub отправит информацию о событии на указанный в настройках адрес. -Для настройки нужен готовый HTTPS-адрес сервиса. Не указывайте случайный сайт: содержимое запроса может включать имена репозитория, веток и участников. +Для обработки событий по указанному адресу должна работать программа (веб-сервер). +Многие сервисы, например Slack или Microsoft Teams, поддерживают таким образом отправку уведомлений в рабочий чат. +Для Telegram можно воспользоваться ботом [\@octo8bot](https://t.me/octo8bot). -1. Откройте репозиторий на GitHub. -2. Перейдите **Settings → Webhooks → Add webhook**. -3. Вставьте адрес в **Payload URL**. -4. Выберите `application/json`. -5. Добавьте отдельный случайный **Secret**, если принимающий сервис умеет проверять подпись. -6. Выберите **Let me select individual events** и оставьте **Pull requests**. -7. Нажмите **Add webhook**. +Добавьте бота в чат и скопируйте присланный им адрес. -![Страница GitHub Add webhook: заполнен Payload URL, content type application/json, выбран Pull requests, секрет скрыт]() +![Чат с ботом: после добавления показан адрес webhook, который нужно скопировать. Чтобы получить состояние, добавьте \@octo8bot в учебный чат]() -В разделе **Recent Deliveries** откройте тестовую доставку. Код `2xx` означает, что сервис принял запрос. Код `4xx` обычно указывает на неверный адрес или авторизацию, `5xx` — на ошибку принимающего сервиса. +Откройте репозиторий на Github и выберите **Settings → Webhooks → Add webhook**. +Вставьте адрес в поле **Payload URL** и заполните форму как на скриншоте ниже. +Нажмите **Add webhook**. -::: {.callout .callout-warning} -Webhook может запускать действия во внешней системе. Проверяйте адрес и минимально необходимый набор событий. Не записывайте secret в репозиторий и не показывайте его на скриншоте. -::: +![Форма Add webhook на GitHub: заполнен Payload URL и выбраны события pull request. Откройте Settings → Webhooks → Add webhook и заполните форму по заданию]() -Для преподавателя генератор проекта умеет создать такой webhook через `gh` в состоянии `github-webhook`; студенту достаточно один раз пройти настройку в интерфейсе и проверить доставку. +Если webhook настроен правильно, в чат придет сообщение с текстом «Successfully installed». + +Когда создаётся новый Pull Request, в него вносятся изменения или он сливается (merge), бот пришлет уведомление с ссылкой на этот Pull Request. + +![Уведомления бота о создании, изменении и слиянии pull request. Команда подготовки: python3 bin/create_course_project.py /tmp/git-course-webhook --state github-webhook --repo OWNER/NAME --webhook-url URL]() diff --git a/docs/404.html b/docs/404.html index e6c9d17..30852a0 100644 --- a/docs/404.html +++ b/docs/404.html @@ -45,31 +45,32 @@