diff --git a/.Rprofile b/.Rprofile new file mode 100644 index 0000000..81b960f --- /dev/null +++ b/.Rprofile @@ -0,0 +1 @@ +source("renv/activate.R") diff --git a/.gitignore b/.gitignore index 5b6a065..b5e9167 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ .Rhistory .RData .Ruserdata + +/.quarto/ + diff --git a/02-tools.Rmd b/01-tools.qmd similarity index 100% rename from 02-tools.Rmd rename to 01-tools.qmd diff --git a/03-database.Rmd b/02-database.qmd similarity index 97% rename from 03-database.Rmd rename to 02-database.qmd index d968b4c..5a0798a 100644 --- a/03-database.Rmd +++ b/02-database.qmd @@ -1,3 +1,15 @@ +```{r setup, include = FALSE} +library(airtabler) + +for (f in list.files(here::here("R"), full.names = TRUE)) source (f) + +airtable_metadata <- airtable( + base = "appAL7fJUpBPYtOq4", + tables = "Meta Data" +)$`Meta Data`$select() +``` + + # Database {#database} The current database is built using [Airtable](https://airtable.com). The current database has the following schema: diff --git a/04-sources.Rmd b/03-sources.qmd similarity index 100% rename from 04-sources.Rmd rename to 03-sources.qmd diff --git a/05-updates.Rmd b/04-updates.qmd similarity index 100% rename from 05-updates.Rmd rename to 04-updates.qmd diff --git a/06-survey.Rmd b/05-survey.qmd similarity index 100% rename from 06-survey.Rmd rename to 05-survey.qmd diff --git a/07-references.Rmd b/06-references.qmd similarity index 100% rename from 07-references.Rmd rename to 06-references.qmd diff --git a/_bookdown.yml b/_bookdown.yml deleted file mode 100644 index 1b0c8df..0000000 --- a/_bookdown.yml +++ /dev/null @@ -1,5 +0,0 @@ -delete_merged_file: true -language: - ui: - chapter_name: "Chapter " -output_dir: "docs" \ No newline at end of file diff --git a/_bookdown_files/_main_files/figure-html/actions diagram-1.png b/_bookdown_files/_main_files/figure-html/actions diagram-1.png deleted file mode 100644 index 383cd4d..0000000 Binary files a/_bookdown_files/_main_files/figure-html/actions diagram-1.png and /dev/null differ diff --git a/_bookdown_files/_main_files/figure-latex/actions diagram-1.pdf b/_bookdown_files/_main_files/figure-latex/actions diagram-1.pdf deleted file mode 100644 index 621bb3f..0000000 Binary files a/_bookdown_files/_main_files/figure-latex/actions diagram-1.pdf and /dev/null differ diff --git a/_output.yml b/_output.yml deleted file mode 100644 index 0e0b9df..0000000 --- a/_output.yml +++ /dev/null @@ -1,22 +0,0 @@ -bookdown::gitbook: - highlight: tango - css: style.css - fig_caption: yes - split_by: chapter - config: - toc: - collapse: section - before: | -
  • RIG Handbook
  • - after: | -
  • @ EcoHealth Alliance 2023
  • - edit: https://github.com/ecohealthalliance/rig-handbook/edit/dev/%s - download: ["pdf", "epub"] -bookdown::pdf_book: - includes: - in_header: preamble.tex - latex_engine: pdflatex - citation_package: natbib - keep_tex: yes - fig_caption: yes -bookdown::epub_book: default diff --git a/_quarto.yml b/_quarto.yml new file mode 100644 index 0000000..25d7a67 --- /dev/null +++ b/_quarto.yml @@ -0,0 +1,55 @@ +project: + type: book + output-dir: docs + +book: + title: Africa CDC Database + subtitle: Technical Handbook + author: + - name: Dr Jonathan Epstein + orcid: 0000-0002-1373-9301 + email: epstein@ecohealthalliance.org + affiliation: + - name: EcoHealth Alliance + city: New York + - name: Ava Sullivan + orcid: 0000-0003-4339-2430 + email: sullivan@ecohealthalliance.org + affiliation: + - name: EcoHealth Alliance + city: New York + - name: Shannon Ball + orcid: 0000-0001-8306-3493 + email: ball@ecohealthalliance.org + affiliation: + - name: EcoHealth Alliance + city: New York + date: last-modified + date-format: "DD MMMM YYYY" + chapters: + - index.qmd + - 01-tools.qmd + - 02-database.qmd + - 03-sources.qmd + - 04-updates.qmd + - 05-survey.qmd + - 06-references.qmd + cover-image: images/AfricaCDC_Logo.png + search: true + repo-url: https://github.com/ecohealthalliance/acdc-db-handbook/ + repo-actions: [edit] + downloads: [pdf, epub] + sharing: [twitter, facebook] + +bibliography: book.bib + +format: + html: + theme: lumen + highlight-style: breeze + pdf: + documentclass: scrreprt + highlight-style: breeze + epub: + cover-image: images/AfricaCDC_Logo.png + highlight-style: breeze \ No newline at end of file diff --git a/rig-handbook.Rproj b/acdc-db-handbook.Rproj similarity index 100% rename from rig-handbook.Rproj rename to acdc-db-handbook.Rproj diff --git a/docs/404.html b/docs/404.html deleted file mode 100644 index 44c1d82..0000000 --- a/docs/404.html +++ /dev/null @@ -1,296 +0,0 @@ - - - - - - - Page not found | Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -

    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.

    -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/docs/_main.epub b/docs/_main.epub deleted file mode 100644 index fc628cb..0000000 Binary files a/docs/_main.epub and /dev/null differ diff --git a/docs/_main.pdf b/docs/_main.pdf deleted file mode 100644 index 326179c..0000000 Binary files a/docs/_main.pdf and /dev/null differ diff --git a/docs/_main.tex b/docs/_main.tex deleted file mode 100644 index ca40046..0000000 --- a/docs/_main.tex +++ /dev/null @@ -1,1520 +0,0 @@ -% Options for packages loaded elsewhere -\PassOptionsToPackage{unicode}{hyperref} -\PassOptionsToPackage{hyphens}{url} -% -\documentclass[ -]{book} -\usepackage{amsmath,amssymb} -\usepackage{lmodern} -\usepackage{iftex} -\ifPDFTeX - \usepackage[T1]{fontenc} - \usepackage[utf8]{inputenc} - \usepackage{textcomp} % provide euro and other symbols -\else % if luatex or xetex - \usepackage{unicode-math} - \defaultfontfeatures{Scale=MatchLowercase} - \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} -\fi -% Use upquote if available, for straight quotes in verbatim environments -\IfFileExists{upquote.sty}{\usepackage{upquote}}{} -\IfFileExists{microtype.sty}{% use microtype if available - \usepackage[]{microtype} - \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts -}{} -\makeatletter -\@ifundefined{KOMAClassName}{% if non-KOMA class - \IfFileExists{parskip.sty}{% - \usepackage{parskip} - }{% else - \setlength{\parindent}{0pt} - \setlength{\parskip}{6pt plus 2pt minus 1pt}} -}{% if KOMA class - \KOMAoptions{parskip=half}} -\makeatother -\usepackage{xcolor} -\usepackage{longtable,booktabs,array} -\usepackage{calc} % for calculating minipage widths -% Correct order of tables after \paragraph or \subparagraph -\usepackage{etoolbox} -\makeatletter -\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{} -\makeatother -% Allow footnotes in longtable head/foot -\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}} -\makesavenoteenv{longtable} -\usepackage{graphicx} -\makeatletter -\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi} -\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} -\makeatother -% Scale images if necessary, so that they will not overflow the page -% margins by default, and it is still possible to overwrite the defaults -% using explicit options in \includegraphics[width, height, ...]{} -\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} -% Set default figure placement to htbp -\makeatletter -\def\fps@figure{htbp} -\makeatother -\setlength{\emergencystretch}{3em} % prevent overfull lines -\providecommand{\tightlist}{% - \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} -\setcounter{secnumdepth}{5} -\usepackage{booktabs} -\usepackage{color} -\usepackage{tcolorbox} -\usepackage{float} -\graphicspath{ {images/} } - -\newenvironment{rmdremind} - {\begin{tcolorbox}[width=\textwidth, - colback = {white}, - title = {\textbf{Remember}}, - colbacktitle = lightgray, - coltitle = black] - \begin{includegraphics}[scale = 1]{remind.png} - \begin{itemize}} - {\end{itemize} - \end{includegraphics} - \end{tcolorbox}} - -\newenvironment{rmdnote} - {\begin{tcolorbox}[width=\textwidth, - colback = {white}, - title = {\textbf{Note}}, - colbacktitle = lightgray, - coltitle = black] - \begin{includegraphics}[scale = 1]{pencil.png}} - {\end{includegraphics} - \end{tcolorbox}} - -\newenvironment{rmdexercise} - {\begin{tcolorbox}[width=\textwidth, - colback = {white}, - title = {\textbf{Exercise}}, - colbacktitle = lightgray, - coltitle = black] - \begin{includegraphics}[scale = 1]{exercise.png}} - {\end{includegraphics} - \end{tcolorbox}} - -\newenvironment{rmdinfo} - {\begin{tcolorbox}[width=\textwidth, - colback = {white}, - title = {\textbf{Info}}, - colbacktitle = lightgray, - coltitle = black] - \begin{includegraphics}[scale = 1]{info.png}} - {\end{includegraphics} - \end{tcolorbox}} - -\newenvironment{rmdwarning} - {\begin{tcolorbox}[width=\textwidth, - colback = {white}, - title = {\textbf{Warning}}, - colbacktitle = lightgray, - coltitle = black] - \begin{includegraphics}[scale = 1]{warning.png}} - {\end{includegraphics} - \end{tcolorbox}} - -\newenvironment{rmddownload} - {\begin{tcolorbox}[width=\textwidth, - colback = {white}, - title = {\textbf{Download}}, - colbacktitle = lightgray, - coltitle = black] - \begin{includegraphics}[scale = 1]{download.png}} - {\end{includegraphics} - \end{tcolorbox}} -\usepackage{booktabs} -\usepackage{longtable} -\usepackage{array} -\usepackage{multirow} -\usepackage{wrapfig} -\usepackage{float} -\usepackage{colortbl} -\usepackage{pdflscape} -\usepackage{tabu} -\usepackage{threeparttable} -\usepackage{threeparttablex} -\usepackage[normalem]{ulem} -\usepackage{makecell} -\usepackage{xcolor} -\ifLuaTeX - \usepackage{selnolig} % disable illegal ligatures -\fi -\usepackage[]{natbib} -\bibliographystyle{plainnat} -\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}} -\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available -\urlstyle{same} % disable monospaced font for URLs -\hypersetup{ - pdftitle={Research Information Gateway Handbook}, - pdfauthor={EcoHealth Alliance}, - hidelinks, - pdfcreator={LaTeX via pandoc}} - -\title{Research Information Gateway Handbook} -\author{EcoHealth Alliance} -\date{2023-03-31} - -\begin{document} -\maketitle - -{ -\setcounter{tocdepth}{1} -\tableofcontents -} -\hypertarget{about}{% -\chapter{About}\label{about}} - -This is a handbook created as a how-to manual for the development and maintenance of a One Health Research Information Gateway for the African continent. - -\hypertarget{introduction}{% -\chapter{Introduction}\label{introduction}} - -\href{https://www.ecohealthalliance.org/}{EcoHelth Alliance} is supporting the creation of a database of active infectious disease research activities and research scientists in Africa. The database contains information about scientific research being conducted on the African continent that has particular relevance to understanding, detecting and responding to zoonotic pathogens. EHA is building a detailed, searchable, and visual database (e.g.~via a dashboard) populated with information about major (e.g.~multi-year) and active One Health research projects that includes subject matter, duration, geographical locations, key personnel, and links to publicly available reports, preprints and publications relevant to zoonoses. Examples of research areas may include epidemiological (syndrome based or disease specific), ecological (studies looking at potential reservoirs or animal hosts for zoonotic pathogens and spillover into humans or livestock); basic science (e.g.~virology, bacteriology; serology); clinical (vaccine or therapeutic trials); or sociological (e.g.~behavioral risk assessments or behavioral intervention studies) or any other preliminary public health findings. A particularly important view within the database includes a directory of subject matter experts associated with research across the continent. This roster view can be used by public health practitioners to engage expert consultations as needed to support training activities, surveillance or outbreak response, for example. - -\hypertarget{tools}{% -\chapter{Tools}\label{tools}} - -The Research Information Gateway (RIG) is currently using the following set of tools for database development and maintenance. - -\hypertarget{airtable}{% -\section{Airtable}\label{airtable}} - -\hypertarget{what-is-airtable}{% -\subsection{What is Airtable?}\label{what-is-airtable}} - -\href{https://airtable.com}{Airtable} is a cloud-based software platform that allows users to create and manage databases, spreadsheets, and other types of organizational tools. It can be used for a variety of purposes, including project management, customer relationship management, inventory tracking, event planning, and much more. - -One of the key features of Airtable is its flexible and customizable nature. Users can create and customize their own database structures, and can choose from a wide range of data types, including text, attachments, checkboxes, and more. This allows for a high degree of customization and adaptability to different use cases and workflows. - -Airtable also offers a variety of collaboration features, including real-time syncing and commenting, as well as integrations with other popular tools such as Slack, Google Drive, and Trello. Additionally, Airtable has a robust API that allows developers to build custom integrations and applications on top of the platform. - -Airtable's flexibility, customizability, and features that support collaboration along with its spreadsheet-style interface that is familiar to most that have used other spreadsheet software such as Microsoft Excel or Google Sheets are the key reasons why it was chosen to be the database tool for RIG. - -This \protect\hyperlink{airtable}{section} will provide an overview of Airtable and good practices for designing data models in relational databases. - -\hypertarget{key-terms}{% -\subsection{Key Terms}\label{key-terms}} - -\begin{itemize} -\tightlist -\item - \textbf{Workspace} - A collection of bases -\item - \textbf{Base} - A database. Each is identified by the Airtable API via a \texttt{base\ id} -\item - \textbf{Table} - A tabular data set within a base. Each table is identified by the Airtable API via the name of the table e.g.~``Demo Table'' -\item - \textbf{Record} - An individual cell within a table. Each record is identified by the Airtable API via a \texttt{record\ id} -\item - \textbf{Field} - A property of data in a table -\item - \textbf{Views} - A specific way of displaying a table. Default is grid. -\item - \textbf{Entity} - Something that either physically or logically exists whose properties are typically stored in a table and composed of data elements. -\item - \textbf{Element} - an attribute of a Entity (a field) -\end{itemize} - -\hypertarget{security-and-access-control}{% -\subsection{Security and Access Control}\label{security-and-access-control}} - -Airtable maintains physical and technological security as part of its ISO IEC 27001:2013 and SOC 2 compliance measures. Data are 256-bit encrypted when storing on the server and also when transferring data over the internet. To find vulnerabilities in their software, they run daily, weekly, and monthly scans on different components of their system and regularly commission external penetration tests. They also run a bug bounty program to help identify issues. Their data centers have fire detection and suppression systems, redundant power systems, and strict control for physical access. Because Airtable relies on Amazon Web Services (AWS) for its cloud infrastructure (the same providers used by previous EHA projects), data are geo-redundantly replicated in backups across multiple zones to increase data durability. They also have a team monitoring services at all times. Airtable employees are thoroughly vetted before hiring and continually trained on data protection best practices. Their workstations are secured by using full-disk encryption, automatic locking, and strong password requirements. - -\hypertarget{user--and-administrator-security-features}{% -\subsubsection{User- and Administrator Security Features}\label{user--and-administrator-security-features}} - -\hypertarget{access-controls}{% -\paragraph{Access Controls}\label{access-controls}} - -Airtable provides database (referred to as ``base'') and workspace administrators with granular controls over who can view, edit, comment, or otherwise modify data at the base, table, and field levels. There are four levels of Airtable user permissions: - -\begin{itemize} -\tightlist -\item - \textbf{Owner/Creator}: Full administrative control of base\\ -\item - \textbf{Editor}: Sees full base, create and modify records and views, create and modify view share links\\ -\item - \textbf{Commenter}: Sees full base, comment on records\\ -\item - \textbf{Reader}: Sees full base -\end{itemize} - -Direct access to a base or workspace is granted or removed by base owners and creators to Airtable users. Base owners and creators can control who has access to a base and can control any ``share'' links created for that base. They may also restrict editing of tables or fields within a base. Any collaborator given direct access to a base at any permission level will be able to duplicate that base and share that data further. It is important that direct access to the base is limited to individuals with a need to curate or analyze the data. - -\hypertarget{share-links-and-interfaces}{% -\paragraph{Share Links and Interfaces}\label{share-links-and-interfaces}} - -To further restrict access to a base, users can be given indirect access via revocable share links or interfaces. - -\href{https://support.airtable.com/docs/creating-a-base-share-link-or-a-view-share-link}{Share links} can be customized to prevent users from seeing the full base, prevent duplicating the base, and prevent copying data from the base. The ability to use the link can be password protected, restricted to people with certain email domains, and may be revoked at any time. If there are concerns about data leaks via base or table duplication, inviting people with a need to view the data via share links constrains their ability to extract data from the base. - -\href{https://support.airtable.com/docs/interface-designer-overview}{Interfaces} are dynamic dashboards built on a limited set of data in an airtable base. Users can explore or even edit data based on the permissions provided by the interface creator. Access can be further tuned by setting up a ``current-user filter''. See \href{https://support.airtable.com/docs/interface-designer-permissions}{this guide} for more information. - -\hypertarget{data-in-airtable}{% -\subsection{Data in Airtable}\label{data-in-airtable}} - -See \href{https://support.airtable.com/hc/en-us/articles/115010928147-Airtable-plans}{Airtable plan comparison} for more information on the size of bases and features available. Information in this section pertains to all plans unless specified. - -\hypertarget{workspaces-bases-tables-fields-records}{% -\subsubsection{Workspaces, Bases, Tables, Fields, Records}\label{workspaces-bases-tables-fields-records}} - -Airtable uses workspaces, bases, tables, and fields to manage data. A workspace generally pertains to a particular project and contains all bases relevant to that project. Sharing a workspace with someone allows them to see all bases within that workspace. - -Bases are equivalent to databases. They consist of a set of tables that can be linked and allow you to perform some task (e.g.~IRB tracking, capturing research data, etc.). Bases can be duplicated and shared across your workspaces and you can share bases with other users. - -Tables are where most of the action happens. Data is entered in tables, tables can be transformed via views into calendars, dashboards, or galleries, and tables can be manipulated via the API. They describe a data entity and are composed of fields. In the bat sampling example, each circle would be a table in the bat sampling base. - -Fields represent properties of a data entity. In a spreadsheet view, fields are columns. Airtable allows you to control field types (date, number, text, file attachments, logical, etc.) and paid plans allows you to control who can edit fields. Fields can be linked between tables creating links. - -Records are the individual data points in a table. In a spreadsheet they would be the rows. Records are shaped by the structure you have created in tables and fields. Each record has a URL that can be used to access it programatically or share it. - -\hypertarget{views}{% -\subsection{Views}\label{views}} - -In Airtable, tables can be displayed in different views to emphasis different components of the data. Views are great for creating concise presentations of data, especially in sprawling tables. The default view in an table is the grid (spreadsheet) view. All other views will derive from the data entered in this view. - -For more on views, see \href{https://support.airtable.com/hc/en-us/articles/202624989-Guide-to-views}{the guide to views}. - -\hypertarget{internal-backups-record-history-base-snapshots}{% -\subsection{Internal Backups: Record History, Base Snapshots}\label{internal-backups-record-history-base-snapshots}} - -Airtable has system for tracking changes to a base. They provide revision history for individual records (how long those histories are stored varies by plan). Any comments made in the revision history will be stored for the life of the record (on any plan). The current state of an entire base may be captured through snapshots. Should a systemic issue arise, the base can be restored to a snapshot at a later date. Restoring from a snapshot will remove the revision history for a record but comments on that record will be maintained. - -As revision histories are maintained, ``deleted'' records may be retrieved. In the event of the need to permanently remove data, the revision history of the base may be removed. - -Airtable allows data to be exported as CSVs from individual tables. At this time there is not an Airtable supported base export function. - -\hypertarget{importing-data}{% -\subsection{Importing data}\label{importing-data}} - -Data can be imported to Airtable from a number of sources including CSV files, excel, Google sheets, XML, and via copy paste. Airtable will guess what the most appropriate field type is, so make sure the field type is appropriate for the data (e.g.~convert from text to date type fields). Certain sources, like Google sheets, can be imported as bases. - -For more on importing data see: \href{https://support.airtable.com/hc/en-us/sections/200928025-Importing-and-adding-data}{Importing and Adding data} - -\hypertarget{base-design}{% -\section{Base Design}\label{base-design}} - -Having a good base design will make using your data easier. Generally, the process looks like this: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi})} -\setcounter{enumi}{-1} -\tightlist -\item - Describe what the database will do and collect use cases -\item - Determine the roles of various stakeholders -\item - List out the entities in the database and define their properties -\item - Map out how the entities fit together (which properties link them) -\item - Check that the mapping meets the use cases -\item - Build base in Airtable -\item - Check that the base meets the use cases -\end{enumerate} - -If you are migrating from spreadsheets, you likely already have an idea of what you need the base to do and a collection of data properties. It is still a good idea to follow the steps outlined above for mapping out entities. You may find that entire sheets can be replaced by views or that the data in one sheet should actually be stored in two different tables. - -Feel free to reach out to the data librarian for questions about base design. - -\hypertarget{automating-airtable}{% -\section{Automating Airtable}\label{automating-airtable}} - -Airtable has five main routes for automating processes. - -\begin{enumerate} -\def\labelenumi{\arabic{enumi})} -\tightlist -\item - \href{https://support.airtable.com/hc/en-us/articles/360050974153-Automations-overview}{Automations} - a drag and drop visual programming tool -\item - \href{https://support.airtable.com/docs/airtable-extensions-overview}{Extensions} - pre-built applications that perform some task -\item - \href{https://support.airtable.com/hc/en-us/articles/360043041074-Scripting-app-overview}{Scripting} - use JavaScript to automate tasks within Airtable -\item - \href{https://www.airtable.com/developers/apps/guides/getting-started}{Blocks} - use JavaScript to create custom applications -\item - \href{https://airtable.com/api}{REST API} - use whatever programming language you like to automate processes -\end{enumerate} - -\hypertarget{automations-with-drag-and-drop-programing-pro-and-above}{% -\subsection{Automations with Drag and Drop Programing (pro and above)}\label{automations-with-drag-and-drop-programing-pro-and-above}} - -The automations feature within Airtable allows you to visually program routines. Each automation has three basic components: - -\begin{itemize} -\tightlist -\item - Status - controls whether or not the automation will run when the trigger condition is met -\item - Triggers - condition for automation to run: the creation or change of a record, a scheduled time, or some other external action -\item - Actions - what the automation will do -\end{itemize} - -\includegraphics{_main_files/figure-latex/actions diagram-1.pdf} - -Automations are commonly used to augment the synced tables feature, send notifications, check data quality, and manipulate or create records. - -This automation creates a weekly summary of applicants who applied for a position. Its trigger is time based, then it finds records that match a condition, and finally it generates an email from those records and sends to the appropriate recipients. - -\begin{figure} -\centering -\includegraphics{./images/airtable_Weekly Digest.png} -\caption{airtable weekly summary} -\end{figure} - -\hypertarget{scripting-and-blocks-pro-plan-and-above}{% -\subsection{Scripting and Blocks (pro plan and above)}\label{scripting-and-blocks-pro-plan-and-above}} - -Scripting uses JavaScript to manipulate a base from within an application in Airtable. Scripting is flexible but has a steep learning curve. The scripting environment Airtable provides can be helpful as it provides code \href{https://en.wikipedia.org/wiki/Lint_(software)}{linting}, direct access to documentation, and example scripts to build from. The major drawback to scripting is that scripts live in the base and files are not version controlled. - -\begin{itemize} -\tightlist -\item - There are a LOT of \href{https://airtable.com/marketplace/category/scripts}{pre-written scripts, in a shared ``marketplace''} to perform automatic actions. Search the marketplace before you start writing bespoke code. -\end{itemize} - -Blocks are custom applications built in JavaScript and node.js that add to base functionality. They are created in a development environment outside of Airtable then brought back into platform. There are number of \href{https://www.airtable.com/developers/apps/guides/getting-started}{tutorials for getting started with blocks}. - -\hypertarget{using-the-rest-api}{% -\section{Using the REST API}\label{using-the-rest-api}} - -All Airtable bases are automatically accessible to authorized users via a REST API. The list of API accessible bases you have access to can be found here: \url{https://airtable.com/api}. By clicking on a base you will be able to see the full API documentation for that base. - -\hypertarget{scoped-tokens}{% -\subsection{Scoped Tokens}\label{scoped-tokens}} - -Airtable is moving to a \href{https://airtable.com/developers/web/guides/personal-access-tokens}{scoped tokens} based approach to api access. Scoped personal access tokens allow you to create a token for a specific base with specific permissions - e.g.~token has read-only access to a bat sampling base. Using scoped tokens in this way means that if the token is compromised (leaked, stolen, accidentally committed unencrypted to a github repo, etc), you can delete that token to remove any access it might have had and the limited scope means that you know exactly what a person would have been able to access. - -To create a personal access token go here: \url{https://airtable.com/create/tokens} - -** Remember to save the token in a secure place. Do not store unencrypted tokens on the web (e.g.~pushing them to github). - -Airtable has also deployed \href{https://airtable.com/developers/web/api/oauth-reference}{oauth tokens} for all users. - -\hypertarget{airtable-and-r}{% -\subsection{Airtable and R}\label{airtable-and-r}} - -The Airtable REST API can be used via R with the \href{https://github.com/ecohealthalliance/airtabler}{airtabler package}. EHA has started a fork of the package that has additional functionality so it is recommended to use that version. The original package design works well for exploring the data. Our extension adds additional functionality to help use \texttt{airtabler} in automation via continuous integration such as GitHub Actions. - -\begin{verbatim} -devtools::install_github("ecohealthalliance/airtabler") -\end{verbatim} - -The Airtable API serves up data as JSON, which has a hierarchical structure similar to a list in R. To handle JSON, \texttt{airtabler} uses the \texttt{jsonlite} package. Its helpful to understand how \texttt{jsonlite} handles different JSON structures when working with more complicated Airtable data. See the \texttt{jsonlite} \href{https://cran.r-project.org/web/packages/jsonlite/vignettes/json-aaquickstart.html}{quick-start guide} for a basic overview. The \href{https://purrr.tidyverse.org/}{\texttt{purr} package} is extremely helpful when dealing with data objects derived from JSON because it facilitates navigating nested data structures. - -The \texttt{airtabler} package provides instructions for setting up access to the Airtable API. You will need to follow those instructions for the following examples to work. - -\textbf{One to One join} - -\begin{verbatim} -library(airtabler) - -table1 <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "One To One") - -table2 <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "Table 2") - -## Linked records are stored as JSON arrays so they become lists -## when part of a data frame. Because each array has a length of 1 -## we can safely unlist the arrays and add them back as to the -## data frame. - -table1$LinkedRec <- unlist(table1$LinkedRec) - -joinedTables <- dplyr::left_join(table1,table2, by = c("LinkedRec"="id")) - -recordKey <- joinedTables[c("Name","LinkedRec","Number")] - -recordKey - -\end{verbatim} - -\textbf{One to Many Join} - -\begin{verbatim} -library(airtabler) -library(dplyr) -library(purrr) - -oneToMany <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "One To Many") - -table2 <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "Table 2") - -# Depending on how you want to work with the data joins are a -# little trickier here. - -## to replace the values but keep the structure - -oneToMany$LinkedRecReplace <- purrr::map(oneToMany$LinkedRec, function(x){ - table2 %>% - filter(id %in% x) %>% - select(c("id","Number")) %>% - pull("Number") -}) - -data.frame( - id = unlist(oneToMany$LinkedRec), - label = unlist(oneToMany$LinkedRecReplace) -) -\end{verbatim} - -\hypertarget{data-management}{% -\section{Data Management}\label{data-management}} - -Because of its flexibility and ease of use, it is extremely important that data -management for airtable be taken seriously. Unlike most other relational databases, -the fundamental properties of your base can be changed easily by multiple users -without warning! Documenting the structure and purpose of your base, as well -as creating regular external backups could save you from catastrophe. - -\hypertarget{metadata}{% -\subsection{Metadata}\label{metadata}} - -\begin{itemize} -\tightlist -\item - \textbf{Structural metadata} - Information about a resource that tells you how its - put together - e.g.~the relationship between a table, field, and automation. With - the exception of users on the enterprise plan, you must be deliberate about - creating and maintaining structural metadata for your base. -\end{itemize} - -Example of Airtable Structural Metadata: - -\begin{itemize} -\tightlist -\item - \textbf{Descriptive metadata} - Information about a resource that makes it easier to - find and attribute data. This includes things attributes like author, title, description, - keywords, etc. This table becomes especially important when data are transitioned - out of airtable, at the end of a project, or if the base will be shared broadly - with collaborators. -\end{itemize} - -Example of Airtable Descriptive Metadata: - -To see the template base, follow this \href{https://airtable.com/invite/l?inviteId=inv5ycCAbIVw1WM3Z\&inviteToken=ef7b72e998a0a69d835244f87f88b6b9b6b1094915239ebc93423e1257fcd72b\&utm_medium=email\&utm_source=product_team\&utm_content=transactional-alerts}{link} - -\hypertarget{metadata-for-automations-and-extensions}{% -\subsubsection{Metadata for automations and extensions}\label{metadata-for-automations-and-extensions}} - -Automations and extensions live entirely inside airtable. As of August 2022, Airtable introduced a ``Manage Fields'' tab that provides metadata for a specific table, including any automation dependencies. It is not possible to export those dependency tables or the code used in automations automatically. This makes it extremely important to document any automations and extensions outside your base. - -\hypertarget{external-backups}{% -\subsection{External Backups}\label{external-backups}} - -It is a good idea to create regular external backups of airtable data in the event -that something catastrophic happens to your base or you simply decide you no longer wish -to use airtable as your data store.Unfortunately, airtable does not provide an -off the shelf solution for this. Below are three options for extracting all data -from your base. - -\hypertarget{using-airtabler}{% -\subsubsection{Using airtabler}\label{using-airtabler}} - -Using \texttt{airtabler::air\_dump()} and \texttt{airtabler::air\_dump\_to\_csv()} functions, you can export all tables to R then create a versioned folder of CSVs. See the \texttt{air\_dump\_to\_csv} help page for more information. - -\hypertarget{other-open-source-projects}{% -\subsubsection{Other Open Source Projects}\label{other-open-source-projects}} - -UnlyEd - use this template to push airtable backups to AWS S3. - -\begin{itemize} -\tightlist -\item - \url{https://github.com/UnlyEd/airtable-backups-boilerplate} -\end{itemize} - -\hypertarget{paid-services}{% -\subsubsection{Paid services}\label{paid-services}} - -Sequin - replicate airtable to postGres database -- \url{https://www.sequin.io/sources/airtable} - -\hypertarget{r}{% -\section{R}\label{r}} - -\href{https://cran.r-project.org}{R} is a free and open-source programming language and software environment for statistical computing and graphics. It was first developed in the early 1990s by Ross Ihaka and Robert Gentleman at the University of Auckland, New Zealand, and is now widely used by statisticians, data analysts, and researchers across various fields. - -R provides a wide range of statistical and graphical techniques, including linear and nonlinear modeling, classical statistical tests, time-series analysis, classification, clustering, and more. It also has a large and active community of users and developers who contribute to the development of new packages and extensions for the language. - -R is popular in the field of data science, as it provides a powerful and flexible platform for analyzing and visualizing data. It can be used in conjuction with other tools such as Airtable through community-developed packages making it particularly well-suited for the current use-case of the RIG. - -\hypertarget{database}{% -\chapter{Database}\label{database}} - -The current database is built using \href{https://airtable.com}{Airtable}. The current database has the following schema: - -\includegraphics{images/database_schema.png} - -This schema can be viewed interactively from here - \url{https://airtable.com/appAL7fJUpBPYtOq4/tblt9ott045tWENcg/viwznxjIFAsTu0jzJ?blocks=bliZ6LV2bkGQNzgKF} - -\hypertarget{activities-table}{% -\section{Activities Table}\label{activities-table}} - -\hypertarget{table-details}{% -\subsection{Table details}\label{table-details}} - -Activities pertain to the formal/official title of the project that has been identified during the database search or survey. - -Following are the different fields within the Activities table with their description. - -\hypertarget{fields-details}{% -\subsection{Fields details}\label{fields-details}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -Activity & Activity name & singleLineText & NA\\ -\hline -Source Name (from Primary Sources) & Name of primary source & multipleLookupValues & NA\\ -\hline -Notes & Internal notes for maintenance & singleLineText & NA\\ -\hline -Topic & Activity Topic & multipleRecordLinks & Topics\\ -\hline -Grant ID & Grand Identifier & singleLineText & NA\\ -\hline -Collaborators & Activity collaborators & multipleRecordLinks & Institutions\\ -\hline -Researchers & Researchers involved in activity & multipleRecordLinks & Researchers\\ -\hline -Published Work & Links to published work & singleLineText & NA\\ -\hline -Activity Location alt & Activity location & multipleRecordLinks & Countries\\ -\hline -UN Stats Sub-region Name (from Activity Location alt) & NA & multipleLookupValues & NA\\ -\hline -Activity Outputs & Activity Outputs & multipleSelects & Data, Publication, Report, Guideline/SOP, Archive, Improving Diagnostics, Vaccine development, Therapeutics, Epidemic/Pandemic Preparedness, Biosurveillance technology, Prophylaxis, Surveillance, Improving Vaccine strategies, Training, Risk Assessment, Improving Capacity, Policies\\ -\hline -Activity Status & Activity Status & singleSelect & Active, Completed\\ -\hline -Activity Website & Activity Website & url & NA\\ -\hline -Activity Identifier & Activity identifier & formula & NA\\ -\hline -Primary Sources & Primary source of information & multipleRecordLinks & Sources\\ -\hline -Additional Sources & Additional sources & singleLineText & NA\\ -\hline -Continent Name (from Activity Location alt) & NA & multipleLookupValues & NA\\ -\hline -AU Region Name (from Activity Location alt) & NA & multipleLookupValues & NA\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{countries-table}{% -\section{Countries Table}\label{countries-table}} - -\hypertarget{table-details-1}{% -\subsection{Table details}\label{table-details-1}} - -List of countries used to indicate the location information for the researchers, topics, funders, sources, institutions, and activities tables - -Following are the different fields within the Countries table with their description. - -\hypertarget{fields-details-1}{% -\subsection{Fields details}\label{fields-details-1}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -Researchers & NA & multipleRecordLinks & Researchers\\ -\hline -Funders & NA & multipleRecordLinks & Funders\\ -\hline -AU Region Name & NA & singleSelect & Northern Africa, Eastern Africa, NA, Central Africa, Southern Africa, Western Africa\\ -\hline -UN Stats Sub-region Name & Name of further sub-regional grouping to which country is usually classified within. This is based on the UN Statistics Division nomenclature. & singleSelect & NA, Eastern Africa, Middle Africa, Southern Africa, Western Africa, Channel Islands, Sark\\ -\hline -Country Name & County name based on UN Statistics Division nomenclature & multilineText & NA\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{description-table}{% -\section{Description Table}\label{description-table}} - -\hypertarget{table-details-2}{% -\subsection{Table details}\label{table-details-2}} - -The Description table provides overall description of this entire database. - -Following are the different fields within the Description table with their description. - -\hypertarget{field-details}{% -\subsection{Field details}\label{field-details}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -Email & Email for primary contact & email & NA\\ -\hline -Primary Contact & Person to correspond with about the base & singleLineText & NA\\ -\hline -IRB & Optional: Link to IRB & url & NA\\ -\hline -Base Description & Characterization of the base. What is the base describing? & multilineText & NA\\ -\hline -Title & Title of the base & singleLineText & NA\\ -\hline -Data Management Plan & Link to data management plan & url & NA\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{funders-table}{% -\section{Funder Table}\label{funders-table}} - -\hypertarget{table-details-3}{% -\subsection{Table details}\label{table-details-3}} - -Funders pertain to the entities funding each activity. - -The funders' information is retrieved from declared funders for the activities identified during the database search or the survey. - -Following are the different fields within the Funders table with their description. - -\hypertarget{field-details-1}{% -\subsection{Field details}\label{field-details-1}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -Funder Type & Type of funder & singleSelect & Charitable organization, Foundation, Pharmaceutical company , Not-for-profit Partnership, NGO, Government Agency, University, Research Institut, Public- public partnership , Public-private partnership\\ -\hline -Funder Website & Website of funder & url & NA\\ -\hline -Source Name (from Primary Sources) & Source from where funder was identified & multipleLookupValues & NA\\ -\hline -Activities & Activities supported by funder & multipleRecordLinks & Activities\\ -\hline -WHO Region Name (from Funder Location alt) & NA & multipleLookupValues & NA\\ -\hline -Continent Name (from Funder Location alt) & NA & multipleLookupValues & NA\\ -\hline -Primary Sources & Source from where funder was identified & multipleRecordLinks & Sources\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{institutions-table}{% -\section{Institutions Table}\label{institutions-table}} - -\hypertarget{table-details-4}{% -\subsection{Table details}\label{table-details-4}} - -Institutions pertain to the entities directly related to or implementing the activity and/or the affiliation of the researcher implementing the activity. - -Following are the different fields within the Institutions table with their description. - -\hypertarget{field-details-2}{% -\subsection{Field details}\label{field-details-2}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -Institution Email & Email of institution & email & NA\\ -\hline -Institution Website & Institution Website & url & NA\\ -\hline -Activities & Name of activity identified with institution & multipleRecordLinks & Activities\\ -\hline -Sources & Name of primary source & multipleRecordLinks & Sources\\ -\hline -Institution Type & Institution Type & singleSelect & Research Institute, University, NGO, National Government Institution, Non-profit Organisation , Hospital, Government Agency, Consortium, Partnership of Institutes, Industry, Charity, Public-private partnetship, International Coalition , Inter-governmental Organisation, Medical Service Provider, Network\\ -\hline -Institution Location & Institution location & multipleRecordLinks & WHO Countries\\ -\hline -Notes & Internal notes (for maintenance) & singleLineText & NA\\ -\hline -Topic (from Activities) & Name of topic identified with the institution & multipleLookupValues & NA\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{researchers-table}{% -\section{Researchers Table}\label{researchers-table}} - -\hypertarget{table-details-5}{% -\subsection{Table details}\label{table-details-5}} - -Researchers pertains to the people involved in the activities contained in this database, and maybe involved in a variety of activity types. including but not limited to, research. - -Researchers identified during the database search. Information on researchers are primarily retrieved once activities have been identified from the database search process. It is possible that researchers are identified apriori and from which information on topics, funders, sources, institutions, and activities may be identified relevant to the specific researcher. This may happen when the planned/proposed survey is implemented and sent to known researchers who may or may not be in the database to begin with. - -Following are the different fields within the Researchers table with their description. - -\hypertarget{field-details-3}{% -\subsection{Field details}\label{field-details-3}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -WHO Region Name (from Researcher Country Location alt) & NA & multipleLookupValues & NA\\ -\hline -ACDC Status & Is researcher from the Africa CDC? & singleSelect & Non-member, Member\\ -\hline -Sources & Name of source & multipleRecordLinks & Sources\\ -\hline -UN Stats Region Name (from Researcher Country Location alt) & NA & multipleLookupValues & NA\\ -\hline -Affiliation & Institution researcher is affiliated with. Choices from the institutions table & multipleRecordLinks & Institutions\\ -\hline -Institution Location alt (from Affiliation) & NA & multipleLookupValues & NA\\ -\hline -Topic (from Activity) & Name of topic & multipleLookupValues & NA\\ -\hline -Researcher Name & Full name of researcher identified in the search & singleLineText & NA\\ -\hline -Notes & Internal notes (for maintenance) & singleLineText & NA\\ -\hline -Source Name (from Sources) & Name of source & multipleLookupValues & NA\\ -\hline -Additional Sources & Additional sources & singleLineText & NA\\ -\hline -Activity Type (from Activity) & Type of activity & multipleLookupValues & NA\\ -\hline -Website & Personal website of researcher (if any) & singleLineText & NA\\ -\hline -Activity & Activity/activities researchers is involved in & multipleRecordLinks & Activities\\ -\hline -Institution Location (from Affiliation) & Name of location where institution is based & multipleLookupValues & NA\\ -\hline -Willing to be contacted & Is the researcher willing to be contacted? & checkbox & NA\\ -\hline -Continent Name (from Researcher Country Location alt) & NA & multipleLookupValues & NA\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{sources-table}{% -\section{Sources Table}\label{sources-table}} - -\hypertarget{table-details-6}{% -\subsection{Table details}\label{table-details-6}} - -Sources contain initial set of sources (primarily funders) identified to initiate the database search. These original sources are fully described here - \url{https://ecohealthalliance.github.io/rig-handbook/sources.html}. - -From the initial search, other sources were identified from which additional streams of searches were performed. Currently, the sources table is updated through a primary search of possible sources in addition to the search performed on the original sources list. - -Following are the different fields within the Sources table with their description. - -\hypertarget{field-details-4}{% -\subsection{Field details}\label{field-details-4}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -Source Type & Type of primary source & singleSelect & Website text page, Website table, Website search, Downloadable document in PDF, Downloadable document in XLSX, Downloadable document in CSV, Downloadable document in DOCX, A form of database, Website text page, Website search, Links to downloadable documents in PDF, Website table, Website search\\ -\hline -Source Notes & Internal notes for primary source (for maintenance) & multilineText & NA\\ -\hline -Topics & Topics identified from primary source & multipleRecordLinks & Topics\\ -\hline -Relevant tables & Notes on relevant tables found from primary source & multipleSelects & Researchers, Topics, Activities, Funders, Institutions, Countries\\ -\hline -Funders & Funders identified from primary source & multipleRecordLinks & Funders\\ -\hline -Source Name & Name of primary source & singleLineText & NA\\ -\hline -Created By & Person who created the entry & createdBy & NA\\ -\hline -Researchers & Name of researcher identified from primary source & multipleRecordLinks & Researchers\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{survey-results-table}{% -\section{Survey Results Table}\label{survey-results-table}} - -\hypertarget{table-details-7}{% -\subsection{Table details}\label{table-details-7}} - -NA - -Following are the different fields within the Survey Results table with their description. - -\hypertarget{field-details-5}{% -\subsection{Field details}\label{field-details-5}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -Activity description/ purpose & Description of activity & multilineText & NA\\ -\hline -Sharing with Colleagues & Is respondent going to share with colleagues? & singleLineText & NA\\ -\hline -Lead Researcher & Name of lead researcher & singleLineText & NA\\ -\hline -Created By & Name of survey respondent & createdBy & NA\\ -\hline -Other websites listing this project & Other website listings for this project & singleLineText & NA\\ -\hline -Funder & Name of funder for this project & singleLineText & NA\\ -\hline -Official Project Title & Official project title & singleLineText & NA\\ -\hline -Official Project website & Official project website & singleLineText & NA\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{topics-table}{% -\section{Topics Table}\label{topics-table}} - -\hypertarget{table-details-8}{% -\subsection{Table details}\label{table-details-8}} - -Topics pertain to the disease names and disease types. - -The topics table contains disease types/disease entities of interest to the Africa CDC based on their priorities (as described in their Framework document) and is continually updated with whatever disease/disease entity/disease type were deemed relevant by the database contributor. - -Following are the different fields within the Topics table with their description. - -\hypertarget{field-details-6}{% -\subsection{Field details}\label{field-details-6}} - -\begin{table} -\centering -\begin{tabular}{l|l|l|l} -\hline -\textbf{Field Name} & \textbf{Field Description} & \textbf{Field Type} & \textbf{Field Values}\\ -\hline -Sources & Name of Source & multipleRecordLinks & Sources\\ -\hline -Diseases & Disease entity related/relevant to the field/topic of interest & multipleSelects & HIV, TB, COVID-19, Monkeypox, Lassa fever, Bat flu, Avian flu, Swine flu, Ebola virus disease, Marburg virus disease, Marburg haemorrhagic fever, H7N9, H5N1, H1N1, H1N2, H3N2, Plague, Anthrax, Crimean-Congo Haemorrhagic Fever, Rift Valley Fever, Nipah Virus, Brucellosis, undulant fever, Malta fever, Mediterranean fever, Hantavirus haemorrhagic fever with renal syndrome, Hantavirus pulmonary syndrome, Q fever, Chikungunya, Henipavirus, Ghanaian bat henipavirus, Leptospirosis, Weill's disease, West Nile Fever, Zika fever, Dengue fever, African trypanosomiasis, Chagas disease, Yellow fever, Malaria, Re-emerging viruses, Visceral Leishmaniasis, Kala-azar, Cutaneous leishmaniasis , Hepatitis E , Viral Hepatitis, Hepatitis C, Hepatitis B, Leprosy, Hookworm, Schistosomiasis, Ascariasis, Trichuriasis, Lymphatic filariasis, Trachoma, Buruli ulcer, Dracunculiasis, Bilharzia, Whipworm Infection, Elephantiasis, Guinea-worm disease , Burkitt lymphoma, Cryptococcal meningitis, Kaposi sarcoma, schistosomiasis, Viral haemorrhagic fever, Rabies\\ -\hline -Activity Location (from Activities) & Name of location of activity in which topic was identified & multipleLookupValues & NA\\ -\hline -Survey Results & Results from survey & multipleRecordLinks & Survey Results\\ -\hline -Search terms & Search terms used to identify topic & multipleSelects & antimycobacterial, anti-mycobacterial, COVID-19, coronavirus, omicron, rifampicin, ritonavir, darunavir, dolutegravir, MIS-C, HVTN, ART, antiretroviral, lopinavir, bedaquiline, clofazimine, isoniazid, pyrazinamide, antitubercular, tenofovir disoproxil fumarate, emtricitabine, dolutegravir , efavirenz, tubercular, drug-resistant, AMR, raltegravir, DR-, DR-TB, helminth, TBM, fluke, wildlife sampling, biosurveillance, surveillance network, seroprevalence, detection of \_\_, monitoring of \_\_, seroevidence, identification of \_\_, seropositive, seroepidemiological, survey, screened, \_\_ prevalence\\ -\hline -Disease Types & Type/category to which disease is grouped under & multipleSelects & infectious disease, viral, bacterial, parasitic, vector-bourne, zoonotic, virus, soil-transmitted\\ -\hline -Continent Name (from Activity Location alt) (from Activities) & NA & multipleLookupValues & NA\\ -\hline -Activity Location alt (from Activities) & NA & multipleLookupValues & NA\\ -\hline -Institutions & Institutions & multipleRecordLinks & Institutions\\ -\hline -Region (from Activity Location) (from Activities) & Name of region where topic was identified & multipleLookupValues & NA\\ -\hline -AU Region Name (from Activity Location alt) (from Activities) & NA & multipleLookupValues & NA\\ -\hline -Source Name (from Sources) & Name of source & multipleLookupValues & NA\\ -\hline -\end{tabular} -\end{table} - -\hypertarget{sources}{% -\chapter{Sources}\label{sources}} - -Following is an initial list of sources of information used for the RIG database. - -The initial search performed was non-systematic and focused primarily on a known funder of global research related/relevant to the topics of interest for the database . The main aim of focusing first on this limited and focused search was to get a sense of what information is available from such bodies/organisations, and the limitations of the information available. This is based on an initial idea that research funders would tend to have a system of collecting/archiving information on research they have funded. The expectation was that at the minimum, the information available from funders would lead to identifying further sources of information relevant to the ACDC database specifically those of research groups/institutions particularly those based in countries/regions within Africa. This initial search will hopefully inform a more systematic and informed search strategy for the database information. - -\hypertarget{ukri}{% -\section{UKRI}\label{ukri}} - -\href{https://www.ukri.org/}{UK Research and Innovation or UKRI} is a non-departmental public body in the United Kingdom that was established in 2018. It brings together the seven UK Research Councils, \href{https://www.ukri.org/councils/innovate-uk/}{Innovate UK}, and \href{https://www.ukri.org/councils/research-england/}{Research England}, which were previously separate organizations, to create a single body that oversees research and innovation funding and strategy in the UK. - -The seven UK Research Councils are: - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\tightlist -\item - Arts and Humanities Research Council (AHRC) -\item - Biotechnology and Biological Sciences Research Council (BBSRC) -\item - Engineering and Physical Sciences Research Council (EPSRC) -\item - Economic and Social Research Council (ESRC) -\item - Medical Research Council (MRC) -\item - Natural Environment Research Council (NERC) -\item - Science and Technology Facilities Council (STFC) -\end{enumerate} - -Innovate UK is the UK's innovation agency, which provides funding and support for innovative businesses and projects. - -Research England is responsible for funding and overseeing research in English universities and higher education institutions. - -UKRI's main role is to drive innovation and research in the UK and to support research and development that benefits society and the economy. It funds research projects, provides support to researchers, promotes international collaboration, and works to ensure that research and innovation are integrated with government policies and priorities. - -Of these various groups within UKRI, we further focused on the \href{https://www.ukri.org/councils/bbsrc/}{Biotechnology and Biological Sciences Research Council (BBSRC)}, \href{https://www.ukri.org/councils/mrc/}{Medical Research Council (MRC)}, \href{https://www.ukri.org/councils/stfc/}{Science and Technology Facilities Council (STFC)}, \href{https://www.ukri.org/councils/innovate-uk/}{Innovate UK}, and \href{https://www.ukri.org/councils/research-england/}{Research England}. - -\hypertarget{wellcome}{% -\section{Wellcome Trust}\label{wellcome}} - -The Wellcome Trust is a global charitable foundation based in the UK. It was established in 1936 by Sir Henry Wellcome, a pharmaceutical entrepreneur and philanthropist. The Wellcome Trust is one of the largest charitable organizations in the world, with an endowment of over £29 billion. - -The Trust's mission is to improve health by supporting scientists, researchers, and innovators in their work to understand, treat, and prevent disease. The Trust funds research in areas such as neuroscience, genetics, infectious diseases, and global health. It also provides support for public engagement with science, education and training for scientists, and the translation of research into practical applications that benefit patients and communities. - -The Wellcome Trust is known for its long-term, strategic approach to funding research, and for its commitment to open science and data sharing. It also operates the Wellcome Collection, a public venue in London that hosts exhibitions and events related to health, medicine, and science. - -\hypertarget{nih}{% -\section{National Insitutes of Health}\label{nih}} - -The National Institutes of Health (NIH) is a biomedical research agency of the United States federal government. It is the largest biomedical research institution in the world, with its main campus located in Bethesda, Maryland. The NIH is composed of 27 separate institutes and centers, each with a specific research focus, and is responsible for conducting and funding research in a wide range of areas, including cancer, genetics, infectious diseases, and neuroscience. - -The NIH was founded in 1887 as the Hygienic Laboratory and was later renamed the National Institutes of Health in 1930. Today, it is one of the world's foremost centers for medical research, with a mission to seek fundamental knowledge about the nature and behavior of living systems and to apply that knowledge to enhance health, lengthen life, and reduce illness and disability. The NIH is funded by the U.S. government through the Department of Health and Human Services and operates under the direction of the Office of the Director. - -\hypertarget{nsf}{% -\section{National Science Foundation}\label{nsf}} - -The National Science Foundation (NSF) is an independent federal agency of the United States government that supports fundamental research and education across all fields of science and engineering. The NSF was established by the National Science Foundation Act of 1950 and has a budget of around \$8 billion. - -The NSF funds research and education in areas such as mathematics, computer science, physics, chemistry, biology, social sciences, and engineering. It supports individual researchers, small teams, and large interdisciplinary research collaborations through a competitive, merit-based process of proposal submission and review. The NSF also supports the development of science, technology, engineering, and mathematics (STEM) education at all levels, from K-12 through graduate education. - -The NSF operates through several directorates and offices, each with a specific research focus or mission, such as the Directorate for Biological Sciences, the Directorate for Social, Behavioral and Economic Sciences, and the Office of Polar Programs. The NSF works to advance scientific discovery, promote science education and outreach, and promote innovation and economic growth through its investments in research and education. - -\hypertarget{darpa}{% -\section{Defense Advanced Research Projects Agency}\label{darpa}} - -The Defense Advanced Research Projects Agency is a research and development agency of the United States Department of Defense that is responsible for the development of emerging technologies for use by the military. - -DARPA was established in 1958 in response to the Soviet Union's launch of Sputnik, the first artificial satellite, and has been involved in a number of high-profile technological innovations, including the development of the Internet, GPS, and stealth technology. - -DARPA's mission is to maintain the technological superiority of the U.S. military by sponsoring and conducting research in a wide range of fields, including artificial intelligence, robotics, biotechnology, materials science, and aerospace technology. DARPA works with academic researchers, private companies, and other government agencies to develop and test new technologies, and it is known for its high-risk, high-reward approach to research and development. - -Some of DARPA's current research initiatives include the development of hypersonic weapons, the creation of autonomous drone swarms, and the development of brain-machine interfaces for use in treating neurological disorders. DARPA's work has had significant impacts on both military and civilian technology, and the agency is seen as a leader in cutting-edge research and development. - -\hypertarget{clinicaltrials.gov}{% -\section{ClinicalTrials.gov}\label{clinicaltrials.gov}} - -ClinicalTrials.gov is a publicly accessible database of clinical trials that are being conducted worldwide. It is maintained by the National Library of Medicine, a part of the National Institutes of Health (NIH) in the United States. - -The database provides information on clinical trials for a wide range of diseases and conditions, including both interventional and observational studies. It includes information about the purpose of the trial, who may participate, where the trial is being conducted, and the status of the trial, such as whether it is recruiting participants or has been completed. - -ClinicalTrials.gov was created in response to a 1997 law requiring the registration of clinical trials for certain serious or life-threatening diseases or conditions. Since then, the database has grown to include information on thousands of trials from around the world. - -ClinicalTrials.gov is an important resource for researchers, healthcare professionals, and members of the public who are interested in clinical research. It can be used to identify ongoing or completed trials, learn about the purpose and design of a study, and find out how to participate in a trial. It also serves as a platform for researchers to share their results and comply with the requirements of various funding agencies and regulatory bodies. - -\hypertarget{gepris}{% -\section{GEPRIS}\label{gepris}} - -Geförderte Projekte in der Forschung und Entwicklung (Funded Projects in Research and Development) or GEPRIS is an online database of research projects funded by the German Research Foundation (DFG). - -The DFG is the largest independent research funding organization in Germany and funds projects across all scientific disciplines, from the humanities and social sciences to the natural and life sciences. GEPRIS provides information about the projects that the DFG has funded, including their aims, methods, and outcomes, as well as the institutions and researchers involved. - -Researchers and members of the public can use GEPRIS to search for projects that have been funded by the DFG, and to access information about these projects. The database includes information about ongoing and completed projects, and users can search by various criteria, such as by researcher name, institution, scientific discipline, or project title. - -GEPRIS is a valuable tool for researchers to identify potential collaborators, explore research trends, and find information about the funding landscape in their field. It is also useful for members of the public who are interested in learning about the research being conducted in Germany and the impact of this research on society. - -\hypertarget{edctp}{% -\section{EDCTP}\label{edctp}} - -European and Developing Countries Clinical Trials Partnership or EDCTP is a public-public partnership between countries in Europe and sub-Saharan Africa, established in 2003, with the aim of accelerating the development of new clinical interventions to fight infectious diseases that disproportionately affect Africa. - -The partnership's mission is to improve the health of people in Africa by supporting the development of new medicines, vaccines, and other health interventions to prevent and treat diseases such as HIV/AIDS, tuberculosis, malaria, and neglected infectious diseases. EDCTP supports collaborative research projects that bring together scientists, institutions, and countries from both regions to conduct clinical trials and other research activities. - -EDCTP works with a range of partners, including national governments, research institutions, civil society organizations, and the private sector, to support research that is relevant and responsive to the needs of African communities. It also provides training and capacity-building opportunities to support the development of sustainable health research infrastructure and expertise in Africa. - -The partnership is funded by the European Union, its member states, and other donors. Since its inception, EDCTP has supported over 100 collaborative research projects and played a key role in advancing the development of new interventions for infectious diseases that affect the people of Africa. - -\hypertarget{glopidr}{% -\section{GLOPID-R}\label{glopidr}} - -Global Research Collaboration for Infectious Disease Preparedness or GLOPID-R is an international partnership that aims to strengthen global research efforts in the field of infectious disease preparedness. The partnership was established in response to the 2014 Ebola outbreak in West Africa, which highlighted the need for improved global coordination and collaboration in research and development for emerging and re-emerging infectious diseases. - -GLOPID-R brings together stakeholders from the global health community, including research funders, policy-makers, researchers, and public health organizations. The partnership aims to promote international cooperation and coordination in research to accelerate the development of new tools and approaches to prevent, detect, and respond to infectious disease outbreaks. - -GLOPID-R's main objectives include identifying research priorities for infectious disease preparedness, coordinating research efforts across different regions and countries, and promoting capacity building and knowledge exchange to strengthen global health research infrastructure. - -The partnership focuses on a range of infectious diseases, including those caused by emerging and re-emerging pathogens, neglected tropical diseases, and antimicrobial resistance. It works to support research efforts across the entire spectrum of infectious disease preparedness, from basic research to clinical trials and implementation research. - -GLOPID-R is supported by a range of funding agencies and partners from around the world and is seen as an important platform for promoting global cooperation and collaboration in infectious disease research and preparedness. - -\hypertarget{nrfza}{% -\section{NRF South Africa}\label{nrfza}} - -The National Research Foundation of South Africa (NRF) is an independent organization that promotes and supports research and innovation in all fields of science, engineering, technology, and social sciences in South Africa. The NRF was established in 1999 through the National Research Foundation Act and operates under the jurisdiction of the Department of Science and Innovation. - -The NRF provides funding, develops policies, and manages research infrastructure to support South African researchers and institutions. It also fosters international collaboration in research, and supports the training and development of the next generation of researchers through various funding and fellowship schemes. - -The NRF provides funding through a number of programs, including competitive grants, fellowships, and research chairs. It also supports the development of research infrastructure and the establishment of research centers of excellence. - -In addition to providing funding and support for research, the NRF plays a key role in developing research policies and strategies at the national level. It advises the South African government on research priorities and is involved in various initiatives aimed at promoting science, technology, and innovation in the country. - -The NRF is an important organization for the South African research community and has been instrumental in advancing the country's research and innovation capabilities. Its funding and support have contributed to numerous scientific discoveries and innovations in a wide range of fields, including health, energy, and the environment. - -\hypertarget{updates}{% -\chapter{Updates}\label{updates}} - -The current update process of the RIG database is summarised in this workflow: - -\includegraphics{images/initial-acdc-db-search_NK.png} - -Following are the source-specific process of updating or retrieving information for the RIG database. - -\hypertarget{update-wellcome}{% -\section{Wellcome Trust Grant Funding Data}\label{update-wellcome}} - -\hypertarget{general-information}{% -\subsection{General Information}\label{general-information}} - -Using the downloadable spreadsheet of funds awarded between 01st of October 2005 and 4th of May 2022 found at \url{https://cms.wellcome.org/sites/default/files/2022-05/Wellcome-grants-awarded-1-October-2005-to-04-05-2022.xlsx}, the following steps were taken to retrieve relevant information for the database: - -\hypertarget{how-to-update}{% -\subsection{How to update}\label{how-to-update}} - -Please note that the steps below were done using the current available spreadsheet from the Wellcome Trust website and added the relevant projects to the RIG database. These steps can therefore be used as a guide for how to update the database with new information in the future to when the Wellcome Trust publishes its most up-to-date spreadsheet. - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\item - Go to column J -- Recipient Org:Country -\textgreater{} deselect all and then select all the African countries in the list -\item - Go to column N -- Planned end date -\textgreater{} select all the years in the future -\item - These two steps reduced the list from 19,833 projects to 111 projects -\item - Read the project title and decide if the project is relevant for our database or not -\item - If unsure, read the abstract -- that also helps to identify the keywords to tag the project within our database -\item - If the project is relevant transfer all the information into our database -\end{enumerate} - -\textbf{Note:} This method is only able to detect projects/activities where an African organisation itself holds the grant. It does not detect projects where African researchers are involved as collaborators. The spreadsheet does not list collaborators on projects, so it's yet to be determined how we will identify projects on which African research institutes collaborate with international organisations being awarded the grant. - -\hypertarget{update-clinicaltrials}{% -\section{ClinicalTrials.gov}\label{update-clinicaltrials}} - -\hypertarget{how-to-update-1}{% -\subsection{How to update}\label{how-to-update-1}} - -Following are steps taken to extract data from \href{https://clinicaltrials.gov/}{ClinicalTrials.gov}. - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\tightlist -\item - Start with searching a disease/topic of interest -\end{enumerate} - -\includegraphics{images/clinicaltrial1.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{1} -\tightlist -\item - On the results page apply the following filters to look for active studies -\end{enumerate} - -\includegraphics{images/clinicaltrial2.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{2} -\tightlist -\item - Click on `Apply' and then look manually through the column `Locations' of the list of the results to find studies that take place in African countries -\end{enumerate} - -\includegraphics{images/clinicaltrial3.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{3} -\item - Click on the first study to start working your way through the information available -\item - The first information provided is the sponsor -\textgreater{} this information should be added to the Funder -- column in the Activities table -\item - Information about collaborators can be added to Collaborators column -\end{enumerate} - -\includegraphics{images/clinicaltrial4.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{6} -\item - Staying in the `Study Details'-tab, scroll down to `Study Design' -\item - This section contains the official title, which should be used as the name for the Activity -\item - Additionally it contains information about the start and end date, which should be copied into the respective fields in the Activities table -\end{enumerate} - -\includegraphics{images/clinicaltrial5.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{9} -\item - Scroll further down to `Contact and Locations' -\item - The information given under contacts should be added to the Researcher column in Airtable -\item - Switching into the Researcher-table within in Airtable the given contact details should be added to the newly created entries for the involved researchers -\item - Also the affiliation to a certain institute can be added based on these information as well as the researcher's location -\textgreater{} is it possible to link the Location with the Affiliation so that the location is automatically added based on the information about the institution the researcher is affiliated with? -\item - Switch back into the Activities table and add information about the Locations to the Activity Location and the Institutions columns -\end{enumerate} - -\includegraphics{images/clinicaltrial6.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{14} -\item - Scroll up again to the selection of tabs -\item - Click on the Results tab -\textgreater{} it's worth checking this tab even when it's called No Results Posted as it might still contain links to publications that are affiliated with the study -\item - These links can be copied into the Published Work column in the Activities table -\end{enumerate} - -\includegraphics{images/clinicaltrial7.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{17} -\tightlist -\item - I also copied the link of the study page on clinicaltrials.gov into the Activity Website column -\end{enumerate} - -\includegraphics{images/clinicaltrial8.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{18} -\tightlist -\item - to determine the Research Field, I had to use my own understanding of the study so I am not sure if this can be automated or rather needs to be done by a database librarian -\end{enumerate} - -\hypertarget{update-public-research}{% -\section{Public journal/research databases}\label{update-public-research}} - -In order to aid in automation, maintain a list relevant search terms for each topic of interest (stored in the ``Topics'' table in Airtable). Even if the terms are not used for the purposes of developing a search strategy, they can be used by those who are not subject matter experts when collection information on a specific topic - -\hypertarget{example-of-a-successful-search}{% -\subsection{Example of a successful search:}\label{example-of-a-successful-search}} - -\begin{verbatim} -(zoonoses OR zoonotic disease OR zoonotic illness) and (africa*) and (surveillance OR tracking OR sampling) -\end{verbatim} - -The majority of results from this search, when conducted in \href{https://pubmed.ncbi.nlm.nih.gov/}{PubMed}, appeared relevant to the database (based on title/abstract scanning) - -\hypertarget{example-of-pubmed-search-for-surveillance-activities-for-brucellosis}{% -\subsection{Example of PubMed search for surveillance activities for Brucellosis:}\label{example-of-pubmed-search-for-surveillance-activities-for-brucellosis}} - -\begin{verbatim} -("surveillance"[Title/Abstract] OR "prevalence"[Title/Abstract] OR "monitoring"[Title/Abstract] OR "seropositive"[Title/Abstract] OR "seroprevalence"[Title/Abstract] OR "seroevidence"[Title/Abstract] OR "screened"[Title/Abstract] OR "biosurveillance"[Title/Abstract] OR "sampl*"[Title/Abstract]) AND (brucellosis[Title/Abstract] OR "Brucella melitensis"[Title/Abstract] OR "B. melitensis"[Title/Abstract] OR "Brucella abortus"[Title/Abstract] OR "B. abortus"[Title/Abstract]) -\end{verbatim} - -This search yielded a large quantity of results, not all of which were relevant. Manual processes are required to validate results. - -Including terms to filter the results based on location were helpful, but still included results not located on the African continent. Search term to filter for African countries: - -\begin{verbatim} -(Djibouti[Title/Abstract] OR Seychelles[Title/Abstract] OR DR Congo[Title/Abstract] OR Comoros[Title/Abstract] OR Togo[Title/Abstract] OR Sierra Leone[Title/Abstract] OR Libya[Title/Abstract] OR Tanzania[Title/Abstract] OR South Africa[Title/Abstract] OR Cabo Verde[Title/Abstract] OR Congo[Title/Abstract] OR Kenya[Title/Abstract] OR Liberia[Title/Abstract] OR Central African Republic[Title/Abstract] OR Mauritania[Title/Abstract] OR Uganda[Title/Abstract] OR Algeria[Title/Abstract] OR Sudan[Title/Abstract] OR Morocco[Title/Abstract] OR Eritrea[Title/Abstract] OR Angola[Title/Abstract] OR Mozambique[Title/Abstract] OR Ghana[Title/Abstract] OR Madagascar[Title/Abstract] OR Cameroon[Title/Abstract] OR Côte d'Ivoire[Title/Abstract] OR Namibia[Title/Abstract] OR Niger[Title/Abstract] OR Gambia[Title/Abstract] OR Botswana[Title/Abstract] OR Gabon[Title/Abstract] OR Sao Tome & Principe[Title/Abstract] OR Lesotho[Title/Abstract] OR Burkina Faso[Title/Abstract] OR Nigeria[Title/Abstract] OR Mali[Title/Abstract] OR Guinea-Bissau[Title/Abstract] OR Malawi[Title/Abstract] OR Zambia[Title/Abstract] OR Senegal[Title/Abstract] OR Chad[Title/Abstract] OR Somalia[Title/Abstract] OR Zimbabwe[Title/Abstract] OR Equatorial Guinea[Title/Abstract] OR Guinea[Title/Abstract] OR Rwanda[Title/Abstract] OR Mauritius[Title/Abstract] OR Benin[Title/Abstract] OR Burundi[Title/Abstract] OR Tunisia[Title/Abstract] OR Eswatini[Title/Abstract] OR Ethiopia[Title/Abstract] OR South Sudan[Title/Abstract] OR Egypt[Title/Abstract]) -\end{verbatim} - -From publications, can extract researchers, institutions, funders, activities. Ideally, researchers, institutions, and funders can be extracted automatically as opposed to manually, but scripts would need to be customized for each journal. - -\hypertarget{validation-of-results}{% -\subsection{Validation of results}\label{validation-of-results}} - -Validation of results can be useful to better understand the overlap between publications and activities and determine the priority of searching through publications vs.~navigating to institution sites directly (or other strategies). - -After finding a relevant publication, look at the publication's authors and their respective institutions - -Navigate to institutions' sites to search for publications or results from research - -Are their activities listed on the site? Are those activities explicitly mentioned in the publications? Etc. - -\hypertarget{some-relevant-journalsdatabases}{% -\subsection{Some relevant journals/databases:}\label{some-relevant-journalsdatabases}} - -\begin{itemize} -\item - Zoonoses \& Public Health from Wiley Online Library : \url{https://onlinelibrary.wiley.com/action/doSearch?SeriesKey=18632378\&sortBy=Earliest} -\item - Journal of Public Health in Africa: \url{https://www.publichealthinafrica.org/jphia/issue/view/30} -\item - PLoS Journal of Neglected Tropical Diseases: \url{https://journals.plos.org/plosntds/search?filterJournals=PLoSNTD} -\end{itemize} - -\hypertarget{update-gepris}{% -\section{GEPRIS}\label{update-gepris}} - -\hypertarget{general-information-1}{% -\subsection{General Information:}\label{general-information-1}} - -GEPRIS is a database listing all projects funded by the German Research Foundation (German: Deutsche Forschungsgemeinschaft; abbr. DFG) The DFG is a research funding organisation, which functions as a self-governing institution for the promotion of science and research in the Federal Republic Germany. In 2019, the DFG had a funding budget of €3.3 billion. - -\hypertarget{how-to-use}{% -\subsection{How to Use:}\label{how-to-use}} - -The database can be accessed here: \url{https://gepris.dfg.de/gepris/OCTOPUS?language=en\&task=showSearchSimple} - -This link should directly lead to the English version of the website, otherwise the language can be changed by clicking on English in the top right corner. - -\begin{itemize} -\item - In the database one can search for Projects, People, or Institutions -- for our purpose the project option is the most relevant -\item - One can either search for keywords or filter for different criteria -- for a systematic approach I found using the filtering options easier than going through all our -\end{itemize} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\item - On the search start site stay in the Projects tab. -\item - Click on Show extended search. -\item - Under Subject Area select one of the following: - - \begin{itemize} - \item - Agriculture, Forestry and Veterinary Medicine - \item - Basic Research in Biology and Medicine - \item - Medicine - \item - Microbiology, Virology, and Immunology - \item - Social Sciences - \item - Water Research - \item - Zoology - \end{itemize} -\end{enumerate} - -\textbf{Note:} After working through all these subject areas, any relevant project in the field of One Health should be picked up by the searches - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{3} -\item - Leave everything under DFG Programme as it is -\item - Move on to Funding and change Status to Current -\item - Move on to International and change Continent to Africa -\item - Click on Find -\item - Read through the project titles on the results page to identify relevant projects -\item - Import all the relevant project information (as highlighted on the screenshots) into the Africa CDC database -\end{enumerate} - -\includegraphics{images/gepris1.png} -\includegraphics{images/gepris2.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{9} -\tightlist -\item - To identify the research institutes that are involved in the project one has to click on the researchers names and extract that information from their profile (their affiliation with a research institute is listed there) -\end{enumerate} - -\hypertarget{positive-aspects-of-this-source}{% -\subsection{Positive aspects of this source:}\label{positive-aspects-of-this-source}} - -The filtering options allow to filter for several criteria which are crucial for the relevance of a project to our database. That removes a lot of irrelevant projects from the results pages. The project pages list almost all the information we are interested in. - -\hypertarget{downsides-of-this-source}{% -\subsection{Downsides of this source:}\label{downsides-of-this-source}} - -The project page doesn't list the anticipated end date of a project. - -One has to click on the link to the researcher's profile to identify the participating organisations. - -Even using all the different filtering options not all resulting hits are relevant for our database, so I don't think the process can be fully automated or at least requires a subsequent manual validation or clean up step to remove irrelevant projects. - -\hypertarget{update-edctp}{% -\section{EDCTP}\label{update-edctp}} - -\hypertarget{general-information-2}{% -\subsection{General Information}\label{general-information-2}} - -The European \& Developing Countries Clinical Trials Partnership (EDCTP) is a non-profit organisation with a European office in The Hague, The Netherlands and an African office in Cape Town, South Africa. EDCTP is a partnership between European Union (EU), Norway, Switzerland, and African countries to accelerate the development of new clinical interventions such as drugs, vaccines, microbicides, and diagnostics against poverty-related diseases in Africa. The organisation supports clinical trials, capacity strengthening and networking in Africa and Europe. Funding comes from the EU, member states, pharmaceutical industry and private organisations and charities like The Wellcome Trust and The Bill \& Melinda Gates foundation. - -\textbf{Note:} Since funding comes from several sources that we also list as sources for populating the database such as the European Union (European Commission), The Wellcome Trust and The Bill \& Melinda Gates Foundation, there is the possibility that downloading project information from all these sources into our database could lead to duplicate entries. I created a column in the Actvities table for the Project ID, as this might be helpful to identify duplicates and remove them automatically. - -\hypertarget{how-to-use-1}{% -\subsection{How to use:}\label{how-to-use-1}} - -The database of funded project can be accessed here: \url{https://www.edctp.org/edctp2-project-portal/} - -There is the option to download the list of projects as a PDF, CSV or XLXS file. Personally, I did not find that helpful for manually adding projects to the database, but it might be useful for an automated process. - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\item - Go to Status of Project and select the filter Active -\item - Go to Classification and select one of the following filters: - - \begin{itemize} - \tightlist - \item - Co-Infections - \item - COVID-19 - \item - Cysticercosis/Taeniasis\\ - \item - Diagnostics - \item - Diarrhoeal Diseases - \item - Drugs - \item - Emerging Infections, incl.~Ebola, Lassa - \item - Epidemiology - \item - HIV - \item - Human African trypanosomiasis (sleeping sickness)\\ - \item - Implementation Research\\ - \item - Leishmaniases - \item - Leprosy (Hansen disease) - \item - Lower respiratory infections\\ - \item - Lymphatic filariasis - \item - Malaria - \item - Microbicides - \item - Onchocerciasis (river blindness) - \item - Rabies - \item - Schistosomiasis - \item - Soil-transmitted helminthiasis\\ - \item - Social Science - \item - Tuberculosis - \item - Vaccines - \item - Yaws - \item - Yellow Fever - \end{itemize} -\end{enumerate} - -\textbf{Note:} Only one Classification at a time can be selected - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{2} -\item - Once one Classification was selected click on search -\item - Change from Show Map to Show List -\textgreater{} this makes it easier to systematically look through the projects -\item - On the results list you can see the location of the coordinating organisation, but even if it is not in an African country, it is worth checking the project details for the Participating Organisations. So read the project title and decide whether this could be a relevant project, if so, click on View details -\end{enumerate} - -\includegraphics{images/edctp1.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{5} -\tightlist -\item - Check the Participating Organisations first to decide whether the project is relevant to our database: -\end{enumerate} - -\includegraphics{images/edctp2.png} - -\begin{enumerate} -\def\labelenumi{\arabic{enumi}.} -\setcounter{enumi}{6} -\item - If the project is relevant use the Project Name + Acronym for the Activity Column -\item - Transfer all the relevant information to our database, including Project ID, Start and End date, Participating Organisations and corresponding locations, Project Website, Coordinating Organisation and Coordinating Researcher -\item - Tag the project with the correct keywords in the Activity Type, Activity Outputs, Target Species, Topic, and Research Field columns based on your understanding of the project abstract -\end{enumerate} - -\hypertarget{benefits-of-this-source}{% -\subsection{Benefits of this Source:}\label{benefits-of-this-source}} - -The projects can be easily filtered for currently active projects. - -The EDCTP is specifically focused on projects in Africa or Europe with African collaborators so most projects fulfil at least one of our selection criteria - -A lot of the projects (not all) are also topic-wise relevant for our database - -The database lists most of the information that we are interested in for our database - -\hypertarget{shortcomings-of-this-source}{% -\subsection{Shortcomings of this source:}\label{shortcomings-of-this-source}} - -Only one disease/topic can be selected at a time so sequential searches are necessary - -Project details only list the Coordinating researcher but no other lead researchers at the participating organisations - -\hypertarget{survey}{% -\chapter{Survey}\label{survey}} - - \bibliography{book.bib} - -\end{document} diff --git a/docs/_main_files/figure-html/actions diagram-1.png b/docs/_main_files/figure-html/actions diagram-1.png deleted file mode 100644 index 383cd4d..0000000 Binary files a/docs/_main_files/figure-html/actions diagram-1.png and /dev/null differ diff --git a/docs/database.html b/docs/database.html deleted file mode 100644 index f5568ce..0000000 --- a/docs/database.html +++ /dev/null @@ -1,1944 +0,0 @@ - - - - - - - Chapter 4 Database | Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -

    Chapter 4 Database

    -

    The current database is built using Airtable. The current database has the following schema:

    -

    -

    This schema can be viewed interactively from here - https://airtable.com/appAL7fJUpBPYtOq4/tblt9ott045tWENcg/viwznxjIFAsTu0jzJ?blocks=bliZ6LV2bkGQNzgKF

    -
    -

    4.1 Activities Table

    -
    -

    4.1.1 Table details

    -

    Activities pertain to the formal/official title of the project that has been identified during the database search or survey.

    -

    Following are the different fields within the Activities table with their description.

    -
    -
    -

    4.1.2 Fields details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -Activity - -Activity name - -singleLineText - -NA -
    -Source Name (from Primary Sources) - -Name of primary source - -multipleLookupValues - -NA -
    -Notes - -Internal notes for maintenance - -singleLineText - -NA -
    -Topic - -Activity Topic - -multipleRecordLinks - -Topics -
    -Grant ID - -Grand Identifier - -singleLineText - -NA -
    -Collaborators - -Activity collaborators - -multipleRecordLinks - -Institutions -
    -Researchers - -Researchers involved in activity - -multipleRecordLinks - -Researchers -
    -Published Work - -Links to published work - -singleLineText - -NA -
    -Activity Location alt - -Activity location - -multipleRecordLinks - -Countries -
    -UN Stats Sub-region Name (from Activity Location alt) - -NA - -multipleLookupValues - -NA -
    -Activity Outputs - -Activity Outputs - -multipleSelects - -Data, Publication, Report, Guideline/SOP, Archive, Improving Diagnostics, Vaccine development, Therapeutics, Epidemic/Pandemic Preparedness, Biosurveillance technology, Prophylaxis, Surveillance, Improving Vaccine strategies, Training, Risk Assessment, Improving Capacity, Policies -
    -Activity Status - -Activity Status - -singleSelect - -Active, Completed -
    -Activity Website - -Activity Website - -url - -NA -
    -Activity Identifier - -Activity identifier - -formula - -NA -
    -Primary Sources - -Primary source of information - -multipleRecordLinks - -Sources -
    -Additional Sources - -Additional sources - -singleLineText - -NA -
    -Continent Name (from Activity Location alt) - -NA - -multipleLookupValues - -NA -
    -AU Region Name (from Activity Location alt) - -NA - -multipleLookupValues - -NA -
    -
    -
    -
    -

    4.2 Countries Table

    -
    -

    4.2.1 Table details

    -

    List of countries used to indicate the location information for the researchers, topics, funders, sources, institutions, and activities tables

    -

    Following are the different fields within the Countries table with their description.

    -
    -
    -

    4.2.2 Fields details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -Researchers - -NA - -multipleRecordLinks - -Researchers -
    -Funders - -NA - -multipleRecordLinks - -Funders -
    -AU Region Name - -NA - -singleSelect - -Northern Africa, Eastern Africa, NA, Central Africa, Southern Africa, Western Africa -
    -UN Stats Sub-region Name - -Name of further sub-regional grouping to which country is usually classified within. This is based on the UN Statistics Division nomenclature. - -singleSelect - -NA, Eastern Africa, Middle Africa, Southern Africa, Western Africa, Channel Islands, Sark -
    -Country Name - -County name based on UN Statistics Division nomenclature - -multilineText - -NA -
    - -
    -
    -
    -

    4.3 Description Table

    -
    -

    4.3.1 Table details

    -

    The Description table provides overall description of this entire database.

    -

    Following are the different fields within the Description table with their description.

    -
    -
    -

    4.3.2 Field details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -Email - -Email for primary contact - -email - -NA -
    -Primary Contact - -Person to correspond with about the base - -singleLineText - -NA -
    -IRB - -Optional: Link to IRB - -url - -NA -
    -Base Description - -Characterization of the base. What is the base describing? - -multilineText - -NA -
    -Title - -Title of the base - -singleLineText - -NA -
    -Data Management Plan - -Link to data management plan - -url - -NA -
    -
    -
    -
    -

    4.4 Funder Table

    -
    -

    4.4.1 Table details

    -

    Funders pertain to the entities funding each activity.

    -

    The funders’ information is retrieved from declared funders for the activities identified during the database search or the survey.

    -

    Following are the different fields within the Funders table with their description.

    -
    -
    -

    4.4.2 Field details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -Funder Type - -Type of funder - -singleSelect - -Charitable organization, Foundation, Pharmaceutical company , Not-for-profit Partnership, NGO, Government Agency, University, Research Institut, Public- public partnership , Public-private partnership -
    -Funder Website - -Website of funder - -url - -NA -
    -Source Name (from Primary Sources) - -Source from where funder was identified - -multipleLookupValues - -NA -
    -Activities - -Activities supported by funder - -multipleRecordLinks - -Activities -
    -WHO Region Name (from Funder Location alt) - -NA - -multipleLookupValues - -NA -
    -Continent Name (from Funder Location alt) - -NA - -multipleLookupValues - -NA -
    -Primary Sources - -Source from where funder was identified - -multipleRecordLinks - -Sources -
    -
    -
    -
    -

    4.5 Institutions Table

    -
    -

    4.5.1 Table details

    -

    Institutions pertain to the entities directly related to or implementing the activity and/or the affiliation of the researcher implementing the activity.

    -

    Following are the different fields within the Institutions table with their description.

    -
    -
    -

    4.5.2 Field details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -Institution Email - -Email of institution - -email - -NA -
    -Institution Website - -Institution Website - -url - -NA -
    -Activities - -Name of activity identified with institution - -multipleRecordLinks - -Activities -
    -Sources - -Name of primary source - -multipleRecordLinks - -Sources -
    -Institution Type - -Institution Type - -singleSelect - -Research Institute, University, NGO, National Government Institution, Non-profit Organisation , Hospital, Government Agency, Consortium, Partnership of Institutes, Industry, Charity, Public-private partnetship, International Coalition , Inter-governmental Organisation, Medical Service Provider, Network -
    -Institution Location - -Institution location - -multipleRecordLinks - -WHO Countries -
    -Notes - -Internal notes (for maintenance) - -singleLineText - -NA -
    -Topic (from Activities) - -Name of topic identified with the institution - -multipleLookupValues - -NA -
    -
    -
    -
    -

    4.6 Researchers Table

    -
    -

    4.6.1 Table details

    -

    Researchers pertains to the people involved in the activities contained in this database, and maybe involved in a variety of activity types. including but not limited to, research.

    -

    Researchers identified during the database search. Information on researchers are primarily retrieved once activities have been identified from the database search process. It is possible that researchers are identified apriori and from which information on topics, funders, sources, institutions, and activities may be identified relevant to the specific researcher. This may happen when the planned/proposed survey is implemented and sent to known researchers who may or may not be in the database to begin with.

    -

    Following are the different fields within the Researchers table with their description.

    -
    -
    -

    4.6.2 Field details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -WHO Region Name (from Researcher Country Location alt) - -NA - -multipleLookupValues - -NA -
    -ACDC Status - -Is researcher from the Africa CDC? - -singleSelect - -Non-member, Member -
    -Sources - -Name of source - -multipleRecordLinks - -Sources -
    -UN Stats Region Name (from Researcher Country Location alt) - -NA - -multipleLookupValues - -NA -
    -Affiliation - -Institution researcher is affiliated with. Choices from the institutions table - -multipleRecordLinks - -Institutions -
    -Institution Location alt (from Affiliation) - -NA - -multipleLookupValues - -NA -
    -Topic (from Activity) - -Name of topic - -multipleLookupValues - -NA -
    -Researcher Name - -Full name of researcher identified in the search - -singleLineText - -NA -
    -Notes - -Internal notes (for maintenance) - -singleLineText - -NA -
    -Source Name (from Sources) - -Name of source - -multipleLookupValues - -NA -
    -Additional Sources - -Additional sources - -singleLineText - -NA -
    -Activity Type (from Activity) - -Type of activity - -multipleLookupValues - -NA -
    -Website - -Personal website of researcher (if any) - -singleLineText - -NA -
    -Activity - -Activity/activities researchers is involved in - -multipleRecordLinks - -Activities -
    -Institution Location (from Affiliation) - -Name of location where institution is based - -multipleLookupValues - -NA -
    -Willing to be contacted - -Is the researcher willing to be contacted? - -checkbox - -NA -
    -Continent Name (from Researcher Country Location alt) - -NA - -multipleLookupValues - -NA -
    -
    -
    -
    -

    4.7 Sources Table

    -
    -

    4.7.1 Table details

    -

    Sources contain initial set of sources (primarily funders) identified to initiate the database search. These original sources are fully described here - https://ecohealthalliance.github.io/rig-handbook/sources.html.

    -

    From the initial search, other sources were identified from which additional streams of searches were performed. Currently, the sources table is updated through a primary search of possible sources in addition to the search performed on the original sources list.

    -

    Following are the different fields within the Sources table with their description.

    -
    -
    -

    4.7.2 Field details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -Source Type - -Type of primary source - -singleSelect - -Website text page, Website table, Website search, Downloadable document in PDF, Downloadable document in XLSX, Downloadable document in CSV, Downloadable document in DOCX, A form of database, Website text page, Website search, Links to downloadable documents in PDF, Website table, Website search -
    -Source Notes - -Internal notes for primary source (for maintenance) - -multilineText - -NA -
    -Topics - -Topics identified from primary source - -multipleRecordLinks - -Topics -
    -Relevant tables - -Notes on relevant tables found from primary source - -multipleSelects - -Researchers, Topics, Activities, Funders, Institutions, Countries -
    -Funders - -Funders identified from primary source - -multipleRecordLinks - -Funders -
    -Source Name - -Name of primary source - -singleLineText - -NA -
    -Created By - -Person who created the entry - -createdBy - -NA -
    -Researchers - -Name of researcher identified from primary source - -multipleRecordLinks - -Researchers -
    -
    -
    -
    -

    4.8 Survey Results Table

    -
    -

    4.8.1 Table details

    -

    NA

    -

    Following are the different fields within the Survey Results table with their description.

    -
    -
    -

    4.8.2 Field details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -Activity description/ purpose - -Description of activity - -multilineText - -NA -
    -Sharing with Colleagues - -Is respondent going to share with colleagues? - -singleLineText - -NA -
    -Lead Researcher - -Name of lead researcher - -singleLineText - -NA -
    -Created By - -Name of survey respondent - -createdBy - -NA -
    -Other websites listing this project - -Other website listings for this project - -singleLineText - -NA -
    -Funder - -Name of funder for this project - -singleLineText - -NA -
    -Official Project Title - -Official project title - -singleLineText - -NA -
    -Official Project website - -Official project website - -singleLineText - -NA -
    -
    -
    -
    -

    4.9 Topics Table

    -
    -

    4.9.1 Table details

    -

    Topics pertain to the disease names and disease types.

    -

    The topics table contains disease types/disease entities of interest to the Africa CDC based on their priorities (as described in their Framework document) and is continually updated with whatever disease/disease entity/disease type were deemed relevant by the database contributor.

    -

    Following are the different fields within the Topics table with their description.

    -
    -
    -

    4.9.2 Field details

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -Field Name - -Field Description - -Field Type - -Field Values -
    -Sources - -Name of Source - -multipleRecordLinks - -Sources -
    -Diseases - -Disease entity related/relevant to the field/topic of interest - -multipleSelects - -HIV, TB, COVID-19, Monkeypox, Lassa fever, Bat flu, Avian flu, Swine flu, Ebola virus disease, Marburg virus disease, Marburg haemorrhagic fever, H7N9, H5N1, H1N1, H1N2, H3N2, Plague, Anthrax, Crimean-Congo Haemorrhagic Fever, Rift Valley Fever, Nipah Virus, Brucellosis, undulant fever, Malta fever, Mediterranean fever, Hantavirus haemorrhagic fever with renal syndrome, Hantavirus pulmonary syndrome, Q fever, Chikungunya, Henipavirus, Ghanaian bat henipavirus, Leptospirosis, Weill’s disease, West Nile Fever, Zika fever, Dengue fever, African trypanosomiasis, Chagas disease, Yellow fever, Malaria, Re-emerging viruses, Visceral Leishmaniasis, Kala-azar, Cutaneous leishmaniasis , Hepatitis E , Viral Hepatitis, Hepatitis C, Hepatitis B, Leprosy, Hookworm, Schistosomiasis, Ascariasis, Trichuriasis, Lymphatic filariasis, Trachoma, Buruli ulcer, Dracunculiasis, Bilharzia, Whipworm Infection, Elephantiasis, Guinea-worm disease , Burkitt lymphoma, Cryptococcal meningitis, Kaposi sarcoma, schistosomiasis, Viral haemorrhagic fever, Rabies -
    -Activity Location (from Activities) - -Name of location of activity in which topic was identified - -multipleLookupValues - -NA -
    -Survey Results - -Results from survey - -multipleRecordLinks - -Survey Results -
    -Search terms - -Search terms used to identify topic - -multipleSelects - -antimycobacterial, anti-mycobacterial, COVID-19, coronavirus, omicron, rifampicin, ritonavir, darunavir, dolutegravir, MIS-C, HVTN, ART, antiretroviral, lopinavir, bedaquiline, clofazimine, isoniazid, pyrazinamide, antitubercular, tenofovir disoproxil fumarate, emtricitabine, dolutegravir , efavirenz, tubercular, drug-resistant, AMR, raltegravir, DR-, DR-TB, helminth, TBM, fluke, wildlife sampling, biosurveillance, surveillance network, seroprevalence, detection of , monitoring of , seroevidence, identification of , seropositive, seroepidemiological, survey, screened, prevalence -
    -Disease Types - -Type/category to which disease is grouped under - -multipleSelects - -infectious disease, viral, bacterial, parasitic, vector-bourne, zoonotic, virus, soil-transmitted -
    -Continent Name (from Activity Location alt) (from Activities) - -NA - -multipleLookupValues - -NA -
    -Activity Location alt (from Activities) - -NA - -multipleLookupValues - -NA -
    -Institutions - -Institutions - -multipleRecordLinks - -Institutions -
    -Region (from Activity Location) (from Activities) - -Name of region where topic was identified - -multipleLookupValues - -NA -
    -AU Region Name (from Activity Location alt) (from Activities) - -NA - -multipleLookupValues - -NA -
    -Source Name (from Sources) - -Name of source - -multipleLookupValues - -NA -
    - - -
    -
    -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/docs/images/airtable_Weekly Digest.png b/docs/images/airtable_Weekly Digest.png deleted file mode 100644 index 942ee64..0000000 Binary files a/docs/images/airtable_Weekly Digest.png and /dev/null differ diff --git a/docs/images/clinicaltrial1.png b/docs/images/clinicaltrial1.png deleted file mode 100644 index ba291f5..0000000 Binary files a/docs/images/clinicaltrial1.png and /dev/null differ diff --git a/docs/images/clinicaltrial2.png b/docs/images/clinicaltrial2.png deleted file mode 100644 index 7f327b2..0000000 Binary files a/docs/images/clinicaltrial2.png and /dev/null differ diff --git a/docs/images/clinicaltrial3.png b/docs/images/clinicaltrial3.png deleted file mode 100644 index d19cb0e..0000000 Binary files a/docs/images/clinicaltrial3.png and /dev/null differ diff --git a/docs/images/clinicaltrial4.png b/docs/images/clinicaltrial4.png deleted file mode 100644 index caa3c57..0000000 Binary files a/docs/images/clinicaltrial4.png and /dev/null differ diff --git a/docs/images/clinicaltrial5.png b/docs/images/clinicaltrial5.png deleted file mode 100644 index 3421b6c..0000000 Binary files a/docs/images/clinicaltrial5.png and /dev/null differ diff --git a/docs/images/clinicaltrial6.png b/docs/images/clinicaltrial6.png deleted file mode 100644 index 32f1780..0000000 Binary files a/docs/images/clinicaltrial6.png and /dev/null differ diff --git a/docs/images/clinicaltrial7.png b/docs/images/clinicaltrial7.png deleted file mode 100644 index 40dfbae..0000000 Binary files a/docs/images/clinicaltrial7.png and /dev/null differ diff --git a/docs/images/clinicaltrial8.png b/docs/images/clinicaltrial8.png deleted file mode 100644 index 33b0fdc..0000000 Binary files a/docs/images/clinicaltrial8.png and /dev/null differ diff --git a/docs/images/database_schema.png b/docs/images/database_schema.png deleted file mode 100644 index 8089c43..0000000 Binary files a/docs/images/database_schema.png and /dev/null differ diff --git a/docs/images/edctp1.png b/docs/images/edctp1.png deleted file mode 100644 index d4db9cc..0000000 Binary files a/docs/images/edctp1.png and /dev/null differ diff --git a/docs/images/edctp2.png b/docs/images/edctp2.png deleted file mode 100644 index be5b1a1..0000000 Binary files a/docs/images/edctp2.png and /dev/null differ diff --git a/docs/images/gepris1.png b/docs/images/gepris1.png deleted file mode 100644 index 36d91d9..0000000 Binary files a/docs/images/gepris1.png and /dev/null differ diff --git a/docs/images/gepris2.png b/docs/images/gepris2.png deleted file mode 100644 index a8fe135..0000000 Binary files a/docs/images/gepris2.png and /dev/null differ diff --git a/docs/images/initial-acdc-db-search_NK.png b/docs/images/initial-acdc-db-search_NK.png deleted file mode 100644 index 570c9c3..0000000 Binary files a/docs/images/initial-acdc-db-search_NK.png and /dev/null differ diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 20edac1..0000000 --- a/docs/index.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - - - - Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    - -
    -

    Chapter 1 About

    -

    This is a handbook created as a how-to manual for the development and maintenance of a One Health Research Information Gateway for the African continent.

    - -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/docs/introduction.html b/docs/introduction.html deleted file mode 100644 index 5c834ba..0000000 --- a/docs/introduction.html +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - Chapter 2 Introduction | Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -

    Chapter 2 Introduction

    -

    EcoHelth Alliance is supporting the creation of a database of active infectious disease research activities and research scientists in Africa. The database contains information about scientific research being conducted on the African continent that has particular relevance to understanding, detecting and responding to zoonotic pathogens. EHA is building a detailed, searchable, and visual database (e.g. via a dashboard) populated with information about major (e.g. multi-year) and active One Health research projects that includes subject matter, duration, geographical locations, key personnel, and links to publicly available reports, preprints and publications relevant to zoonoses. Examples of research areas may include epidemiological (syndrome based or disease specific), ecological (studies looking at potential reservoirs or animal hosts for zoonotic pathogens and spillover into humans or livestock); basic science (e.g. virology, bacteriology; serology); clinical (vaccine or therapeutic trials); or sociological (e.g. behavioral risk assessments or behavioral intervention studies) or any other preliminary public health findings. A particularly important view within the database includes a directory of subject matter experts associated with research across the continent. This roster view can be used by public health practitioners to engage expert consultations as needed to support training activities, surveillance or outbreak response, for example.

    - -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/docs/libs/anchor-sections-1.1.0/anchor-sections-hash.css b/docs/libs/anchor-sections-1.1.0/anchor-sections-hash.css deleted file mode 100644 index b563ec9..0000000 --- a/docs/libs/anchor-sections-1.1.0/anchor-sections-hash.css +++ /dev/null @@ -1,2 +0,0 @@ -/* Styles for section anchors */ -a.anchor-section::before {content: '#';font-size: 80%;} diff --git a/docs/libs/anchor-sections-1.1.0/anchor-sections.css b/docs/libs/anchor-sections-1.1.0/anchor-sections.css deleted file mode 100644 index 041905f..0000000 --- a/docs/libs/anchor-sections-1.1.0/anchor-sections.css +++ /dev/null @@ -1,4 +0,0 @@ -/* Styles for section anchors */ -a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} -.hasAnchor:hover a.anchor-section {visibility: visible;} -ul > li > .anchor-section {display: none;} diff --git a/docs/libs/anchor-sections-1.1.0/anchor-sections.js b/docs/libs/anchor-sections-1.1.0/anchor-sections.js deleted file mode 100644 index fee005d..0000000 --- a/docs/libs/anchor-sections-1.1.0/anchor-sections.js +++ /dev/null @@ -1,11 +0,0 @@ -document.addEventListener('DOMContentLoaded', function () { - // If section divs is used, we need to put the anchor in the child header - const headers = document.querySelectorAll("div.hasAnchor.section[class*='level'] > :first-child") - - headers.forEach(function (x) { - // Add to the header node - if (!x.classList.contains('hasAnchor')) x.classList.add('hasAnchor') - // Remove from the section or div created by Pandoc - x.parentElement.classList.remove('hasAnchor') - }) -}) diff --git a/docs/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf b/docs/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf deleted file mode 100644 index 35acda2..0000000 Binary files a/docs/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf and /dev/null differ diff --git a/docs/libs/gitbook-2.6.7/css/plugin-bookdown.css b/docs/libs/gitbook-2.6.7/css/plugin-bookdown.css deleted file mode 100644 index ab7c20e..0000000 --- a/docs/libs/gitbook-2.6.7/css/plugin-bookdown.css +++ /dev/null @@ -1,105 +0,0 @@ -.book .book-header h1 { - padding-left: 20px; - padding-right: 20px; -} -.book .book-header.fixed { - position: fixed; - right: 0; - top: 0; - left: 0; - border-bottom: 1px solid rgba(0,0,0,.07); -} -span.search-highlight { - background-color: #ffff88; -} -@media (min-width: 600px) { - .book.with-summary .book-header.fixed { - left: 300px; - } -} -@media (max-width: 1240px) { - .book .book-body.fixed { - top: 50px; - } - .book .book-body.fixed .body-inner { - top: auto; - } -} -@media (max-width: 600px) { - .book.with-summary .book-header.fixed { - left: calc(100% - 60px); - min-width: 300px; - } - .book.with-summary .book-body { - transform: none; - left: calc(100% - 60px); - min-width: 300px; - } - .book .book-body.fixed { - top: 0; - } -} - -.book .book-body.fixed .body-inner { - top: 50px; -} -.book .book-body .page-wrapper .page-inner section.normal sub, .book .book-body .page-wrapper .page-inner section.normal sup { - font-size: 85%; -} - -@media print { - .book .book-summary, .book .book-body .book-header, .fa { - display: none !important; - } - .book .book-body.fixed { - left: 0px; - } - .book .book-body,.book .book-body .body-inner, .book.with-summary { - overflow: visible !important; - } -} -.kable_wrapper { - border-spacing: 20px 0; - border-collapse: separate; - border: none; - margin: auto; -} -.kable_wrapper > tbody > tr > td { - vertical-align: top; -} -.book .book-body .page-wrapper .page-inner section.normal table tr.header { - border-top-width: 2px; -} -.book .book-body .page-wrapper .page-inner section.normal table tr:last-child td { - border-bottom-width: 2px; -} -.book .book-body .page-wrapper .page-inner section.normal table td, .book .book-body .page-wrapper .page-inner section.normal table th { - border-left: none; - border-right: none; -} -.book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr, .book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr > td { - border-top: none; -} -.book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr:last-child > td { - border-bottom: none; -} - -div.theorem, div.lemma, div.corollary, div.proposition, div.conjecture { - font-style: italic; -} -span.theorem, span.lemma, span.corollary, span.proposition, span.conjecture { - font-style: normal; -} -div.proof>*:last-child:after { - content: "\25a2"; - float: right; -} -.header-section-number { - padding-right: .5em; -} -#header .multi-author { - margin: 0.5em 0 -0.5em 0; -} -#header .date { - margin-top: 1.5em; -} diff --git a/docs/libs/gitbook-2.6.7/css/plugin-clipboard.css b/docs/libs/gitbook-2.6.7/css/plugin-clipboard.css deleted file mode 100644 index 6844a70..0000000 --- a/docs/libs/gitbook-2.6.7/css/plugin-clipboard.css +++ /dev/null @@ -1,18 +0,0 @@ -div.sourceCode { - position: relative; -} - -.copy-to-clipboard-button { - position: absolute; - right: 0; - top: 0; - visibility: hidden; -} - -.copy-to-clipboard-button:focus { - outline: 0; -} - -div.sourceCode:hover > .copy-to-clipboard-button { - visibility: visible; -} diff --git a/docs/libs/gitbook-2.6.7/css/plugin-fontsettings.css b/docs/libs/gitbook-2.6.7/css/plugin-fontsettings.css deleted file mode 100644 index 3fa6f35..0000000 --- a/docs/libs/gitbook-2.6.7/css/plugin-fontsettings.css +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Theme 1 - */ -.color-theme-1 .dropdown-menu { - background-color: #111111; - border-color: #7e888b; -} -.color-theme-1 .dropdown-menu .dropdown-caret .caret-inner { - border-bottom: 9px solid #111111; -} -.color-theme-1 .dropdown-menu .buttons { - border-color: #7e888b; -} -.color-theme-1 .dropdown-menu .button { - color: #afa790; -} -.color-theme-1 .dropdown-menu .button:hover { - color: #73553c; -} -/* - * Theme 2 - */ -.color-theme-2 .dropdown-menu { - background-color: #2d3143; - border-color: #272a3a; -} -.color-theme-2 .dropdown-menu .dropdown-caret .caret-inner { - border-bottom: 9px solid #2d3143; -} -.color-theme-2 .dropdown-menu .buttons { - border-color: #272a3a; -} -.color-theme-2 .dropdown-menu .button { - color: #62677f; -} -.color-theme-2 .dropdown-menu .button:hover { - color: #f4f4f5; -} -.book .book-header .font-settings .font-enlarge { - line-height: 30px; - font-size: 1.4em; -} -.book .book-header .font-settings .font-reduce { - line-height: 30px; - font-size: 1em; -} - -/* sidebar transition background */ -div.book.color-theme-1 { - background: #f3eacb; -} -.book.color-theme-1 .book-body { - color: #704214; - background: #f3eacb; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section { - background: #f3eacb; -} - -/* sidebar transition background */ -div.book.color-theme-2 { - background: #1c1f2b; -} - -.book.color-theme-2 .book-body { - color: #bdcadb; - background: #1c1f2b; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section { - background: #1c1f2b; -} -.book.font-size-0 .book-body .page-inner section { - font-size: 1.2rem; -} -.book.font-size-1 .book-body .page-inner section { - font-size: 1.4rem; -} -.book.font-size-2 .book-body .page-inner section { - font-size: 1.6rem; -} -.book.font-size-3 .book-body .page-inner section { - font-size: 2.2rem; -} -.book.font-size-4 .book-body .page-inner section { - font-size: 4rem; -} -.book.font-family-0 { - font-family: Georgia, serif; -} -.book.font-family-1 { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal { - color: #704214; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal a { - color: inherit; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h3, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h4, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h5, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { - color: inherit; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2 { - border-color: inherit; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { - color: inherit; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal hr { - background-color: inherit; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal blockquote { - border-color: #c4b29f; - opacity: 0.9; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { - background: #fdf6e3; - color: #657b83; - border-color: #f8df9c; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal .highlight { - background-color: inherit; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table th, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table td { - border-color: #f5d06c; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr { - color: inherit; - background-color: #fdf6e3; - border-color: #444444; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { - background-color: #fbeecb; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal { - color: #bdcadb; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal a { - color: #3eb1d0; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h3, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h4, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h5, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { - color: #fffffa; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2 { - border-color: #373b4e; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { - color: #373b4e; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal hr { - background-color: #373b4e; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal blockquote { - border-color: #373b4e; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { - color: #9dbed8; - background: #2d3143; - border-color: #2d3143; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal .highlight { - background-color: #282a39; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table th, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table td { - border-color: #3b3f54; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr { - color: #b6c2d2; - background-color: #2d3143; - border-color: #3b3f54; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { - background-color: #35394b; -} -.book.color-theme-1 .book-header { - color: #afa790; - background: transparent; -} -.book.color-theme-1 .book-header .btn { - color: #afa790; -} -.book.color-theme-1 .book-header .btn:hover { - color: #73553c; - background: none; -} -.book.color-theme-1 .book-header h1 { - color: #704214; -} -.book.color-theme-2 .book-header { - color: #7e888b; - background: transparent; -} -.book.color-theme-2 .book-header .btn { - color: #3b3f54; -} -.book.color-theme-2 .book-header .btn:hover { - color: #fffff5; - background: none; -} -.book.color-theme-2 .book-header h1 { - color: #bdcadb; -} -.book.color-theme-1 .book-body .navigation { - color: #afa790; -} -.book.color-theme-1 .book-body .navigation:hover { - color: #73553c; -} -.book.color-theme-2 .book-body .navigation { - color: #383f52; -} -.book.color-theme-2 .book-body .navigation:hover { - color: #fffff5; -} -/* - * Theme 1 - */ -.book.color-theme-1 .book-summary { - color: #afa790; - background: #111111; - border-right: 1px solid rgba(0, 0, 0, 0.07); -} -.book.color-theme-1 .book-summary .book-search { - background: transparent; -} -.book.color-theme-1 .book-summary .book-search input, -.book.color-theme-1 .book-summary .book-search input:focus { - border: 1px solid transparent; -} -.book.color-theme-1 .book-summary ul.summary li.divider { - background: #7e888b; - box-shadow: none; -} -.book.color-theme-1 .book-summary ul.summary li i.fa-check { - color: #33cc33; -} -.book.color-theme-1 .book-summary ul.summary li.done > a { - color: #877f6a; -} -.book.color-theme-1 .book-summary ul.summary li a, -.book.color-theme-1 .book-summary ul.summary li span { - color: #877f6a; - background: transparent; - font-weight: normal; -} -.book.color-theme-1 .book-summary ul.summary li.active > a, -.book.color-theme-1 .book-summary ul.summary li a:hover { - color: #704214; - background: transparent; - font-weight: normal; -} -/* - * Theme 2 - */ -.book.color-theme-2 .book-summary { - color: #bcc1d2; - background: #2d3143; - border-right: none; -} -.book.color-theme-2 .book-summary .book-search { - background: transparent; -} -.book.color-theme-2 .book-summary .book-search input, -.book.color-theme-2 .book-summary .book-search input:focus { - border: 1px solid transparent; -} -.book.color-theme-2 .book-summary ul.summary li.divider { - background: #272a3a; - box-shadow: none; -} -.book.color-theme-2 .book-summary ul.summary li i.fa-check { - color: #33cc33; -} -.book.color-theme-2 .book-summary ul.summary li.done > a { - color: #62687f; -} -.book.color-theme-2 .book-summary ul.summary li a, -.book.color-theme-2 .book-summary ul.summary li span { - color: #c1c6d7; - background: transparent; - font-weight: 600; -} -.book.color-theme-2 .book-summary ul.summary li.active > a, -.book.color-theme-2 .book-summary ul.summary li a:hover { - color: #f4f4f5; - background: #252737; - font-weight: 600; -} diff --git a/docs/libs/gitbook-2.6.7/css/plugin-highlight.css b/docs/libs/gitbook-2.6.7/css/plugin-highlight.css deleted file mode 100644 index 2aabd3d..0000000 --- a/docs/libs/gitbook-2.6.7/css/plugin-highlight.css +++ /dev/null @@ -1,426 +0,0 @@ -.book .book-body .page-wrapper .page-inner section.normal pre, -.book .book-body .page-wrapper .page-inner section.normal code { - /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ - /* Tomorrow Comment */ - /* Tomorrow Red */ - /* Tomorrow Orange */ - /* Tomorrow Yellow */ - /* Tomorrow Green */ - /* Tomorrow Aqua */ - /* Tomorrow Blue */ - /* Tomorrow Purple */ -} -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-comment, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-title { - color: #8e908c; -} -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-variable, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-tag, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, -.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant, -.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant, -.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi, -.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi, -.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype, -.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype, -.book .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype, -.book .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype, -.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id, -.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-id, -.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class, -.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-class, -.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, -.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo { - color: #c82829; -} -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-number, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-number, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-literal, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-params, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-params, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-constant { - color: #f5871f; -} -.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute, -.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute { - color: #eab700; -} -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-string, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-string, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-value, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-value, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance, -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-header, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-header, -.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol, -.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol, -.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, -.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { - color: #718c00; -} -.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor, -.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor { - color: #3e999f; -} -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-function, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-function, -.book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator, -.book .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator, -.book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal code .python .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword, -.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword, -.book .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub, -.book .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub, -.book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title, -.book .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title { - color: #4271ae; -} -.book .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, -.book .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, -.book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function, -.book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function { - color: #8959a8; -} -.book .book-body .page-wrapper .page-inner section.normal pre .hljs, -.book .book-body .page-wrapper .page-inner section.normal code .hljs { - display: block; - background: white; - color: #4d4d4c; - padding: 0.5em; -} -.book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript, -.book .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript, -.book .book-body .page-wrapper .page-inner section.normal pre .javascript .xml, -.book .book-body .page-wrapper .page-inner section.normal code .javascript .xml, -.book .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, -.book .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, -.book .book-body .page-wrapper .page-inner section.normal pre .xml .javascript, -.book .book-body .page-wrapper .page-inner section.normal code .xml .javascript, -.book .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript, -.book .book-body .page-wrapper .page-inner section.normal code .xml .vbscript, -.book .book-body .page-wrapper .page-inner section.normal pre .xml .css, -.book .book-body .page-wrapper .page-inner section.normal code .xml .css, -.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, -.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { - opacity: 0.5; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { - /* - -Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull - -*/ - /* Solarized Green */ - /* Solarized Cyan */ - /* Solarized Blue */ - /* Solarized Yellow */ - /* Solarized Orange */ - /* Solarized Red */ - /* Solarized Violet */ -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs { - display: block; - padding: 0.5em; - background: #fdf6e3; - color: #657b83; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-template_comment, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-template_comment, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-header, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-header, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-doctype, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-doctype, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pi, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pi, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-string, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-string, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-javadoc, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-javadoc { - color: #93a1a1; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-winutils, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-winutils, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .method, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .method, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-addition, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-tag, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-tag, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-request, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-request, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-status, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-status, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .nginx .hljs-title, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .nginx .hljs-title { - color: #859900; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-number, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-command, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-command, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-string, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag .hljs-value, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-tag .hljs-value, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-rules .hljs-value, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-rules .hljs-value, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-phpdoc, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-phpdoc, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-hexcolor, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-hexcolor, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_url, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_url { - color: #2aa198; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-localvars, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-localvars, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-chunk, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-chunk, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-decorator, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-decorator, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-identifier, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-identifier, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .vhdl .hljs-literal, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .vhdl .hljs-literal, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-id, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-id, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-function, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-function { - color: #268bd2; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-body, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-body, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .smalltalk .hljs-number, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .smalltalk .hljs-number, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-constant, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-class .hljs-title, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-class .hljs-title, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-parent, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-parent, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .haskell .hljs-type, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .haskell .hljs-type, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_reference, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_reference { - color: #b58900; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor .hljs-keyword, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor .hljs-keyword, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-shebang, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-shebang, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol .hljs-string, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol .hljs-string, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-change, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-change, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-special, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-special, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attr_selector, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attr_selector, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-subst, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-subst, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-cdata, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-cdata, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .clojure .hljs-title, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .clojure .hljs-title, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-header, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-header { - color: #cb4b16; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-important, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-important { - color: #dc322f; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_label, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_label { - color: #6c71c4; -} -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, -.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula { - background: #eee8d5; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { - /* Tomorrow Night Bright Theme */ - /* Original theme - https://github.com/chriskempson/tomorrow-theme */ - /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ - /* Tomorrow Comment */ - /* Tomorrow Red */ - /* Tomorrow Orange */ - /* Tomorrow Yellow */ - /* Tomorrow Green */ - /* Tomorrow Aqua */ - /* Tomorrow Blue */ - /* Tomorrow Purple */ -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-title { - color: #969896; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-tag, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-id, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-class, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo { - color: #d54e53; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-number, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-literal, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-params, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-params, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-constant { - color: #e78c45; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute { - color: #e7c547; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-string, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-value, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-value, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-header, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-header, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { - color: #b9ca4a; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor { - color: #70c0b1; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-function, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-function, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title { - color: #7aa6da; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function { - color: #c397d8; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs { - display: block; - background: black; - color: #eaeaea; - padding: 0.5em; -} -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .xml, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .xml, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .javascript, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .javascript, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .vbscript, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .css, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .css, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata, -.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata { - opacity: 0.5; -} diff --git a/docs/libs/gitbook-2.6.7/css/plugin-search.css b/docs/libs/gitbook-2.6.7/css/plugin-search.css deleted file mode 100644 index c85e557..0000000 --- a/docs/libs/gitbook-2.6.7/css/plugin-search.css +++ /dev/null @@ -1,31 +0,0 @@ -.book .book-summary .book-search { - padding: 6px; - background: transparent; - position: absolute; - top: -50px; - left: 0px; - right: 0px; - transition: top 0.5s ease; -} -.book .book-summary .book-search input, -.book .book-summary .book-search input:focus, -.book .book-summary .book-search input:hover { - width: 100%; - background: transparent; - border: 1px solid #ccc; - box-shadow: none; - outline: none; - line-height: 22px; - padding: 7px 4px; - color: inherit; - box-sizing: border-box; -} -.book.with-search .book-summary .book-search { - top: 0px; -} -.book.with-search .book-summary ul.summary { - top: 50px; -} -.with-search .summary li[data-level] a[href*=".html#"] { - display: none; -} diff --git a/docs/libs/gitbook-2.6.7/css/plugin-table.css b/docs/libs/gitbook-2.6.7/css/plugin-table.css deleted file mode 100644 index 7fba1b9..0000000 --- a/docs/libs/gitbook-2.6.7/css/plugin-table.css +++ /dev/null @@ -1 +0,0 @@ -.book .book-body .page-wrapper .page-inner section.normal table{display:table;width:100%;border-collapse:collapse;border-spacing:0;overflow:auto}.book .book-body .page-wrapper .page-inner section.normal table td,.book .book-body .page-wrapper .page-inner section.normal table th{padding:6px 13px;border:1px solid #ddd}.book .book-body .page-wrapper .page-inner section.normal table tr{background-color:#fff;border-top:1px solid #ccc}.book .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n){background-color:#f8f8f8}.book .book-body .page-wrapper .page-inner section.normal table th{font-weight:700} diff --git a/docs/libs/gitbook-2.6.7/css/style.css b/docs/libs/gitbook-2.6.7/css/style.css deleted file mode 100644 index cba69b2..0000000 --- a/docs/libs/gitbook-2.6.7/css/style.css +++ /dev/null @@ -1,13 +0,0 @@ -/*! normalize.css v2.1.0 | MIT License | git.io/normalize */img,legend{border:0}*{-webkit-font-smoothing:antialiased}sub,sup{position:relative}.book .book-body .page-wrapper .page-inner section.normal hr:after,.book-langs-index .inner .languages:after,.buttons:after,.dropdown-menu .buttons:after{clear:both}body,html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}.hidden,[hidden]{display:none}audio:not([controls]){display:none;height:0}html{font-family:sans-serif}body,figure{margin:0}a:focus{outline:dotted thin}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}svg:not(:root){overflow:hidden}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button{margin-right:10px;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}/*! - * Preboot v2 - * - * Open sourced under MIT license by @mdo. - * Some variables and mixins from Bootstrap (Apache 2 license). - */.link-inherit,.link-inherit:focus,.link-inherit:hover{color:inherit}/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('./fontawesome/fontawesome-webfont.ttf?v=4.7.0') format('truetype');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} -.book .book-header,.book .book-summary{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.book-langs-index{width:100%;height:100%;padding:40px 0;margin:0;overflow:auto}@media (max-width:600px){.book-langs-index{padding:0}}.book-langs-index .inner{max-width:600px;width:100%;margin:0 auto;padding:30px;background:#fff;border-radius:3px}.book-langs-index .inner h3{margin:0}.book-langs-index .inner .languages{list-style:none;padding:20px 30px;margin-top:20px;border-top:1px solid #eee}.book-langs-index .inner .languages:after,.book-langs-index .inner .languages:before{content:" ";display:table;line-height:0}.book-langs-index .inner .languages li{width:50%;float:left;padding:10px 5px;font-size:16px}@media (max-width:600px){.book-langs-index .inner .languages li{width:100%;max-width:100%}}.book .book-header{overflow:visible;height:50px;padding:0 8px;z-index:2;font-size:.85em;color:#7e888b;background:0 0}.book .book-header .btn{display:block;height:50px;padding:0 15px;border-bottom:none;color:#ccc;text-transform:uppercase;line-height:50px;-webkit-box-shadow:none!important;box-shadow:none!important;position:relative;font-size:14px}.book .book-header .btn:hover{position:relative;text-decoration:none;color:#444;background:0 0}.book .book-header h1{margin:0;font-size:20px;font-weight:200;text-align:center;line-height:50px;opacity:0;padding-left:200px;padding-right:200px;-webkit-transition:opacity .2s ease;-moz-transition:opacity .2s ease;-o-transition:opacity .2s ease;transition:opacity .2s ease;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.book .book-header h1 a,.book .book-header h1 a:hover{color:inherit;text-decoration:none}@media (max-width:1000px){.book .book-header h1{display:none}}.book .book-header h1 i{display:none}.book .book-header:hover h1{opacity:1}.book.is-loading .book-header h1 i{display:inline-block}.book.is-loading .book-header h1 a{display:none}.dropdown{position:relative}.dropdown-menu{position:absolute;top:100%;left:0;z-index:100;display:none;float:left;min-width:160px;padding:0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fafafa;border:1px solid rgba(0,0,0,.07);border-radius:1px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.open{display:block}.dropdown-menu.dropdown-left{left:auto;right:4%}.dropdown-menu.dropdown-left .dropdown-caret{right:14px;left:auto}.dropdown-menu .dropdown-caret{position:absolute;top:-8px;left:14px;width:18px;height:10px;float:left;overflow:hidden}.dropdown-menu .dropdown-caret .caret-inner,.dropdown-menu .dropdown-caret .caret-outer{display:inline-block;top:0;border-left:9px solid transparent;border-right:9px solid transparent;position:absolute}.dropdown-menu .dropdown-caret .caret-outer{border-bottom:9px solid rgba(0,0,0,.1);height:auto;left:0;width:auto;margin-left:-1px}.dropdown-menu .dropdown-caret .caret-inner{margin-top:-1px;top:1px;border-bottom:9px solid #fafafa}.dropdown-menu .buttons{border-bottom:1px solid rgba(0,0,0,.07)}.dropdown-menu .buttons:after,.dropdown-menu .buttons:before{content:" ";display:table;line-height:0}.dropdown-menu .buttons:last-child{border-bottom:none}.dropdown-menu .buttons .button{border:0;background-color:transparent;color:#a6a6a6;width:100%;text-align:center;float:left;line-height:1.42857143;padding:8px 4px}.alert,.dropdown-menu .buttons .button:hover{color:#444}.dropdown-menu .buttons .button:focus,.dropdown-menu .buttons .button:hover{outline:0}.dropdown-menu .buttons .button.size-2{width:50%}.dropdown-menu .buttons .button.size-3{width:33%}.alert{padding:15px;margin-bottom:20px;background:#eee;border-bottom:5px solid #ddd}.alert-success{background:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-info{background:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-danger{background:#f2dede;border-color:#ebccd1;color:#a94442}.alert-warning{background:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.book .book-summary{position:absolute;top:0;left:-300px;bottom:0;z-index:1;width:300px;color:#364149;background:#fafafa;border-right:1px solid rgba(0,0,0,.07);-webkit-transition:left 250ms ease;-moz-transition:left 250ms ease;-o-transition:left 250ms ease;transition:left 250ms ease}.book .book-summary ul.summary{position:absolute;top:0;left:0;right:0;bottom:0;overflow-y:auto;list-style:none;margin:0;padding:0;-webkit-transition:top .5s ease;-moz-transition:top .5s ease;-o-transition:top .5s ease;transition:top .5s ease}.book .book-summary ul.summary li{list-style:none}.book .book-summary ul.summary li.divider{height:1px;margin:7px 0;overflow:hidden;background:rgba(0,0,0,.07)}.book .book-summary ul.summary li i.fa-check{display:none;position:absolute;right:9px;top:16px;font-size:9px;color:#3c3}.book .book-summary ul.summary li.done>a{color:#364149;font-weight:400}.book .book-summary ul.summary li.done>a i{display:inline}.book .book-summary ul.summary li a,.book .book-summary ul.summary li span{display:block;padding:10px 15px;border-bottom:none;color:#364149;background:0 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative}.book .book-summary ul.summary li span{cursor:not-allowed;opacity:.3;filter:alpha(opacity=30)}.book .book-summary ul.summary li a:hover,.book .book-summary ul.summary li.active>a{color:#008cff;background:0 0;text-decoration:none}.book .book-summary ul.summary li ul{padding-left:20px}@media (max-width:600px){.book .book-summary{width:calc(100% - 60px);bottom:0;left:-100%}}.book.with-summary .book-summary{left:0}.book.without-animation .book-summary{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.book{position:relative;width:100%;height:100%}.book .book-body,.book .book-body .body-inner{position:absolute;top:0;left:0;overflow-y:auto;bottom:0;right:0}.book .book-body{color:#000;background:#fff;-webkit-transition:left 250ms ease;-moz-transition:left 250ms ease;-o-transition:left 250ms ease;transition:left 250ms ease}.book .book-body .page-wrapper{position:relative;outline:0}.book .book-body .page-wrapper .page-inner{max-width:800px;margin:0 auto;padding:20px 0 40px}.book .book-body .page-wrapper .page-inner section{margin:0;padding:5px 15px;background:#fff;border-radius:2px;line-height:1.7;font-size:1.6rem}.book .book-body .page-wrapper .page-inner .btn-group .btn{border-radius:0;background:#eee;border:0}@media (max-width:1240px){.book .book-body{-webkit-transition:-webkit-transform 250ms ease;-moz-transition:-moz-transform 250ms ease;-o-transition:-o-transform 250ms ease;transition:transform 250ms ease;padding-bottom:20px}.book .book-body .body-inner{position:static;min-height:calc(100% - 50px)}}@media (min-width:600px){.book.with-summary .book-body{left:300px}}@media (max-width:600px){.book.with-summary{overflow:hidden}.book.with-summary .book-body{-webkit-transform:translate(calc(100% - 60px),0);-moz-transform:translate(calc(100% - 60px),0);-ms-transform:translate(calc(100% - 60px),0);-o-transform:translate(calc(100% - 60px),0);transform:translate(calc(100% - 60px),0)}}.book.without-animation .book-body{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.buttons:after,.buttons:before{content:" ";display:table;line-height:0}.button{border:0;background:#eee;color:#666;width:100%;text-align:center;float:left;line-height:1.42857143;padding:8px 4px}.button:hover{color:#444}.button:focus,.button:hover{outline:0}.button.size-2{width:50%}.button.size-3{width:33%}.book .book-body .page-wrapper .page-inner section{display:none}.book .book-body .page-wrapper .page-inner section.normal{display:block;word-wrap:break-word;overflow:hidden;color:#333;line-height:1.7;text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%}.book .book-body .page-wrapper .page-inner section.normal *{box-sizing:border-box;-webkit-box-sizing:border-box;}.book .book-body .page-wrapper .page-inner section.normal>:first-child{margin-top:0!important}.book .book-body .page-wrapper .page-inner section.normal>:last-child{margin-bottom:0!important}.book .book-body .page-wrapper .page-inner section.normal blockquote,.book .book-body .page-wrapper .page-inner section.normal code,.book .book-body .page-wrapper .page-inner section.normal figure,.book .book-body .page-wrapper .page-inner section.normal img,.book .book-body .page-wrapper .page-inner section.normal pre,.book .book-body .page-wrapper .page-inner section.normal table,.book .book-body .page-wrapper .page-inner section.normal tr{page-break-inside:avoid}.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5,.book .book-body .page-wrapper .page-inner section.normal p{orphans:3;widows:3}.book .book-body .page-wrapper .page-inner section.normal h1,.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5{page-break-after:avoid}.book .book-body .page-wrapper .page-inner section.normal b,.book .book-body .page-wrapper .page-inner section.normal strong{font-weight:700}.book .book-body .page-wrapper .page-inner section.normal em{font-style:italic}.book .book-body .page-wrapper .page-inner section.normal blockquote,.book .book-body .page-wrapper .page-inner section.normal dl,.book .book-body .page-wrapper .page-inner section.normal ol,.book .book-body .page-wrapper .page-inner section.normal p,.book .book-body .page-wrapper .page-inner section.normal table,.book .book-body .page-wrapper .page-inner section.normal ul{margin-top:0;margin-bottom:.85em}.book .book-body .page-wrapper .page-inner section.normal a{color:#4183c4;text-decoration:none;background:0 0}.book .book-body .page-wrapper .page-inner section.normal a:active,.book .book-body .page-wrapper .page-inner section.normal a:focus,.book .book-body .page-wrapper .page-inner section.normal a:hover{outline:0;text-decoration:underline}.book .book-body .page-wrapper .page-inner section.normal img{border:0;max-width:100%}.book .book-body .page-wrapper .page-inner section.normal hr{height:4px;padding:0;margin:1.7em 0;overflow:hidden;background-color:#e7e7e7;border:none}.book .book-body .page-wrapper .page-inner section.normal hr:after,.book .book-body .page-wrapper .page-inner section.normal hr:before{display:table;content:" "}.book .book-body .page-wrapper .page-inner section.normal h1,.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5,.book .book-body .page-wrapper .page-inner section.normal h6{margin-top:1.275em;margin-bottom:.85em;}.book .book-body .page-wrapper .page-inner section.normal h1{font-size:2em}.book .book-body .page-wrapper .page-inner section.normal h2{font-size:1.75em}.book .book-body .page-wrapper .page-inner section.normal h3{font-size:1.5em}.book .book-body .page-wrapper .page-inner section.normal h4{font-size:1.25em}.book .book-body .page-wrapper .page-inner section.normal h5{font-size:1em}.book .book-body .page-wrapper .page-inner section.normal h6{font-size:1em;color:#777}.book .book-body .page-wrapper .page-inner section.normal code,.book .book-body .page-wrapper .page-inner section.normal pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;direction:ltr;border:none;color:inherit}.book .book-body .page-wrapper .page-inner section.normal pre{overflow:auto;word-wrap:normal;margin:0 0 1.275em;padding:.85em 1em;background:#f7f7f7}.book .book-body .page-wrapper .page-inner section.normal pre>code{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;font-size:.85em;white-space:pre;background:0 0}.book .book-body .page-wrapper .page-inner section.normal pre>code:after,.book .book-body .page-wrapper .page-inner section.normal pre>code:before{content:normal}.book .book-body .page-wrapper .page-inner section.normal code{padding:.2em;margin:0;font-size:.85em;background-color:#f7f7f7}.book .book-body .page-wrapper .page-inner section.normal code:after,.book .book-body .page-wrapper .page-inner section.normal code:before{letter-spacing:-.2em;content:"\00a0"}.book .book-body .page-wrapper .page-inner section.normal ol,.book .book-body .page-wrapper .page-inner section.normal ul{padding:0 0 0 2em;margin:0 0 .85em}.book .book-body .page-wrapper .page-inner section.normal ol ol,.book .book-body .page-wrapper .page-inner section.normal ol ul,.book .book-body .page-wrapper .page-inner section.normal ul ol,.book .book-body .page-wrapper .page-inner section.normal ul ul{margin-top:0;margin-bottom:0}.book .book-body .page-wrapper .page-inner section.normal ol ol{list-style-type:lower-roman}.book .book-body .page-wrapper .page-inner section.normal blockquote{margin:0 0 .85em;padding:0 15px;opacity:0.75;border-left:4px solid #dcdcdc}.book .book-body .page-wrapper .page-inner section.normal blockquote:first-child{margin-top:0}.book .book-body .page-wrapper .page-inner section.normal blockquote:last-child{margin-bottom:0}.book .book-body .page-wrapper .page-inner section.normal dl{padding:0}.book .book-body .page-wrapper .page-inner section.normal dl dt{padding:0;margin-top:.85em;font-style:italic;font-weight:700}.book .book-body .page-wrapper .page-inner section.normal dl dd{padding:0 .85em;margin-bottom:.85em}.book .book-body .page-wrapper .page-inner section.normal dd{margin-left:0}.book .book-body .page-wrapper .page-inner section.normal .glossary-term{cursor:help;text-decoration:underline}.book .book-body .navigation{position:absolute;top:50px;bottom:0;margin:0;max-width:150px;min-width:90px;display:flex;justify-content:center;align-content:center;flex-direction:column;font-size:40px;color:#ccc;text-align:center;-webkit-transition:all 350ms ease;-moz-transition:all 350ms ease;-o-transition:all 350ms ease;transition:all 350ms ease}.book .book-body .navigation:hover{text-decoration:none;color:#444}.book .book-body .navigation.navigation-next{right:0}.book .book-body .navigation.navigation-prev{left:0}@media (max-width:1240px){.book .book-body .navigation{position:static;top:auto;max-width:50%;width:50%;display:inline-block;float:left}.book .book-body .navigation.navigation-unique{max-width:100%;width:100%}}.book .book-body .page-wrapper .page-inner section.glossary{margin-bottom:40px}.book .book-body .page-wrapper .page-inner section.glossary h2 a,.book .book-body .page-wrapper .page-inner section.glossary h2 a:hover{color:inherit;text-decoration:none}.book .book-body .page-wrapper .page-inner section.glossary .glossary-index{list-style:none;margin:0;padding:0}.book .book-body .page-wrapper .page-inner section.glossary .glossary-index li{display:inline;margin:0 8px;white-space:nowrap}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-overflow-scrolling:auto;-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:none;-webkit-touch-callout:none}a{text-decoration:none}body,html{height:100%}html{font-size:62.5%}body{text-rendering:optimizeLegibility;font-smoothing:antialiased;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;letter-spacing:.2px;text-size-adjust:100%} -.book .book-summary ul.summary li a span {display:inline;padding:initial;overflow:visible;cursor:auto;opacity:1;} -/* show arrow before summary tag as in bootstrap */ -details > summary {display:list-item;cursor:pointer;} diff --git a/docs/libs/gitbook-2.6.7/js/app.min.js b/docs/libs/gitbook-2.6.7/js/app.min.js deleted file mode 100644 index 643f1f9..0000000 --- a/docs/libs/gitbook-2.6.7/js/app.min.js +++ /dev/null @@ -1 +0,0 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o"'`]/g,reHasEscapedHtml=RegExp(reEscapedHtml.source),reHasUnescapedHtml=RegExp(reUnescapedHtml.source);var reEscape=/<%-([\s\S]+?)%>/g,reEvaluate=/<%([\s\S]+?)%>/g,reInterpolate=/<%=([\s\S]+?)%>/g;var reIsDeepProp=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,reIsPlainProp=/^\w*$/,rePropName=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;var reRegExpChars=/^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,reHasRegExpChars=RegExp(reRegExpChars.source);var reComboMark=/[\u0300-\u036f\ufe20-\ufe23]/g;var reEscapeChar=/\\(\\)?/g;var reEsTemplate=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;var reFlags=/\w*$/;var reHasHexPrefix=/^0[xX]/;var reIsHostCtor=/^\[object .+?Constructor\]$/;var reIsUint=/^\d+$/;var reLatin1=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;var reNoMatch=/($^)/;var reUnescapedString=/['\n\r\u2028\u2029\\]/g;var reWords=function(){var upper="[A-Z\\xc0-\\xd6\\xd8-\\xde]",lower="[a-z\\xdf-\\xf6\\xf8-\\xff]+";return RegExp(upper+"+(?="+upper+lower+")|"+upper+"?"+lower+"|"+upper+"+|[0-9]+","g")}();var contextProps=["Array","ArrayBuffer","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Math","Number","Object","RegExp","Set","String","_","clearTimeout","isFinite","parseFloat","parseInt","setTimeout","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap"];var templateCounter=-1;var typedArrayTags={};typedArrayTags[float32Tag]=typedArrayTags[float64Tag]=typedArrayTags[int8Tag]=typedArrayTags[int16Tag]=typedArrayTags[int32Tag]=typedArrayTags[uint8Tag]=typedArrayTags[uint8ClampedTag]=typedArrayTags[uint16Tag]=typedArrayTags[uint32Tag]=true;typedArrayTags[argsTag]=typedArrayTags[arrayTag]=typedArrayTags[arrayBufferTag]=typedArrayTags[boolTag]=typedArrayTags[dateTag]=typedArrayTags[errorTag]=typedArrayTags[funcTag]=typedArrayTags[mapTag]=typedArrayTags[numberTag]=typedArrayTags[objectTag]=typedArrayTags[regexpTag]=typedArrayTags[setTag]=typedArrayTags[stringTag]=typedArrayTags[weakMapTag]=false;var cloneableTags={};cloneableTags[argsTag]=cloneableTags[arrayTag]=cloneableTags[arrayBufferTag]=cloneableTags[boolTag]=cloneableTags[dateTag]=cloneableTags[float32Tag]=cloneableTags[float64Tag]=cloneableTags[int8Tag]=cloneableTags[int16Tag]=cloneableTags[int32Tag]=cloneableTags[numberTag]=cloneableTags[objectTag]=cloneableTags[regexpTag]=cloneableTags[stringTag]=cloneableTags[uint8Tag]=cloneableTags[uint8ClampedTag]=cloneableTags[uint16Tag]=cloneableTags[uint32Tag]=true;cloneableTags[errorTag]=cloneableTags[funcTag]=cloneableTags[mapTag]=cloneableTags[setTag]=cloneableTags[weakMapTag]=false;var deburredLetters={"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss"};var htmlEscapes={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};var htmlUnescapes={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"};var objectTypes={function:true,object:true};var regexpEscapes={0:"x30",1:"x31",2:"x32",3:"x33",4:"x34",5:"x35",6:"x36",7:"x37",8:"x38",9:"x39",A:"x41",B:"x42",C:"x43",D:"x44",E:"x45",F:"x46",a:"x61",b:"x62",c:"x63",d:"x64",e:"x65",f:"x66",n:"x6e",r:"x72",t:"x74",u:"x75",v:"x76",x:"x78"};var stringEscapes={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"};var freeExports=objectTypes[typeof exports]&&exports&&!exports.nodeType&&exports;var freeModule=objectTypes[typeof module]&&module&&!module.nodeType&&module;var freeGlobal=freeExports&&freeModule&&typeof global=="object"&&global&&global.Object&&global;var freeSelf=objectTypes[typeof self]&&self&&self.Object&&self;var freeWindow=objectTypes[typeof window]&&window&&window.Object&&window;var moduleExports=freeModule&&freeModule.exports===freeExports&&freeExports;var root=freeGlobal||freeWindow!==(this&&this.window)&&freeWindow||freeSelf||this;function baseCompareAscending(value,other){if(value!==other){var valIsNull=value===null,valIsUndef=value===undefined,valIsReflexive=value===value;var othIsNull=other===null,othIsUndef=other===undefined,othIsReflexive=other===other;if(value>other&&!othIsNull||!valIsReflexive||valIsNull&&!othIsUndef&&othIsReflexive||valIsUndef&&othIsReflexive){return 1}if(value-1){}return index}function charsRightIndex(string,chars){var index=string.length;while(index--&&chars.indexOf(string.charAt(index))>-1){}return index}function compareAscending(object,other){return baseCompareAscending(object.criteria,other.criteria)||object.index-other.index}function compareMultiple(object,other,orders){var index=-1,objCriteria=object.criteria,othCriteria=other.criteria,length=objCriteria.length,ordersLength=orders.length;while(++index=ordersLength){return result}var order=orders[index];return result*(order==="asc"||order===true?1:-1)}}return object.index-other.index}function deburrLetter(letter){return deburredLetters[letter]}function escapeHtmlChar(chr){return htmlEscapes[chr]}function escapeRegExpChar(chr,leadingChar,whitespaceChar){if(leadingChar){chr=regexpEscapes[chr]}else if(whitespaceChar){chr=stringEscapes[chr]}return"\\"+chr}function escapeStringChar(chr){return"\\"+stringEscapes[chr]}function indexOfNaN(array,fromIndex,fromRight){var length=array.length,index=fromIndex+(fromRight?0:-1);while(fromRight?index--:++index=9&&charCode<=13)||charCode==32||charCode==160||charCode==5760||charCode==6158||charCode>=8192&&(charCode<=8202||charCode==8232||charCode==8233||charCode==8239||charCode==8287||charCode==12288||charCode==65279)}function replaceHolders(array,placeholder){var index=-1,length=array.length,resIndex=-1,result=[];while(++index>>1;var MAX_SAFE_INTEGER=9007199254740991;var metaMap=WeakMap&&new WeakMap;var realNames={};function lodash(value){if(isObjectLike(value)&&!isArray(value)&&!(value instanceof LazyWrapper)){if(value instanceof LodashWrapper){return value}if(hasOwnProperty.call(value,"__chain__")&&hasOwnProperty.call(value,"__wrapped__")){return wrapperClone(value)}}return new LodashWrapper(value)}function baseLodash(){}function LodashWrapper(value,chainAll,actions){this.__wrapped__=value;this.__actions__=actions||[];this.__chain__=!!chainAll}var support=lodash.support={};lodash.templateSettings={escape:reEscape,evaluate:reEvaluate,interpolate:reInterpolate,variable:"",imports:{_:lodash}};function LazyWrapper(value){this.__wrapped__=value;this.__actions__=[];this.__dir__=1;this.__filtered__=false;this.__iteratees__=[];this.__takeCount__=POSITIVE_INFINITY;this.__views__=[]}function lazyClone(){var result=new LazyWrapper(this.__wrapped__);result.__actions__=arrayCopy(this.__actions__);result.__dir__=this.__dir__;result.__filtered__=this.__filtered__;result.__iteratees__=arrayCopy(this.__iteratees__);result.__takeCount__=this.__takeCount__;result.__views__=arrayCopy(this.__views__);return result}function lazyReverse(){if(this.__filtered__){var result=new LazyWrapper(this);result.__dir__=-1;result.__filtered__=true}else{result=this.clone();result.__dir__*=-1}return result}function lazyValue(){var array=this.__wrapped__.value(),dir=this.__dir__,isArr=isArray(array),isRight=dir<0,arrLength=isArr?array.length:0,view=getView(0,arrLength,this.__views__),start=view.start,end=view.end,length=end-start,index=isRight?end:start-1,iteratees=this.__iteratees__,iterLength=iteratees.length,resIndex=0,takeCount=nativeMin(length,this.__takeCount__);if(!isArr||arrLength=LARGE_ARRAY_SIZE?createCache(values):null,valuesLength=values.length;if(cache){indexOf=cacheIndexOf;isCommon=false;values=cache}outer:while(++indexlength?0:length+start}end=end===undefined||end>length?length:+end||0;if(end<0){end+=length}length=start>end?0:end>>>0;start>>>=0;while(startlength?0:length+start}end=end===undefined||end>length?length:+end||0;if(end<0){end+=length}length=start>end?0:end-start>>>0;start>>>=0;var result=Array(length);while(++index=LARGE_ARRAY_SIZE,seen=isLarge?createCache():null,result=[];if(seen){indexOf=cacheIndexOf;isCommon=false}else{isLarge=false;seen=iteratee?[]:result}outer:while(++index>>1,computed=array[mid];if((retHighest?computed<=value:computed2?sources[length-2]:undefined,guard=length>2?sources[2]:undefined,thisArg=length>1?sources[length-1]:undefined;if(typeof customizer=="function"){customizer=bindCallback(customizer,thisArg,5);length-=2}else{customizer=typeof thisArg=="function"?thisArg:undefined;length-=customizer?1:0}if(guard&&isIterateeCall(sources[0],sources[1],guard)){customizer=length<3?undefined:customizer;length=1}while(++index-1?collection[index]:undefined}return baseFind(collection,predicate,eachFunc)}}function createFindIndex(fromRight){return function(array,predicate,thisArg){if(!(array&&array.length)){return-1}predicate=getCallback(predicate,thisArg,3);return baseFindIndex(array,predicate,fromRight)}}function createFindKey(objectFunc){return function(object,predicate,thisArg){predicate=getCallback(predicate,thisArg,3);return baseFind(object,predicate,objectFunc,true)}}function createFlow(fromRight){return function(){var wrapper,length=arguments.length,index=fromRight?length:-1,leftIndex=0,funcs=Array(length);while(fromRight?index--:++index=LARGE_ARRAY_SIZE){return wrapper.plant(value).value()}var index=0,result=length?funcs[index].apply(this,args):value;while(++index=length||!nativeIsFinite(length)){return""}var padLength=length-strLength;chars=chars==null?" ":chars+"";return repeat(chars,nativeCeil(padLength/chars.length)).slice(0,padLength)}function createPartialWrapper(func,bitmask,thisArg,partials){var isBind=bitmask&BIND_FLAG,Ctor=createCtorWrapper(func);function wrapper(){var argsIndex=-1,argsLength=arguments.length,leftIndex=-1,leftLength=partials.length,args=Array(leftLength+argsLength);while(++leftIndexarrLength)){return false}while(++index-1&&value%1==0&&value-1&&value%1==0&&value<=MAX_SAFE_INTEGER}function isStrictComparable(value){return value===value&&!isObject(value)}function mergeData(data,source){var bitmask=data[1],srcBitmask=source[1],newBitmask=bitmask|srcBitmask,isCommon=newBitmask0){if(++count>=HOT_COUNT){return key}}else{count=0}return baseSetData(key,value)}}();function shimKeys(object){var props=keysIn(object),propsLength=props.length,length=propsLength&&object.length;var allowIndexes=!!length&&isLength(length)&&(isArray(object)||isArguments(object));var index=-1,result=[];while(++index=120?createCache(othIndex&&value):null}var array=arrays[0],index=-1,length=array?array.length:0,seen=caches[0];outer:while(++index-1){splice.call(array,fromIndex,1)}}return array}var pullAt=restParam(function(array,indexes){indexes=baseFlatten(indexes);var result=baseAt(array,indexes);basePullAt(array,indexes.sort(baseCompareAscending));return result});function remove(array,predicate,thisArg){var result=[];if(!(array&&array.length)){return result}var index=-1,indexes=[],length=array.length;predicate=getCallback(predicate,thisArg,3);while(++index2?arrays[length-2]:undefined,thisArg=length>1?arrays[length-1]:undefined;if(length>2&&typeof iteratee=="function"){length-=2}else{iteratee=length>1&&typeof thisArg=="function"?(--length,thisArg):undefined;thisArg=undefined}arrays.length=length;return unzipWith(arrays,iteratee,thisArg)});function chain(value){var result=lodash(value);result.__chain__=true;return result}function tap(value,interceptor,thisArg){interceptor.call(thisArg,value);return value}function thru(value,interceptor,thisArg){return interceptor.call(thisArg,value)}function wrapperChain(){return chain(this)}function wrapperCommit(){return new LodashWrapper(this.value(),this.__chain__)}var wrapperConcat=restParam(function(values){values=baseFlatten(values);return this.thru(function(array){return arrayConcat(isArray(array)?array:[toObject(array)],values)})});function wrapperPlant(value){var result,parent=this;while(parent instanceof baseLodash){var clone=wrapperClone(parent);if(result){previous.__wrapped__=clone}else{result=clone}var previous=clone;parent=parent.__wrapped__}previous.__wrapped__=value;return result}function wrapperReverse(){var value=this.__wrapped__;var interceptor=function(value){return wrapped&&wrapped.__dir__<0?value:value.reverse()};if(value instanceof LazyWrapper){var wrapped=value;if(this.__actions__.length){wrapped=new LazyWrapper(this)}wrapped=wrapped.reverse();wrapped.__actions__.push({func:thru,args:[interceptor],thisArg:undefined});return new LodashWrapper(wrapped,this.__chain__)}return this.thru(interceptor)}function wrapperToString(){return this.value()+""}function wrapperValue(){return baseWrapperValue(this.__wrapped__,this.__actions__)}var at=restParam(function(collection,props){return baseAt(collection,baseFlatten(props))});var countBy=createAggregator(function(result,value,key){hasOwnProperty.call(result,key)?++result[key]:result[key]=1});function every(collection,predicate,thisArg){var func=isArray(collection)?arrayEvery:baseEvery;if(thisArg&&isIterateeCall(collection,predicate,thisArg)){predicate=undefined}if(typeof predicate!="function"||thisArg!==undefined){predicate=getCallback(predicate,thisArg,3)}return func(collection,predicate)}function filter(collection,predicate,thisArg){var func=isArray(collection)?arrayFilter:baseFilter;predicate=getCallback(predicate,thisArg,3);return func(collection,predicate)}var find=createFind(baseEach);var findLast=createFind(baseEachRight,true);function findWhere(collection,source){return find(collection,baseMatches(source))}var forEach=createForEach(arrayEach,baseEach);var forEachRight=createForEach(arrayEachRight,baseEachRight);var groupBy=createAggregator(function(result,value,key){if(hasOwnProperty.call(result,key)){result[key].push(value)}else{result[key]=[value]}});function includes(collection,target,fromIndex,guard){var length=collection?getLength(collection):0;if(!isLength(length)){collection=values(collection);length=collection.length}if(typeof fromIndex!="number"||guard&&isIterateeCall(target,fromIndex,guard)){fromIndex=0}else{fromIndex=fromIndex<0?nativeMax(length+fromIndex,0):fromIndex||0}return typeof collection=="string"||!isArray(collection)&&isString(collection)?fromIndex<=length&&collection.indexOf(target,fromIndex)>-1:!!length&&getIndexOf(collection,target,fromIndex)>-1}var indexBy=createAggregator(function(result,value,key){result[key]=value});var invoke=restParam(function(collection,path,args){var index=-1,isFunc=typeof path=="function",isProp=isKey(path),result=isArrayLike(collection)?Array(collection.length):[];baseEach(collection,function(value){var func=isFunc?path:isProp&&value!=null?value[path]:undefined;result[++index]=func?func.apply(value,args):invokePath(value,path,args)});return result});function map(collection,iteratee,thisArg){var func=isArray(collection)?arrayMap:baseMap;iteratee=getCallback(iteratee,thisArg,3);return func(collection,iteratee)}var partition=createAggregator(function(result,value,key){result[key?0:1].push(value)},function(){return[[],[]]});function pluck(collection,path){return map(collection,property(path))}var reduce=createReduce(arrayReduce,baseEach);var reduceRight=createReduce(arrayReduceRight,baseEachRight);function reject(collection,predicate,thisArg){var func=isArray(collection)?arrayFilter:baseFilter;predicate=getCallback(predicate,thisArg,3);return func(collection,function(value,index,collection){return!predicate(value,index,collection)})}function sample(collection,n,guard){if(guard?isIterateeCall(collection,n,guard):n==null){collection=toIterable(collection);var length=collection.length;return length>0?collection[baseRandom(0,length-1)]:undefined}var index=-1,result=toArray(collection),length=result.length,lastIndex=length-1;n=nativeMin(n<0?0:+n||0,length);while(++index0){result=func.apply(this,arguments)}if(n<=1){func=undefined}return result}}var bind=restParam(function(func,thisArg,partials){var bitmask=BIND_FLAG;if(partials.length){var holders=replaceHolders(partials,bind.placeholder);bitmask|=PARTIAL_FLAG}return createWrapper(func,bitmask,thisArg,partials,holders)});var bindAll=restParam(function(object,methodNames){methodNames=methodNames.length?baseFlatten(methodNames):functions(object);var index=-1,length=methodNames.length;while(++indexwait){complete(trailingCall,maxTimeoutId)}else{timeoutId=setTimeout(delayed,remaining)}}function maxDelayed(){complete(trailing,timeoutId)}function debounced(){args=arguments;stamp=now();thisArg=this;trailingCall=trailing&&(timeoutId||!leading);if(maxWait===false){var leadingCall=leading&&!timeoutId}else{if(!maxTimeoutId&&!leading){lastCalled=stamp}var remaining=maxWait-(stamp-lastCalled),isCalled=remaining<=0||remaining>maxWait;if(isCalled){if(maxTimeoutId){maxTimeoutId=clearTimeout(maxTimeoutId)}lastCalled=stamp;result=func.apply(thisArg,args)}else if(!maxTimeoutId){maxTimeoutId=setTimeout(maxDelayed,remaining)}}if(isCalled&&timeoutId){timeoutId=clearTimeout(timeoutId)}else if(!timeoutId&&wait!==maxWait){timeoutId=setTimeout(delayed,wait)}if(leadingCall){isCalled=true;result=func.apply(thisArg,args)}if(isCalled&&!timeoutId&&!maxTimeoutId){args=thisArg=undefined}return result}debounced.cancel=cancel;return debounced}var defer=restParam(function(func,args){return baseDelay(func,1,args)});var delay=restParam(function(func,wait,args){return baseDelay(func,wait,args)});var flow=createFlow();var flowRight=createFlow(true);function memoize(func,resolver){if(typeof func!="function"||resolver&&typeof resolver!="function"){throw new TypeError(FUNC_ERROR_TEXT)}var memoized=function(){var args=arguments,key=resolver?resolver.apply(this,args):args[0],cache=memoized.cache;if(cache.has(key)){return cache.get(key)}var result=func.apply(this,args);memoized.cache=cache.set(key,result);return result};memoized.cache=new memoize.Cache;return memoized}var modArgs=restParam(function(func,transforms){transforms=baseFlatten(transforms);if(typeof func!="function"||!arrayEvery(transforms,baseIsFunction)){throw new TypeError(FUNC_ERROR_TEXT)}var length=transforms.length;return restParam(function(args){var index=nativeMin(args.length,length);while(index--){args[index]=transforms[index](args[index])}return func.apply(this,args)})});function negate(predicate){if(typeof predicate!="function"){throw new TypeError(FUNC_ERROR_TEXT)}return function(){return!predicate.apply(this,arguments)}}function once(func){return before(2,func)}var partial=createPartial(PARTIAL_FLAG);var partialRight=createPartial(PARTIAL_RIGHT_FLAG);var rearg=restParam(function(func,indexes){return createWrapper(func,REARG_FLAG,undefined,undefined,undefined,baseFlatten(indexes))});function restParam(func,start){if(typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}start=nativeMax(start===undefined?func.length-1:+start||0,0);return function(){var args=arguments,index=-1,length=nativeMax(args.length-start,0),rest=Array(length);while(++indexother}function gte(value,other){return value>=other}function isArguments(value){return isObjectLike(value)&&isArrayLike(value)&&hasOwnProperty.call(value,"callee")&&!propertyIsEnumerable.call(value,"callee")}var isArray=nativeIsArray||function(value){return isObjectLike(value)&&isLength(value.length)&&objToString.call(value)==arrayTag};function isBoolean(value){return value===true||value===false||isObjectLike(value)&&objToString.call(value)==boolTag}function isDate(value){return isObjectLike(value)&&objToString.call(value)==dateTag}function isElement(value){return!!value&&value.nodeType===1&&isObjectLike(value)&&!isPlainObject(value)}function isEmpty(value){if(value==null){return true}if(isArrayLike(value)&&(isArray(value)||isString(value)||isArguments(value)||isObjectLike(value)&&isFunction(value.splice))){return!value.length}return!keys(value).length}function isEqual(value,other,customizer,thisArg){customizer=typeof customizer=="function"?bindCallback(customizer,thisArg,3):undefined;var result=customizer?customizer(value,other):undefined;return result===undefined?baseIsEqual(value,other,customizer):!!result}function isError(value){return isObjectLike(value)&&typeof value.message=="string"&&objToString.call(value)==errorTag}function isFinite(value){return typeof value=="number"&&nativeIsFinite(value)}function isFunction(value){return isObject(value)&&objToString.call(value)==funcTag}function isObject(value){var type=typeof value;return!!value&&(type=="object"||type=="function")}function isMatch(object,source,customizer,thisArg){customizer=typeof customizer=="function"?bindCallback(customizer,thisArg,3):undefined;return baseIsMatch(object,getMatchData(source),customizer)}function isNaN(value){return isNumber(value)&&value!=+value}function isNative(value){if(value==null){return false}if(isFunction(value)){return reIsNative.test(fnToString.call(value))}return isObjectLike(value)&&reIsHostCtor.test(value)}function isNull(value){return value===null}function isNumber(value){return typeof value=="number"||isObjectLike(value)&&objToString.call(value)==numberTag}function isPlainObject(value){var Ctor;if(!(isObjectLike(value)&&objToString.call(value)==objectTag&&!isArguments(value))||!hasOwnProperty.call(value,"constructor")&&(Ctor=value.constructor,typeof Ctor=="function"&&!(Ctor instanceof Ctor))){return false}var result;baseForIn(value,function(subValue,key){result=key});return result===undefined||hasOwnProperty.call(value,result)}function isRegExp(value){return isObject(value)&&objToString.call(value)==regexpTag}function isString(value){return typeof value=="string"||isObjectLike(value)&&objToString.call(value)==stringTag}function isTypedArray(value){return isObjectLike(value)&&isLength(value.length)&&!!typedArrayTags[objToString.call(value)]}function isUndefined(value){return value===undefined}function lt(value,other){return value0;while(++index=nativeMin(start,end)&&value=0&&string.indexOf(target,position)==position}function escape(string){string=baseToString(string);return string&&reHasUnescapedHtml.test(string)?string.replace(reUnescapedHtml,escapeHtmlChar):string}function escapeRegExp(string){string=baseToString(string);return string&&reHasRegExpChars.test(string)?string.replace(reRegExpChars,escapeRegExpChar):string||"(?:)"}var kebabCase=createCompounder(function(result,word,index){return result+(index?"-":"")+word.toLowerCase()});function pad(string,length,chars){string=baseToString(string);length=+length;var strLength=string.length;if(strLength>=length||!nativeIsFinite(length)){return string}var mid=(length-strLength)/2,leftLength=nativeFloor(mid),rightLength=nativeCeil(mid);chars=createPadding("",rightLength,chars);return chars.slice(0,leftLength)+string+chars}var padLeft=createPadDir();var padRight=createPadDir(true);function parseInt(string,radix,guard){if(guard?isIterateeCall(string,radix,guard):radix==null){radix=0}else if(radix){radix=+radix}string=trim(string);return nativeParseInt(string,radix||(reHasHexPrefix.test(string)?16:10))}function repeat(string,n){var result="";string=baseToString(string);n=+n;if(n<1||!string||!nativeIsFinite(n)){return result}do{if(n%2){result+=string}n=nativeFloor(n/2);string+=string}while(n);return result}var snakeCase=createCompounder(function(result,word,index){return result+(index?"_":"")+word.toLowerCase()});var startCase=createCompounder(function(result,word,index){return result+(index?" ":"")+(word.charAt(0).toUpperCase()+word.slice(1))});function startsWith(string,target,position){string=baseToString(string);position=position==null?0:nativeMin(position<0?0:+position||0,string.length);return string.lastIndexOf(target,position)==position}function template(string,options,otherOptions){var settings=lodash.templateSettings;if(otherOptions&&isIterateeCall(string,options,otherOptions)){options=otherOptions=undefined}string=baseToString(string);options=assignWith(baseAssign({},otherOptions||options),settings,assignOwnDefaults);var imports=assignWith(baseAssign({},options.imports),settings.imports,assignOwnDefaults),importsKeys=keys(imports),importsValues=baseValues(imports,importsKeys);var isEscaping,isEvaluating,index=0,interpolate=options.interpolate||reNoMatch,source="__p += '";var reDelimiters=RegExp((options.escape||reNoMatch).source+"|"+interpolate.source+"|"+(interpolate===reInterpolate?reEsTemplate:reNoMatch).source+"|"+(options.evaluate||reNoMatch).source+"|$","g");var sourceURL="//# sourceURL="+("sourceURL"in options?options.sourceURL:"lodash.templateSources["+ ++templateCounter+"]")+"\n";string.replace(reDelimiters,function(match,escapeValue,interpolateValue,esTemplateValue,evaluateValue,offset){interpolateValue||(interpolateValue=esTemplateValue);source+=string.slice(index,offset).replace(reUnescapedString,escapeStringChar);if(escapeValue){isEscaping=true;source+="' +\n__e("+escapeValue+") +\n'"}if(evaluateValue){isEvaluating=true;source+="';\n"+evaluateValue+";\n__p += '"}if(interpolateValue){source+="' +\n((__t = ("+interpolateValue+")) == null ? '' : __t) +\n'"}index=offset+match.length;return match});source+="';\n";var variable=options.variable;if(!variable){source="with (obj) {\n"+source+"\n}\n"}source=(isEvaluating?source.replace(reEmptyStringLeading,""):source).replace(reEmptyStringMiddle,"$1").replace(reEmptyStringTrailing,"$1;");source="function("+(variable||"obj")+") {\n"+(variable?"":"obj || (obj = {});\n")+"var __t, __p = ''"+(isEscaping?", __e = _.escape":"")+(isEvaluating?", __j = Array.prototype.join;\n"+"function print() { __p += __j.call(arguments, '') }\n":";\n")+source+"return __p\n}";var result=attempt(function(){return Function(importsKeys,sourceURL+"return "+source).apply(undefined,importsValues)});result.source=source;if(isError(result)){throw result}return result}function trim(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(trimmedLeftIndex(string),trimmedRightIndex(string)+1)}chars=chars+"";return string.slice(charsLeftIndex(string,chars),charsRightIndex(string,chars)+1)}function trimLeft(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(trimmedLeftIndex(string))}return string.slice(charsLeftIndex(string,chars+""))}function trimRight(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(0,trimmedRightIndex(string)+1)}return string.slice(0,charsRightIndex(string,chars+"")+1)}function trunc(string,options,guard){if(guard&&isIterateeCall(string,options,guard)){options=undefined}var length=DEFAULT_TRUNC_LENGTH,omission=DEFAULT_TRUNC_OMISSION;if(options!=null){if(isObject(options)){var separator="separator"in options?options.separator:separator;length="length"in options?+options.length||0:length;omission="omission"in options?baseToString(options.omission):omission}else{length=+options||0}}string=baseToString(string);if(length>=string.length){return string}var end=length-omission.length;if(end<1){return omission}var result=string.slice(0,end);if(separator==null){return result+omission}if(isRegExp(separator)){if(string.slice(end).search(separator)){var match,newEnd,substring=string.slice(0,end);if(!separator.global){separator=RegExp(separator.source,(reFlags.exec(separator)||"")+"g")}separator.lastIndex=0;while(match=separator.exec(substring)){newEnd=match.index}result=result.slice(0,newEnd==null?end:newEnd)}}else if(string.indexOf(separator,end)!=end){var index=result.lastIndexOf(separator);if(index>-1){result=result.slice(0,index)}}return result+omission}function unescape(string){string=baseToString(string);return string&&reHasEscapedHtml.test(string)?string.replace(reEscapedHtml,unescapeHtmlChar):string}function words(string,pattern,guard){if(guard&&isIterateeCall(string,pattern,guard)){pattern=undefined}string=baseToString(string);return string.match(pattern||reWords)||[]}var attempt=restParam(function(func,args){try{return func.apply(undefined,args)}catch(e){return isError(e)?e:new Error(e)}});function callback(func,thisArg,guard){if(guard&&isIterateeCall(func,thisArg,guard)){thisArg=undefined}return isObjectLike(func)?matches(func):baseCallback(func,thisArg)}function constant(value){return function(){return value}}function identity(value){return value}function matches(source){return baseMatches(baseClone(source,true))}function matchesProperty(path,srcValue){return baseMatchesProperty(path,baseClone(srcValue,true))}var method=restParam(function(path,args){return function(object){return invokePath(object,path,args)}});var methodOf=restParam(function(object,args){return function(path){return invokePath(object,path,args)}});function mixin(object,source,options){if(options==null){var isObj=isObject(source),props=isObj?keys(source):undefined,methodNames=props&&props.length?baseFunctions(source,props):undefined;if(!(methodNames?methodNames.length:isObj)){methodNames=false;options=source;source=object;object=this}}if(!methodNames){methodNames=baseFunctions(source,keys(source))}var chain=true,index=-1,isFunc=isFunction(object),length=methodNames.length;if(options===false){chain=false}else if(isObject(options)&&"chain"in options){chain=options.chain}while(++index0||end<0)){return new LazyWrapper(result)}if(start<0){result=result.takeRight(-start)}else if(start){result=result.drop(start)}if(end!==undefined){end=+end||0;result=end<0?result.dropRight(-end):result.take(end-start)}return result};LazyWrapper.prototype.takeRightWhile=function(predicate,thisArg){return this.reverse().takeWhile(predicate,thisArg).reverse()};LazyWrapper.prototype.toArray=function(){return this.take(POSITIVE_INFINITY)};baseForOwn(LazyWrapper.prototype,function(func,methodName){var checkIteratee=/^(?:filter|map|reject)|While$/.test(methodName),retUnwrapped=/^(?:first|last)$/.test(methodName),lodashFunc=lodash[retUnwrapped?"take"+(methodName=="last"?"Right":""):methodName];if(!lodashFunc){return}lodash.prototype[methodName]=function(){var args=retUnwrapped?[1]:arguments,chainAll=this.__chain__,value=this.__wrapped__,isHybrid=!!this.__actions__.length,isLazy=value instanceof LazyWrapper,iteratee=args[0],useLazy=isLazy||isArray(value);if(useLazy&&checkIteratee&&typeof iteratee=="function"&&iteratee.length!=1){isLazy=useLazy=false}var interceptor=function(value){return retUnwrapped&&chainAll?lodashFunc(value,1)[0]:lodashFunc.apply(undefined,arrayPush([value],args))};var action={func:thru,args:[interceptor],thisArg:undefined},onlyLazy=isLazy&&!isHybrid;if(retUnwrapped&&!chainAll){if(onlyLazy){value=value.clone();value.__actions__.push(action);return func.call(value)}return lodashFunc.call(undefined,this.value())[0]}if(!retUnwrapped&&useLazy){value=onlyLazy?value:new LazyWrapper(this);var result=func.apply(value,args);result.__actions__.push(action);return new LodashWrapper(result,chainAll)}return this.thru(interceptor)}});arrayEach(["join","pop","push","replace","shift","sort","splice","split","unshift"],function(methodName){var func=(/^(?:replace|split)$/.test(methodName)?stringProto:arrayProto)[methodName],chainName=/^(?:push|sort|unshift)$/.test(methodName)?"tap":"thru",retUnwrapped=/^(?:join|pop|replace|shift)$/.test(methodName);lodash.prototype[methodName]=function(){var args=arguments;if(retUnwrapped&&!this.__chain__){return func.apply(this.value(),args)}return this[chainName](function(value){return func.apply(value,args)})}});baseForOwn(LazyWrapper.prototype,function(func,methodName){var lodashFunc=lodash[methodName];if(lodashFunc){var key=lodashFunc.name,names=realNames[key]||(realNames[key]=[]);names.push({name:methodName,func:lodashFunc})}});realNames[createHybridWrapper(undefined,BIND_KEY_FLAG).name]=[{name:"wrapper",func:undefined}];LazyWrapper.prototype.clone=lazyClone;LazyWrapper.prototype.reverse=lazyReverse;LazyWrapper.prototype.value=lazyValue;lodash.prototype.chain=wrapperChain;lodash.prototype.commit=wrapperCommit;lodash.prototype.concat=wrapperConcat;lodash.prototype.plant=wrapperPlant;lodash.prototype.reverse=wrapperReverse;lodash.prototype.toString=wrapperToString;lodash.prototype.run=lodash.prototype.toJSON=lodash.prototype.valueOf=lodash.prototype.value=wrapperValue;lodash.prototype.collect=lodash.prototype.map;lodash.prototype.head=lodash.prototype.first;lodash.prototype.select=lodash.prototype.filter;lodash.prototype.tail=lodash.prototype.rest;return lodash}var _=runInContext();if(typeof define=="function"&&typeof define.amd=="object"&&define.amd){root._=_;define(function(){return _})}else if(freeExports&&freeModule){if(moduleExports){(freeModule.exports=_)._=_}else{freeExports._=_}}else{root._=_}}).call(this)}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],3:[function(require,module,exports){(function(window,document,undefined){var _MAP={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"};var _KEYCODE_MAP={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"};var _SHIFT_MAP={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"};var _SPECIAL_ALIASES={option:"alt",command:"meta",return:"enter",escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"};var _REVERSE_MAP;for(var i=1;i<20;++i){_MAP[111+i]="f"+i}for(i=0;i<=9;++i){_MAP[i+96]=i}function _addEvent(object,type,callback){if(object.addEventListener){object.addEventListener(type,callback,false);return}object.attachEvent("on"+type,callback)}function _characterFromEvent(e){if(e.type=="keypress"){var character=String.fromCharCode(e.which);if(!e.shiftKey){character=character.toLowerCase()}return character}if(_MAP[e.which]){return _MAP[e.which]}if(_KEYCODE_MAP[e.which]){return _KEYCODE_MAP[e.which]}return String.fromCharCode(e.which).toLowerCase()}function _modifiersMatch(modifiers1,modifiers2){return modifiers1.sort().join(",")===modifiers2.sort().join(",")}function _eventModifiers(e){var modifiers=[];if(e.shiftKey){modifiers.push("shift")}if(e.altKey){modifiers.push("alt")}if(e.ctrlKey){modifiers.push("ctrl")}if(e.metaKey){modifiers.push("meta")}return modifiers}function _preventDefault(e){if(e.preventDefault){e.preventDefault();return}e.returnValue=false}function _stopPropagation(e){if(e.stopPropagation){e.stopPropagation();return}e.cancelBubble=true}function _isModifier(key){return key=="shift"||key=="ctrl"||key=="alt"||key=="meta"}function _getReverseMap(){if(!_REVERSE_MAP){_REVERSE_MAP={};for(var key in _MAP){if(key>95&&key<112){continue}if(_MAP.hasOwnProperty(key)){_REVERSE_MAP[_MAP[key]]=key}}}return _REVERSE_MAP}function _pickBestAction(key,modifiers,action){if(!action){action=_getReverseMap()[key]?"keydown":"keypress"}if(action=="keypress"&&modifiers.length){action="keydown"}return action}function _keysFromString(combination){if(combination==="+"){return["+"]}combination=combination.replace(/\+{2}/g,"+plus");return combination.split("+")}function _getKeyInfo(combination,action){var keys;var key;var i;var modifiers=[];keys=_keysFromString(combination);for(i=0;i1){_bindSequence(combination,sequence,callback,action);return}info=_getKeyInfo(combination,action);self._callbacks[info.key]=self._callbacks[info.key]||[];_getMatches(info.key,info.modifiers,{type:info.action},sequenceName,combination,level);self._callbacks[info.key][sequenceName?"unshift":"push"]({callback:callback,modifiers:info.modifiers,action:info.action,seq:sequenceName,level:level,combo:combination})}self._bindMultiple=function(combinations,callback,action){for(var i=0;i-1){return false}if(_belongsTo(element,self.target)){return false}return element.tagName=="INPUT"||element.tagName=="SELECT"||element.tagName=="TEXTAREA"||element.isContentEditable};Mousetrap.prototype.handleKey=function(){var self=this;return self._handleKey.apply(self,arguments)};Mousetrap.init=function(){var documentMousetrap=Mousetrap(document);for(var method in documentMousetrap){if(method.charAt(0)!=="_"){Mousetrap[method]=function(method){return function(){return documentMousetrap[method].apply(documentMousetrap,arguments)}}(method)}}};Mousetrap.init();window.Mousetrap=Mousetrap;if(typeof module!=="undefined"&&module.exports){module.exports=Mousetrap}if(typeof define==="function"&&define.amd){define(function(){return Mousetrap})}})(window,document)},{}],4:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var splitPath=function(filename){return splitPathRe.exec(filename).slice(1)};exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i1){for(var i=1;i= 0x80 (not a basic code point)","invalid-input":"Invalid input"},baseMinusTMin=base-tMin,floor=Math.floor,stringFromCharCode=String.fromCharCode,key;function error(type){throw RangeError(errors[type])}function map(array,fn){var length=array.length;var result=[];while(length--){result[length]=fn(array[length])}return result}function mapDomain(string,fn){var parts=string.split("@");var result="";if(parts.length>1){result=parts[0]+"@";string=parts[1]}string=string.replace(regexSeparators,".");var labels=string.split(".");var encoded=map(labels,fn).join(".");return result+encoded}function ucs2decode(string){var output=[],counter=0,length=string.length,value,extra;while(counter=55296&&value<=56319&&counter65535){value-=65536;output+=stringFromCharCode(value>>>10&1023|55296);value=56320|value&1023}output+=stringFromCharCode(value);return output}).join("")}function basicToDigit(codePoint){if(codePoint-48<10){return codePoint-22}if(codePoint-65<26){return codePoint-65}if(codePoint-97<26){return codePoint-97}return base}function digitToBasic(digit,flag){return digit+22+75*(digit<26)-((flag!=0)<<5)}function adapt(delta,numPoints,firstTime){var k=0;delta=firstTime?floor(delta/damp):delta>>1;delta+=floor(delta/numPoints);for(;delta>baseMinusTMin*tMax>>1;k+=base){delta=floor(delta/baseMinusTMin)}return floor(k+(baseMinusTMin+1)*delta/(delta+skew))}function decode(input){var output=[],inputLength=input.length,out,i=0,n=initialN,bias=initialBias,basic,j,index,oldi,w,k,digit,t,baseMinusT;basic=input.lastIndexOf(delimiter);if(basic<0){basic=0}for(j=0;j=128){error("not-basic")}output.push(input.charCodeAt(j))}for(index=basic>0?basic+1:0;index=inputLength){error("invalid-input")}digit=basicToDigit(input.charCodeAt(index++));if(digit>=base||digit>floor((maxInt-i)/w)){error("overflow")}i+=digit*w;t=k<=bias?tMin:k>=bias+tMax?tMax:k-bias;if(digitfloor(maxInt/baseMinusT)){error("overflow")}w*=baseMinusT}out=output.length+1;bias=adapt(i-oldi,out,oldi==0);if(floor(i/out)>maxInt-n){error("overflow")}n+=floor(i/out);i%=out;output.splice(i++,0,n)}return ucs2encode(output)}function encode(input){var n,delta,handledCPCount,basicLength,bias,j,m,q,k,t,currentValue,output=[],inputLength,handledCPCountPlusOne,baseMinusT,qMinusT;input=ucs2decode(input);inputLength=input.length;n=initialN;delta=0;bias=initialBias;for(j=0;j=n&¤tValuefloor((maxInt-delta)/handledCPCountPlusOne)){error("overflow")}delta+=(m-n)*handledCPCountPlusOne;n=m;for(j=0;jmaxInt){error("overflow")}if(currentValue==n){for(q=delta,k=base;;k+=base){t=k<=bias?tMin:k>=bias+tMax?tMax:k-bias;if(q0&&len>maxKeys){len=maxKeys}for(var i=0;i=0){kstr=x.substr(0,idx);vstr=x.substr(idx+1)}else{kstr=x;vstr=""}k=decodeURIComponent(kstr);v=decodeURIComponent(vstr);if(!hasOwnProperty(obj,k)){obj[k]=v}else if(isArray(obj[k])){obj[k].push(v)}else{obj[k]=[obj[k],v]}}return obj};var isArray=Array.isArray||function(xs){return Object.prototype.toString.call(xs)==="[object Array]"}},{}],8:[function(require,module,exports){"use strict";var stringifyPrimitive=function(v){switch(typeof v){case"string":return v;case"boolean":return v?"true":"false";case"number":return isFinite(v)?v:"";default:return""}};module.exports=function(obj,sep,eq,name){sep=sep||"&";eq=eq||"=";if(obj===null){obj=undefined}if(typeof obj==="object"){return map(objectKeys(obj),function(k){var ks=encodeURIComponent(stringifyPrimitive(k))+eq;if(isArray(obj[k])){return map(obj[k],function(v){return ks+encodeURIComponent(stringifyPrimitive(v))}).join(sep)}else{return ks+encodeURIComponent(stringifyPrimitive(obj[k]))}}).join(sep)}if(!name)return"";return encodeURIComponent(stringifyPrimitive(name))+eq+encodeURIComponent(stringifyPrimitive(obj))};var isArray=Array.isArray||function(xs){return Object.prototype.toString.call(xs)==="[object Array]"};function map(xs,f){if(xs.map)return xs.map(f);var res=[];for(var i=0;i",'"',"`"," ","\r","\n","\t"],unwise=["{","}","|","\\","^","`"].concat(delims),autoEscape=["'"].concat(unwise),nonHostChars=["%","/","?",";","#"].concat(autoEscape),hostEndingChars=["/","?","#"],hostnameMaxLen=255,hostnamePartPattern=/^[a-z0-9A-Z_-]{0,63}$/,hostnamePartStart=/^([a-z0-9A-Z_-]{0,63})(.*)$/,unsafeProtocol={javascript:true,"javascript:":true},hostlessProtocol={javascript:true,"javascript:":true},slashedProtocol={http:true,https:true,ftp:true,gopher:true,file:true,"http:":true,"https:":true,"ftp:":true,"gopher:":true,"file:":true},querystring=require("querystring");function urlParse(url,parseQueryString,slashesDenoteHost){if(url&&isObject(url)&&url instanceof Url)return url;var u=new Url;u.parse(url,parseQueryString,slashesDenoteHost);return u}Url.prototype.parse=function(url,parseQueryString,slashesDenoteHost){if(!isString(url)){throw new TypeError("Parameter 'url' must be a string, not "+typeof url)}var rest=url;rest=rest.trim();var proto=protocolPattern.exec(rest);if(proto){proto=proto[0];var lowerProto=proto.toLowerCase();this.protocol=lowerProto;rest=rest.substr(proto.length)}if(slashesDenoteHost||proto||rest.match(/^\/\/[^@\/]+@[^@\/]+/)){var slashes=rest.substr(0,2)==="//";if(slashes&&!(proto&&hostlessProtocol[proto])){rest=rest.substr(2);this.slashes=true}}if(!hostlessProtocol[proto]&&(slashes||proto&&!slashedProtocol[proto])){var hostEnd=-1;for(var i=0;i127){newpart+="x"}else{newpart+=part[j]}}if(!newpart.match(hostnamePartPattern)){var validParts=hostparts.slice(0,i);var notHost=hostparts.slice(i+1);var bit=part.match(hostnamePartStart);if(bit){validParts.push(bit[1]);notHost.unshift(bit[2])}if(notHost.length){rest="/"+notHost.join(".")+rest}this.hostname=validParts.join(".");break}}}}if(this.hostname.length>hostnameMaxLen){this.hostname=""}else{this.hostname=this.hostname.toLowerCase()}if(!ipv6Hostname){var domainArray=this.hostname.split(".");var newOut=[];for(var i=0;i0?result.host.split("@"):false;if(authInHost){result.auth=authInHost.shift();result.host=result.hostname=authInHost.shift()}}result.search=relative.search;result.query=relative.query;if(!isNull(result.pathname)||!isNull(result.search)){result.path=(result.pathname?result.pathname:"")+(result.search?result.search:"")}result.href=result.format();return result}if(!srcPath.length){result.pathname=null;if(result.search){result.path="/"+result.search}else{result.path=null}result.href=result.format();return result}var last=srcPath.slice(-1)[0];var hasTrailingSlash=(result.host||relative.host)&&(last==="."||last==="..")||last==="";var up=0;for(var i=srcPath.length;i>=0;i--){last=srcPath[i];if(last=="."){srcPath.splice(i,1)}else if(last===".."){srcPath.splice(i,1);up++}else if(up){srcPath.splice(i,1);up--}}if(!mustEndAbs&&!removeAllDots){for(;up--;up){srcPath.unshift("..")}}if(mustEndAbs&&srcPath[0]!==""&&(!srcPath[0]||srcPath[0].charAt(0)!=="/")){srcPath.unshift("")}if(hasTrailingSlash&&srcPath.join("/").substr(-1)!=="/"){srcPath.push("")}var isAbsolute=srcPath[0]===""||srcPath[0]&&srcPath[0].charAt(0)==="/";if(psychotic){result.hostname=result.host=isAbsolute?"":srcPath.length?srcPath.shift():"";var authInHost=result.host&&result.host.indexOf("@")>0?result.host.split("@"):false;if(authInHost){result.auth=authInHost.shift();result.host=result.hostname=authInHost.shift()}}mustEndAbs=mustEndAbs||result.host&&srcPath.length;if(mustEndAbs&&!isAbsolute){srcPath.unshift("")}if(!srcPath.length){result.pathname=null;result.path=null}else{result.pathname=srcPath.join("/")}if(!isNull(result.pathname)||!isNull(result.search)){result.path=(result.pathname?result.pathname:"")+(result.search?result.search:"")}result.auth=relative.auth||result.auth;result.slashes=result.slashes||relative.slashes;result.href=result.format();return result};Url.prototype.parseHost=function(){var host=this.host;var port=portPattern.exec(host);if(port){port=port[0];if(port!==":"){this.port=port.substr(1)}host=host.substr(0,host.length-port.length)}if(host)this.hostname=host};function isString(arg){return typeof arg==="string"}function isObject(arg){return typeof arg==="object"&&arg!==null}function isNull(arg){return arg===null}function isNullOrUndefined(arg){return arg==null}},{punycode:6,querystring:9}],11:[function(require,module,exports){var $=require("jquery");function toggleDropdown(e){var $dropdown=$(e.currentTarget).parent().find(".dropdown-menu");$dropdown.toggleClass("open");e.stopPropagation();e.preventDefault()}function closeDropdown(e){$(".dropdown-menu").removeClass("open")}function init(){$(document).on("click",".toggle-dropdown",toggleDropdown);$(document).on("click",".dropdown-menu",function(e){e.stopPropagation()});$(document).on("click",closeDropdown)}module.exports={init:init}},{jquery:1}],12:[function(require,module,exports){var $=require("jquery");module.exports=$({})},{jquery:1}],13:[function(require,module,exports){var $=require("jquery");var _=require("lodash");var storage=require("./storage");var dropdown=require("./dropdown");var events=require("./events");var state=require("./state");var keyboard=require("./keyboard");var navigation=require("./navigation");var sidebar=require("./sidebar");var toolbar=require("./toolbar");function start(config){sidebar.init();keyboard.init();dropdown.init();navigation.init();toolbar.createButton({index:0,icon:"fa fa-align-justify",label:"Toggle Sidebar",onClick:function(e){e.preventDefault();sidebar.toggle()}});events.trigger("start",config);navigation.notify()}var gitbook={start:start,events:events,state:state,toolbar:toolbar,sidebar:sidebar,storage:storage,keyboard:keyboard};var MODULES={gitbook:gitbook,jquery:$,lodash:_};window.gitbook=gitbook;window.$=$;window.jQuery=$;gitbook.require=function(mods,fn){mods=_.map(mods,function(mod){mod=mod.toLowerCase();if(!MODULES[mod]){throw new Error("GitBook module "+mod+" doesn't exist")}return MODULES[mod]});fn.apply(null,mods)};module.exports={}},{"./dropdown":11,"./events":12,"./keyboard":14,"./navigation":16,"./sidebar":18,"./state":19,"./storage":20,"./toolbar":21,jquery:1,lodash:2}],14:[function(require,module,exports){var Mousetrap=require("mousetrap");var navigation=require("./navigation");var sidebar=require("./sidebar");function bindShortcut(keys,fn){Mousetrap.bind(keys,function(e){fn();return false})}function init(){bindShortcut(["right"],function(e){navigation.goNext()});bindShortcut(["left"],function(e){navigation.goPrev()});bindShortcut(["s"],function(e){sidebar.toggle()})}module.exports={init:init,bind:bindShortcut}},{"./navigation":16,"./sidebar":18,mousetrap:3}],15:[function(require,module,exports){var state=require("./state");function showLoading(p){state.$book.addClass("is-loading");p.always(function(){state.$book.removeClass("is-loading")});return p}module.exports={show:showLoading}},{"./state":19}],16:[function(require,module,exports){var $=require("jquery");var url=require("url");var events=require("./events");var state=require("./state");var loading=require("./loading");var usePushState=typeof history.pushState!=="undefined";function handleNavigation(relativeUrl,push){var uri=url.resolve(window.location.pathname,relativeUrl);notifyPageChange();location.href=relativeUrl;return}function updateNavigationPosition(){var bodyInnerWidth,pageWrapperWidth;bodyInnerWidth=parseInt($(".body-inner").css("width"),10);pageWrapperWidth=parseInt($(".page-wrapper").css("width"),10);$(".navigation-next").css("margin-right",bodyInnerWidth-pageWrapperWidth+"px")}function notifyPageChange(){events.trigger("page.change")}function preparePage(notify){var $bookBody=$(".book-body");var $bookInner=$bookBody.find(".body-inner");var $pageWrapper=$bookInner.find(".page-wrapper");updateNavigationPosition();$bookInner.scrollTop(0);$bookBody.scrollTop(0);if(notify!==false)notifyPageChange()}function isLeftClickEvent(e){return e.button===0}function isModifiedEvent(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function handlePagination(e){if(isModifiedEvent(e)||!isLeftClickEvent(e)){return}e.stopPropagation();e.preventDefault();var url=$(this).attr("href");if(url)handleNavigation(url,true)}function goNext(){var url=$(".navigation-next").attr("href");if(url)handleNavigation(url,true)}function goPrev(){var url=$(".navigation-prev").attr("href");if(url)handleNavigation(url,true)}function init(){$.ajaxSetup({});if(location.protocol!=="file:"){history.replaceState({path:window.location.href},"")}window.onpopstate=function(event){if(event.state===null){return}return handleNavigation(event.state.path,false)};$(document).on("click",".navigation-prev",handlePagination);$(document).on("click",".navigation-next",handlePagination);$(document).on("click",".summary [data-path] a",handlePagination);$(window).resize(updateNavigationPosition);preparePage(false)}module.exports={init:init,goNext:goNext,goPrev:goPrev,notify:notifyPageChange}},{"./events":12,"./loading":15,"./state":19,jquery:1,url:10}],17:[function(require,module,exports){module.exports={isMobile:function(){return document.body.clientWidth<=600}}},{}],18:[function(require,module,exports){var $=require("jquery");var _=require("lodash");var storage=require("./storage");var platform=require("./platform");var state=require("./state");function toggleSidebar(_state,animation){if(state!=null&&isOpen()==_state)return;if(animation==null)animation=true;state.$book.toggleClass("without-animation",!animation);state.$book.toggleClass("with-summary",_state);storage.set("sidebar",isOpen())}function isOpen(){return state.$book.hasClass("with-summary")}function init(){if(platform.isMobile()){toggleSidebar(false,false)}else{toggleSidebar(storage.get("sidebar",true),false)}$(document).on("click",".book-summary li.chapter a",function(e){if(platform.isMobile())toggleSidebar(false,false)})}function filterSummary(paths){var $summary=$(".book-summary");$summary.find("li").each(function(){var path=$(this).data("path");var st=paths==null||_.contains(paths,path);$(this).toggle(st);if(st)$(this).parents("li").show()})}module.exports={init:init,isOpen:isOpen,toggle:toggleSidebar,filter:filterSummary}},{"./platform":17,"./state":19,"./storage":20,jquery:1,lodash:2}],19:[function(require,module,exports){var $=require("jquery");var url=require("url");var path=require("path");var state={};state.update=function(dom){var $book=$(dom.find(".book"));state.$book=$book;state.level=$book.data("level");state.basePath=$book.data("basepath");state.innerLanguage=$book.data("innerlanguage");state.revision=$book.data("revision");state.filepath=$book.data("filepath");state.chapterTitle=$book.data("chapter-title");state.root=url.resolve(location.protocol+"//"+location.host,path.dirname(path.resolve(location.pathname.replace(/\/$/,"/index.html"),state.basePath))).replace(/\/?$/,"/");state.bookRoot=state.innerLanguage?url.resolve(state.root,".."):state.root};state.update($);module.exports=state},{jquery:1,path:4,url:10}],20:[function(require,module,exports){var baseKey="";module.exports={setBaseKey:function(key){baseKey=key},set:function(key,value){key=baseKey+":"+key;try{sessionStorage[key]=JSON.stringify(value)}catch(e){}},get:function(key,def){key=baseKey+":"+key;if(sessionStorage[key]===undefined)return def;try{var v=JSON.parse(sessionStorage[key]);return v==null?def:v}catch(err){return sessionStorage[key]||def}},remove:function(key){key=baseKey+":"+key;sessionStorage.removeItem(key)}}},{}],21:[function(require,module,exports){var $=require("jquery");var _=require("lodash");var events=require("./events");var buttons=[];function insertAt(parent,selector,index,element){var lastIndex=parent.children(selector).length;if(index<0){index=Math.max(0,lastIndex+1+index)}parent.append(element);if(index",{class:"dropdown-menu",html:''});if(_.isString(dropdown)){$menu.append(dropdown)}else{var groups=_.map(dropdown,function(group){if(_.isArray(group))return group;else return[group]});_.each(groups,function(group){var $group=$("
    ",{class:"buttons"});var sizeClass="size-"+group.length;_.each(group,function(btn){btn=_.defaults(btn||{},{text:"",className:"",onClick:defaultOnClick});var $btn=$("'; - var clipboard; - - gitbook.events.bind("page.change", function() { - - if (!ClipboardJS.isSupported()) return; - - // the page.change event is thrown twice: before and after the page changes - if (clipboard) { - // clipboard is already defined but we are on the same page - if (clipboard._prevPage === window.location.pathname) return; - // clipboard is already defined and url path change - // we can deduct that we are before page changes - clipboard.destroy(); // destroy the previous events listeners - clipboard = undefined; // reset the clipboard object - return; - } - - $(copyButton).prependTo("div.sourceCode"); - - clipboard = new ClipboardJS(".copy-to-clipboard-button", { - text: function(trigger) { - return trigger.parentNode.textContent; - } - }); - - clipboard._prevPage = window.location.pathname - - }); - -}); diff --git a/docs/libs/gitbook-2.6.7/js/plugin-fontsettings.js b/docs/libs/gitbook-2.6.7/js/plugin-fontsettings.js deleted file mode 100644 index a70f0fb..0000000 --- a/docs/libs/gitbook-2.6.7/js/plugin-fontsettings.js +++ /dev/null @@ -1,152 +0,0 @@ -gitbook.require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { - var fontState; - - var THEMES = { - "white": 0, - "sepia": 1, - "night": 2 - }; - - var FAMILY = { - "serif": 0, - "sans": 1 - }; - - // Save current font settings - function saveFontSettings() { - gitbook.storage.set("fontState", fontState); - update(); - } - - // Increase font size - function enlargeFontSize(e) { - e.preventDefault(); - if (fontState.size >= 4) return; - - fontState.size++; - saveFontSettings(); - }; - - // Decrease font size - function reduceFontSize(e) { - e.preventDefault(); - if (fontState.size <= 0) return; - - fontState.size--; - saveFontSettings(); - }; - - // Change font family - function changeFontFamily(index, e) { - e.preventDefault(); - - fontState.family = index; - saveFontSettings(); - }; - - // Change type of color - function changeColorTheme(index, e) { - e.preventDefault(); - - var $book = $(".book"); - - if (fontState.theme !== 0) - $book.removeClass("color-theme-"+fontState.theme); - - fontState.theme = index; - if (fontState.theme !== 0) - $book.addClass("color-theme-"+fontState.theme); - - saveFontSettings(); - }; - - function update() { - var $book = gitbook.state.$book; - - $(".font-settings .font-family-list li").removeClass("active"); - $(".font-settings .font-family-list li:nth-child("+(fontState.family+1)+")").addClass("active"); - - $book[0].className = $book[0].className.replace(/\bfont-\S+/g, ''); - $book.addClass("font-size-"+fontState.size); - $book.addClass("font-family-"+fontState.family); - - if(fontState.theme !== 0) { - $book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, ''); - $book.addClass("color-theme-"+fontState.theme); - } - }; - - function init(config) { - var $bookBody, $book; - - //Find DOM elements. - $book = gitbook.state.$book; - $bookBody = $book.find(".book-body"); - - // Instantiate font state object - fontState = gitbook.storage.get("fontState", { - size: config.size || 2, - family: FAMILY[config.family || "sans"], - theme: THEMES[config.theme || "white"] - }); - - update(); - }; - - - gitbook.events.bind("start", function(e, config) { - var opts = config.fontsettings; - if (!opts) return; - - // Create buttons in toolbar - gitbook.toolbar.createButton({ - icon: 'fa fa-font', - label: 'Font Settings', - className: 'font-settings', - dropdown: [ - [ - { - text: 'A', - className: 'font-reduce', - onClick: reduceFontSize - }, - { - text: 'A', - className: 'font-enlarge', - onClick: enlargeFontSize - } - ], - [ - { - text: 'Serif', - onClick: _.partial(changeFontFamily, 0) - }, - { - text: 'Sans', - onClick: _.partial(changeFontFamily, 1) - } - ], - [ - { - text: 'White', - onClick: _.partial(changeColorTheme, 0) - }, - { - text: 'Sepia', - onClick: _.partial(changeColorTheme, 1) - }, - { - text: 'Night', - onClick: _.partial(changeColorTheme, 2) - } - ] - ] - }); - - - // Init current settings - init(opts); - }); -}); - - diff --git a/docs/libs/gitbook-2.6.7/js/plugin-search.js b/docs/libs/gitbook-2.6.7/js/plugin-search.js deleted file mode 100644 index 747fcce..0000000 --- a/docs/libs/gitbook-2.6.7/js/plugin-search.js +++ /dev/null @@ -1,270 +0,0 @@ -gitbook.require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { - var index = null; - var fuse = null; - var _search = {engine: 'lunr', opts: {}}; - var $searchInput, $searchLabel, $searchForm; - var $highlighted = [], hi, hiOpts = { className: 'search-highlight' }; - var collapse = false, toc_visible = []; - - function init(config) { - // Instantiate search settings - _search = gitbook.storage.get("search", { - engine: config.search.engine || 'lunr', - opts: config.search.options || {}, - }); - }; - - // Save current search settings - function saveSearchSettings() { - gitbook.storage.set("search", _search); - } - - // Use a specific index - function loadIndex(data) { - // [Yihui] In bookdown, I use a character matrix to store the chapter - // content, and the index is dynamically built on the client side. - // Gitbook prebuilds the index data instead: https://github.com/GitbookIO/plugin-search - // We can certainly do that via R packages V8 and jsonlite, but let's - // see how slow it really is before improving it. On the other hand, - // lunr cannot handle non-English text very well, e.g. the default - // tokenizer cannot deal with Chinese text, so we may want to replace - // lunr with a dumb simple text matching approach. - if (_search.engine === 'lunr') { - index = lunr(function () { - this.ref('url'); - this.field('title', { boost: 10 }); - this.field('body'); - }); - data.map(function(item) { - index.add({ - url: item[0], - title: item[1], - body: item[2] - }); - }); - return; - } - fuse = new Fuse(data.map((_data => { - return { - url: _data[0], - title: _data[1], - body: _data[2] - }; - })), Object.assign( - { - includeScore: true, - threshold: 0.1, - ignoreLocation: true, - keys: ["title", "body"] - }, - _search.opts - )); - } - - // Fetch the search index - function fetchIndex() { - return $.getJSON(gitbook.state.basePath+"/search_index.json") - .then(loadIndex); // [Yihui] we need to use this object later - } - - // Search for a term and return results - function search(q) { - let results = []; - switch (_search.engine) { - case 'fuse': - if (!fuse) return; - results = fuse.search(q).map(function(result) { - var parts = result.item.url.split('#'); - return { - path: parts[0], - hash: parts[1] - }; - }); - break; - case 'lunr': - default: - if (!index) return; - results = _.chain(index.search(q)).map(function(result) { - var parts = result.ref.split("#"); - return { - path: parts[0], - hash: parts[1] - }; - }) - .value(); - } - - // [Yihui] Highlight the search keyword on current page - $highlighted = $('.page-inner') - .unhighlight(hiOpts).highlight(q, hiOpts).find('span.search-highlight'); - scrollToHighlighted(0); - - return results; - } - - // [Yihui] Scroll the chapter body to the i-th highlighted string - function scrollToHighlighted(d) { - var n = $highlighted.length; - hi = hi === undefined ? 0 : hi + d; - // navignate to the previous/next page in the search results if reached the top/bottom - var b = hi < 0; - if (d !== 0 && (b || hi >= n)) { - var path = currentPath(), n2 = toc_visible.length; - if (n2 === 0) return; - for (var i = b ? 0 : n2; (b && i < n2) || (!b && i >= 0); i += b ? 1 : -1) { - if (toc_visible.eq(i).data('path') === path) break; - } - i += b ? -1 : 1; - if (i < 0) i = n2 - 1; - if (i >= n2) i = 0; - var lnk = toc_visible.eq(i).find('a[href$=".html"]'); - if (lnk.length) lnk[0].click(); - return; - } - if (n === 0) return; - var $p = $highlighted.eq(hi); - $p[0].scrollIntoView(); - $highlighted.css('background-color', ''); - // an orange background color on the current item and removed later - $p.css('background-color', 'orange'); - setTimeout(function() { - $p.css('background-color', ''); - }, 2000); - } - - function currentPath() { - var href = window.location.pathname; - href = href.substr(href.lastIndexOf('/') + 1); - return href === '' ? 'index.html' : href; - } - - // Create search form - function createForm(value) { - if ($searchForm) $searchForm.remove(); - if ($searchLabel) $searchLabel.remove(); - if ($searchInput) $searchInput.remove(); - - $searchForm = $('
    ', { - 'class': 'book-search', - 'role': 'search' - }); - - $searchLabel = $('",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 - - - - - - References | Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -

    References

    - -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/docs/search_index.json b/docs/search_index.json deleted file mode 100644 index 325fbb3..0000000 --- a/docs/search_index.json +++ /dev/null @@ -1 +0,0 @@ -[["index.html", "Research Information Gateway Handbook Chapter 1 About", " Research Information Gateway Handbook EcoHealth Alliance 2023-03-31 Chapter 1 About This is a handbook created as a how-to manual for the development and maintenance of a One Health Research Information Gateway for the African continent. "],["introduction.html", "Chapter 2 Introduction", " Chapter 2 Introduction EcoHelth Alliance is supporting the creation of a database of active infectious disease research activities and research scientists in Africa. The database contains information about scientific research being conducted on the African continent that has particular relevance to understanding, detecting and responding to zoonotic pathogens. EHA is building a detailed, searchable, and visual database (e.g. via a dashboard) populated with information about major (e.g. multi-year) and active One Health research projects that includes subject matter, duration, geographical locations, key personnel, and links to publicly available reports, preprints and publications relevant to zoonoses. Examples of research areas may include epidemiological (syndrome based or disease specific), ecological (studies looking at potential reservoirs or animal hosts for zoonotic pathogens and spillover into humans or livestock); basic science (e.g. virology, bacteriology; serology); clinical (vaccine or therapeutic trials); or sociological (e.g. behavioral risk assessments or behavioral intervention studies) or any other preliminary public health findings. A particularly important view within the database includes a directory of subject matter experts associated with research across the continent. This roster view can be used by public health practitioners to engage expert consultations as needed to support training activities, surveillance or outbreak response, for example. "],["tools.html", "Chapter 3 Tools 3.1 Airtable 3.2 Base Design 3.3 Automating Airtable 3.4 Using the REST API 3.5 Data Management 3.6 R", " Chapter 3 Tools The Research Information Gateway (RIG) is currently using the following set of tools for database development and maintenance. 3.1 Airtable 3.1.1 What is Airtable? Airtable is a cloud-based software platform that allows users to create and manage databases, spreadsheets, and other types of organizational tools. It can be used for a variety of purposes, including project management, customer relationship management, inventory tracking, event planning, and much more. One of the key features of Airtable is its flexible and customizable nature. Users can create and customize their own database structures, and can choose from a wide range of data types, including text, attachments, checkboxes, and more. This allows for a high degree of customization and adaptability to different use cases and workflows. Airtable also offers a variety of collaboration features, including real-time syncing and commenting, as well as integrations with other popular tools such as Slack, Google Drive, and Trello. Additionally, Airtable has a robust API that allows developers to build custom integrations and applications on top of the platform. Airtable’s flexibility, customizability, and features that support collaboration along with its spreadsheet-style interface that is familiar to most that have used other spreadsheet software such as Microsoft Excel or Google Sheets are the key reasons why it was chosen to be the database tool for RIG. This section will provide an overview of Airtable and good practices for designing data models in relational databases. 3.1.2 Key Terms Workspace - A collection of bases Base - A database. Each is identified by the Airtable API via a base id Table - A tabular data set within a base. Each table is identified by the Airtable API via the name of the table e.g. “Demo Table” Record - An individual cell within a table. Each record is identified by the Airtable API via a record id Field - A property of data in a table Views - A specific way of displaying a table. Default is grid. Entity - Something that either physically or logically exists whose properties are typically stored in a table and composed of data elements. Element - an attribute of a Entity (a field) 3.1.3 Security and Access Control Airtable maintains physical and technological security as part of its ISO IEC 27001:2013 and SOC 2 compliance measures. Data are 256-bit encrypted when storing on the server and also when transferring data over the internet. To find vulnerabilities in their software, they run daily, weekly, and monthly scans on different components of their system and regularly commission external penetration tests. They also run a bug bounty program to help identify issues. Their data centers have fire detection and suppression systems, redundant power systems, and strict control for physical access. Because Airtable relies on Amazon Web Services (AWS) for its cloud infrastructure (the same providers used by previous EHA projects), data are geo-redundantly replicated in backups across multiple zones to increase data durability. They also have a team monitoring services at all times. Airtable employees are thoroughly vetted before hiring and continually trained on data protection best practices. Their workstations are secured by using full-disk encryption, automatic locking, and strong password requirements. 3.1.3.1 User- and Administrator Security Features 3.1.3.1.1 Access Controls Airtable provides database (referred to as “base”) and workspace administrators with granular controls over who can view, edit, comment, or otherwise modify data at the base, table, and field levels. There are four levels of Airtable user permissions: Owner/Creator: Full administrative control of base Editor: Sees full base, create and modify records and views, create and modify view share links Commenter: Sees full base, comment on records Reader: Sees full base Direct access to a base or workspace is granted or removed by base owners and creators to Airtable users. Base owners and creators can control who has access to a base and can control any “share” links created for that base. They may also restrict editing of tables or fields within a base. Any collaborator given direct access to a base at any permission level will be able to duplicate that base and share that data further. It is important that direct access to the base is limited to individuals with a need to curate or analyze the data. 3.1.3.1.2 Share Links and Interfaces To further restrict access to a base, users can be given indirect access via revocable share links or interfaces. Share links can be customized to prevent users from seeing the full base, prevent duplicating the base, and prevent copying data from the base. The ability to use the link can be password protected, restricted to people with certain email domains, and may be revoked at any time. If there are concerns about data leaks via base or table duplication, inviting people with a need to view the data via share links constrains their ability to extract data from the base. Interfaces are dynamic dashboards built on a limited set of data in an airtable base. Users can explore or even edit data based on the permissions provided by the interface creator. Access can be further tuned by setting up a “current-user filter”. See this guide for more information. 3.1.4 Data in Airtable See Airtable plan comparison for more information on the size of bases and features available. Information in this section pertains to all plans unless specified. 3.1.4.1 Workspaces, Bases, Tables, Fields, Records Airtable uses workspaces, bases, tables, and fields to manage data. A workspace generally pertains to a particular project and contains all bases relevant to that project. Sharing a workspace with someone allows them to see all bases within that workspace. Bases are equivalent to databases. They consist of a set of tables that can be linked and allow you to perform some task (e.g. IRB tracking, capturing research data, etc.). Bases can be duplicated and shared across your workspaces and you can share bases with other users. Tables are where most of the action happens. Data is entered in tables, tables can be transformed via views into calendars, dashboards, or galleries, and tables can be manipulated via the API. They describe a data entity and are composed of fields. In the bat sampling example, each circle would be a table in the bat sampling base. Fields represent properties of a data entity. In a spreadsheet view, fields are columns. Airtable allows you to control field types (date, number, text, file attachments, logical, etc.) and paid plans allows you to control who can edit fields. Fields can be linked between tables creating links. Records are the individual data points in a table. In a spreadsheet they would be the rows. Records are shaped by the structure you have created in tables and fields. Each record has a URL that can be used to access it programatically or share it. 3.1.5 Views In Airtable, tables can be displayed in different views to emphasis different components of the data. Views are great for creating concise presentations of data, especially in sprawling tables. The default view in an table is the grid (spreadsheet) view. All other views will derive from the data entered in this view. For more on views, see the guide to views. 3.1.6 Internal Backups: Record History, Base Snapshots Airtable has system for tracking changes to a base. They provide revision history for individual records (how long those histories are stored varies by plan). Any comments made in the revision history will be stored for the life of the record (on any plan). The current state of an entire base may be captured through snapshots. Should a systemic issue arise, the base can be restored to a snapshot at a later date. Restoring from a snapshot will remove the revision history for a record but comments on that record will be maintained. As revision histories are maintained, “deleted” records may be retrieved. In the event of the need to permanently remove data, the revision history of the base may be removed. Airtable allows data to be exported as CSVs from individual tables. At this time there is not an Airtable supported base export function. 3.1.7 Importing data Data can be imported to Airtable from a number of sources including CSV files, excel, Google sheets, XML, and via copy paste. Airtable will guess what the most appropriate field type is, so make sure the field type is appropriate for the data (e.g. convert from text to date type fields). Certain sources, like Google sheets, can be imported as bases. For more on importing data see: Importing and Adding data 3.2 Base Design Having a good base design will make using your data easier. Generally, the process looks like this: Describe what the database will do and collect use cases Determine the roles of various stakeholders List out the entities in the database and define their properties Map out how the entities fit together (which properties link them) Check that the mapping meets the use cases Build base in Airtable Check that the base meets the use cases If you are migrating from spreadsheets, you likely already have an idea of what you need the base to do and a collection of data properties. It is still a good idea to follow the steps outlined above for mapping out entities. You may find that entire sheets can be replaced by views or that the data in one sheet should actually be stored in two different tables. Feel free to reach out to the data librarian for questions about base design. 3.3 Automating Airtable Airtable has five main routes for automating processes. Automations - a drag and drop visual programming tool Extensions - pre-built applications that perform some task Scripting - use JavaScript to automate tasks within Airtable Blocks - use JavaScript to create custom applications REST API - use whatever programming language you like to automate processes 3.3.1 Automations with Drag and Drop Programing (pro and above) The automations feature within Airtable allows you to visually program routines. Each automation has three basic components: Status - controls whether or not the automation will run when the trigger condition is met Triggers - condition for automation to run: the creation or change of a record, a scheduled time, or some other external action Actions - what the automation will do Automations are commonly used to augment the synced tables feature, send notifications, check data quality, and manipulate or create records. This automation creates a weekly summary of applicants who applied for a position. Its trigger is time based, then it finds records that match a condition, and finally it generates an email from those records and sends to the appropriate recipients. airtable weekly summary 3.3.2 Scripting and Blocks (pro plan and above) Scripting uses JavaScript to manipulate a base from within an application in Airtable. Scripting is flexible but has a steep learning curve. The scripting environment Airtable provides can be helpful as it provides code linting, direct access to documentation, and example scripts to build from. The major drawback to scripting is that scripts live in the base and files are not version controlled. There are a LOT of pre-written scripts, in a shared “marketplace” to perform automatic actions. Search the marketplace before you start writing bespoke code. Blocks are custom applications built in JavaScript and node.js that add to base functionality. They are created in a development environment outside of Airtable then brought back into platform. There are number of tutorials for getting started with blocks. 3.4 Using the REST API All Airtable bases are automatically accessible to authorized users via a REST API. The list of API accessible bases you have access to can be found here: https://airtable.com/api. By clicking on a base you will be able to see the full API documentation for that base. 3.4.1 Scoped Tokens Airtable is moving to a scoped tokens based approach to api access. Scoped personal access tokens allow you to create a token for a specific base with specific permissions - e.g. token has read-only access to a bat sampling base. Using scoped tokens in this way means that if the token is compromised (leaked, stolen, accidentally committed unencrypted to a github repo, etc), you can delete that token to remove any access it might have had and the limited scope means that you know exactly what a person would have been able to access. To create a personal access token go here: https://airtable.com/create/tokens ** Remember to save the token in a secure place. Do not store unencrypted tokens on the web (e.g. pushing them to github). Airtable has also deployed oauth tokens for all users. 3.4.2 Airtable and R The Airtable REST API can be used via R with the airtabler package. EHA has started a fork of the package that has additional functionality so it is recommended to use that version. The original package design works well for exploring the data. Our extension adds additional functionality to help use airtabler in automation via continuous integration such as GitHub Actions. devtools::install_github("ecohealthalliance/airtabler") The Airtable API serves up data as JSON, which has a hierarchical structure similar to a list in R. To handle JSON, airtabler uses the jsonlite package. Its helpful to understand how jsonlite handles different JSON structures when working with more complicated Airtable data. See the jsonlite quick-start guide for a basic overview. The purr package is extremely helpful when dealing with data objects derived from JSON because it facilitates navigating nested data structures. The airtabler package provides instructions for setting up access to the Airtable API. You will need to follow those instructions for the following examples to work. One to One join library(airtabler) table1 <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "One To One") table2 <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "Table 2") ## Linked records are stored as JSON arrays so they become lists ## when part of a data frame. Because each array has a length of 1 ## we can safely unlist the arrays and add them back as to the ## data frame. table1$LinkedRec <- unlist(table1$LinkedRec) joinedTables <- dplyr::left_join(table1,table2, by = c("LinkedRec"="id")) recordKey <- joinedTables[c("Name","LinkedRec","Number")] recordKey One to Many Join library(airtabler) library(dplyr) library(purrr) oneToMany <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "One To Many") table2 <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "Table 2") # Depending on how you want to work with the data joins are a # little trickier here. ## to replace the values but keep the structure oneToMany$LinkedRecReplace <- purrr::map(oneToMany$LinkedRec, function(x){ table2 %>% filter(id %in% x) %>% select(c("id","Number")) %>% pull("Number") }) data.frame( id = unlist(oneToMany$LinkedRec), label = unlist(oneToMany$LinkedRecReplace) ) 3.5 Data Management Because of its flexibility and ease of use, it is extremely important that data management for airtable be taken seriously. Unlike most other relational databases, the fundamental properties of your base can be changed easily by multiple users without warning! Documenting the structure and purpose of your base, as well as creating regular external backups could save you from catastrophe. 3.5.1 Metadata Structural metadata - Information about a resource that tells you how its put together - e.g. the relationship between a table, field, and automation. With the exception of users on the enterprise plan, you must be deliberate about creating and maintaining structural metadata for your base. Example of Airtable Structural Metadata: Descriptive metadata - Information about a resource that makes it easier to find and attribute data. This includes things attributes like author, title, description, keywords, etc. This table becomes especially important when data are transitioned out of airtable, at the end of a project, or if the base will be shared broadly with collaborators. Example of Airtable Descriptive Metadata: To see the template base, follow this link 3.5.1.1 Metadata for automations and extensions Automations and extensions live entirely inside airtable. As of August 2022, Airtable introduced a “Manage Fields” tab that provides metadata for a specific table, including any automation dependencies. It is not possible to export those dependency tables or the code used in automations automatically. This makes it extremely important to document any automations and extensions outside your base. 3.5.2 External Backups It is a good idea to create regular external backups of airtable data in the event that something catastrophic happens to your base or you simply decide you no longer wish to use airtable as your data store.Unfortunately, airtable does not provide an off the shelf solution for this. Below are three options for extracting all data from your base. 3.5.2.1 Using airtabler Using airtabler::air_dump() and airtabler::air_dump_to_csv() functions, you can export all tables to R then create a versioned folder of CSVs. See the air_dump_to_csv help page for more information. 3.5.2.2 Other Open Source Projects UnlyEd - use this template to push airtable backups to AWS S3. https://github.com/UnlyEd/airtable-backups-boilerplate 3.5.2.3 Paid services Sequin - replicate airtable to postGres database - https://www.sequin.io/sources/airtable 3.6 R R is a free and open-source programming language and software environment for statistical computing and graphics. It was first developed in the early 1990s by Ross Ihaka and Robert Gentleman at the University of Auckland, New Zealand, and is now widely used by statisticians, data analysts, and researchers across various fields. R provides a wide range of statistical and graphical techniques, including linear and nonlinear modeling, classical statistical tests, time-series analysis, classification, clustering, and more. It also has a large and active community of users and developers who contribute to the development of new packages and extensions for the language. R is popular in the field of data science, as it provides a powerful and flexible platform for analyzing and visualizing data. It can be used in conjuction with other tools such as Airtable through community-developed packages making it particularly well-suited for the current use-case of the RIG. "],["database.html", "Chapter 4 Database 4.1 Activities Table 4.2 Countries Table 4.3 Description Table 4.4 Funder Table 4.5 Institutions Table 4.6 Researchers Table 4.7 Sources Table 4.8 Survey Results Table 4.9 Topics Table", " Chapter 4 Database The current database is built using Airtable. The current database has the following schema: This schema can be viewed interactively from here - https://airtable.com/appAL7fJUpBPYtOq4/tblt9ott045tWENcg/viwznxjIFAsTu0jzJ?blocks=bliZ6LV2bkGQNzgKF 4.1 Activities Table 4.1.1 Table details Activities pertain to the formal/official title of the project that has been identified during the database search or survey. Following are the different fields within the Activities table with their description. 4.1.2 Fields details Field Name Field Description Field Type Field Values Activity Activity name singleLineText NA Source Name (from Primary Sources) Name of primary source multipleLookupValues NA Notes Internal notes for maintenance singleLineText NA Topic Activity Topic multipleRecordLinks Topics Grant ID Grand Identifier singleLineText NA Collaborators Activity collaborators multipleRecordLinks Institutions Researchers Researchers involved in activity multipleRecordLinks Researchers Published Work Links to published work singleLineText NA Activity Location alt Activity location multipleRecordLinks Countries UN Stats Sub-region Name (from Activity Location alt) NA multipleLookupValues NA Activity Outputs Activity Outputs multipleSelects Data, Publication, Report, Guideline/SOP, Archive, Improving Diagnostics, Vaccine development, Therapeutics, Epidemic/Pandemic Preparedness, Biosurveillance technology, Prophylaxis, Surveillance, Improving Vaccine strategies, Training, Risk Assessment, Improving Capacity, Policies Activity Status Activity Status singleSelect Active, Completed Activity Website Activity Website url NA Activity Identifier Activity identifier formula NA Primary Sources Primary source of information multipleRecordLinks Sources Additional Sources Additional sources singleLineText NA Continent Name (from Activity Location alt) NA multipleLookupValues NA AU Region Name (from Activity Location alt) NA multipleLookupValues NA 4.2 Countries Table 4.2.1 Table details List of countries used to indicate the location information for the researchers, topics, funders, sources, institutions, and activities tables Following are the different fields within the Countries table with their description. 4.2.2 Fields details Field Name Field Description Field Type Field Values Researchers NA multipleRecordLinks Researchers Funders NA multipleRecordLinks Funders AU Region Name NA singleSelect Northern Africa, Eastern Africa, NA, Central Africa, Southern Africa, Western Africa UN Stats Sub-region Name Name of further sub-regional grouping to which country is usually classified within. This is based on the UN Statistics Division nomenclature. singleSelect NA, Eastern Africa, Middle Africa, Southern Africa, Western Africa, Channel Islands, Sark Country Name County name based on UN Statistics Division nomenclature multilineText NA 4.3 Description Table 4.3.1 Table details The Description table provides overall description of this entire database. Following are the different fields within the Description table with their description. 4.3.2 Field details Field Name Field Description Field Type Field Values Email Email for primary contact email NA Primary Contact Person to correspond with about the base singleLineText NA IRB Optional: Link to IRB url NA Base Description Characterization of the base. What is the base describing? multilineText NA Title Title of the base singleLineText NA Data Management Plan Link to data management plan url NA 4.4 Funder Table 4.4.1 Table details Funders pertain to the entities funding each activity. The funders’ information is retrieved from declared funders for the activities identified during the database search or the survey. Following are the different fields within the Funders table with their description. 4.4.2 Field details Field Name Field Description Field Type Field Values Funder Type Type of funder singleSelect Charitable organization, Foundation, Pharmaceutical company , Not-for-profit Partnership, NGO, Government Agency, University, Research Institut, Public- public partnership , Public-private partnership Funder Website Website of funder url NA Source Name (from Primary Sources) Source from where funder was identified multipleLookupValues NA Activities Activities supported by funder multipleRecordLinks Activities WHO Region Name (from Funder Location alt) NA multipleLookupValues NA Continent Name (from Funder Location alt) NA multipleLookupValues NA Primary Sources Source from where funder was identified multipleRecordLinks Sources 4.5 Institutions Table 4.5.1 Table details Institutions pertain to the entities directly related to or implementing the activity and/or the affiliation of the researcher implementing the activity. Following are the different fields within the Institutions table with their description. 4.5.2 Field details Field Name Field Description Field Type Field Values Institution Email Email of institution email NA Institution Website Institution Website url NA Activities Name of activity identified with institution multipleRecordLinks Activities Sources Name of primary source multipleRecordLinks Sources Institution Type Institution Type singleSelect Research Institute, University, NGO, National Government Institution, Non-profit Organisation , Hospital, Government Agency, Consortium, Partnership of Institutes, Industry, Charity, Public-private partnetship, International Coalition , Inter-governmental Organisation, Medical Service Provider, Network Institution Location Institution location multipleRecordLinks WHO Countries Notes Internal notes (for maintenance) singleLineText NA Topic (from Activities) Name of topic identified with the institution multipleLookupValues NA 4.6 Researchers Table 4.6.1 Table details Researchers pertains to the people involved in the activities contained in this database, and maybe involved in a variety of activity types. including but not limited to, research. Researchers identified during the database search. Information on researchers are primarily retrieved once activities have been identified from the database search process. It is possible that researchers are identified apriori and from which information on topics, funders, sources, institutions, and activities may be identified relevant to the specific researcher. This may happen when the planned/proposed survey is implemented and sent to known researchers who may or may not be in the database to begin with. Following are the different fields within the Researchers table with their description. 4.6.2 Field details Field Name Field Description Field Type Field Values WHO Region Name (from Researcher Country Location alt) NA multipleLookupValues NA ACDC Status Is researcher from the Africa CDC? singleSelect Non-member, Member Sources Name of source multipleRecordLinks Sources UN Stats Region Name (from Researcher Country Location alt) NA multipleLookupValues NA Affiliation Institution researcher is affiliated with. Choices from the institutions table multipleRecordLinks Institutions Institution Location alt (from Affiliation) NA multipleLookupValues NA Topic (from Activity) Name of topic multipleLookupValues NA Researcher Name Full name of researcher identified in the search singleLineText NA Notes Internal notes (for maintenance) singleLineText NA Source Name (from Sources) Name of source multipleLookupValues NA Additional Sources Additional sources singleLineText NA Activity Type (from Activity) Type of activity multipleLookupValues NA Website Personal website of researcher (if any) singleLineText NA Activity Activity/activities researchers is involved in multipleRecordLinks Activities Institution Location (from Affiliation) Name of location where institution is based multipleLookupValues NA Willing to be contacted Is the researcher willing to be contacted? checkbox NA Continent Name (from Researcher Country Location alt) NA multipleLookupValues NA 4.7 Sources Table 4.7.1 Table details Sources contain initial set of sources (primarily funders) identified to initiate the database search. These original sources are fully described here - https://ecohealthalliance.github.io/rig-handbook/sources.html. From the initial search, other sources were identified from which additional streams of searches were performed. Currently, the sources table is updated through a primary search of possible sources in addition to the search performed on the original sources list. Following are the different fields within the Sources table with their description. 4.7.2 Field details Field Name Field Description Field Type Field Values Source Type Type of primary source singleSelect Website text page, Website table, Website search, Downloadable document in PDF, Downloadable document in XLSX, Downloadable document in CSV, Downloadable document in DOCX, A form of database, Website text page, Website search, Links to downloadable documents in PDF, Website table, Website search Source Notes Internal notes for primary source (for maintenance) multilineText NA Topics Topics identified from primary source multipleRecordLinks Topics Relevant tables Notes on relevant tables found from primary source multipleSelects Researchers, Topics, Activities, Funders, Institutions, Countries Funders Funders identified from primary source multipleRecordLinks Funders Source Name Name of primary source singleLineText NA Created By Person who created the entry createdBy NA Researchers Name of researcher identified from primary source multipleRecordLinks Researchers 4.8 Survey Results Table 4.8.1 Table details NA Following are the different fields within the Survey Results table with their description. 4.8.2 Field details Field Name Field Description Field Type Field Values Activity description/ purpose Description of activity multilineText NA Sharing with Colleagues Is respondent going to share with colleagues? singleLineText NA Lead Researcher Name of lead researcher singleLineText NA Created By Name of survey respondent createdBy NA Other websites listing this project Other website listings for this project singleLineText NA Funder Name of funder for this project singleLineText NA Official Project Title Official project title singleLineText NA Official Project website Official project website singleLineText NA 4.9 Topics Table 4.9.1 Table details Topics pertain to the disease names and disease types. The topics table contains disease types/disease entities of interest to the Africa CDC based on their priorities (as described in their Framework document) and is continually updated with whatever disease/disease entity/disease type were deemed relevant by the database contributor. Following are the different fields within the Topics table with their description. 4.9.2 Field details Field Name Field Description Field Type Field Values Sources Name of Source multipleRecordLinks Sources Diseases Disease entity related/relevant to the field/topic of interest multipleSelects HIV, TB, COVID-19, Monkeypox, Lassa fever, Bat flu, Avian flu, Swine flu, Ebola virus disease, Marburg virus disease, Marburg haemorrhagic fever, H7N9, H5N1, H1N1, H1N2, H3N2, Plague, Anthrax, Crimean-Congo Haemorrhagic Fever, Rift Valley Fever, Nipah Virus, Brucellosis, undulant fever, Malta fever, Mediterranean fever, Hantavirus haemorrhagic fever with renal syndrome, Hantavirus pulmonary syndrome, Q fever, Chikungunya, Henipavirus, Ghanaian bat henipavirus, Leptospirosis, Weill’s disease, West Nile Fever, Zika fever, Dengue fever, African trypanosomiasis, Chagas disease, Yellow fever, Malaria, Re-emerging viruses, Visceral Leishmaniasis, Kala-azar, Cutaneous leishmaniasis , Hepatitis E , Viral Hepatitis, Hepatitis C, Hepatitis B, Leprosy, Hookworm, Schistosomiasis, Ascariasis, Trichuriasis, Lymphatic filariasis, Trachoma, Buruli ulcer, Dracunculiasis, Bilharzia, Whipworm Infection, Elephantiasis, Guinea-worm disease , Burkitt lymphoma, Cryptococcal meningitis, Kaposi sarcoma, schistosomiasis, Viral haemorrhagic fever, Rabies Activity Location (from Activities) Name of location of activity in which topic was identified multipleLookupValues NA Survey Results Results from survey multipleRecordLinks Survey Results Search terms Search terms used to identify topic multipleSelects antimycobacterial, anti-mycobacterial, COVID-19, coronavirus, omicron, rifampicin, ritonavir, darunavir, dolutegravir, MIS-C, HVTN, ART, antiretroviral, lopinavir, bedaquiline, clofazimine, isoniazid, pyrazinamide, antitubercular, tenofovir disoproxil fumarate, emtricitabine, dolutegravir , efavirenz, tubercular, drug-resistant, AMR, raltegravir, DR-, DR-TB, helminth, TBM, fluke, wildlife sampling, biosurveillance, surveillance network, seroprevalence, detection of , monitoring of , seroevidence, identification of , seropositive, seroepidemiological, survey, screened, prevalence Disease Types Type/category to which disease is grouped under multipleSelects infectious disease, viral, bacterial, parasitic, vector-bourne, zoonotic, virus, soil-transmitted Continent Name (from Activity Location alt) (from Activities) NA multipleLookupValues NA Activity Location alt (from Activities) NA multipleLookupValues NA Institutions Institutions multipleRecordLinks Institutions Region (from Activity Location) (from Activities) Name of region where topic was identified multipleLookupValues NA AU Region Name (from Activity Location alt) (from Activities) NA multipleLookupValues NA Source Name (from Sources) Name of source multipleLookupValues NA "],["sources.html", "Chapter 5 Sources 5.1 UKRI 5.2 Wellcome Trust 5.3 National Insitutes of Health 5.4 National Science Foundation 5.5 Defense Advanced Research Projects Agency 5.6 ClinicalTrials.gov 5.7 GEPRIS 5.8 EDCTP 5.9 GLOPID-R 5.10 NRF South Africa", " Chapter 5 Sources Following is an initial list of sources of information used for the RIG database. The initial search performed was non-systematic and focused primarily on a known funder of global research related/relevant to the topics of interest for the database . The main aim of focusing first on this limited and focused search was to get a sense of what information is available from such bodies/organisations, and the limitations of the information available. This is based on an initial idea that research funders would tend to have a system of collecting/archiving information on research they have funded. The expectation was that at the minimum, the information available from funders would lead to identifying further sources of information relevant to the ACDC database specifically those of research groups/institutions particularly those based in countries/regions within Africa. This initial search will hopefully inform a more systematic and informed search strategy for the database information. 5.1 UKRI UK Research and Innovation or UKRI is a non-departmental public body in the United Kingdom that was established in 2018. It brings together the seven UK Research Councils, Innovate UK, and Research England, which were previously separate organizations, to create a single body that oversees research and innovation funding and strategy in the UK. The seven UK Research Councils are: Arts and Humanities Research Council (AHRC) Biotechnology and Biological Sciences Research Council (BBSRC) Engineering and Physical Sciences Research Council (EPSRC) Economic and Social Research Council (ESRC) Medical Research Council (MRC) Natural Environment Research Council (NERC) Science and Technology Facilities Council (STFC) Innovate UK is the UK’s innovation agency, which provides funding and support for innovative businesses and projects. Research England is responsible for funding and overseeing research in English universities and higher education institutions. UKRI’s main role is to drive innovation and research in the UK and to support research and development that benefits society and the economy. It funds research projects, provides support to researchers, promotes international collaboration, and works to ensure that research and innovation are integrated with government policies and priorities. Of these various groups within UKRI, we further focused on the Biotechnology and Biological Sciences Research Council (BBSRC), Medical Research Council (MRC), Science and Technology Facilities Council (STFC), Innovate UK, and Research England. 5.2 Wellcome Trust The Wellcome Trust is a global charitable foundation based in the UK. It was established in 1936 by Sir Henry Wellcome, a pharmaceutical entrepreneur and philanthropist. The Wellcome Trust is one of the largest charitable organizations in the world, with an endowment of over £29 billion. The Trust’s mission is to improve health by supporting scientists, researchers, and innovators in their work to understand, treat, and prevent disease. The Trust funds research in areas such as neuroscience, genetics, infectious diseases, and global health. It also provides support for public engagement with science, education and training for scientists, and the translation of research into practical applications that benefit patients and communities. The Wellcome Trust is known for its long-term, strategic approach to funding research, and for its commitment to open science and data sharing. It also operates the Wellcome Collection, a public venue in London that hosts exhibitions and events related to health, medicine, and science. 5.3 National Insitutes of Health The National Institutes of Health (NIH) is a biomedical research agency of the United States federal government. It is the largest biomedical research institution in the world, with its main campus located in Bethesda, Maryland. The NIH is composed of 27 separate institutes and centers, each with a specific research focus, and is responsible for conducting and funding research in a wide range of areas, including cancer, genetics, infectious diseases, and neuroscience. The NIH was founded in 1887 as the Hygienic Laboratory and was later renamed the National Institutes of Health in 1930. Today, it is one of the world’s foremost centers for medical research, with a mission to seek fundamental knowledge about the nature and behavior of living systems and to apply that knowledge to enhance health, lengthen life, and reduce illness and disability. The NIH is funded by the U.S. government through the Department of Health and Human Services and operates under the direction of the Office of the Director. 5.4 National Science Foundation The National Science Foundation (NSF) is an independent federal agency of the United States government that supports fundamental research and education across all fields of science and engineering. The NSF was established by the National Science Foundation Act of 1950 and has a budget of around $8 billion. The NSF funds research and education in areas such as mathematics, computer science, physics, chemistry, biology, social sciences, and engineering. It supports individual researchers, small teams, and large interdisciplinary research collaborations through a competitive, merit-based process of proposal submission and review. The NSF also supports the development of science, technology, engineering, and mathematics (STEM) education at all levels, from K-12 through graduate education. The NSF operates through several directorates and offices, each with a specific research focus or mission, such as the Directorate for Biological Sciences, the Directorate for Social, Behavioral and Economic Sciences, and the Office of Polar Programs. The NSF works to advance scientific discovery, promote science education and outreach, and promote innovation and economic growth through its investments in research and education. 5.5 Defense Advanced Research Projects Agency The Defense Advanced Research Projects Agency is a research and development agency of the United States Department of Defense that is responsible for the development of emerging technologies for use by the military. DARPA was established in 1958 in response to the Soviet Union’s launch of Sputnik, the first artificial satellite, and has been involved in a number of high-profile technological innovations, including the development of the Internet, GPS, and stealth technology. DARPA’s mission is to maintain the technological superiority of the U.S. military by sponsoring and conducting research in a wide range of fields, including artificial intelligence, robotics, biotechnology, materials science, and aerospace technology. DARPA works with academic researchers, private companies, and other government agencies to develop and test new technologies, and it is known for its high-risk, high-reward approach to research and development. Some of DARPA’s current research initiatives include the development of hypersonic weapons, the creation of autonomous drone swarms, and the development of brain-machine interfaces for use in treating neurological disorders. DARPA’s work has had significant impacts on both military and civilian technology, and the agency is seen as a leader in cutting-edge research and development. 5.6 ClinicalTrials.gov ClinicalTrials.gov is a publicly accessible database of clinical trials that are being conducted worldwide. It is maintained by the National Library of Medicine, a part of the National Institutes of Health (NIH) in the United States. The database provides information on clinical trials for a wide range of diseases and conditions, including both interventional and observational studies. It includes information about the purpose of the trial, who may participate, where the trial is being conducted, and the status of the trial, such as whether it is recruiting participants or has been completed. ClinicalTrials.gov was created in response to a 1997 law requiring the registration of clinical trials for certain serious or life-threatening diseases or conditions. Since then, the database has grown to include information on thousands of trials from around the world. ClinicalTrials.gov is an important resource for researchers, healthcare professionals, and members of the public who are interested in clinical research. It can be used to identify ongoing or completed trials, learn about the purpose and design of a study, and find out how to participate in a trial. It also serves as a platform for researchers to share their results and comply with the requirements of various funding agencies and regulatory bodies. 5.7 GEPRIS Geförderte Projekte in der Forschung und Entwicklung (Funded Projects in Research and Development) or GEPRIS is an online database of research projects funded by the German Research Foundation (DFG). The DFG is the largest independent research funding organization in Germany and funds projects across all scientific disciplines, from the humanities and social sciences to the natural and life sciences. GEPRIS provides information about the projects that the DFG has funded, including their aims, methods, and outcomes, as well as the institutions and researchers involved. Researchers and members of the public can use GEPRIS to search for projects that have been funded by the DFG, and to access information about these projects. The database includes information about ongoing and completed projects, and users can search by various criteria, such as by researcher name, institution, scientific discipline, or project title. GEPRIS is a valuable tool for researchers to identify potential collaborators, explore research trends, and find information about the funding landscape in their field. It is also useful for members of the public who are interested in learning about the research being conducted in Germany and the impact of this research on society. 5.8 EDCTP European and Developing Countries Clinical Trials Partnership or EDCTP is a public-public partnership between countries in Europe and sub-Saharan Africa, established in 2003, with the aim of accelerating the development of new clinical interventions to fight infectious diseases that disproportionately affect Africa. The partnership’s mission is to improve the health of people in Africa by supporting the development of new medicines, vaccines, and other health interventions to prevent and treat diseases such as HIV/AIDS, tuberculosis, malaria, and neglected infectious diseases. EDCTP supports collaborative research projects that bring together scientists, institutions, and countries from both regions to conduct clinical trials and other research activities. EDCTP works with a range of partners, including national governments, research institutions, civil society organizations, and the private sector, to support research that is relevant and responsive to the needs of African communities. It also provides training and capacity-building opportunities to support the development of sustainable health research infrastructure and expertise in Africa. The partnership is funded by the European Union, its member states, and other donors. Since its inception, EDCTP has supported over 100 collaborative research projects and played a key role in advancing the development of new interventions for infectious diseases that affect the people of Africa. 5.9 GLOPID-R Global Research Collaboration for Infectious Disease Preparedness or GLOPID-R is an international partnership that aims to strengthen global research efforts in the field of infectious disease preparedness. The partnership was established in response to the 2014 Ebola outbreak in West Africa, which highlighted the need for improved global coordination and collaboration in research and development for emerging and re-emerging infectious diseases. GLOPID-R brings together stakeholders from the global health community, including research funders, policy-makers, researchers, and public health organizations. The partnership aims to promote international cooperation and coordination in research to accelerate the development of new tools and approaches to prevent, detect, and respond to infectious disease outbreaks. GLOPID-R’s main objectives include identifying research priorities for infectious disease preparedness, coordinating research efforts across different regions and countries, and promoting capacity building and knowledge exchange to strengthen global health research infrastructure. The partnership focuses on a range of infectious diseases, including those caused by emerging and re-emerging pathogens, neglected tropical diseases, and antimicrobial resistance. It works to support research efforts across the entire spectrum of infectious disease preparedness, from basic research to clinical trials and implementation research. GLOPID-R is supported by a range of funding agencies and partners from around the world and is seen as an important platform for promoting global cooperation and collaboration in infectious disease research and preparedness. 5.10 NRF South Africa The National Research Foundation of South Africa (NRF) is an independent organization that promotes and supports research and innovation in all fields of science, engineering, technology, and social sciences in South Africa. The NRF was established in 1999 through the National Research Foundation Act and operates under the jurisdiction of the Department of Science and Innovation. The NRF provides funding, develops policies, and manages research infrastructure to support South African researchers and institutions. It also fosters international collaboration in research, and supports the training and development of the next generation of researchers through various funding and fellowship schemes. The NRF provides funding through a number of programs, including competitive grants, fellowships, and research chairs. It also supports the development of research infrastructure and the establishment of research centers of excellence. In addition to providing funding and support for research, the NRF plays a key role in developing research policies and strategies at the national level. It advises the South African government on research priorities and is involved in various initiatives aimed at promoting science, technology, and innovation in the country. The NRF is an important organization for the South African research community and has been instrumental in advancing the country’s research and innovation capabilities. Its funding and support have contributed to numerous scientific discoveries and innovations in a wide range of fields, including health, energy, and the environment. "],["updates.html", "Chapter 6 Updates 6.1 Wellcome Trust Grant Funding Data 6.2 ClinicalTrials.gov 6.3 Public journal/research databases 6.4 GEPRIS 6.5 EDCTP", " Chapter 6 Updates The current update process of the RIG database is summarised in this workflow: Following are the source-specific process of updating or retrieving information for the RIG database. 6.1 Wellcome Trust Grant Funding Data 6.1.1 General Information Using the downloadable spreadsheet of funds awarded between 01st of October 2005 and 4th of May 2022 found at https://cms.wellcome.org/sites/default/files/2022-05/Wellcome-grants-awarded-1-October-2005-to-04-05-2022.xlsx, the following steps were taken to retrieve relevant information for the database: 6.1.2 How to update Please note that the steps below were done using the current available spreadsheet from the Wellcome Trust website and added the relevant projects to the RIG database. These steps can therefore be used as a guide for how to update the database with new information in the future to when the Wellcome Trust publishes its most up-to-date spreadsheet. Go to column J – Recipient Org:Country -> deselect all and then select all the African countries in the list Go to column N – Planned end date -> select all the years in the future These two steps reduced the list from 19,833 projects to 111 projects Read the project title and decide if the project is relevant for our database or not If unsure, read the abstract – that also helps to identify the keywords to tag the project within our database If the project is relevant transfer all the information into our database Note: This method is only able to detect projects/activities where an African organisation itself holds the grant. It does not detect projects where African researchers are involved as collaborators. The spreadsheet does not list collaborators on projects, so it’s yet to be determined how we will identify projects on which African research institutes collaborate with international organisations being awarded the grant. 6.2 ClinicalTrials.gov 6.2.1 How to update Following are steps taken to extract data from ClinicalTrials.gov. Start with searching a disease/topic of interest On the results page apply the following filters to look for active studies Click on ‘Apply’ and then look manually through the column ‘Locations’ of the list of the results to find studies that take place in African countries Click on the first study to start working your way through the information available The first information provided is the sponsor -> this information should be added to the Funder – column in the Activities table Information about collaborators can be added to Collaborators column Staying in the ‘Study Details’-tab, scroll down to ‘Study Design’ This section contains the official title, which should be used as the name for the Activity Additionally it contains information about the start and end date, which should be copied into the respective fields in the Activities table Scroll further down to ‘Contact and Locations’ The information given under contacts should be added to the Researcher column in Airtable Switching into the Researcher-table within in Airtable the given contact details should be added to the newly created entries for the involved researchers Also the affiliation to a certain institute can be added based on these information as well as the researcher’s location -> is it possible to link the Location with the Affiliation so that the location is automatically added based on the information about the institution the researcher is affiliated with? Switch back into the Activities table and add information about the Locations to the Activity Location and the Institutions columns Scroll up again to the selection of tabs Click on the Results tab -> it’s worth checking this tab even when it’s called No Results Posted as it might still contain links to publications that are affiliated with the study These links can be copied into the Published Work column in the Activities table I also copied the link of the study page on clinicaltrials.gov into the Activity Website column to determine the Research Field, I had to use my own understanding of the study so I am not sure if this can be automated or rather needs to be done by a database librarian 6.3 Public journal/research databases In order to aid in automation, maintain a list relevant search terms for each topic of interest (stored in the “Topics” table in Airtable). Even if the terms are not used for the purposes of developing a search strategy, they can be used by those who are not subject matter experts when collection information on a specific topic 6.3.1 Example of a successful search: (zoonoses OR zoonotic disease OR zoonotic illness) and (africa*) and (surveillance OR tracking OR sampling) The majority of results from this search, when conducted in PubMed, appeared relevant to the database (based on title/abstract scanning) 6.3.2 Example of PubMed search for surveillance activities for Brucellosis: ("surveillance"[Title/Abstract] OR "prevalence"[Title/Abstract] OR "monitoring"[Title/Abstract] OR "seropositive"[Title/Abstract] OR "seroprevalence"[Title/Abstract] OR "seroevidence"[Title/Abstract] OR "screened"[Title/Abstract] OR "biosurveillance"[Title/Abstract] OR "sampl*"[Title/Abstract]) AND (brucellosis[Title/Abstract] OR "Brucella melitensis"[Title/Abstract] OR "B. melitensis"[Title/Abstract] OR "Brucella abortus"[Title/Abstract] OR "B. abortus"[Title/Abstract]) This search yielded a large quantity of results, not all of which were relevant. Manual processes are required to validate results. Including terms to filter the results based on location were helpful, but still included results not located on the African continent. Search term to filter for African countries: (Djibouti[Title/Abstract] OR Seychelles[Title/Abstract] OR DR Congo[Title/Abstract] OR Comoros[Title/Abstract] OR Togo[Title/Abstract] OR Sierra Leone[Title/Abstract] OR Libya[Title/Abstract] OR Tanzania[Title/Abstract] OR South Africa[Title/Abstract] OR Cabo Verde[Title/Abstract] OR Congo[Title/Abstract] OR Kenya[Title/Abstract] OR Liberia[Title/Abstract] OR Central African Republic[Title/Abstract] OR Mauritania[Title/Abstract] OR Uganda[Title/Abstract] OR Algeria[Title/Abstract] OR Sudan[Title/Abstract] OR Morocco[Title/Abstract] OR Eritrea[Title/Abstract] OR Angola[Title/Abstract] OR Mozambique[Title/Abstract] OR Ghana[Title/Abstract] OR Madagascar[Title/Abstract] OR Cameroon[Title/Abstract] OR Côte d'Ivoire[Title/Abstract] OR Namibia[Title/Abstract] OR Niger[Title/Abstract] OR Gambia[Title/Abstract] OR Botswana[Title/Abstract] OR Gabon[Title/Abstract] OR Sao Tome & Principe[Title/Abstract] OR Lesotho[Title/Abstract] OR Burkina Faso[Title/Abstract] OR Nigeria[Title/Abstract] OR Mali[Title/Abstract] OR Guinea-Bissau[Title/Abstract] OR Malawi[Title/Abstract] OR Zambia[Title/Abstract] OR Senegal[Title/Abstract] OR Chad[Title/Abstract] OR Somalia[Title/Abstract] OR Zimbabwe[Title/Abstract] OR Equatorial Guinea[Title/Abstract] OR Guinea[Title/Abstract] OR Rwanda[Title/Abstract] OR Mauritius[Title/Abstract] OR Benin[Title/Abstract] OR Burundi[Title/Abstract] OR Tunisia[Title/Abstract] OR Eswatini[Title/Abstract] OR Ethiopia[Title/Abstract] OR South Sudan[Title/Abstract] OR Egypt[Title/Abstract]) From publications, can extract researchers, institutions, funders, activities. Ideally, researchers, institutions, and funders can be extracted automatically as opposed to manually, but scripts would need to be customized for each journal. 6.3.3 Validation of results Validation of results can be useful to better understand the overlap between publications and activities and determine the priority of searching through publications vs. navigating to institution sites directly (or other strategies). After finding a relevant publication, look at the publication’s authors and their respective institutions Navigate to institutions’ sites to search for publications or results from research Are their activities listed on the site? Are those activities explicitly mentioned in the publications? Etc. 6.3.4 Some relevant journals/databases: Zoonoses & Public Health from Wiley Online Library : https://onlinelibrary.wiley.com/action/doSearch?SeriesKey=18632378&sortBy=Earliest Journal of Public Health in Africa: https://www.publichealthinafrica.org/jphia/issue/view/30 PLoS Journal of Neglected Tropical Diseases: https://journals.plos.org/plosntds/search?filterJournals=PLoSNTD 6.4 GEPRIS 6.4.1 General Information: GEPRIS is a database listing all projects funded by the German Research Foundation (German: Deutsche Forschungsgemeinschaft; abbr. DFG) The DFG is a research funding organisation, which functions as a self-governing institution for the promotion of science and research in the Federal Republic Germany. In 2019, the DFG had a funding budget of €3.3 billion. 6.4.2 How to Use: The database can be accessed here: https://gepris.dfg.de/gepris/OCTOPUS?language=en&task=showSearchSimple This link should directly lead to the English version of the website, otherwise the language can be changed by clicking on English in the top right corner. In the database one can search for Projects, People, or Institutions – for our purpose the project option is the most relevant One can either search for keywords or filter for different criteria – for a systematic approach I found using the filtering options easier than going through all our On the search start site stay in the Projects tab. Click on Show extended search. Under Subject Area select one of the following: Agriculture, Forestry and Veterinary Medicine Basic Research in Biology and Medicine Medicine Microbiology, Virology, and Immunology Social Sciences Water Research Zoology Note: After working through all these subject areas, any relevant project in the field of One Health should be picked up by the searches Leave everything under DFG Programme as it is Move on to Funding and change Status to Current Move on to International and change Continent to Africa Click on Find Read through the project titles on the results page to identify relevant projects Import all the relevant project information (as highlighted on the screenshots) into the Africa CDC database To identify the research institutes that are involved in the project one has to click on the researchers names and extract that information from their profile (their affiliation with a research institute is listed there) 6.4.3 Positive aspects of this source: The filtering options allow to filter for several criteria which are crucial for the relevance of a project to our database. That removes a lot of irrelevant projects from the results pages. The project pages list almost all the information we are interested in. 6.4.4 Downsides of this source: The project page doesn’t list the anticipated end date of a project. One has to click on the link to the researcher’s profile to identify the participating organisations. Even using all the different filtering options not all resulting hits are relevant for our database, so I don’t think the process can be fully automated or at least requires a subsequent manual validation or clean up step to remove irrelevant projects. 6.5 EDCTP 6.5.1 General Information The European & Developing Countries Clinical Trials Partnership (EDCTP) is a non-profit organisation with a European office in The Hague, The Netherlands and an African office in Cape Town, South Africa. EDCTP is a partnership between European Union (EU), Norway, Switzerland, and African countries to accelerate the development of new clinical interventions such as drugs, vaccines, microbicides, and diagnostics against poverty-related diseases in Africa. The organisation supports clinical trials, capacity strengthening and networking in Africa and Europe. Funding comes from the EU, member states, pharmaceutical industry and private organisations and charities like The Wellcome Trust and The Bill & Melinda Gates foundation. Note: Since funding comes from several sources that we also list as sources for populating the database such as the European Union (European Commission), The Wellcome Trust and The Bill & Melinda Gates Foundation, there is the possibility that downloading project information from all these sources into our database could lead to duplicate entries. I created a column in the Actvities table for the Project ID, as this might be helpful to identify duplicates and remove them automatically. 6.5.2 How to use: The database of funded project can be accessed here: https://www.edctp.org/edctp2-project-portal/ There is the option to download the list of projects as a PDF, CSV or XLXS file. Personally, I did not find that helpful for manually adding projects to the database, but it might be useful for an automated process. Go to Status of Project and select the filter Active Go to Classification and select one of the following filters: Co-Infections COVID-19 Cysticercosis/Taeniasis Diagnostics Diarrhoeal Diseases Drugs Emerging Infections, incl. Ebola, Lassa Epidemiology HIV Human African trypanosomiasis (sleeping sickness) Implementation Research Leishmaniases Leprosy (Hansen disease) Lower respiratory infections Lymphatic filariasis Malaria Microbicides Onchocerciasis (river blindness) Rabies Schistosomiasis Soil-transmitted helminthiasis Social Science Tuberculosis Vaccines Yaws Yellow Fever Note: Only one Classification at a time can be selected Once one Classification was selected click on search Change from Show Map to Show List -> this makes it easier to systematically look through the projects On the results list you can see the location of the coordinating organisation, but even if it is not in an African country, it is worth checking the project details for the Participating Organisations. So read the project title and decide whether this could be a relevant project, if so, click on View details Check the Participating Organisations first to decide whether the project is relevant to our database: If the project is relevant use the Project Name + Acronym for the Activity Column Transfer all the relevant information to our database, including Project ID, Start and End date, Participating Organisations and corresponding locations, Project Website, Coordinating Organisation and Coordinating Researcher Tag the project with the correct keywords in the Activity Type, Activity Outputs, Target Species, Topic, and Research Field columns based on your understanding of the project abstract 6.5.3 Benefits of this Source: The projects can be easily filtered for currently active projects. The EDCTP is specifically focused on projects in Africa or Europe with African collaborators so most projects fulfil at least one of our selection criteria A lot of the projects (not all) are also topic-wise relevant for our database The database lists most of the information that we are interested in for our database 6.5.4 Shortcomings of this source: Only one disease/topic can be selected at a time so sequential searches are necessary Project details only list the Coordinating researcher but no other lead researchers at the participating organisations "],["survey.html", "Chapter 7 Survey", " Chapter 7 Survey "],["references.html", "References", " References "],["404.html", "Page not found", " 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. "]] diff --git a/docs/sources.html b/docs/sources.html deleted file mode 100644 index 0ea3fa4..0000000 --- a/docs/sources.html +++ /dev/null @@ -1,375 +0,0 @@ - - - - - - - Chapter 5 Sources | Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -

    Chapter 5 Sources

    -

    Following is an initial list of sources of information used for the RIG database.

    -

    The initial search performed was non-systematic and focused primarily on a known funder of global research related/relevant to the topics of interest for the database . The main aim of focusing first on this limited and focused search was to get a sense of what information is available from such bodies/organisations, and the limitations of the information available. This is based on an initial idea that research funders would tend to have a system of collecting/archiving information on research they have funded. The expectation was that at the minimum, the information available from funders would lead to identifying further sources of information relevant to the ACDC database specifically those of research groups/institutions particularly those based in countries/regions within Africa. This initial search will hopefully inform a more systematic and informed search strategy for the database information.

    -
    -

    5.1 UKRI

    -

    UK Research and Innovation or UKRI is a non-departmental public body in the United Kingdom that was established in 2018. It brings together the seven UK Research Councils, Innovate UK, and Research England, which were previously separate organizations, to create a single body that oversees research and innovation funding and strategy in the UK.

    -

    The seven UK Research Councils are:

    -
      -
    1. Arts and Humanities Research Council (AHRC)
    2. -
    3. Biotechnology and Biological Sciences Research Council (BBSRC)
    4. -
    5. Engineering and Physical Sciences Research Council (EPSRC)
    6. -
    7. Economic and Social Research Council (ESRC)
    8. -
    9. Medical Research Council (MRC)
    10. -
    11. Natural Environment Research Council (NERC)
    12. -
    13. Science and Technology Facilities Council (STFC)
    14. -
    -

    Innovate UK is the UK’s innovation agency, which provides funding and support for innovative businesses and projects.

    -

    Research England is responsible for funding and overseeing research in English universities and higher education institutions.

    -

    UKRI’s main role is to drive innovation and research in the UK and to support research and development that benefits society and the economy. It funds research projects, provides support to researchers, promotes international collaboration, and works to ensure that research and innovation are integrated with government policies and priorities.

    -

    Of these various groups within UKRI, we further focused on the Biotechnology and Biological Sciences Research Council (BBSRC), Medical Research Council (MRC), Science and Technology Facilities Council (STFC), Innovate UK, and Research England.

    -
    -
    -

    5.2 Wellcome Trust

    -

    The Wellcome Trust is a global charitable foundation based in the UK. It was established in 1936 by Sir Henry Wellcome, a pharmaceutical entrepreneur and philanthropist. The Wellcome Trust is one of the largest charitable organizations in the world, with an endowment of over £29 billion.

    -

    The Trust’s mission is to improve health by supporting scientists, researchers, and innovators in their work to understand, treat, and prevent disease. The Trust funds research in areas such as neuroscience, genetics, infectious diseases, and global health. It also provides support for public engagement with science, education and training for scientists, and the translation of research into practical applications that benefit patients and communities.

    -

    The Wellcome Trust is known for its long-term, strategic approach to funding research, and for its commitment to open science and data sharing. It also operates the Wellcome Collection, a public venue in London that hosts exhibitions and events related to health, medicine, and science.

    -
    -
    -

    5.3 National Insitutes of Health

    -

    The National Institutes of Health (NIH) is a biomedical research agency of the United States federal government. It is the largest biomedical research institution in the world, with its main campus located in Bethesda, Maryland. The NIH is composed of 27 separate institutes and centers, each with a specific research focus, and is responsible for conducting and funding research in a wide range of areas, including cancer, genetics, infectious diseases, and neuroscience.

    -

    The NIH was founded in 1887 as the Hygienic Laboratory and was later renamed the National Institutes of Health in 1930. Today, it is one of the world’s foremost centers for medical research, with a mission to seek fundamental knowledge about the nature and behavior of living systems and to apply that knowledge to enhance health, lengthen life, and reduce illness and disability. The NIH is funded by the U.S. government through the Department of Health and Human Services and operates under the direction of the Office of the Director.

    -
    -
    -

    5.4 National Science Foundation

    -

    The National Science Foundation (NSF) is an independent federal agency of the United States government that supports fundamental research and education across all fields of science and engineering. The NSF was established by the National Science Foundation Act of 1950 and has a budget of around $8 billion.

    -

    The NSF funds research and education in areas such as mathematics, computer science, physics, chemistry, biology, social sciences, and engineering. It supports individual researchers, small teams, and large interdisciplinary research collaborations through a competitive, merit-based process of proposal submission and review. The NSF also supports the development of science, technology, engineering, and mathematics (STEM) education at all levels, from K-12 through graduate education.

    -

    The NSF operates through several directorates and offices, each with a specific research focus or mission, such as the Directorate for Biological Sciences, the Directorate for Social, Behavioral and Economic Sciences, and the Office of Polar Programs. The NSF works to advance scientific discovery, promote science education and outreach, and promote innovation and economic growth through its investments in research and education.

    -
    -
    -

    5.5 Defense Advanced Research Projects Agency

    -

    The Defense Advanced Research Projects Agency is a research and development agency of the United States Department of Defense that is responsible for the development of emerging technologies for use by the military.

    -

    DARPA was established in 1958 in response to the Soviet Union’s launch of Sputnik, the first artificial satellite, and has been involved in a number of high-profile technological innovations, including the development of the Internet, GPS, and stealth technology.

    -

    DARPA’s mission is to maintain the technological superiority of the U.S. military by sponsoring and conducting research in a wide range of fields, including artificial intelligence, robotics, biotechnology, materials science, and aerospace technology. DARPA works with academic researchers, private companies, and other government agencies to develop and test new technologies, and it is known for its high-risk, high-reward approach to research and development.

    -

    Some of DARPA’s current research initiatives include the development of hypersonic weapons, the creation of autonomous drone swarms, and the development of brain-machine interfaces for use in treating neurological disorders. DARPA’s work has had significant impacts on both military and civilian technology, and the agency is seen as a leader in cutting-edge research and development.

    -
    -
    -

    5.6 ClinicalTrials.gov

    -

    ClinicalTrials.gov is a publicly accessible database of clinical trials that are being conducted worldwide. It is maintained by the National Library of Medicine, a part of the National Institutes of Health (NIH) in the United States.

    -

    The database provides information on clinical trials for a wide range of diseases and conditions, including both interventional and observational studies. It includes information about the purpose of the trial, who may participate, where the trial is being conducted, and the status of the trial, such as whether it is recruiting participants or has been completed.

    -

    ClinicalTrials.gov was created in response to a 1997 law requiring the registration of clinical trials for certain serious or life-threatening diseases or conditions. Since then, the database has grown to include information on thousands of trials from around the world.

    -

    ClinicalTrials.gov is an important resource for researchers, healthcare professionals, and members of the public who are interested in clinical research. It can be used to identify ongoing or completed trials, learn about the purpose and design of a study, and find out how to participate in a trial. It also serves as a platform for researchers to share their results and comply with the requirements of various funding agencies and regulatory bodies.

    -
    -
    -

    5.7 GEPRIS

    -

    Geförderte Projekte in der Forschung und Entwicklung (Funded Projects in Research and Development) or GEPRIS is an online database of research projects funded by the German Research Foundation (DFG).

    -

    The DFG is the largest independent research funding organization in Germany and funds projects across all scientific disciplines, from the humanities and social sciences to the natural and life sciences. GEPRIS provides information about the projects that the DFG has funded, including their aims, methods, and outcomes, as well as the institutions and researchers involved.

    -

    Researchers and members of the public can use GEPRIS to search for projects that have been funded by the DFG, and to access information about these projects. The database includes information about ongoing and completed projects, and users can search by various criteria, such as by researcher name, institution, scientific discipline, or project title.

    -

    GEPRIS is a valuable tool for researchers to identify potential collaborators, explore research trends, and find information about the funding landscape in their field. It is also useful for members of the public who are interested in learning about the research being conducted in Germany and the impact of this research on society.

    -
    -
    -

    5.8 EDCTP

    -

    European and Developing Countries Clinical Trials Partnership or EDCTP is a public-public partnership between countries in Europe and sub-Saharan Africa, established in 2003, with the aim of accelerating the development of new clinical interventions to fight infectious diseases that disproportionately affect Africa.

    -

    The partnership’s mission is to improve the health of people in Africa by supporting the development of new medicines, vaccines, and other health interventions to prevent and treat diseases such as HIV/AIDS, tuberculosis, malaria, and neglected infectious diseases. EDCTP supports collaborative research projects that bring together scientists, institutions, and countries from both regions to conduct clinical trials and other research activities.

    -

    EDCTP works with a range of partners, including national governments, research institutions, civil society organizations, and the private sector, to support research that is relevant and responsive to the needs of African communities. It also provides training and capacity-building opportunities to support the development of sustainable health research infrastructure and expertise in Africa.

    -

    The partnership is funded by the European Union, its member states, and other donors. Since its inception, EDCTP has supported over 100 collaborative research projects and played a key role in advancing the development of new interventions for infectious diseases that affect the people of Africa.

    -
    -
    -

    5.9 GLOPID-R

    -

    Global Research Collaboration for Infectious Disease Preparedness or GLOPID-R is an international partnership that aims to strengthen global research efforts in the field of infectious disease preparedness. The partnership was established in response to the 2014 Ebola outbreak in West Africa, which highlighted the need for improved global coordination and collaboration in research and development for emerging and re-emerging infectious diseases.

    -

    GLOPID-R brings together stakeholders from the global health community, including research funders, policy-makers, researchers, and public health organizations. The partnership aims to promote international cooperation and coordination in research to accelerate the development of new tools and approaches to prevent, detect, and respond to infectious disease outbreaks.

    -

    GLOPID-R’s main objectives include identifying research priorities for infectious disease preparedness, coordinating research efforts across different regions and countries, and promoting capacity building and knowledge exchange to strengthen global health research infrastructure.

    -

    The partnership focuses on a range of infectious diseases, including those caused by emerging and re-emerging pathogens, neglected tropical diseases, and antimicrobial resistance. It works to support research efforts across the entire spectrum of infectious disease preparedness, from basic research to clinical trials and implementation research.

    -

    GLOPID-R is supported by a range of funding agencies and partners from around the world and is seen as an important platform for promoting global cooperation and collaboration in infectious disease research and preparedness.

    -
    -
    -

    5.10 NRF South Africa

    -

    The National Research Foundation of South Africa (NRF) is an independent organization that promotes and supports research and innovation in all fields of science, engineering, technology, and social sciences in South Africa. The NRF was established in 1999 through the National Research Foundation Act and operates under the jurisdiction of the Department of Science and Innovation.

    -

    The NRF provides funding, develops policies, and manages research infrastructure to support South African researchers and institutions. It also fosters international collaboration in research, and supports the training and development of the next generation of researchers through various funding and fellowship schemes.

    -

    The NRF provides funding through a number of programs, including competitive grants, fellowships, and research chairs. It also supports the development of research infrastructure and the establishment of research centers of excellence.

    -

    In addition to providing funding and support for research, the NRF plays a key role in developing research policies and strategies at the national level. It advises the South African government on research priorities and is involved in various initiatives aimed at promoting science, technology, and innovation in the country.

    -

    The NRF is an important organization for the South African research community and has been instrumental in advancing the country’s research and innovation capabilities. Its funding and support have contributed to numerous scientific discoveries and innovations in a wide range of fields, including health, energy, and the environment.

    - -
    -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/docs/style.css b/docs/style.css deleted file mode 100644 index f317b43..0000000 --- a/docs/style.css +++ /dev/null @@ -1,14 +0,0 @@ -p.caption { - color: #777; - margin-top: 10px; -} -p code { - white-space: inherit; -} -pre { - word-break: normal; - word-wrap: normal; -} -pre code { - white-space: inherit; -} diff --git a/docs/survey.html b/docs/survey.html deleted file mode 100644 index c77befc..0000000 --- a/docs/survey.html +++ /dev/null @@ -1,294 +0,0 @@ - - - - - - - Chapter 7 Survey | Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -

    Chapter 7 Survey

    - -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/docs/tools.html b/docs/tools.html deleted file mode 100644 index 7c571d1..0000000 --- a/docs/tools.html +++ /dev/null @@ -1,552 +0,0 @@ - - - - - - - Chapter 3 Tools | Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -

    Chapter 3 Tools

    -

    The Research Information Gateway (RIG) is currently using the following set of tools for database development and maintenance.

    -
    -

    3.1 Airtable

    -
    -

    3.1.1 What is Airtable?

    -

    Airtable is a cloud-based software platform that allows users to create and manage databases, spreadsheets, and other types of organizational tools. It can be used for a variety of purposes, including project management, customer relationship management, inventory tracking, event planning, and much more.

    -

    One of the key features of Airtable is its flexible and customizable nature. Users can create and customize their own database structures, and can choose from a wide range of data types, including text, attachments, checkboxes, and more. This allows for a high degree of customization and adaptability to different use cases and workflows.

    -

    Airtable also offers a variety of collaboration features, including real-time syncing and commenting, as well as integrations with other popular tools such as Slack, Google Drive, and Trello. Additionally, Airtable has a robust API that allows developers to build custom integrations and applications on top of the platform.

    -

    Airtable’s flexibility, customizability, and features that support collaboration along with its spreadsheet-style interface that is familiar to most that have used other spreadsheet software such as Microsoft Excel or Google Sheets are the key reasons why it was chosen to be the database tool for RIG.

    -

    This section will provide an overview of Airtable and good practices for designing data models in relational databases.

    -
    -
    -

    3.1.2 Key Terms

    -
      -
    • Workspace - A collection of bases
    • -
    • Base - A database. Each is identified by the Airtable API via a base id
    • -
    • Table - A tabular data set within a base. Each table is identified by the Airtable API via the name of the table e.g. “Demo Table”
    • -
    • Record - An individual cell within a table. Each record is identified by the Airtable API via a record id
    • -
    • Field - A property of data in a table
    • -
    • Views - A specific way of displaying a table. Default is grid.
    • -
    • Entity - Something that either physically or logically exists whose properties are typically stored in a table and composed of data elements.
    • -
    • Element - an attribute of a Entity (a field)
    • -
    -
    -
    -

    3.1.3 Security and Access Control

    -

    Airtable maintains physical and technological security as part of its ISO IEC 27001:2013 and SOC 2 compliance measures. Data are 256-bit encrypted when storing on the server and also when transferring data over the internet. To find vulnerabilities in their software, they run daily, weekly, and monthly scans on different components of their system and regularly commission external penetration tests. They also run a bug bounty program to help identify issues. Their data centers have fire detection and suppression systems, redundant power systems, and strict control for physical access. Because Airtable relies on Amazon Web Services (AWS) for its cloud infrastructure (the same providers used by previous EHA projects), data are geo-redundantly replicated in backups across multiple zones to increase data durability. They also have a team monitoring services at all times. Airtable employees are thoroughly vetted before hiring and continually trained on data protection best practices. Their workstations are secured by using full-disk encryption, automatic locking, and strong password requirements.

    -
    -

    3.1.3.1 User- and Administrator Security Features

    -
    -
    3.1.3.1.1 Access Controls
    -

    Airtable provides database (referred to as “base”) and workspace administrators with granular controls over who can view, edit, comment, or otherwise modify data at the base, table, and field levels. There are four levels of Airtable user permissions:

    -
      -
    • Owner/Creator: Full administrative control of base
      -
    • -
    • Editor: Sees full base, create and modify records and views, create and modify view share links
      -
    • -
    • Commenter: Sees full base, comment on records
      -
    • -
    • Reader: Sees full base
    • -
    -

    Direct access to a base or workspace is granted or removed by base owners and creators to Airtable users. Base owners and creators can control who has access to a base and can control any “share” links created for that base. They may also restrict editing of tables or fields within a base. Any collaborator given direct access to a base at any permission level will be able to duplicate that base and share that data further. It is important that direct access to the base is limited to individuals with a need to curate or analyze the data.

    -
    - -
    -
    -
    -

    3.1.4 Data in Airtable

    -

    See Airtable plan comparison for more information on the size of bases and features available. Information in this section pertains to all plans unless specified.

    -
    -

    3.1.4.1 Workspaces, Bases, Tables, Fields, Records

    -

    Airtable uses workspaces, bases, tables, and fields to manage data. A workspace generally pertains to a particular project and contains all bases relevant to that project. Sharing a workspace with someone allows them to see all bases within that workspace.

    -

    Bases are equivalent to databases. They consist of a set of tables that can be linked and allow you to perform some task (e.g. IRB tracking, capturing research data, etc.). Bases can be duplicated and shared across your workspaces and you can share bases with other users.

    -

    Tables are where most of the action happens. Data is entered in tables, tables can be transformed via views into calendars, dashboards, or galleries, and tables can be manipulated via the API. They describe a data entity and are composed of fields. In the bat sampling example, each circle would be a table in the bat sampling base.

    -

    Fields represent properties of a data entity. In a spreadsheet view, fields are columns. Airtable allows you to control field types (date, number, text, file attachments, logical, etc.) and paid plans allows you to control who can edit fields. Fields can be linked between tables creating links.

    -

    Records are the individual data points in a table. In a spreadsheet they would be the rows. Records are shaped by the structure you have created in tables and fields. Each record has a URL that can be used to access it programatically or share it.

    -
    -
    -
    -

    3.1.5 Views

    -

    In Airtable, tables can be displayed in different views to emphasis different components of the data. Views are great for creating concise presentations of data, especially in sprawling tables. The default view in an table is the grid (spreadsheet) view. All other views will derive from the data entered in this view.

    -

    For more on views, see the guide to views.

    -
    -
    -

    3.1.6 Internal Backups: Record History, Base Snapshots

    -

    Airtable has system for tracking changes to a base. They provide revision history for individual records (how long those histories are stored varies by plan). Any comments made in the revision history will be stored for the life of the record (on any plan). The current state of an entire base may be captured through snapshots. Should a systemic issue arise, the base can be restored to a snapshot at a later date. Restoring from a snapshot will remove the revision history for a record but comments on that record will be maintained.

    -

    As revision histories are maintained, “deleted” records may be retrieved. In the event of the need to permanently remove data, the revision history of the base may be removed.

    -

    Airtable allows data to be exported as CSVs from individual tables. At this time there is not an Airtable supported base export function.

    -
    -
    -

    3.1.7 Importing data

    -

    Data can be imported to Airtable from a number of sources including CSV files, excel, Google sheets, XML, and via copy paste. Airtable will guess what the most appropriate field type is, so make sure the field type is appropriate for the data (e.g. convert from text to date type fields). Certain sources, like Google sheets, can be imported as bases.

    -

    For more on importing data see: Importing and Adding data

    -
    -
    -
    -

    3.2 Base Design

    -

    Having a good base design will make using your data easier. Generally, the process looks like this:

    -
      -
    1. Describe what the database will do and collect use cases
    2. -
    3. Determine the roles of various stakeholders
    4. -
    5. List out the entities in the database and define their properties
    6. -
    7. Map out how the entities fit together (which properties link them)
    8. -
    9. Check that the mapping meets the use cases
    10. -
    11. Build base in Airtable
    12. -
    13. Check that the base meets the use cases
    14. -
    -

    If you are migrating from spreadsheets, you likely already have an idea of what you need the base to do and a collection of data properties. It is still a good idea to follow the steps outlined above for mapping out entities. You may find that entire sheets can be replaced by views or that the data in one sheet should actually be stored in two different tables.

    -

    Feel free to reach out to the data librarian for questions about base design.

    -
    -
    -

    3.3 Automating Airtable

    -

    Airtable has five main routes for automating processes.

    -
      -
    1. Automations - a drag and drop visual programming tool
    2. -
    3. Extensions - pre-built applications that perform some task
    4. -
    5. Scripting - use JavaScript to automate tasks within Airtable
    6. -
    7. Blocks - use JavaScript to create custom applications
    8. -
    9. REST API - use whatever programming language you like to automate processes
    10. -
    -
    -

    3.3.1 Automations with Drag and Drop Programing (pro and above)

    -

    The automations feature within Airtable allows you to visually program routines. Each automation has three basic components:

    -
      -
    • Status - controls whether or not the automation will run when the trigger condition is met
    • -
    • Triggers - condition for automation to run: the creation or change of a record, a scheduled time, or some other external action
    • -
    • Actions - what the automation will do
    • -
    -

    -

    Automations are commonly used to augment the synced tables feature, send notifications, check data quality, and manipulate or create records.

    -

    This automation creates a weekly summary of applicants who applied for a position. Its trigger is time based, then it finds records that match a condition, and finally it generates an email from those records and sends to the appropriate recipients.

    -
    - -

    airtable weekly summary

    -
    -
    -
    -

    3.3.2 Scripting and Blocks (pro plan and above)

    -

    Scripting uses JavaScript to manipulate a base from within an application in Airtable. Scripting is flexible but has a steep learning curve. The scripting environment Airtable provides can be helpful as it provides code linting, direct access to documentation, and example scripts to build from. The major drawback to scripting is that scripts live in the base and files are not version controlled.

    - -

    Blocks are custom applications built in JavaScript and node.js that add to base functionality. They are created in a development environment outside of Airtable then brought back into platform. There are number of tutorials for getting started with blocks.

    -
    -
    -
    -

    3.4 Using the REST API

    -

    All Airtable bases are automatically accessible to authorized users via a REST API. The list of API accessible bases you have access to can be found here: https://airtable.com/api. By clicking on a base you will be able to see the full API documentation for that base.

    -
    -

    3.4.1 Scoped Tokens

    -

    Airtable is moving to a scoped tokens based approach to api access. Scoped personal access tokens allow you to create a token for a specific base with specific permissions - e.g. token has read-only access to a bat sampling base. Using scoped tokens in this way means that if the token is compromised (leaked, stolen, accidentally committed unencrypted to a github repo, etc), you can delete that token to remove any access it might have had and the limited scope means that you know exactly what a person would have been able to access.

    -

    To create a personal access token go here: https://airtable.com/create/tokens

    -

    ** Remember to save the token in a secure place. Do not store unencrypted tokens on the web (e.g. pushing them to github).

    -

    Airtable has also deployed oauth tokens for all users.

    -
    -
    -

    3.4.2 Airtable and R

    -

    The Airtable REST API can be used via R with the airtabler package. EHA has started a fork of the package that has additional functionality so it is recommended to use that version. The original package design works well for exploring the data. Our extension adds additional functionality to help use airtabler in automation via continuous integration such as GitHub Actions.

    -
    devtools::install_github("ecohealthalliance/airtabler")
    -

    The Airtable API serves up data as JSON, which has a hierarchical structure similar to a list in R. To handle JSON, airtabler uses the jsonlite package. Its helpful to understand how jsonlite handles different JSON structures when working with more complicated Airtable data. See the jsonlite quick-start guide for a basic overview. The purr package is extremely helpful when dealing with data objects derived from JSON because it facilitates navigating nested data structures.

    -

    The airtabler package provides instructions for setting up access to the Airtable API. You will need to follow those instructions for the following examples to work.

    -

    One to One join

    -
    library(airtabler)
    -
    -table1  <-  fetch_all(base = "app49bbyLczZxX9PM",table_name = "One To One")
    -
    -table2 <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "Table 2")
    -
    -## Linked records are stored as JSON arrays so they become lists 
    -## when part of a data frame. Because each array has a length of 1
    -## we can safely unlist the arrays and add them back as to the 
    -## data frame.
    -
    -table1$LinkedRec <- unlist(table1$LinkedRec)
    -
    -joinedTables <- dplyr::left_join(table1,table2, by = c("LinkedRec"="id"))
    -
    -recordKey <- joinedTables[c("Name","LinkedRec","Number")]
    -
    -recordKey
    -
    -
    -

    One to Many Join

    -
    library(airtabler)
    -library(dplyr)
    -library(purrr)
    -
    -oneToMany  <-  fetch_all(base = "app49bbyLczZxX9PM",table_name = "One To Many")
    -
    -table2 <- fetch_all(base = "app49bbyLczZxX9PM",table_name = "Table 2")
    -
    -# Depending on how you want to work with the data joins are a 
    -# little trickier here. 
    -
    -## to replace the values but keep the structure
    -
    -oneToMany$LinkedRecReplace <- purrr::map(oneToMany$LinkedRec, function(x){
    -  table2 %>%
    -    filter(id %in% x) %>%
    -    select(c("id","Number")) %>% 
    -    pull("Number")
    -})
    -
    -data.frame(
    -  id = unlist(oneToMany$LinkedRec), 
    -  label = unlist(oneToMany$LinkedRecReplace)
    -)
    -
    -
    -
    -
    -

    3.5 Data Management

    -

    Because of its flexibility and ease of use, it is extremely important that data -management for airtable be taken seriously. Unlike most other relational databases, -the fundamental properties of your base can be changed easily by multiple users -without warning! Documenting the structure and purpose of your base, as well -as creating regular external backups could save you from catastrophe.

    -
    -

    3.5.1 Metadata

    -
      -
    • Structural metadata - Information about a resource that tells you how its -put together - e.g. the relationship between a table, field, and automation. With -the exception of users on the enterprise plan, you must be deliberate about -creating and maintaining structural metadata for your base.
    • -
    -

    Example of Airtable Structural Metadata: -

    -
      -
    • Descriptive metadata - Information about a resource that makes it easier to -find and attribute data. This includes things attributes like author, title, description, -keywords, etc. This table becomes especially important when data are transitioned -out of airtable, at the end of a project, or if the base will be shared broadly -with collaborators.
    • -
    -

    Example of Airtable Descriptive Metadata: -

    -

    To see the template base, follow this link

    -
    -

    3.5.1.1 Metadata for automations and extensions

    -

    Automations and extensions live entirely inside airtable. As of August 2022, Airtable introduced a “Manage Fields” tab that provides metadata for a specific table, including any automation dependencies. It is not possible to export those dependency tables or the code used in automations automatically. This makes it extremely important to document any automations and extensions outside your base.

    -
    -
    -
    -

    3.5.2 External Backups

    -

    It is a good idea to create regular external backups of airtable data in the event -that something catastrophic happens to your base or you simply decide you no longer wish -to use airtable as your data store.Unfortunately, airtable does not provide an -off the shelf solution for this. Below are three options for extracting all data -from your base.

    -
    -

    3.5.2.1 Using airtabler

    -

    Using airtabler::air_dump() and airtabler::air_dump_to_csv() functions, you can export all tables to R then create a versioned folder of CSVs. See the air_dump_to_csv help page for more information.

    -
    -
    -

    3.5.2.2 Other Open Source Projects

    -

    UnlyEd - use this template to push airtable backups to AWS S3.

    - -
    - -
    -
    -
    -

    3.6 R

    -

    R is a free and open-source programming language and software environment for statistical computing and graphics. It was first developed in the early 1990s by Ross Ihaka and Robert Gentleman at the University of Auckland, New Zealand, and is now widely used by statisticians, data analysts, and researchers across various fields.

    -

    R provides a wide range of statistical and graphical techniques, including linear and nonlinear modeling, classical statistical tests, time-series analysis, classification, clustering, and more. It also has a large and active community of users and developers who contribute to the development of new packages and extensions for the language.

    -

    R is popular in the field of data science, as it provides a powerful and flexible platform for analyzing and visualizing data. It can be used in conjuction with other tools such as Airtable through community-developed packages making it particularly well-suited for the current use-case of the RIG.

    - -
    -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/docs/updates.html b/docs/updates.html deleted file mode 100644 index 5afd2cf..0000000 --- a/docs/updates.html +++ /dev/null @@ -1,533 +0,0 @@ - - - - - - - Chapter 6 Updates | Research Information Gateway Handbook - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -

    Chapter 6 Updates

    -

    The current update process of the RIG database is summarised in this workflow:

    -

    -

    Following are the source-specific process of updating or retrieving information for the RIG database.

    -
    -

    6.1 Wellcome Trust Grant Funding Data

    -
    -

    6.1.1 General Information

    -

    Using the downloadable spreadsheet of funds awarded between 01st of October 2005 and 4th of May 2022 found at https://cms.wellcome.org/sites/default/files/2022-05/Wellcome-grants-awarded-1-October-2005-to-04-05-2022.xlsx, the following steps were taken to retrieve relevant information for the database:

    -
    -
    -

    6.1.2 How to update

    -

    Please note that the steps below were done using the current available spreadsheet from the Wellcome Trust website and added the relevant projects to the RIG database. These steps can therefore be used as a guide for how to update the database with new information in the future to when the Wellcome Trust publishes its most up-to-date spreadsheet.

    -
      -
    1. Go to column J – Recipient Org:Country -> deselect all and then select all the African countries in the list

    2. -
    3. Go to column N – Planned end date -> select all the years in the future

    4. -
    5. These two steps reduced the list from 19,833 projects to 111 projects

    6. -
    7. Read the project title and decide if the project is relevant for our database or not

    8. -
    9. If unsure, read the abstract – that also helps to identify the keywords to tag the project within our database

    10. -
    11. If the project is relevant transfer all the information into our database

    12. -
    -

    Note: This method is only able to detect projects/activities where an African organisation itself holds the grant. It does not detect projects where African researchers are involved as collaborators. The spreadsheet does not list collaborators on projects, so it’s yet to be determined how we will identify projects on which African research institutes collaborate with international organisations being awarded the grant.

    -
    -
    -
    -

    6.2 ClinicalTrials.gov

    -
    -

    6.2.1 How to update

    -

    Following are steps taken to extract data from ClinicalTrials.gov.

    -
      -
    1. Start with searching a disease/topic of interest
    2. -
    -

    -
      -
    1. On the results page apply the following filters to look for active studies
    2. -
    -

    -
      -
    1. Click on ‘Apply’ and then look manually through the column ‘Locations’ of the list of the results to find studies that take place in African countries
    2. -
    -

    -
      -
    1. Click on the first study to start working your way through the information available

    2. -
    3. The first information provided is the sponsor -> this information should be added to the Funder – column in the Activities table

    4. -
    5. Information about collaborators can be added to Collaborators column

    6. -
    -

    -
      -
    1. Staying in the ‘Study Details’-tab, scroll down to ‘Study Design’

    2. -
    3. This section contains the official title, which should be used as the name for the Activity

    4. -
    5. Additionally it contains information about the start and end date, which should be copied into the respective fields in the Activities table

    6. -
    -

    -
      -
    1. Scroll further down to ‘Contact and Locations’

    2. -
    3. The information given under contacts should be added to the Researcher column in Airtable

    4. -
    5. Switching into the Researcher-table within in Airtable the given contact details should be added to the newly created entries for the involved researchers

    6. -
    7. Also the affiliation to a certain institute can be added based on these information as well as the researcher’s location -> is it possible to link the Location with the Affiliation so that the location is automatically added based on the information about the institution the researcher is affiliated with?

    8. -
    9. Switch back into the Activities table and add information about the Locations to the Activity Location and the Institutions columns

    10. -
    -

    -
      -
    1. Scroll up again to the selection of tabs

    2. -
    3. Click on the Results tab -> it’s worth checking this tab even when it’s called No Results Posted as it might still contain links to publications that are affiliated with the study

    4. -
    5. These links can be copied into the Published Work column in the Activities table

    6. -
    -

    -
      -
    1. I also copied the link of the study page on clinicaltrials.gov into the Activity Website column
    2. -
    -

    -
      -
    1. to determine the Research Field, I had to use my own understanding of the study so I am not sure if this can be automated or rather needs to be done by a database librarian
    2. -
    -
    -
    -
    -

    6.3 Public journal/research databases

    -

    In order to aid in automation, maintain a list relevant search terms for each topic of interest (stored in the “Topics” table in Airtable). Even if the terms are not used for the purposes of developing a search strategy, they can be used by those who are not subject matter experts when collection information on a specific topic

    - -
    -

    6.3.2 Example of PubMed search for surveillance activities for Brucellosis:

    -
    ("surveillance"[Title/Abstract] OR "prevalence"[Title/Abstract] OR "monitoring"[Title/Abstract] OR "seropositive"[Title/Abstract] OR "seroprevalence"[Title/Abstract] OR "seroevidence"[Title/Abstract] OR "screened"[Title/Abstract] OR "biosurveillance"[Title/Abstract] OR "sampl*"[Title/Abstract]) AND (brucellosis[Title/Abstract] OR "Brucella melitensis"[Title/Abstract] OR "B. melitensis"[Title/Abstract] OR "Brucella abortus"[Title/Abstract] OR "B. abortus"[Title/Abstract])  
    -

    This search yielded a large quantity of results, not all of which were relevant. Manual processes are required to validate results.

    -

    Including terms to filter the results based on location were helpful, but still included results not located on the African continent. Search term to filter for African countries:

    -
    (Djibouti[Title/Abstract] OR Seychelles[Title/Abstract] OR DR Congo[Title/Abstract] OR Comoros[Title/Abstract] OR Togo[Title/Abstract] OR Sierra Leone[Title/Abstract] OR Libya[Title/Abstract] OR Tanzania[Title/Abstract] OR South Africa[Title/Abstract] OR Cabo Verde[Title/Abstract] OR Congo[Title/Abstract] OR Kenya[Title/Abstract] OR Liberia[Title/Abstract] OR Central African Republic[Title/Abstract] OR Mauritania[Title/Abstract] OR Uganda[Title/Abstract] OR Algeria[Title/Abstract] OR Sudan[Title/Abstract] OR Morocco[Title/Abstract] OR Eritrea[Title/Abstract] OR Angola[Title/Abstract] OR Mozambique[Title/Abstract] OR Ghana[Title/Abstract] OR Madagascar[Title/Abstract] OR Cameroon[Title/Abstract] OR Côte d'Ivoire[Title/Abstract] OR Namibia[Title/Abstract] OR Niger[Title/Abstract] OR Gambia[Title/Abstract] OR Botswana[Title/Abstract] OR Gabon[Title/Abstract] OR Sao Tome & Principe[Title/Abstract] OR Lesotho[Title/Abstract] OR Burkina Faso[Title/Abstract] OR Nigeria[Title/Abstract] OR Mali[Title/Abstract] OR Guinea-Bissau[Title/Abstract] OR Malawi[Title/Abstract] OR Zambia[Title/Abstract] OR Senegal[Title/Abstract] OR Chad[Title/Abstract] OR Somalia[Title/Abstract] OR Zimbabwe[Title/Abstract] OR Equatorial Guinea[Title/Abstract] OR Guinea[Title/Abstract] OR Rwanda[Title/Abstract] OR Mauritius[Title/Abstract] OR Benin[Title/Abstract] OR Burundi[Title/Abstract] OR Tunisia[Title/Abstract] OR Eswatini[Title/Abstract] OR Ethiopia[Title/Abstract] OR South Sudan[Title/Abstract] OR Egypt[Title/Abstract]) 
    -

    From publications, can extract researchers, institutions, funders, activities. Ideally, researchers, institutions, and funders can be extracted automatically as opposed to manually, but scripts would need to be customized for each journal.

    -
    -
    -

    6.3.3 Validation of results

    -

    Validation of results can be useful to better understand the overlap between publications and activities and determine the priority of searching through publications vs. navigating to institution sites directly (or other strategies).

    -

    After finding a relevant publication, look at the publication’s authors and their respective institutions

    -

    Navigate to institutions’ sites to search for publications or results from research

    -

    Are their activities listed on the site? Are those activities explicitly mentioned in the publications? Etc.

    -
    -
    -

    6.3.4 Some relevant journals/databases:

    - -
    -
    -
    -

    6.4 GEPRIS

    -
    -

    6.4.1 General Information:

    -

    GEPRIS is a database listing all projects funded by the German Research Foundation (German: Deutsche Forschungsgemeinschaft; abbr. DFG) The DFG is a research funding organisation, which functions as a self-governing institution for the promotion of science and research in the Federal Republic Germany. In 2019, the DFG had a funding budget of €3.3 billion.

    -
    -
    -

    6.4.2 How to Use:

    -

    The database can be accessed here: https://gepris.dfg.de/gepris/OCTOPUS?language=en&task=showSearchSimple

    -

    This link should directly lead to the English version of the website, otherwise the language can be changed by clicking on English in the top right corner.

    -
      -
    • In the database one can search for Projects, People, or Institutions – for our purpose the project option is the most relevant

    • -
    • One can either search for keywords or filter for different criteria – for a systematic approach I found using the filtering options easier than going through all our

    • -
    -
      -
    1. On the search start site stay in the Projects tab.

    2. -
    3. Click on Show extended search.

    4. -
    5. Under Subject Area select one of the following:

      -
        -
      • Agriculture, Forestry and Veterinary Medicine

      • -
      • Basic Research in Biology and Medicine

      • -
      • Medicine

      • -
      • Microbiology, Virology, and Immunology

      • -
      • Social Sciences

      • -
      • Water Research

      • -
      • Zoology

      • -
    6. -
    -

    Note: After working through all these subject areas, any relevant project in the field of One Health should be picked up by the searches

    -
      -
    1. Leave everything under DFG Programme as it is

    2. -
    3. Move on to Funding and change Status to Current

    4. -
    5. Move on to International and change Continent to Africa

    6. -
    7. Click on Find

    8. -
    9. Read through the project titles on the results page to identify relevant projects

    10. -
    11. Import all the relevant project information (as highlighted on the screenshots) into the Africa CDC database

    12. -
    -

    -

    -
      -
    1. To identify the research institutes that are involved in the project one has to click on the researchers names and extract that information from their profile (their affiliation with a research institute is listed there)
    2. -
    -
    -
    -

    6.4.3 Positive aspects of this source:

    -

    The filtering options allow to filter for several criteria which are crucial for the relevance of a project to our database. That removes a lot of irrelevant projects from the results pages. The project pages list almost all the information we are interested in.

    -
    -
    -

    6.4.4 Downsides of this source:

    -

    The project page doesn’t list the anticipated end date of a project.

    -

    One has to click on the link to the researcher’s profile to identify the participating organisations.

    -

    Even using all the different filtering options not all resulting hits are relevant for our database, so I don’t think the process can be fully automated or at least requires a subsequent manual validation or clean up step to remove irrelevant projects.

    -
    -
    -
    -

    6.5 EDCTP

    -
    -

    6.5.1 General Information

    -

    The European & Developing Countries Clinical Trials Partnership (EDCTP) is a non-profit organisation with a European office in The Hague, The Netherlands and an African office in Cape Town, South Africa. EDCTP is a partnership between European Union (EU), Norway, Switzerland, and African countries to accelerate the development of new clinical interventions such as drugs, vaccines, microbicides, and diagnostics against poverty-related diseases in Africa. The organisation supports clinical trials, capacity strengthening and networking in Africa and Europe. Funding comes from the EU, member states, pharmaceutical industry and private organisations and charities like The Wellcome Trust and The Bill & Melinda Gates foundation.

    -

    Note: Since funding comes from several sources that we also list as sources for populating the database such as the European Union (European Commission), The Wellcome Trust and The Bill & Melinda Gates Foundation, there is the possibility that downloading project information from all these sources into our database could lead to duplicate entries. I created a column in the Actvities table for the Project ID, as this might be helpful to identify duplicates and remove them automatically.

    -
    -
    -

    6.5.2 How to use:

    -

    The database of funded project can be accessed here: https://www.edctp.org/edctp2-project-portal/

    -

    There is the option to download the list of projects as a PDF, CSV or XLXS file. Personally, I did not find that helpful for manually adding projects to the database, but it might be useful for an automated process.

    -
      -
    1. Go to Status of Project and select the filter Active

    2. -
    3. Go to Classification and select one of the following filters:

      -
        -
      • Co-Infections
      • -
      • COVID-19
      • -
      • Cysticercosis/Taeniasis
        -
      • -
      • Diagnostics
      • -
      • Diarrhoeal Diseases
      • -
      • Drugs
      • -
      • Emerging Infections, incl. Ebola, Lassa
      • -
      • Epidemiology
      • -
      • HIV
      • -
      • Human African trypanosomiasis (sleeping sickness)
        -
      • -
      • Implementation Research
        -
      • -
      • Leishmaniases
      • -
      • Leprosy (Hansen disease)
      • -
      • Lower respiratory infections
        -
      • -
      • Lymphatic filariasis
      • -
      • Malaria
      • -
      • Microbicides
      • -
      • Onchocerciasis (river blindness)
      • -
      • Rabies
      • -
      • Schistosomiasis
      • -
      • Soil-transmitted helminthiasis
        -
      • -
      • Social Science
      • -
      • Tuberculosis
      • -
      • Vaccines
      • -
      • Yaws
      • -
      • Yellow Fever
      • -
    4. -
    -

    Note: Only one Classification at a time can be selected

    -
      -
    1. Once one Classification was selected click on search

    2. -
    3. Change from Show Map to Show List -> this makes it easier to systematically look through the projects

    4. -
    5. On the results list you can see the location of the coordinating organisation, but even if it is not in an African country, it is worth checking the project details for the Participating Organisations. So read the project title and decide whether this could be a relevant project, if so, click on View details

    6. -
    -

    -
      -
    1. Check the Participating Organisations first to decide whether the project is relevant to our database:
    2. -
    -

    -
      -
    1. If the project is relevant use the Project Name + Acronym for the Activity Column

    2. -
    3. Transfer all the relevant information to our database, including Project ID, Start and End date, Participating Organisations and corresponding locations, Project Website, Coordinating Organisation and Coordinating Researcher

    4. -
    5. Tag the project with the correct keywords in the Activity Type, Activity Outputs, Target Species, Topic, and Research Field columns based on your understanding of the project abstract

    6. -
    -
    -
    -

    6.5.3 Benefits of this Source:

    -

    The projects can be easily filtered for currently active projects.

    -

    The EDCTP is specifically focused on projects in Africa or Europe with African collaborators so most projects fulfil at least one of our selection criteria

    -

    A lot of the projects (not all) are also topic-wise relevant for our database

    -

    The database lists most of the information that we are interested in for our database

    -
    -
    -

    6.5.4 Shortcomings of this source:

    -

    Only one disease/topic can be selected at a time so sequential searches are necessary

    -

    Project details only list the Coordinating researcher but no other lead researchers at the participating organisations

    - -
    -
    -
    -
    - -
    -
    -
    - - -
    -
    - - - - - - - - - - - - - diff --git a/images/AfricaCDC_Logo.png b/images/AfricaCDC_Logo.png new file mode 100644 index 0000000..661b091 Binary files /dev/null and b/images/AfricaCDC_Logo.png differ diff --git a/images/eha_logo.png b/images/eha_logo.png new file mode 100644 index 0000000..790d0d4 Binary files /dev/null and b/images/eha_logo.png differ diff --git a/index.Rmd b/index.Rmd deleted file mode 100644 index 4c4855a..0000000 --- a/index.Rmd +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Research Information Gateway Handbook" -author: "EcoHealth Alliance" -date: "`r Sys.Date()`" -site: bookdown::bookdown_site -documentclass: book -bibliography: [book.bib] -# url: your book url like https://bookdown.org/yihui/bookdown -# cover-image: path to the social sharing image like images/cover.jpg -description: | - This is a handbook created as a guide for the development and maintenance of - a One Health Research Information Gateway. -link-citations: yes -github-repo: ecohealthalliance/rig-handbook ---- - -```{r setup, include = FALSE} -knitr::opts_chunk$set( - message = FALSE, - warning = FALSE, - echo = FALSE -) - -library(dplyr) -library(here) -library(airtabler) -library(kableExtra) - -for (f in list.files(here::here("R"), full.names = TRUE)) source (f) - -airtable_metadata <- airtable( - base = Sys.getenv("AIRTABLE_ACDC"), - tables = "Meta Data" -)$`Meta Data`$select() -``` - -# About - -This is a handbook created as a how-to manual for the development and maintenance of a One Health Research Information Gateway for the African continent. - - - - diff --git a/01-introduction.Rmd b/index.qmd similarity index 75% rename from 01-introduction.Rmd rename to index.qmd index 85f2e83..93c719f 100644 --- a/01-introduction.Rmd +++ b/index.qmd @@ -1,3 +1,22 @@ +```{r setup, include = FALSE} +library(quarto) +library(dplyr) +library(here) +library(airtabler) +library(kableExtra) + +for (f in list.files(here::here("R"), full.names = TRUE)) source (f) + +airtable_metadata <- airtable( + base = "appAL7fJUpBPYtOq4", + tables = "Meta Data" +)$`Meta Data`$select() +``` + # Introduction {#introduction} +This is a handbook created as a how-to manual for the development and maintenance of a One Health Research Information Gateway for the African continent. + +## About the database {#about-database} + [EcoHelth Alliance](https://www.ecohealthalliance.org/) is supporting the creation of a database of active infectious disease research activities and research scientists in Africa. The database contains information about scientific research being conducted on the African continent that has particular relevance to understanding, detecting and responding to zoonotic pathogens. EHA is building a detailed, searchable, and visual database (e.g. via a dashboard) populated with information about major (e.g. multi-year) and active One Health research projects that includes subject matter, duration, geographical locations, key personnel, and links to publicly available reports, preprints and publications relevant to zoonoses. Examples of research areas may include epidemiological (syndrome based or disease specific), ecological (studies looking at potential reservoirs or animal hosts for zoonotic pathogens and spillover into humans or livestock); basic science (e.g. virology, bacteriology; serology); clinical (vaccine or therapeutic trials); or sociological (e.g. behavioral risk assessments or behavioral intervention studies) or any other preliminary public health findings. A particularly important view within the database includes a directory of subject matter experts associated with research across the continent. This roster view can be used by public health practitioners to engage expert consultations as needed to support training activities, surveillance or outbreak response, for example. diff --git a/renv.lock b/renv.lock new file mode 100644 index 0000000..8fe1176 --- /dev/null +++ b/renv.lock @@ -0,0 +1,1209 @@ +{ + "R": { + "Version": "4.4.2", + "Repositories": [ + { + "Name": "P3M", + "URL": "https://packagemanager.posit.co/cran/latest" + }, + { + "Name": "CRAN", + "URL": "https://cloud.r-project.org" + } + ] + }, + "Packages": { + "MASS": { + "Package": "MASS", + "Version": "7.3-61", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "methods", + "stats", + "utils" + ], + "Hash": "0cafd6f0500e5deba33be22c46bf6055" + }, + "Matrix": { + "Package": "Matrix", + "Version": "1.7-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "lattice", + "methods", + "stats", + "utils" + ], + "Hash": "5122bb14d8736372411f955e1b16bc8a" + }, + "R6": { + "Package": "R6", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "470851b6d5d0ac559e9d01bb352b4021" + }, + "RColorBrewer": { + "Package": "RColorBrewer", + "Version": "1.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "45f0398006e83a5b10b72a90663d8d8c" + }, + "Rcpp": { + "Package": "Rcpp", + "Version": "1.0.13-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods", + "utils" + ], + "Hash": "6b868847b365672d6c1677b1608da9ed" + }, + "V8": { + "Package": "V8", + "Version": "6.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "Rcpp", + "curl", + "jsonlite", + "utils" + ], + "Hash": "6603bfcbc7883a5fed41fb13042a3899" + }, + "airtabler": { + "Package": "airtabler", + "Version": "0.2.16", + "Source": "GitHub", + "RemoteType": "github", + "RemoteHost": "api.github.com", + "RemoteUsername": "ecohealthalliance", + "RemoteRepo": "airtabler", + "RemoteRef": "master", + "RemoteSha": "a4028cd5f8a80d73ce07b3de049e0f98777b59cc", + "Remotes": "ropenscilabs/deposits", + "Requirements": [ + "R", + "assertthat", + "curl", + "deposits", + "dplyr", + "glue", + "httr", + "jsonlite", + "purrr", + "readxl", + "rlang", + "snakecase", + "stringr", + "tibble", + "tidyselect", + "utils" + ], + "Hash": "b444a4419bd89e05e3c37d333224a1bd" + }, + "askpass": { + "Package": "askpass", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "sys" + ], + "Hash": "c39f4155b3ceb1a9a2799d700fbd4b6a" + }, + "assertthat": { + "Package": "assertthat", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "tools" + ], + "Hash": "50c838a310445e954bc13f26f26a6ecf" + }, + "backports": { + "Package": "backports", + "Version": "1.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "e1e1b9d75c37401117b636b7ae50827a" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "543776ae6848fde2f48ff3816d0628bc" + }, + "bookdown": { + "Package": "bookdown", + "Version": "0.40", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "htmltools", + "jquerylib", + "knitr", + "rmarkdown", + "tinytex", + "xfun", + "yaml" + ], + "Hash": "896a79478a50c78fb035a37148638f4e" + }, + "bslib": { + "Package": "bslib", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cachem", + "fastmap", + "grDevices", + "htmltools", + "jquerylib", + "jsonlite", + "lifecycle", + "memoise", + "mime", + "rlang", + "sass" + ], + "Hash": "b299c6741ca9746fb227debcb0f9fb6c" + }, + "cachem": { + "Package": "cachem", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "fastmap", + "rlang" + ], + "Hash": "cd9a672193789068eb5a2aad65a0dedf" + }, + "cellranger": { + "Package": "cellranger", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "rematch", + "tibble" + ], + "Hash": "f61dbaec772ccd2e17705c1e872e9e7c" + }, + "checkmate": { + "Package": "checkmate", + "Version": "2.3.2", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "backports", + "utils" + ], + "Hash": "0e14e01ce07e7c88fd25de6d4260d26b" + }, + "cli": { + "Package": "cli", + "Version": "3.6.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "utils" + ], + "Hash": "b21916dd77a27642b447374a5d30ecf3" + }, + "colorspace": { + "Package": "colorspace", + "Version": "2.1-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "methods", + "stats" + ], + "Hash": "d954cb1c57e8d8b756165d7ba18aa55a" + }, + "cpp11": { + "Package": "cpp11", + "Version": "0.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "91570bba75d0c9d3f1040c835cee8fba" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "859d96e65ef198fd43e82b9628d593ef" + }, + "curl": { + "Package": "curl", + "Version": "6.0.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R" + ], + "Hash": "e8ba62486230951fcd2b881c5be23f96" + }, + "deposits": { + "Package": "deposits", + "Version": "0.2.1.061", + "Source": "GitHub", + "RemoteType": "github", + "RemoteHost": "api.github.com", + "RemoteUsername": "ropenscilabs", + "RemoteRepo": "deposits", + "RemoteRef": "main", + "RemoteSha": "3495041f03c4d29c58f392cb46e7a621aeece0c6", + "Requirements": [ + "R6", + "checkmate", + "fs", + "here", + "httr2", + "jsonlite", + "jsonvalidate", + "methods", + "withr", + "xml2" + ], + "Hash": "12aa333f6dbac59f8bd180a8c0a658f6" + }, + "digest": { + "Package": "digest", + "Version": "0.6.37", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "33698c4b3127fc9f506654607fb73676" + }, + "dplyr": { + "Package": "dplyr", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "generics", + "glue", + "lifecycle", + "magrittr", + "methods", + "pillar", + "rlang", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "fedd9d00c2944ff00a0e2696ccf048ec" + }, + "evaluate": { + "Package": "evaluate", + "Version": "1.0.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R" + ], + "Hash": "6b567375113ceb7d9f800de4dd42218e" + }, + "fansi": { + "Package": "fansi", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "utils" + ], + "Hash": "962174cf2aeb5b9eea581522286a911f" + }, + "farver": { + "Package": "farver", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "680887028577f3fa2a81e410ed0d6e42" + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "aa5e1cd11c2d15497494c5292d7ffcc8" + }, + "fontawesome": { + "Package": "fontawesome", + "Version": "0.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "htmltools", + "rlang" + ], + "Hash": "c2efdd5f0bcd1ea861c2d4e2a883a67d" + }, + "fs": { + "Package": "fs", + "Version": "1.6.5", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "methods" + ], + "Hash": "7f48af39fa27711ea5fbd183b399920d" + }, + "generics": { + "Package": "generics", + "Version": "0.1.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "15e9634c0fcd294799e9b2e929ed1b86" + }, + "ggplot2": { + "Package": "ggplot2", + "Version": "3.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "MASS", + "R", + "cli", + "glue", + "grDevices", + "grid", + "gtable", + "isoband", + "lifecycle", + "mgcv", + "rlang", + "scales", + "stats", + "tibble", + "vctrs", + "withr" + ], + "Hash": "44c6a2f8202d5b7e878ea274b1092426" + }, + "glue": { + "Package": "glue", + "Version": "1.8.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "methods" + ], + "Hash": "5899f1eaa825580172bb56c08266f37c" + }, + "gtable": { + "Package": "gtable", + "Version": "0.3.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "grid", + "lifecycle", + "rlang" + ], + "Hash": "e18861963cbc65a27736e02b3cd3c4a0" + }, + "here": { + "Package": "here", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "rprojroot" + ], + "Hash": "24b224366f9c2e7534d2344d10d59211" + }, + "highr": { + "Package": "highr", + "Version": "0.11", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "xfun" + ], + "Hash": "d65ba49117ca223614f71b60d85b8ab7" + }, + "hms": { + "Package": "hms", + "Version": "1.1.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "lifecycle", + "methods", + "pkgconfig", + "rlang", + "vctrs" + ], + "Hash": "b59377caa7ed00fa41808342002138f9" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.8.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "digest", + "fastmap", + "grDevices", + "rlang", + "utils" + ], + "Hash": "81d371a9cc60640e74e4ab6ac46dcedc" + }, + "httr": { + "Package": "httr", + "Version": "1.4.7", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "R6", + "curl", + "jsonlite", + "mime", + "openssl" + ], + "Hash": "ac107251d9d9fd72f0ca8049988f1d7f" + }, + "httr2": { + "Package": "httr2", + "Version": "1.0.7", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "R6", + "cli", + "curl", + "glue", + "lifecycle", + "magrittr", + "openssl", + "rappdirs", + "rlang", + "vctrs", + "withr" + ], + "Hash": "5a76da345ed4f3e6430517e08441edaf" + }, + "isoband": { + "Package": "isoband", + "Version": "0.2.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grid", + "utils" + ], + "Hash": "0080607b4a1a7b28979aecef976d8bc2" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "1.8.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods" + ], + "Hash": "4e993b65c2c3ffbffce7bb3e2c6f832b" + }, + "jsonvalidate": { + "Package": "jsonvalidate", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "V8" + ], + "Hash": "cdc2843ef7f44f157198bb99aea7552d" + }, + "kableExtra": { + "Package": "kableExtra", + "Version": "1.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "digest", + "grDevices", + "graphics", + "htmltools", + "knitr", + "magrittr", + "rmarkdown", + "rstudioapi", + "scales", + "stats", + "stringr", + "svglite", + "tools", + "viridisLite", + "xml2" + ], + "Hash": "532d16304274c23c8563f94b79351c86" + }, + "knitr": { + "Package": "knitr", + "Version": "1.48", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "evaluate", + "highr", + "methods", + "tools", + "xfun", + "yaml" + ], + "Hash": "acf380f300c721da9fde7df115a5f86f" + }, + "labeling": { + "Package": "labeling", + "Version": "0.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "graphics", + "stats" + ], + "Hash": "b64ec208ac5bc1852b285f665d6368b3" + }, + "later": { + "Package": "later", + "Version": "1.4.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "Rcpp", + "rlang" + ], + "Hash": "501744395cac0bab0fbcfab9375ae92c" + }, + "lattice": { + "Package": "lattice", + "Version": "0.22-6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "grid", + "stats", + "utils" + ], + "Hash": "cc5ac1ba4c238c7ca9fa6a87ca11a7e2" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "rlang" + ], + "Hash": "b8552d117e1b808b09a832f589b79035" + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "7ce2733a9826b3aeb1775d56fd305472" + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cachem", + "rlang" + ], + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" + }, + "mgcv": { + "Package": "mgcv", + "Version": "1.9-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "Matrix", + "R", + "graphics", + "methods", + "nlme", + "splines", + "stats", + "utils" + ], + "Hash": "110ee9d83b496279960e162ac97764ce" + }, + "mime": { + "Package": "mime", + "Version": "0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "tools" + ], + "Hash": "18e9c28c1d3ca1560ce30658b22ce104" + }, + "munsell": { + "Package": "munsell", + "Version": "0.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "colorspace", + "methods" + ], + "Hash": "4fd8900853b746af55b81fda99da7695" + }, + "nlme": { + "Package": "nlme", + "Version": "3.1-166", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "graphics", + "lattice", + "stats", + "utils" + ], + "Hash": "ccbb8846be320b627e6aa2b4616a2ded" + }, + "openssl": { + "Package": "openssl", + "Version": "2.2.2", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "askpass" + ], + "Hash": "d413e0fef796c9401a4419485f709ca1" + }, + "pillar": { + "Package": "pillar", + "Version": "1.9.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cli", + "fansi", + "glue", + "lifecycle", + "rlang", + "utf8", + "utils", + "vctrs" + ], + "Hash": "15da5a8412f317beeee6175fbc76f4bb" + }, + "pkgconfig": { + "Package": "pkgconfig", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "01f28d4278f15c76cddbea05899c5d6f" + }, + "prettyunits": { + "Package": "prettyunits", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "6b01fc98b1e86c4f705ce9dcfd2f57c7" + }, + "processx": { + "Package": "processx", + "Version": "3.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "ps", + "utils" + ], + "Hash": "0c90a7d71988856bad2a2a45dd871bb9" + }, + "progress": { + "Package": "progress", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "crayon", + "hms", + "prettyunits" + ], + "Hash": "f4625e061cb2865f111b47ff163a5ca6" + }, + "ps": { + "Package": "ps", + "Version": "1.8.1", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "utils" + ], + "Hash": "b4404b1de13758dea1c0484ad0d48563" + }, + "purrr": { + "Package": "purrr", + "Version": "1.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "rlang", + "vctrs" + ], + "Hash": "1cba04a4e9414bdefc9dcaa99649a8dc" + }, + "quarto": { + "Package": "quarto", + "Version": "1.4.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "jsonlite", + "later", + "processx", + "rlang", + "rmarkdown", + "rstudioapi", + "tools", + "utils", + "yaml" + ], + "Hash": "af456d7a181750812bd8b2bfedb3ea4e" + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5e3c5dc0b071b21fa128676560dbe94d" + }, + "readxl": { + "Package": "readxl", + "Version": "1.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cellranger", + "cpp11", + "progress", + "tibble", + "utils" + ], + "Hash": "8cf9c239b96df1bbb133b74aef77ad0a" + }, + "rematch": { + "Package": "rematch", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "cbff1b666c6fa6d21202f07e2318d4f1" + }, + "renv": { + "Package": "renv", + "Version": "1.0.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "397b7b2a265bc5a7a06852524dabae20" + }, + "rlang": { + "Package": "rlang", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "utils" + ], + "Hash": "3eec01f8b1dee337674b2e34ab1f9bc1" + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.28", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bslib", + "evaluate", + "fontawesome", + "htmltools", + "jquerylib", + "jsonlite", + "knitr", + "methods", + "tinytex", + "tools", + "utils", + "xfun", + "yaml" + ], + "Hash": "062470668513dcda416927085ee9bdc7" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" + }, + "rstudioapi": { + "Package": "rstudioapi", + "Version": "0.16.0", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "96710351d642b70e8f02ddeb237c46a7" + }, + "sass": { + "Package": "sass", + "Version": "0.4.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ], + "Hash": "d53dbfddf695303ea4ad66f86e99b95d" + }, + "scales": { + "Package": "scales", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "RColorBrewer", + "cli", + "farver", + "glue", + "labeling", + "lifecycle", + "munsell", + "rlang", + "viridisLite" + ], + "Hash": "c19df082ba346b0ffa6f833e92de34d1" + }, + "snakecase": { + "Package": "snakecase", + "Version": "0.11.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stringi", + "stringr" + ], + "Hash": "58767e44739b76965332e8a4fe3f91f1" + }, + "stringi": { + "Package": "stringi", + "Version": "1.8.4", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "stats", + "tools", + "utils" + ], + "Hash": "39e1144fd75428983dc3f63aa53dfa91" + }, + "stringr": { + "Package": "stringr", + "Version": "1.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "stringi", + "vctrs" + ], + "Hash": "960e2ae9e09656611e0b8214ad543207" + }, + "svglite": { + "Package": "svglite", + "Version": "2.1.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11", + "systemfonts" + ], + "Hash": "124a41fdfa23e8691cb744c762f10516" + }, + "sys": { + "Package": "sys", + "Version": "3.4.3", + "Source": "Repository", + "Repository": "P3M", + "Hash": "de342ebfebdbf40477d0758d05426646" + }, + "systemfonts": { + "Package": "systemfonts", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "6d538cff441f0f1f36db2209ac7495ac" + }, + "tibble": { + "Package": "tibble", + "Version": "3.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "fansi", + "lifecycle", + "magrittr", + "methods", + "pillar", + "pkgconfig", + "rlang", + "utils", + "vctrs" + ], + "Hash": "a84e2cc86d07289b3b6f5069df7a004c" + }, + "tidyselect": { + "Package": "tidyselect", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang", + "vctrs", + "withr" + ], + "Hash": "829f27b9c4919c16b593794a6344d6c0" + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.53", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "xfun" + ], + "Hash": "9db859e8aabbb474293dde3097839420" + }, + "utf8": { + "Package": "utf8", + "Version": "1.2.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "62b65c52671e6665f803ff02954446e9" + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.6.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang" + ], + "Hash": "c03fa420630029418f7e6da3667aac4a" + }, + "viridisLite": { + "Package": "viridisLite", + "Version": "0.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "c826c7c4241b6fc89ff55aaea3fa7491" + }, + "withr": { + "Package": "withr", + "Version": "3.0.2", + "Source": "Repository", + "Repository": "P3M", + "Requirements": [ + "R", + "grDevices", + "graphics" + ], + "Hash": "cc2d62c76458d425210d1eb1478b30b4" + }, + "xfun": { + "Package": "xfun", + "Version": "0.48", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "stats", + "tools" + ], + "Hash": "89e455b87c84e227eb7f60a1b4e5fe1f" + }, + "xml2": { + "Package": "xml2", + "Version": "1.3.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "methods", + "rlang" + ], + "Hash": "1d0336142f4cd25d8d23cd3ba7a8fb61" + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.10", + "Source": "Repository", + "Repository": "P3M", + "Hash": "51dab85c6c98e50a18d7551e9d49f76c" + } + } +} diff --git a/renv/.gitignore b/renv/.gitignore new file mode 100644 index 0000000..0ec0cbb --- /dev/null +++ b/renv/.gitignore @@ -0,0 +1,7 @@ +library/ +local/ +cellar/ +lock/ +python/ +sandbox/ +staging/ diff --git a/renv/activate.R b/renv/activate.R new file mode 100644 index 0000000..d13f993 --- /dev/null +++ b/renv/activate.R @@ -0,0 +1,1220 @@ + +local({ + + # the requested version of renv + version <- "1.0.7" + attr(version, "sha") <- NULL + + # the project directory + project <- Sys.getenv("RENV_PROJECT") + if (!nzchar(project)) + project <- getwd() + + # use start-up diagnostics if enabled + diagnostics <- Sys.getenv("RENV_STARTUP_DIAGNOSTICS", unset = "FALSE") + if (diagnostics) { + start <- Sys.time() + profile <- tempfile("renv-startup-", fileext = ".Rprof") + utils::Rprof(profile) + on.exit({ + utils::Rprof(NULL) + elapsed <- signif(difftime(Sys.time(), start, units = "auto"), digits = 2L) + writeLines(sprintf("- renv took %s to run the autoloader.", format(elapsed))) + writeLines(sprintf("- Profile: %s", profile)) + print(utils::summaryRprof(profile)) + }, add = TRUE) + } + + # figure out whether the autoloader is enabled + enabled <- local({ + + # first, check config option + override <- getOption("renv.config.autoloader.enabled") + if (!is.null(override)) + return(override) + + # if we're being run in a context where R_LIBS is already set, + # don't load -- presumably we're being run as a sub-process and + # the parent process has already set up library paths for us + rcmd <- Sys.getenv("R_CMD", unset = NA) + rlibs <- Sys.getenv("R_LIBS", unset = NA) + if (!is.na(rlibs) && !is.na(rcmd)) + return(FALSE) + + # next, check environment variables + # TODO: prefer using the configuration one in the future + envvars <- c( + "RENV_CONFIG_AUTOLOADER_ENABLED", + "RENV_AUTOLOADER_ENABLED", + "RENV_ACTIVATE_PROJECT" + ) + + for (envvar in envvars) { + envval <- Sys.getenv(envvar, unset = NA) + if (!is.na(envval)) + return(tolower(envval) %in% c("true", "t", "1")) + } + + # enable by default + TRUE + + }) + + # bail if we're not enabled + if (!enabled) { + + # if we're not enabled, we might still need to manually load + # the user profile here + profile <- Sys.getenv("R_PROFILE_USER", unset = "~/.Rprofile") + if (file.exists(profile)) { + cfg <- Sys.getenv("RENV_CONFIG_USER_PROFILE", unset = "TRUE") + if (tolower(cfg) %in% c("true", "t", "1")) + sys.source(profile, envir = globalenv()) + } + + return(FALSE) + + } + + # avoid recursion + if (identical(getOption("renv.autoloader.running"), TRUE)) { + warning("ignoring recursive attempt to run renv autoloader") + return(invisible(TRUE)) + } + + # signal that we're loading renv during R startup + options(renv.autoloader.running = TRUE) + on.exit(options(renv.autoloader.running = NULL), add = TRUE) + + # signal that we've consented to use renv + options(renv.consent = TRUE) + + # load the 'utils' package eagerly -- this ensures that renv shims, which + # mask 'utils' packages, will come first on the search path + library(utils, lib.loc = .Library) + + # unload renv if it's already been loaded + if ("renv" %in% loadedNamespaces()) + unloadNamespace("renv") + + # load bootstrap tools + `%||%` <- function(x, y) { + if (is.null(x)) y else x + } + + catf <- function(fmt, ..., appendLF = TRUE) { + + quiet <- getOption("renv.bootstrap.quiet", default = FALSE) + if (quiet) + return(invisible()) + + msg <- sprintf(fmt, ...) + cat(msg, file = stdout(), sep = if (appendLF) "\n" else "") + + invisible(msg) + + } + + header <- function(label, + ..., + prefix = "#", + suffix = "-", + n = min(getOption("width"), 78)) + { + label <- sprintf(label, ...) + n <- max(n - nchar(label) - nchar(prefix) - 2L, 8L) + if (n <= 0) + return(paste(prefix, label)) + + tail <- paste(rep.int(suffix, n), collapse = "") + paste0(prefix, " ", label, " ", tail) + + } + + heredoc <- function(text, leave = 0) { + + # remove leading, trailing whitespace + trimmed <- gsub("^\\s*\\n|\\n\\s*$", "", text) + + # split into lines + lines <- strsplit(trimmed, "\n", fixed = TRUE)[[1L]] + + # compute common indent + indent <- regexpr("[^[:space:]]", lines) + common <- min(setdiff(indent, -1L)) - leave + paste(substring(lines, common), collapse = "\n") + + } + + startswith <- function(string, prefix) { + substring(string, 1, nchar(prefix)) == prefix + } + + bootstrap <- function(version, library) { + + friendly <- renv_bootstrap_version_friendly(version) + section <- header(sprintf("Bootstrapping renv %s", friendly)) + catf(section) + + # attempt to download renv + catf("- Downloading renv ... ", appendLF = FALSE) + withCallingHandlers( + tarball <- renv_bootstrap_download(version), + error = function(err) { + catf("FAILED") + stop("failed to download:\n", conditionMessage(err)) + } + ) + catf("OK") + on.exit(unlink(tarball), add = TRUE) + + # now attempt to install + catf("- Installing renv ... ", appendLF = FALSE) + withCallingHandlers( + status <- renv_bootstrap_install(version, tarball, library), + error = function(err) { + catf("FAILED") + stop("failed to install:\n", conditionMessage(err)) + } + ) + catf("OK") + + # add empty line to break up bootstrapping from normal output + catf("") + + return(invisible()) + } + + renv_bootstrap_tests_running <- function() { + getOption("renv.tests.running", default = FALSE) + } + + renv_bootstrap_repos <- function() { + + # get CRAN repository + cran <- getOption("renv.repos.cran", "https://cloud.r-project.org") + + # check for repos override + repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) + if (!is.na(repos)) { + + # check for RSPM; if set, use a fallback repository for renv + rspm <- Sys.getenv("RSPM", unset = NA) + if (identical(rspm, repos)) + repos <- c(RSPM = rspm, CRAN = cran) + + return(repos) + + } + + # check for lockfile repositories + repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) + if (!inherits(repos, "error") && length(repos)) + return(repos) + + # retrieve current repos + repos <- getOption("repos") + + # ensure @CRAN@ entries are resolved + repos[repos == "@CRAN@"] <- cran + + # add in renv.bootstrap.repos if set + default <- c(FALLBACK = "https://cloud.r-project.org") + extra <- getOption("renv.bootstrap.repos", default = default) + repos <- c(repos, extra) + + # remove duplicates that might've snuck in + dupes <- duplicated(repos) | duplicated(names(repos)) + repos[!dupes] + + } + + renv_bootstrap_repos_lockfile <- function() { + + lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") + if (!file.exists(lockpath)) + return(NULL) + + lockfile <- tryCatch(renv_json_read(lockpath), error = identity) + if (inherits(lockfile, "error")) { + warning(lockfile) + return(NULL) + } + + repos <- lockfile$R$Repositories + if (length(repos) == 0) + return(NULL) + + keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) + vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) + names(vals) <- keys + + return(vals) + + } + + renv_bootstrap_download <- function(version) { + + sha <- attr(version, "sha", exact = TRUE) + + methods <- if (!is.null(sha)) { + + # attempting to bootstrap a development version of renv + c( + function() renv_bootstrap_download_tarball(sha), + function() renv_bootstrap_download_github(sha) + ) + + } else { + + # attempting to bootstrap a release version of renv + c( + function() renv_bootstrap_download_tarball(version), + function() renv_bootstrap_download_cran_latest(version), + function() renv_bootstrap_download_cran_archive(version) + ) + + } + + for (method in methods) { + path <- tryCatch(method(), error = identity) + if (is.character(path) && file.exists(path)) + return(path) + } + + stop("All download methods failed") + + } + + renv_bootstrap_download_impl <- function(url, destfile) { + + mode <- "wb" + + # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 + fixup <- + Sys.info()[["sysname"]] == "Windows" && + substring(url, 1L, 5L) == "file:" + + if (fixup) + mode <- "w+b" + + args <- list( + url = url, + destfile = destfile, + mode = mode, + quiet = TRUE + ) + + if ("headers" %in% names(formals(utils::download.file))) + args$headers <- renv_bootstrap_download_custom_headers(url) + + do.call(utils::download.file, args) + + } + + renv_bootstrap_download_custom_headers <- function(url) { + + headers <- getOption("renv.download.headers") + if (is.null(headers)) + return(character()) + + if (!is.function(headers)) + stopf("'renv.download.headers' is not a function") + + headers <- headers(url) + if (length(headers) == 0L) + return(character()) + + if (is.list(headers)) + headers <- unlist(headers, recursive = FALSE, use.names = TRUE) + + ok <- + is.character(headers) && + is.character(names(headers)) && + all(nzchar(names(headers))) + + if (!ok) + stop("invocation of 'renv.download.headers' did not return a named character vector") + + headers + + } + + renv_bootstrap_download_cran_latest <- function(version) { + + spec <- renv_bootstrap_download_cran_latest_find(version) + type <- spec$type + repos <- spec$repos + + baseurl <- utils::contrib.url(repos = repos, type = type) + ext <- if (identical(type, "source")) + ".tar.gz" + else if (Sys.info()[["sysname"]] == "Windows") + ".zip" + else + ".tgz" + name <- sprintf("renv_%s%s", version, ext) + url <- paste(baseurl, name, sep = "/") + + destfile <- file.path(tempdir(), name) + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (inherits(status, "condition")) + return(FALSE) + + # report success and return + destfile + + } + + renv_bootstrap_download_cran_latest_find <- function(version) { + + # check whether binaries are supported on this system + binary <- + getOption("renv.bootstrap.binary", default = TRUE) && + !identical(.Platform$pkgType, "source") && + !identical(getOption("pkgType"), "source") && + Sys.info()[["sysname"]] %in% c("Darwin", "Windows") + + types <- c(if (binary) "binary", "source") + + # iterate over types + repositories + for (type in types) { + for (repos in renv_bootstrap_repos()) { + + # retrieve package database + db <- tryCatch( + as.data.frame( + utils::available.packages(type = type, repos = repos), + stringsAsFactors = FALSE + ), + error = identity + ) + + if (inherits(db, "error")) + next + + # check for compatible entry + entry <- db[db$Package %in% "renv" & db$Version %in% version, ] + if (nrow(entry) == 0) + next + + # found it; return spec to caller + spec <- list(entry = entry, type = type, repos = repos) + return(spec) + + } + } + + # if we got here, we failed to find renv + fmt <- "renv %s is not available from your declared package repositories" + stop(sprintf(fmt, version)) + + } + + renv_bootstrap_download_cran_archive <- function(version) { + + name <- sprintf("renv_%s.tar.gz", version) + repos <- renv_bootstrap_repos() + urls <- file.path(repos, "src/contrib/Archive/renv", name) + destfile <- file.path(tempdir(), name) + + for (url in urls) { + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (identical(status, 0L)) + return(destfile) + + } + + return(FALSE) + + } + + renv_bootstrap_download_tarball <- function(version) { + + # if the user has provided the path to a tarball via + # an environment variable, then use it + tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) + if (is.na(tarball)) + return() + + # allow directories + if (dir.exists(tarball)) { + name <- sprintf("renv_%s.tar.gz", version) + tarball <- file.path(tarball, name) + } + + # bail if it doesn't exist + if (!file.exists(tarball)) { + + # let the user know we weren't able to honour their request + fmt <- "- RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." + msg <- sprintf(fmt, tarball) + warning(msg) + + # bail + return() + + } + + catf("- Using local tarball '%s'.", tarball) + tarball + + } + + renv_bootstrap_download_github <- function(version) { + + enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") + if (!identical(enabled, "TRUE")) + return(FALSE) + + # prepare download options + pat <- Sys.getenv("GITHUB_PAT") + if (nzchar(Sys.which("curl")) && nzchar(pat)) { + fmt <- "--location --fail --header \"Authorization: token %s\"" + extra <- sprintf(fmt, pat) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "curl", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } else if (nzchar(Sys.which("wget")) && nzchar(pat)) { + fmt <- "--header=\"Authorization: token %s\"" + extra <- sprintf(fmt, pat) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "wget", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } + + url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) + name <- sprintf("renv_%s.tar.gz", version) + destfile <- file.path(tempdir(), name) + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (!identical(status, 0L)) + return(FALSE) + + renv_bootstrap_download_augment(destfile) + + return(destfile) + + } + + # Add Sha to DESCRIPTION. This is stop gap until #890, after which we + # can use renv::install() to fully capture metadata. + renv_bootstrap_download_augment <- function(destfile) { + sha <- renv_bootstrap_git_extract_sha1_tar(destfile) + if (is.null(sha)) { + return() + } + + # Untar + tempdir <- tempfile("renv-github-") + on.exit(unlink(tempdir, recursive = TRUE), add = TRUE) + untar(destfile, exdir = tempdir) + pkgdir <- dir(tempdir, full.names = TRUE)[[1]] + + # Modify description + desc_path <- file.path(pkgdir, "DESCRIPTION") + desc_lines <- readLines(desc_path) + remotes_fields <- c( + "RemoteType: github", + "RemoteHost: api.github.com", + "RemoteRepo: renv", + "RemoteUsername: rstudio", + "RemotePkgRef: rstudio/renv", + paste("RemoteRef: ", sha), + paste("RemoteSha: ", sha) + ) + writeLines(c(desc_lines[desc_lines != ""], remotes_fields), con = desc_path) + + # Re-tar + local({ + old <- setwd(tempdir) + on.exit(setwd(old), add = TRUE) + + tar(destfile, compression = "gzip") + }) + invisible() + } + + # Extract the commit hash from a git archive. Git archives include the SHA1 + # hash as the comment field of the tarball pax extended header + # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html) + # For GitHub archives this should be the first header after the default one + # (512 byte) header. + renv_bootstrap_git_extract_sha1_tar <- function(bundle) { + + # open the bundle for reading + # We use gzcon for everything because (from ?gzcon) + # > Reading from a connection which does not supply a 'gzip' magic + # > header is equivalent to reading from the original connection + conn <- gzcon(file(bundle, open = "rb", raw = TRUE)) + on.exit(close(conn)) + + # The default pax header is 512 bytes long and the first pax extended header + # with the comment should be 51 bytes long + # `52 comment=` (11 chars) + 40 byte SHA1 hash + len <- 0x200 + 0x33 + res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len]) + + if (grepl("^52 comment=", res)) { + sub("52 comment=", "", res) + } else { + NULL + } + } + + renv_bootstrap_install <- function(version, tarball, library) { + + # attempt to install it into project library + dir.create(library, showWarnings = FALSE, recursive = TRUE) + output <- renv_bootstrap_install_impl(library, tarball) + + # check for successful install + status <- attr(output, "status") + if (is.null(status) || identical(status, 0L)) + return(status) + + # an error occurred; report it + header <- "installation of renv failed" + lines <- paste(rep.int("=", nchar(header)), collapse = "") + text <- paste(c(header, lines, output), collapse = "\n") + stop(text) + + } + + renv_bootstrap_install_impl <- function(library, tarball) { + + # invoke using system2 so we can capture and report output + bin <- R.home("bin") + exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" + R <- file.path(bin, exe) + + args <- c( + "--vanilla", "CMD", "INSTALL", "--no-multiarch", + "-l", shQuote(path.expand(library)), + shQuote(path.expand(tarball)) + ) + + system2(R, args, stdout = TRUE, stderr = TRUE) + + } + + renv_bootstrap_platform_prefix <- function() { + + # construct version prefix + version <- paste(R.version$major, R.version$minor, sep = ".") + prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-") + + # include SVN revision for development versions of R + # (to avoid sharing platform-specific artefacts with released versions of R) + devel <- + identical(R.version[["status"]], "Under development (unstable)") || + identical(R.version[["nickname"]], "Unsuffered Consequences") + + if (devel) + prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") + + # build list of path components + components <- c(prefix, R.version$platform) + + # include prefix if provided by user + prefix <- renv_bootstrap_platform_prefix_impl() + if (!is.na(prefix) && nzchar(prefix)) + components <- c(prefix, components) + + # build prefix + paste(components, collapse = "/") + + } + + renv_bootstrap_platform_prefix_impl <- function() { + + # if an explicit prefix has been supplied, use it + prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) + if (!is.na(prefix)) + return(prefix) + + # if the user has requested an automatic prefix, generate it + auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) + if (is.na(auto) && getRversion() >= "4.4.0") + auto <- "TRUE" + + if (auto %in% c("TRUE", "True", "true", "1")) + return(renv_bootstrap_platform_prefix_auto()) + + # empty string on failure + "" + + } + + renv_bootstrap_platform_prefix_auto <- function() { + + prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) + if (inherits(prefix, "error") || prefix %in% "unknown") { + + msg <- paste( + "failed to infer current operating system", + "please file a bug report at https://github.com/rstudio/renv/issues", + sep = "; " + ) + + warning(msg) + + } + + prefix + + } + + renv_bootstrap_platform_os <- function() { + + sysinfo <- Sys.info() + sysname <- sysinfo[["sysname"]] + + # handle Windows + macOS up front + if (sysname == "Windows") + return("windows") + else if (sysname == "Darwin") + return("macos") + + # check for os-release files + for (file in c("/etc/os-release", "/usr/lib/os-release")) + if (file.exists(file)) + return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) + + # check for redhat-release files + if (file.exists("/etc/redhat-release")) + return(renv_bootstrap_platform_os_via_redhat_release()) + + "unknown" + + } + + renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { + + # read /etc/os-release + release <- utils::read.table( + file = file, + sep = "=", + quote = c("\"", "'"), + col.names = c("Key", "Value"), + comment.char = "#", + stringsAsFactors = FALSE + ) + + vars <- as.list(release$Value) + names(vars) <- release$Key + + # get os name + os <- tolower(sysinfo[["sysname"]]) + + # read id + id <- "unknown" + for (field in c("ID", "ID_LIKE")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + id <- vars[[field]] + break + } + } + + # read version + version <- "unknown" + for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + version <- vars[[field]] + break + } + } + + # join together + paste(c(os, id, version), collapse = "-") + + } + + renv_bootstrap_platform_os_via_redhat_release <- function() { + + # read /etc/redhat-release + contents <- readLines("/etc/redhat-release", warn = FALSE) + + # infer id + id <- if (grepl("centos", contents, ignore.case = TRUE)) + "centos" + else if (grepl("redhat", contents, ignore.case = TRUE)) + "redhat" + else + "unknown" + + # try to find a version component (very hacky) + version <- "unknown" + + parts <- strsplit(contents, "[[:space:]]")[[1L]] + for (part in parts) { + + nv <- tryCatch(numeric_version(part), error = identity) + if (inherits(nv, "error")) + next + + version <- nv[1, 1] + break + + } + + paste(c("linux", id, version), collapse = "-") + + } + + renv_bootstrap_library_root_name <- function(project) { + + # use project name as-is if requested + asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") + if (asis) + return(basename(project)) + + # otherwise, disambiguate based on project's path + id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) + paste(basename(project), id, sep = "-") + + } + + renv_bootstrap_library_root <- function(project) { + + prefix <- renv_bootstrap_profile_prefix() + + path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) + if (!is.na(path)) + return(paste(c(path, prefix), collapse = "/")) + + path <- renv_bootstrap_library_root_impl(project) + if (!is.null(path)) { + name <- renv_bootstrap_library_root_name(project) + return(paste(c(path, prefix, name), collapse = "/")) + } + + renv_bootstrap_paths_renv("library", project = project) + + } + + renv_bootstrap_library_root_impl <- function(project) { + + root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) + if (!is.na(root)) + return(root) + + type <- renv_bootstrap_project_type(project) + if (identical(type, "package")) { + userdir <- renv_bootstrap_user_dir() + return(file.path(userdir, "library")) + } + + } + + renv_bootstrap_validate_version <- function(version, description = NULL) { + + # resolve description file + # + # avoid passing lib.loc to `packageDescription()` below, since R will + # use the loaded version of the package by default anyhow. note that + # this function should only be called after 'renv' is loaded + # https://github.com/rstudio/renv/issues/1625 + description <- description %||% packageDescription("renv") + + # check whether requested version 'version' matches loaded version of renv + sha <- attr(version, "sha", exact = TRUE) + valid <- if (!is.null(sha)) + renv_bootstrap_validate_version_dev(sha, description) + else + renv_bootstrap_validate_version_release(version, description) + + if (valid) + return(TRUE) + + # the loaded version of renv doesn't match the requested version; + # give the user instructions on how to proceed + dev <- identical(description[["RemoteType"]], "github") + remote <- if (dev) + paste("rstudio/renv", description[["RemoteSha"]], sep = "@") + else + paste("renv", description[["Version"]], sep = "@") + + # display both loaded version + sha if available + friendly <- renv_bootstrap_version_friendly( + version = description[["Version"]], + sha = if (dev) description[["RemoteSha"]] + ) + + fmt <- heredoc(" + renv %1$s was loaded from project library, but this project is configured to use renv %2$s. + - Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile. + - Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library. + ") + catf(fmt, friendly, renv_bootstrap_version_friendly(version), remote) + + FALSE + + } + + renv_bootstrap_validate_version_dev <- function(version, description) { + expected <- description[["RemoteSha"]] + is.character(expected) && startswith(expected, version) + } + + renv_bootstrap_validate_version_release <- function(version, description) { + expected <- description[["Version"]] + is.character(expected) && identical(expected, version) + } + + renv_bootstrap_hash_text <- function(text) { + + hashfile <- tempfile("renv-hash-") + on.exit(unlink(hashfile), add = TRUE) + + writeLines(text, con = hashfile) + tools::md5sum(hashfile) + + } + + renv_bootstrap_load <- function(project, libpath, version) { + + # try to load renv from the project library + if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) + return(FALSE) + + # warn if the version of renv loaded does not match + renv_bootstrap_validate_version(version) + + # execute renv load hooks, if any + hooks <- getHook("renv::autoload") + for (hook in hooks) + if (is.function(hook)) + tryCatch(hook(), error = warnify) + + # load the project + renv::load(project) + + TRUE + + } + + renv_bootstrap_profile_load <- function(project) { + + # if RENV_PROFILE is already set, just use that + profile <- Sys.getenv("RENV_PROFILE", unset = NA) + if (!is.na(profile) && nzchar(profile)) + return(profile) + + # check for a profile file (nothing to do if it doesn't exist) + path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project) + if (!file.exists(path)) + return(NULL) + + # read the profile, and set it if it exists + contents <- readLines(path, warn = FALSE) + if (length(contents) == 0L) + return(NULL) + + # set RENV_PROFILE + profile <- contents[[1L]] + if (!profile %in% c("", "default")) + Sys.setenv(RENV_PROFILE = profile) + + profile + + } + + renv_bootstrap_profile_prefix <- function() { + profile <- renv_bootstrap_profile_get() + if (!is.null(profile)) + return(file.path("profiles", profile, "renv")) + } + + renv_bootstrap_profile_get <- function() { + profile <- Sys.getenv("RENV_PROFILE", unset = "") + renv_bootstrap_profile_normalize(profile) + } + + renv_bootstrap_profile_set <- function(profile) { + profile <- renv_bootstrap_profile_normalize(profile) + if (is.null(profile)) + Sys.unsetenv("RENV_PROFILE") + else + Sys.setenv(RENV_PROFILE = profile) + } + + renv_bootstrap_profile_normalize <- function(profile) { + + if (is.null(profile) || profile %in% c("", "default")) + return(NULL) + + profile + + } + + renv_bootstrap_path_absolute <- function(path) { + + substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( + substr(path, 1L, 1L) %in% c(letters, LETTERS) && + substr(path, 2L, 3L) %in% c(":/", ":\\") + ) + + } + + renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { + renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") + root <- if (renv_bootstrap_path_absolute(renv)) NULL else project + prefix <- if (profile) renv_bootstrap_profile_prefix() + components <- c(root, renv, prefix, ...) + paste(components, collapse = "/") + } + + renv_bootstrap_project_type <- function(path) { + + descpath <- file.path(path, "DESCRIPTION") + if (!file.exists(descpath)) + return("unknown") + + desc <- tryCatch( + read.dcf(descpath, all = TRUE), + error = identity + ) + + if (inherits(desc, "error")) + return("unknown") + + type <- desc$Type + if (!is.null(type)) + return(tolower(type)) + + package <- desc$Package + if (!is.null(package)) + return("package") + + "unknown" + + } + + renv_bootstrap_user_dir <- function() { + dir <- renv_bootstrap_user_dir_impl() + path.expand(chartr("\\", "/", dir)) + } + + renv_bootstrap_user_dir_impl <- function() { + + # use local override if set + override <- getOption("renv.userdir.override") + if (!is.null(override)) + return(override) + + # use R_user_dir if available + tools <- asNamespace("tools") + if (is.function(tools$R_user_dir)) + return(tools$R_user_dir("renv", "cache")) + + # try using our own backfill for older versions of R + envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") + for (envvar in envvars) { + root <- Sys.getenv(envvar, unset = NA) + if (!is.na(root)) + return(file.path(root, "R/renv")) + } + + # use platform-specific default fallbacks + if (Sys.info()[["sysname"]] == "Windows") + file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") + else if (Sys.info()[["sysname"]] == "Darwin") + "~/Library/Caches/org.R-project.R/R/renv" + else + "~/.cache/R/renv" + + } + + renv_bootstrap_version_friendly <- function(version, shafmt = NULL, sha = NULL) { + sha <- sha %||% attr(version, "sha", exact = TRUE) + parts <- c(version, sprintf(shafmt %||% " [sha: %s]", substring(sha, 1L, 7L))) + paste(parts, collapse = "") + } + + renv_bootstrap_exec <- function(project, libpath, version) { + if (!renv_bootstrap_load(project, libpath, version)) + renv_bootstrap_run(version, libpath) + } + + renv_bootstrap_run <- function(version, libpath) { + + # perform bootstrap + bootstrap(version, libpath) + + # exit early if we're just testing bootstrap + if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) + return(TRUE) + + # try again to load + if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { + return(renv::load(project = getwd())) + } + + # failed to download or load renv; warn the user + msg <- c( + "Failed to find an renv installation: the project will not be loaded.", + "Use `renv::activate()` to re-initialize the project." + ) + + warning(paste(msg, collapse = "\n"), call. = FALSE) + + } + + renv_json_read <- function(file = NULL, text = NULL) { + + jlerr <- NULL + + # if jsonlite is loaded, use that instead + if ("jsonlite" %in% loadedNamespaces()) { + + json <- tryCatch(renv_json_read_jsonlite(file, text), error = identity) + if (!inherits(json, "error")) + return(json) + + jlerr <- json + + } + + # otherwise, fall back to the default JSON reader + json <- tryCatch(renv_json_read_default(file, text), error = identity) + if (!inherits(json, "error")) + return(json) + + # report an error + if (!is.null(jlerr)) + stop(jlerr) + else + stop(json) + + } + + renv_json_read_jsonlite <- function(file = NULL, text = NULL) { + text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") + jsonlite::fromJSON(txt = text, simplifyVector = FALSE) + } + + renv_json_read_default <- function(file = NULL, text = NULL) { + + # find strings in the JSON + text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") + pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + locs <- gregexpr(pattern, text, perl = TRUE)[[1]] + + # if any are found, replace them with placeholders + replaced <- text + strings <- character() + replacements <- character() + + if (!identical(c(locs), -1L)) { + + # get the string values + starts <- locs + ends <- locs + attr(locs, "match.length") - 1L + strings <- substring(text, starts, ends) + + # only keep those requiring escaping + strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE) + + # compute replacements + replacements <- sprintf('"\032%i\032"', seq_along(strings)) + + # replace the strings + mapply(function(string, replacement) { + replaced <<- sub(string, replacement, replaced, fixed = TRUE) + }, strings, replacements) + + } + + # transform the JSON into something the R parser understands + transformed <- replaced + transformed <- gsub("{}", "`names<-`(list(), character())", transformed, fixed = TRUE) + transformed <- gsub("[[{]", "list(", transformed, perl = TRUE) + transformed <- gsub("[]}]", ")", transformed, perl = TRUE) + transformed <- gsub(":", "=", transformed, fixed = TRUE) + text <- paste(transformed, collapse = "\n") + + # parse it + json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]] + + # construct map between source strings, replaced strings + map <- as.character(parse(text = strings)) + names(map) <- as.character(parse(text = replacements)) + + # convert to list + map <- as.list(map) + + # remap strings in object + remapped <- renv_json_read_remap(json, map) + + # evaluate + eval(remapped, envir = baseenv()) + + } + + renv_json_read_remap <- function(json, map) { + + # fix names + if (!is.null(names(json))) { + lhs <- match(names(json), names(map), nomatch = 0L) + rhs <- match(names(map), names(json), nomatch = 0L) + names(json)[rhs] <- map[lhs] + } + + # fix values + if (is.character(json)) + return(map[[json]] %||% json) + + # handle true, false, null + if (is.name(json)) { + text <- as.character(json) + if (text == "true") + return(TRUE) + else if (text == "false") + return(FALSE) + else if (text == "null") + return(NULL) + } + + # recurse + if (is.recursive(json)) { + for (i in seq_along(json)) { + json[i] <- list(renv_json_read_remap(json[[i]], map)) + } + } + + json + + } + + # load the renv profile, if any + renv_bootstrap_profile_load(project) + + # construct path to library root + root <- renv_bootstrap_library_root(project) + + # construct library prefix for platform + prefix <- renv_bootstrap_platform_prefix() + + # construct full libpath + libpath <- file.path(root, prefix) + + # run bootstrap code + renv_bootstrap_exec(project, libpath, version) + + invisible() + +}) diff --git a/renv/settings.json b/renv/settings.json new file mode 100644 index 0000000..ffdbb32 --- /dev/null +++ b/renv/settings.json @@ -0,0 +1,19 @@ +{ + "bioconductor.version": null, + "external.libraries": [], + "ignored.packages": [], + "package.dependency.fields": [ + "Imports", + "Depends", + "LinkingTo" + ], + "ppm.enabled": null, + "ppm.ignored.urls": [], + "r.version": null, + "snapshot.type": "implicit", + "use.cache": true, + "vcs.ignore.cellar": true, + "vcs.ignore.library": true, + "vcs.ignore.local": true, + "vcs.manage.ignores": true +}