├── .dir-locals.el ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── QUERY.md ├── README.md ├── deps.edn ├── dev.cljs.edn ├── dev ├── dave │ └── debug.cljs └── user.clj ├── docs ├── algorithm_definitions │ ├── followedRecommendations.pdf │ ├── followedRecommendations.tex │ ├── mostDifficultAssessmentQuestions.pdf │ ├── mostDifficultAssessmentQuestions.tex │ ├── rateOfCompletions.pdf │ ├── rateOfCompletions.tex │ ├── timelineLearnerSuccess.pdf │ └── timelineLearnerSuccess.tex ├── algorithms │ ├── followed_recommendations.pdf │ ├── followed_recommendations.tex │ ├── introduction.pdf │ ├── introduction.tex │ ├── most_difficult_assessment_questions.pdf │ ├── most_difficult_assessment_questions.tex │ ├── rate_of_completions.pdf │ ├── rate_of_completions.tex │ ├── timeline_learner_success.pdf │ └── timeline_learner_success.tex ├── appendices │ ├── a.pdf │ └── a.tex ├── main.pdf ├── main.tex ├── operations │ ├── collections │ │ ├── append.pdf │ │ ├── append.tex │ │ ├── array?.pdf │ │ ├── array?.tex │ │ ├── atIndex.pdf │ │ ├── atIndex.tex │ │ ├── remove.pdf │ │ ├── remove.tex │ │ ├── update.pdf │ │ └── update.tex │ ├── kv │ │ ├── associate.pdf │ │ ├── associate.tex │ │ ├── atKey.pdf │ │ ├── atKey.tex │ │ ├── dissociate.pdf │ │ ├── dissociate.tex │ │ ├── map?.pdf │ │ └── map?.tex │ └── util │ │ ├── isoToUnix.pdf │ │ ├── isoToUnix.tex │ │ ├── map.pdf │ │ ├── map.tex │ │ ├── rateOf.pdf │ │ ├── rateOf.tex │ │ ├── timeUnitToNumberOfSeconds.pdf │ │ └── timeUnitToNumberOfSeconds.tex ├── primitives │ ├── atJsonPath.pdf │ ├── atJsonPath.tex │ ├── walk.pdf │ └── walk.tex └── z │ ├── Z-notation reference manual.pdf │ ├── introduction.pdf │ ├── introduction.tex │ ├── xapi.pdf │ ├── xapi.tex │ └── zed-csp-documentation.pdf ├── figwheel-main.edn ├── prod.cljs.edn ├── resources ├── dave │ └── ui │ │ └── sass │ │ ├── bootstrap │ │ ├── _alert.scss │ │ ├── _badge.scss │ │ ├── _breadcrumb.scss │ │ ├── _button-group.scss │ │ ├── _buttons.scss │ │ ├── _card.scss │ │ ├── _carousel.scss │ │ ├── _close.scss │ │ ├── _code.scss │ │ ├── _custom-forms.scss │ │ ├── _dropdown.scss │ │ ├── _forms.scss │ │ ├── _functions.scss │ │ ├── _grid.scss │ │ ├── _images.scss │ │ ├── _input-group.scss │ │ ├── _jumbotron.scss │ │ ├── _list-group.scss │ │ ├── _media.scss │ │ ├── _mixins.scss │ │ ├── _modal.scss │ │ ├── _nav.scss │ │ ├── _navbar.scss │ │ ├── _pagination.scss │ │ ├── _popover.scss │ │ ├── _print.scss │ │ ├── _progress.scss │ │ ├── _reboot.scss │ │ ├── _root.scss │ │ ├── _tables.scss │ │ ├── _tooltip.scss │ │ ├── _transitions.scss │ │ ├── _type.scss │ │ ├── _utilities.scss │ │ ├── _variables.scss │ │ ├── bootstrap-grid.scss │ │ ├── bootstrap-reboot.scss │ │ ├── bootstrap.scss │ │ ├── mixins │ │ │ ├── _alert.scss │ │ │ ├── _background-variant.scss │ │ │ ├── _badge.scss │ │ │ ├── _border-radius.scss │ │ │ ├── _box-shadow.scss │ │ │ ├── _breakpoints.scss │ │ │ ├── _buttons.scss │ │ │ ├── _caret.scss │ │ │ ├── _clearfix.scss │ │ │ ├── _float.scss │ │ │ ├── _forms.scss │ │ │ ├── _gradients.scss │ │ │ ├── _grid-framework.scss │ │ │ ├── _grid.scss │ │ │ ├── _hover.scss │ │ │ ├── _image.scss │ │ │ ├── _list-group.scss │ │ │ ├── _lists.scss │ │ │ ├── _nav-divider.scss │ │ │ ├── _pagination.scss │ │ │ ├── _reset-text.scss │ │ │ ├── _resize.scss │ │ │ ├── _screen-reader.scss │ │ │ ├── _size.scss │ │ │ ├── _table-row.scss │ │ │ ├── _text-emphasis.scss │ │ │ ├── _text-hide.scss │ │ │ ├── _text-truncate.scss │ │ │ ├── _transition.scss │ │ │ └── _visibility.scss │ │ └── utilities │ │ │ ├── _align.scss │ │ │ ├── _background.scss │ │ │ ├── _borders.scss │ │ │ ├── _clearfix.scss │ │ │ ├── _display.scss │ │ │ ├── _embed.scss │ │ │ ├── _flex.scss │ │ │ ├── _float.scss │ │ │ ├── _position.scss │ │ │ ├── _screenreaders.scss │ │ │ ├── _shadows.scss │ │ │ ├── _sizing.scss │ │ │ ├── _spacing.scss │ │ │ ├── _text.scss │ │ │ └── _visibility.scss │ │ ├── buttons.scss │ │ ├── codemirror.scss │ │ ├── debug.scss │ │ ├── dialog.scss │ │ ├── fonts.scss │ │ ├── form.scss │ │ ├── func.scss │ │ ├── mdc.scss │ │ ├── nav.scss │ │ ├── picker.scss │ │ ├── style.scss │ │ ├── vega.scss │ │ └── wizard.scss ├── figures │ ├── algorithm-step-args.png │ ├── algorithm-step-expanded.png │ ├── algorithm-step-flat.png │ ├── algorithm-tree.png │ ├── operation-x-prime.png │ ├── operation-x.png │ ├── primitive-flat.png │ └── primitive-tree.png ├── plots │ ├── gradient.pdf │ ├── multiple_line.pdf │ └── scatter_plot.pdf └── public │ ├── css │ └── .gitkeep │ ├── data │ ├── dave │ │ └── ds.json │ └── kokea │ │ ├── kokea.json │ │ └── rate_of_completions_16.json │ ├── img │ ├── .gitkeep │ ├── db.png │ ├── dev │ │ ├── DAVElogo.png │ │ ├── Githublogo.png │ │ ├── dave-logo-sm.png │ │ ├── dave_logo.png │ │ ├── dave_logo_no_text.png │ │ ├── dave_text_white_logo.png │ │ ├── headerdetailimg.png │ │ ├── line_chart.png │ │ ├── pie_chart.png │ │ ├── top_image.png │ │ ├── white_logo.png │ │ └── white_text_logo.png │ ├── folder.png │ └── lambda.svg │ ├── index.html │ ├── prod_index.html │ └── test.html ├── scratch ├── dave-transform │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── deps.edn │ ├── doc │ │ └── intro.md │ └── src │ │ ├── main │ │ └── com │ │ │ └── yetanalytics │ │ │ └── dave │ │ │ └── transform.clj │ │ └── test │ │ └── com │ │ └── yetanalytics │ │ └── dave │ │ └── transform_test.clj ├── filter-scratch │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── deps.edn │ ├── dev-resources │ │ ├── jolt │ │ │ └── sample │ │ │ │ ├── input.json │ │ │ │ ├── output.json │ │ │ │ └── spec.json │ │ └── statements │ │ │ ├── kokea.json │ │ │ └── long.json │ ├── doc │ │ ├── dev.org │ │ └── intro.md │ └── src │ │ ├── dev │ │ └── user.clj │ │ ├── main │ │ └── com │ │ │ └── yetanalytics │ │ │ └── dave │ │ │ ├── filter_scratch.clj │ │ │ └── filter_scratch │ │ │ ├── json.clj │ │ │ ├── json │ │ │ └── path.clj │ │ │ └── surfer.clj │ │ └── test │ │ └── com │ │ └── yetanalytics │ │ └── dave │ │ └── filter_scratch_test.clj └── json-transforms │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── deps.edn │ ├── doc │ └── intro.md │ ├── resources │ ├── ds.json │ └── kokea.json │ ├── src │ └── com │ │ └── yetanalytics │ │ └── json_transforms.clj │ └── test │ └── com │ └── yetanalytics │ └── json_transforms_test.clj ├── src └── com │ └── yetanalytics │ ├── dave.cljc │ └── dave │ ├── datalog.cljc │ ├── datalog │ ├── builtins.cljc │ ├── builtins │ │ └── time.cljc │ ├── patterns.cljc │ ├── rules.cljc │ └── schema.cljc │ ├── func │ ├── common.cljc │ └── util.cljc │ ├── ui │ ├── app │ │ ├── crud.cljs │ │ ├── db.cljs │ │ ├── dialog.cljs │ │ ├── dom.cljs │ │ ├── http.cljs │ │ ├── io.cljs │ │ ├── nav.cljs │ │ ├── notify.cljs │ │ ├── picker.cljs │ │ ├── template.cljs │ │ ├── vega.cljs │ │ ├── workbook.cljs │ │ └── workbook │ │ │ ├── analysis.cljs │ │ │ ├── data.cljs │ │ │ └── data │ │ │ └── lrs.cljs │ ├── core.cljs │ ├── events.cljs │ ├── interceptor.cljs │ ├── subs.cljs │ ├── util │ │ └── vega.cljs │ ├── views.cljs │ └── views │ │ ├── dialog.cljs │ │ ├── download.cljs │ │ ├── form │ │ ├── select.cljs │ │ └── textfield.cljs │ │ ├── nav.cljs │ │ ├── picker.cljs │ │ ├── root.cljs │ │ ├── snackbar.cljs │ │ ├── vega.cljs │ │ ├── workbook.cljs │ │ └── workbook │ │ ├── analysis.cljs │ │ └── data.cljs │ ├── util │ ├── log.cljc │ └── spec.cljc │ ├── vis │ ├── bar.cljc │ ├── line.cljc │ ├── pie.cljc │ └── scatter.cljc │ ├── workbook.cljc │ └── workbook │ ├── analysis.cljc │ ├── data.cljc │ └── data │ ├── file.cljc │ ├── lrs.cljc │ ├── lrs │ ├── auth.cljc │ └── client.cljc │ └── state.cljc ├── templates ├── algorithm_template.pdf └── algorithm_template.tex ├── test.cljs.edn └── test └── com └── yetanalytics ├── dave ├── datalog_test.cljc ├── func │ ├── common_test.cljc │ └── util_test.cljc ├── test_runner.cljs └── test_support.cljc └── dave_test.cljc /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ;;; Directory Local Variables 2 | ;;; For more information see (info "(emacs) Directory Variables") 3 | 4 | ((nil . 5 | ((cider-clojure-cli-global-options . "-A:fig")))) 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | pom.xml 2 | pom.xml.asc 3 | *.jar 4 | *.class 5 | /lib/ 6 | /classes/ 7 | /out/ 8 | /target/ 9 | /checkouts/ 10 | .lein-deps-sum 11 | .lein-repl-history 12 | .lein-plugins/ 13 | .lein-failures 14 | .repl 15 | .nrepl-port 16 | .cpcache/ 17 | .rebel_readline_history 18 | *.aux 19 | *.log 20 | *.log.lck 21 | *.out 22 | .DS_Store 23 | /resources/public/css/*.css 24 | /resources/public/css/*.css.map 25 | /node_modules/ 26 | package.json 27 | package-lock.json 28 | *.el 29 | *.dat 30 | *.script 31 | /gh_pages/ 32 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | before_install: 3 | - curl -O https://download.clojure.org/install/linux-install.sh 4 | - chmod +x linux-install.sh 5 | - sudo ./linux-install.sh 6 | script: make ci 7 | cache: 8 | directories: 9 | - /usr/local/bin/clj 10 | - /usr/local/bin/clj 11 | - /usr/local/lib/clojure 12 | - $HOME/.clojure 13 | - $HOME/.cljs 14 | - $HOME/.m2 15 | - .cpcache 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [0.0.4] - Unreleased 8 | ### Added 9 | - Statement `timestamp` and `stored` are parsed and indexed as `:statement/timestamp-inst` and `:statement/stored-inst` 10 | 11 | ### Removed 12 | - Timestamp strings are no longer indexed 13 | 14 | ## [0.0.3] - 2020-02-24 15 | ### Added 16 | - DAVE Analysis entity 17 | - Analysis Editor 18 | - Datalog parsing and query for xAPI 19 | - Vega input specification in Analysis Editor 20 | - Makefile for easier building w/o clojure syntax 21 | - CI via travis.org 22 | - DAVE Primitives Specification 23 | - `vega-tooltip` plugin for Vega renderer 24 | - Learning Path algorithm 25 | - Common xAPI Statement parsers 26 | 27 | ### Changed 28 | - Changed DAVE navigation to use Analysis under Workbook instead of Question/visualization 29 | - Removed Wizard flow 30 | - Run headless cljs tests via nodejs 31 | - Documentation split up into stand alone .tex and .pdf files which are required within main.tex 32 | - docs/algorithms/master. => docs/main. 33 | 34 | ### Removed 35 | - "Functions" 36 | - "Question" and "Visualization" entities 37 | 38 | ### Fixed 39 | - Tooltips now display properly 40 | 41 | ## [0.0.2] - 2019-05-31 42 | ### Added 43 | - Navigation footer 44 | 45 | ### Changed 46 | - Improved, centralized edit forms 47 | - Simplify object navigation 48 | - Various copy changes 49 | - Algorithm Doc Updates 50 | - Wizard navigation UX improvements 51 | 52 | ### Fixed 53 | - Visualization sizing issues 54 | 55 | ## [0.0.1] - 2019-03-29 56 | ### Added 57 | - DAVE Wizard for guided workbook creation 58 | - Live LRS connection functionality 59 | - Implemented visualization 60 | - Implemented browser data persistence 61 | - Implemented workbook UI + navigation scheme 62 | - Function implementations 63 | - Reducible function protocol + Schema 64 | - Reference implementation of pre-alpha algorithms 65 | - Manual creation of appropriate xAPI dataset for Pre-Alpha functionality 66 | - Defined data model for DAVE UI 67 | - Defined Dave UI general states and navigation based on data model 68 | 69 | [Unreleased]: https://github.com/yetanalytics/dave/compare/v0.0.2...HEAD 70 | [0.0.2]: https://github.com/yetanalytics/dave/compare/v0.0.1...v0.0.2 71 | [0.0.1]: https://github.com/yetanalytics/dave/releases/tag/v0.0.1 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Yet Analytics 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean watch-sass dev-repl test-clj test-cljs ci build-sass build-prod build-prod-server build-sass 2 | 3 | clean: 4 | rm -rf target node_modules package.json package-lock.json gh_pages *.log resources/public/css/style.css* 5 | 6 | watch-sass: 7 | clojure -A:watch-sass 8 | 9 | dev-repl: 10 | clojure -A:fig:build 11 | 12 | test-cljs: 13 | clojure -Afig:test-cljs 14 | 15 | test-clj: 16 | clojure -Atest-clj 17 | 18 | ci: test-cljs test-clj 19 | 20 | build-prod: 21 | clojure -Abuild-prod 22 | 23 | build-prod-server: 24 | clojure -Abuild-prod-server 25 | 26 | build-sass: 27 | clojure -Abuild-sass 28 | 29 | gh_pages: build-prod build-sass 30 | mkdir -p gh_pages/cljs-out 31 | cp -rv resources/public/* gh_pages/ 32 | rm gh_pages/index.html gh_pages/test.html 33 | mv gh_pages/prod_index.html gh_pages/index.html 34 | cp target/public/cljs-out/prod-main.js gh_pages/cljs-out/ 35 | -------------------------------------------------------------------------------- /dev.cljs.edn: -------------------------------------------------------------------------------- 1 | ^{:watch-dirs ["test" "src" "dev"] 2 | :css-dirs ["resources/public/css"] 3 | :auto-testing false ;; true 4 | :log-file "figwheel-main.log" 5 | } 6 | {:closure-defines {"re_frame.trace.trace_enabled_QMARK_" true} 7 | :preloads [day8.re-frame-10x.preload] 8 | :main com.yetanalytics.dave.ui.core 9 | :install-deps true 10 | :source-map true 11 | :npm-deps {"material-components-web" "0.41.1" 12 | "source-map-support" "0.5.9"}} 13 | -------------------------------------------------------------------------------- /dev/user.clj: -------------------------------------------------------------------------------- 1 | (ns user) 2 | 3 | (comment 4 | 5 | (require '[clj-http.client :as client] 6 | '[cheshire.core :as json] 7 | '[clojure.java.io :as io]) 8 | 9 | 10 | (do (def kokea-endpoint "https://demo-lrs.yetanalytics.io/xapi/statements") 11 | (def kokea-api-key "26589566c610a046c322f87cfcc1383032d09d0774d20b68") 12 | (def kokea-api-key-secret "d50f0b8711acc82793ed040d005f41ed571e2a1e69cf975339aa784d50ea8d1c") 13 | (def viewed-verb-id "https://xapinet.org/kokea-concepts/verbs/viewed") 14 | (def page-obj-id "https://xapinet.org/kokea-concepts/activities/Page-1-Listening-to-the-Customer") 15 | (def query-params {:verb viewed-verb-id 16 | :activity page-obj-id}) 17 | 18 | (defn query-lrs 19 | [{:keys [endpoint api-key api-key-secret query-params]}] 20 | (clj-http.client/get 21 | endpoint 22 | {:basic-auth [api-key api-key-secret] 23 | :headers {"X-Experience-API-Version" "1.0.3" 24 | "Content-Type" "application/json;"} 25 | :query-params query-params}))) 26 | 27 | 28 | (def rate-of-completions-statements 29 | (-> {:endpoint kokea-endpoint 30 | :api-key kokea-api-key 31 | :api-key-secret kokea-api-key-secret 32 | :query-params {:verb "https://xapinet.org/kokea-concepts/verbs/completed"}} 33 | query-lrs 34 | :body 35 | (cheshire.core/parse-string true) 36 | :statements)) 37 | 38 | (with-open [w (io/writer (io/file "resources/public/data/kokea/rate_of_completions_16.json"))] 39 | (json/generate-stream rate-of-completions-statements w)) 40 | 41 | (clojure.pprint/pprint rate-of-completions-statements) 42 | 43 | 44 | (defn rate-of-completions 45 | [stmts] 46 | (let [c-per-obj (loop [accum {} 47 | src stmts] 48 | (if (empty? src) 49 | accum 50 | (let [cur-stmt (first src) 51 | {{{{obj-name :en-US} :name} :definition 52 | obj-id :id} :object} cur-stmt] 53 | (recur 54 | (update-in accum [obj-id] 55 | (fn [old] 56 | (if (nil? old) 57 | {:name obj-name 58 | :count 1} 59 | (let [{c :count} old 60 | updated-c (inc c)] 61 | {:name obj-name 62 | :count updated-c})))) 63 | (rest src)))))] 64 | (loop [accum [] 65 | src c-per-obj] 66 | (if (empty? src) 67 | accum 68 | (let [[obj-id obj-info] (first src) 69 | {obj-n :name 70 | obj-c :count} obj-info] 71 | (recur (conj accum [obj-id obj-n obj-c]) (rest src))))))) 72 | 73 | (count (rate-of-completions rate-of-completions-statements))) 74 | -------------------------------------------------------------------------------- /docs/algorithm_definitions/followedRecommendations.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithm_definitions/followedRecommendations.pdf -------------------------------------------------------------------------------- /docs/algorithm_definitions/followedRecommendations.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../main.tex]{subfiles} 2 | \begin{document} 3 | 4 | \section{How Often are Recommendations Followed} 5 | Intro text about the Algorithm 6 | \subsection{Initialization} 7 | What does $state_{0}$ look like? 8 | \subsection{Relevant?} 9 | What primitives are used to determine if a Statement is relevant 10 | \subsection{Accept?} 11 | What primitives are used to determine if a Statement is accepted 12 | \subsection{Step} 13 | What primitives are used to process a Statement to update $state$ 14 | \subsection{Result} 15 | What $opts$ are used if any + what does the $state$ look like? 16 | \end{document} 17 | -------------------------------------------------------------------------------- /docs/algorithm_definitions/mostDifficultAssessmentQuestions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithm_definitions/mostDifficultAssessmentQuestions.pdf -------------------------------------------------------------------------------- /docs/algorithm_definitions/mostDifficultAssessmentQuestions.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../main.tex]{subfiles} 2 | \begin{document} 3 | 4 | \section{Which Assessment Questions are the Most Difficult} 5 | Intro text about the Algorithm 6 | \subsection{Initialization} 7 | What does $state_{0}$ look like? 8 | \subsection{Relevant?} 9 | What primitives are used to determine if a Statement is relevant 10 | \subsection{Accept?} 11 | What primitives are used to determine if a Statement is accepted 12 | \subsection{Step} 13 | What primitives are used to process a Statement to update $state$ 14 | \subsection{Result} 15 | What $opts$ are used if any + what does the $state$ look like? 16 | \end{document} 17 | -------------------------------------------------------------------------------- /docs/algorithm_definitions/rateOfCompletions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithm_definitions/rateOfCompletions.pdf -------------------------------------------------------------------------------- /docs/algorithm_definitions/timelineLearnerSuccess.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithm_definitions/timelineLearnerSuccess.pdf -------------------------------------------------------------------------------- /docs/algorithm_definitions/timelineLearnerSuccess.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../main.tex]{subfiles} 2 | \begin{document} 3 | 4 | \section{Timeline Of Learner Success} 5 | Intro text about the Algorithm 6 | \subsection{Initialization} 7 | What does $state_{0}$ look like? 8 | \subsection{Relevant?} 9 | What primitives are used to determine if a Statement is relevant 10 | \subsection{Accept?} 11 | What primitives are used to determine if a Statement is accepted 12 | \subsection{Step} 13 | What primitives are used to process a Statement to update $state$ 14 | \subsection{Result} 15 | What $opts$ are used if any + what does the $state$ look like? 16 | \end{document} 17 | -------------------------------------------------------------------------------- /docs/algorithms/followed_recommendations.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithms/followed_recommendations.pdf -------------------------------------------------------------------------------- /docs/algorithms/introduction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithms/introduction.pdf -------------------------------------------------------------------------------- /docs/algorithms/most_difficult_assessment_questions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithms/most_difficult_assessment_questions.pdf -------------------------------------------------------------------------------- /docs/algorithms/rate_of_completions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithms/rate_of_completions.pdf -------------------------------------------------------------------------------- /docs/algorithms/timeline_learner_success.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/algorithms/timeline_learner_success.pdf -------------------------------------------------------------------------------- /docs/appendices/a.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/appendices/a.pdf -------------------------------------------------------------------------------- /docs/main.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/main.pdf -------------------------------------------------------------------------------- /docs/operations/collections/append.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/collections/append.pdf -------------------------------------------------------------------------------- /docs/operations/collections/append.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Append} 4 | 5 | The operation $append$ will return a Collection with a Value added at a specified numeric Index. 6 | \begin{schema}{Append[Collection, V, \nat]} 7 | coll?, coll! : Collection \\ 8 | v? : V \\ 9 | idx? : \nat \\ 10 | append~\_ : Collection \cross V \cross \nat \bij Collection 11 | \where 12 | \#~idx? = 1 \\ 13 | coll! = append(coll?, v?, idx?) @ \\ 14 | \t1 let ~ ~ coll' == front(\{~ i : \nat ~| ~ i \in 0~..~idx?\} \extract coll?) \cat v? \\ 15 | \t1 \ \ \ ~~~ coll'' == \{~ j : \nat ~| ~ j \in idx?~..~\#~coll?\} \extract coll? \\ 16 | \t1 = coll' \cat coll'' \implies \\ 17 | \t2 (front(coll') \cat v? \cat coll'') ~ \land \\ 18 | \t2 (~ v? \mapsto idx? \in coll!) ~\land \\ 19 | \t2 (~\#~ coll! = \#~ coll? + 1) 20 | \end{schema} 21 | $append$ results in the composition of $coll'$ and $coll''$ such that 22 | $$coll! = coll' \cat coll'' ~ \land ~idx? \mapsto v? \in coll!$$ 23 | \begin{itemize} 24 | \item $coll'$ is the items in $coll?$ up to and including $idx?$ but the value at $idx?$ is replaced with $v?$ such that 25 | $idx? \mapsto coll?_{idx?} \not \in coll'$ 26 | \item $coll''$ is the items in $coll?$ from $idx?$ to $\#~coll? \implies coll?_{idx?} \in coll''$ 27 | \end{itemize} 28 | The following example illustrates these properties. 29 | \begin{argue} 30 | X = \langle x_{0}, x_{1}, x_{2} \rangle \\ 31 | \t1 x_{0} = 0 \\ 32 | \t1 x_{1} = foo \\ 33 | \t1 x_{2} = \langle a, b, c \rangle \\ 34 | \t1 v? = bar \\ 35 | append(X, v?, 0) = \langle bar, 0, foo, \langle a, b, c \rangle \rangle \\ 36 | append(X, v?, 1) = \langle 0, bar, foo, \langle a, b, c \rangle \rangle \\ 37 | append(X, v?, 2) = \langle 0, foo, bar, \langle a, b, c \rangle \rangle \\ 38 | append(X, v?, 3) = \langle 0, foo, \langle a, b, c \rangle, bar \rangle \\ 39 | append(X, v?, 4) = append(X, v?, 3) \iff 3 \not \in \dom X 40 | \end{argue} 41 | \end{document} 42 | -------------------------------------------------------------------------------- /docs/operations/collections/array?.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/collections/array?.pdf -------------------------------------------------------------------------------- /docs/operations/collections/array?.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Array?} 4 | The operation $array?$ will return a boolean which indicates if the passed in argument is a Collection 5 | \begin{schema}{Array?[V]} 6 | coll? : V \\ 7 | bol! : Boolean \\ 8 | array?~\_ : V \fun Boolean 9 | \where 10 | bol! = array?(coll?) @ bol! = true \iff coll? : Collection \implies V \hide (Scalar, KV) 11 | \end{schema} 12 | where $V \hide (Scalar, KV)$ is used to indicate that $coll?$ is of type $V$ 13 | \begin{zed} 14 | V ::= Scalar ~| ~Collection ~| ~KV 15 | \end{zed} 16 | but in order for $bol! = true$, $coll?$ must not be of type $Scalar ~\lor KV$ such that 17 | \begin{argue} 18 | X = \langle x_{0}, x_{1}, x_{2}, x_{3}, x_{4} \rangle \\ 19 | \t1 x_{0} = 0 \\ 20 | \t1 x_{1} = foo \\ 21 | \t1 x_{2} = \langle baz, \ qux \rangle \\ 22 | \t1 x_{3} = \ldata abc \mapsto 123, \ def \mapsto 456 \rdata \\ 23 | \t1 x_{4} = \langle \ldata ghi \mapsto 789, \ jkl \mapsto 101112 \rdata, \ \ldata ghi \mapsto 131415, \ jkl \mapsto 161718 \rdata \rangle \\ 24 | array?(X) = true & collection by definition\\ 25 | array?(x_{2}) = true & collection of $0 \mapsto baz$, $1 \mapsto qux$\\ 26 | array?(x_{4}) = true & collection of maps\\ 27 | array?(x_{0}) = false & Scalar \\ 28 | array?(x_{1}) = false & String \\ 29 | array?(x_{3}) = false & Map 30 | \end{argue} 31 | \end{document} 32 | -------------------------------------------------------------------------------- /docs/operations/collections/atIndex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/collections/atIndex.pdf -------------------------------------------------------------------------------- /docs/operations/collections/atIndex.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{At Index} 4 | The operation $atIndex$ will return the Value at a 5 | specified numeric index within a Collection or 6 | an empty Collection if there is no value at the specified index. 7 | \begin{schema}{AtIndex[Collection, \nat]} 8 | idx? : \nat\\ 9 | coll? : Collection \\ 10 | atIndex~\_ : Collection \cross \nat \surj V 11 | \where 12 | \# ~ idx? = 1 \\ 13 | coll! = atIndex(coll?, idx?) = (head ~(~idx? \extract coll?)) \iff idx? \in coll? \\ 14 | coll! = atIndex(coll?, idx?) = \langle \rangle \iff idx? \not \in coll? 15 | \end{schema} 16 | Given the definition of the $Collection$ and $V$ free types 17 | \begin{zed} 18 | Collection :== emptyColl ~| ~append \ldata Collection \cross Scalar ~\lor Collection ~\lor KV \cross \nat \rdata \\ 19 | V ::= Scalar ~| ~Collection ~| ~KV 20 | \end{zed} 21 | The collection member $coll?_{idx?} : V$ is implied from $append$ accepting the argument of type $Scalar ~\lor Collection ~\lor KV \equiv V$ which means each Collection member is of type $V$. Given that extraction ($~\_~\extract~\_$) returns a Collection, 22 | \begin{axdef} 23 | \seq X : Collection 24 | \where 25 | \_~\extract~\_ : \power \nat_1 \cross \seq X \fun \seq X 26 | \end{axdef} 27 | in order for $atIndex$ to return the collection member without altering its type, 28 | the first member of $atIdx'$ must be returned, not $atIdx'$ itself. 29 | \begin{axdef} 30 | atIdx' : Collection \\ 31 | coll!, coll?_{idx?} : V \\ 32 | \where 33 | atIdx' = (~idx? \extract coll?) \implies \langle coll?_{idx?} \rangle \\ 34 | coll! = head(atIdx') = coll?_{idx?} 35 | \end{axdef} 36 | The $head$ call is made possible by restricting $idx?$ to be a single numeric value. 37 | \begin{argue} 38 | idx?, idx' : \nat \\ 39 | \t1 \# ~ idx? = 1 @ (~idx? \extract coll?) = \langle coll?_{idx?} \rangle @ \\ 40 | \t2 (head (~idx? \extract coll?)) = coll?_{idx?} & expected return given $idx?$ \\ 41 | \t1 \# ~ idx' \geq 2 @ (~idx' \extract coll?) = \langle coll?_{idx'_{i}}~..~~coll?_{idx'_{j}} \rangle @ \\ 42 | \t2 (head (~idx' \extract coll?)) = coll?_{idx'_{i}} & unexpected return given $idx'$ 43 | \end{argue} 44 | Additionally, if the provided $idx? \not \in coll?$ then an empty Collection will be returned 45 | given that $head$ must be passed a non-empty Collection. 46 | \begin{axdef} 47 | head : \seq_1 X \fun X 48 | \where 49 | idx? \not \in coll? \implies (~idx? \extract coll?) = \langle \rangle ~ \lnot ~\seq_1 50 | \end{axdef} 51 | The properties of $atIndex$ are illustrated in the following examples. 52 | \begin{argue} 53 | X = \langle x_{0}, x_{1}, x_{2} \rangle \\ 54 | \t1 x_{0} = 0 \\ 55 | \t1 x_{1} = foo \\ 56 | \t1 x_{2} = \langle a, b, c \rangle \\ 57 | atIndex(X, 0) = 0 & $head~(\langle~x_{0}~\rangle)$\\ 58 | atIndex(X, 1) = foo & $head~(\langle~x_{1}~\rangle)$\\ 59 | atIndex(X, 2) = \langle a, b, c \rangle & $head~(\langle~x_{2}~\rangle)$\\ 60 | atIndex(X, 3) = \langle \rangle & $3 \not \in X \implies x_{3} \not \in X$ 61 | \end{argue} 62 | \end{document} 63 | -------------------------------------------------------------------------------- /docs/operations/collections/remove.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/collections/remove.pdf -------------------------------------------------------------------------------- /docs/operations/collections/remove.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Remove} 4 | The inverse of the $append$ Operations. 5 | \begin{zed} 6 | remove(coll, idx) = \inv append(coll, idx) 7 | \end{zed} 8 | The operation $remove$ will return a Collection minus the Value removed from the specified Numeric Index 9 | \begin{schema}{Remove[Collection, \nat]} 10 | coll?, coll! : Collection \\ 11 | idx? : \nat \\ 12 | remove~\_ : Collection \cross \nat \surj Collection 13 | \where 14 | \#~ idx? = 1 \\ 15 | coll! = remove(coll?, idx?) @ \\ 16 | \t1 let ~ ~ coll' == front(\{~ i : \nat ~| ~ i \in 0~..~idx?\} \extract coll?) \\ 17 | \t1 \ \ \ ~~~ coll'' == tail(\{~ j : \nat ~| ~ j \in idx?~..~\#~coll?\} \extract coll?) \\ 18 | \t1 = coll' \cat coll'' \implies \\ 19 | \t2 (coll?_{idx?} \not \in coll') ~\land \\ 20 | \t2 (coll?_{idx?} \not \in coll'') ~\land \\ 21 | \t2 (~\#~ coll! = \#~ coll? - 1) 22 | \end{schema} 23 | such that 24 | \begin{argue} 25 | X = \langle x_{0}, x_{1}, x_{2} \rangle \\ 26 | \t1 x_{0} = 0 \\ 27 | \t1 x_{1} = foo \\ 28 | \t1 x_{2} = baz \\ 29 | remove(X, 0) = \langle foo, baz \rangle & 0 was removed from $X$\\ 30 | remove(X, 1) = \langle 0, baz \rangle & foo was removed from $X$ \\ 31 | remove(X, 2) = \langle 0, foo \rangle & baz was removed from $X$ \\ 32 | remove(X, 3) = \langle 0, foo, baz \rangle = X & nothing at 3, X unaltered 33 | \end{argue} 34 | \end{document} 35 | -------------------------------------------------------------------------------- /docs/operations/collections/update.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/collections/update.pdf -------------------------------------------------------------------------------- /docs/operations/collections/update.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Update} 4 | The operation $update$ will return a Collection $coll!$ which is the same as the input Collection $coll?$ 5 | except for at index $idx?$. The existing member $coll?_{idx?}$ is replaced by the provided Value $v?$ at $idx?$ in $coll!$ 6 | such that 7 | $$idx? \mapsto v? \in coll! ~ \land ~ idx? \mapsto coll?_{idx?} \not \in coll!$$ 8 | which is equivalent to $remove ~\pipe ~append$ 9 | \begin{zed} 10 | update(coll?, v?, idx?) \equiv append(remove(coll?, idx?), v?, idx?) 11 | \end{zed} 12 | The functionality of $update$ is further explained in the following schema. 13 | \begin{schema}{Update[Collection, V, \nat]} 14 | idx? : \nat \\ 15 | coll?, coll! : Collection \\ 16 | v? : V \\ 17 | update~\_ : Collection \cross V \cross \nat \bij Collection 18 | \where 19 | 1 = \#~idx? \\ 20 | coll! = update(coll?, v?, idx?) @ \\ 21 | \t1 let ~ ~ coll' == \{~ i : \nat ~| ~ i \in 0~..~idx?\} \extract coll? \\ 22 | \t1 \ \ \ ~~~ coll'' == head(coll') ~\cat ~ v?\\ 23 | \t1 \ \ \ ~~~ coll''' == \{~ j : \nat ~| ~ j \in idx?+1~..~\#~coll?\} \extract coll? \\ 24 | \t1 = coll'' ~\cat ~coll'' \implies \\ 25 | \t2 (append(remove(coll', idx?), v?, idx?) \cat coll'') ~ \land \\ 26 | \t2 (~ v? \mapsto idx? \in coll!) ~\land \\ 27 | \t2 (~\#~ coll! = \#~ coll?) ~\land 28 | \end{schema} 29 | The value which previously existed at $idx? \in coll?$ is replaced with $v?$ to result in $coll!$ 30 | \begin{itemize} 31 | \item $coll'$ is the items in $coll?$ up to and including $idx?$ 32 | \item $coll''$ is the items in $coll?$ except the item at $idx?$ has been replaced with $v?$ 33 | \item $coll'''$ is the items in $coll?$ from $idx?+1$ to $\#~coll? \implies coll?_{idx?} \not \in coll''$ 34 | \end{itemize} 35 | The following example illustrates these properties. 36 | \begin{argue} 37 | X = \langle x_{0}, x_{1}, x_{2} \rangle \\ 38 | \t1 x_{0} = 0 \\ 39 | \t1 x_{1} = foo \\ 40 | \t1 x_{2} = \langle a, b, c \rangle \\ 41 | \t1 v? = bar \\ 42 | update(X, v?, 0) = \langle bar, foo, \langle a, b, c \rangle \rangle \\ 43 | update(X, v?, 1) = \langle 0, bar, \langle a, b, c \rangle \rangle \\ 44 | update(X, v?, 2) = \langle 0, foo, bar \rangle \\ 45 | update(X, v?, 3) = \langle 0, foo, \langle a, b, c \rangle, bar \rangle \\ 46 | update(X, v?, 4) = append(X, v?, 3) = update(X, v?, 3) \iff 3 \not \in \dom X 47 | \end{argue} 48 | \end{document} 49 | -------------------------------------------------------------------------------- /docs/operations/kv/associate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/kv/associate.pdf -------------------------------------------------------------------------------- /docs/operations/kv/associate.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Associate} 4 | The operation $associate$ establishes a relationship between $k?$ and $v?$ at the top level of $m!$. 5 | \begin{schema}{Associate[KV, K, V]} 6 | m?, m!, m' : KV \\ 7 | k? : K \\ 8 | v? : V \\ 9 | associate~\_ : KV \cross K \cross V \bij KV\ 10 | \where 11 | m! = associate(m?, k?, v?) @ \\ 12 | \t1 let ~~ m' == m? ~\ndres ~k? \implies \\ 13 | \t3 (\dom ~m' = \dom ~(~m? \setminus ~k?)) ~\land \\ 14 | \t3 (~m? \setminus ~m' = k? \iff k? \in m?) ~\land \\ 15 | \t3 (~m? \setminus ~m' = \emptyset \iff k? \not \in m? \implies m? = m')\\ 16 | \ \ \ ~ = \ldata k? \mapsto v? \rdata ~\union ~m' 17 | \end{schema} 18 | This implies that any existing mapping at $k? \in m?$ will be overwritten by $associate$ 19 | but an existing mapping is not a precondition. 20 | \begin{axdef} 21 | (k?, m?_{k?}) \in m? ~\lor ~(k?, m?_{k?}) \not \in m? \\ 22 | (k?, m?_{k?}) \not \in m! \\ 23 | (k?, v?) \in m! 24 | \where 25 | m! = associate(m?, k?, v?) 26 | \end{axdef} 27 | $associate$ does not alter any other mappings within $m?$ and this property is illustrated by the definition of local variable $m'$ 28 | \begin{axdef} 29 | m' : KV ~ | ~ m' = m? \ndres ~k? \implies m' \dres (m? \setminus ~k?) 30 | \where 31 | \dom ~m? = \{~ k_{i} : K ~|~ 0~..~\# ~m? @ k_{i} \in m? ~\land ~~0 ~\leq ~i ~\leq ~\# ~m?\} \\ 32 | \dom ~m' = \{~ k'_{i} : K ~|~ 0~..~\# ~m' @ k'_{i} \in m? ~\land ~k'_{i} \not = k? ~\land ~~0 ~\leq ~i ~\leq ~\# ~m'\} \\ 33 | \dom ~m' = \dom ~m? \iff k? \not \in m? \implies \forall k_{i} \in m? ~|~ k_{i} \not = k? \\ 34 | \# ~m' = \# ~m? \iff k? \not \in m? \\ 35 | \# ~m' = \# ~m? - 1 \iff k? \in m? 36 | \end{axdef} 37 | and its usage within the definition of $associate$. 38 | \begin{zed} 39 | m! = m? ~\cup ~\ldata ~k? \mapsto v? \rdata \implies k? \not \in m? \\ 40 | m! = m' ~\cup ~\ldata ~k? \mapsto v? \rdata \implies m' \not = m? ~\land ~~k? \in m? 41 | \end{zed} 42 | The following examples demonstrate the intended functionality of $associate$. 43 | \begin{argue} 44 | M = \ldata k_{0}v_{k_{0}}, k_{1}v_{k_{1}} \rdata \\ 45 | \t1 k_{0} = abc \ \land v_{k_{0}} = 123 & $k_{0}v_{k_{0}} = abc \mapsto 123$ \\ 46 | \t1 k_{1} = def \ \land v_{k_{1}} = xyz \mapsto 456 & $k_{1}v_{k_{1}} = def \mapsto xyz \mapsto 456$ \\ 47 | associate(M, baz, foo) = \ldata abc \mapsto 123, \ def \mapsto xyz \mapsto 456, \ baz \mapsto foo \rdata \\ 48 | associate(M, abc, 321) = \ldata abc \mapsto 321, \ def \mapsto xyz \mapsto 456 \rdata 49 | \end{argue} 50 | \end{document} 51 | -------------------------------------------------------------------------------- /docs/operations/kv/atKey.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/kv/atKey.pdf -------------------------------------------------------------------------------- /docs/operations/kv/atKey.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{At Key} 4 | The operation $atKey$ will return the Value $v$ at some specified Key $k$. 5 | \begin{schema}{AtKey[KV, K]} 6 | m? : KV \\ 7 | v! : V \\ 8 | k? : K \\ 9 | atKey~\_ : KV \cross K \surj V 10 | \where 11 | v! = atKey(m?, k?) @ \\ 12 | \t2 let ~~ coll == ((\seq m?) \filter (k?, m?_{k?})) \implies \langle (k?, m?_{k?}) \rangle \iff k? \in \dom m? \\ 13 | \ \ \ = (second(head(coll)) \iff k? \mapsto m?_{k?} \in coll) ~\lor \\ 14 | \t1 (\emptyset \iff k? \not \in \dom m?) 15 | \end{schema} 16 | In the schema above, $coll$ is the result of filtering for $(k?, m?_{k?})$ within $\seq m?$. 17 | If the mapping was in the original $m?$, it will also be in the sequence of mappings. This means 18 | we can filter over the sequence to look for the mapping and if found, it is returned as $\langle (k?, m?_{k?}) \rangle$. 19 | To return the mapping itself, $head(coll)$ is used to extract the mapping such that the value mapped to $k?$ can be returned. 20 | \begin{zed} 21 | v! = atKey(m?, k?) = second(head(coll)) = m?_{k?} @ m?_{k?} : V \iff k? \in \dom m? 22 | \end{zed} 23 | The following examples demonstrate the properties of $atKey$ 24 | \begin{argue} 25 | M = \ldata k_{0}v_{k_{0}}, k_{1}v_{k_{1}} \rdata \\ 26 | \t1 k_{0} = abc \ \land v_{k_{0}} = 123 & $k_{0}v_{k_{0}} = abc \mapsto 123$ \\ 27 | \t1 k_{1} = def \ \land v_{k_{1}} = xyz \mapsto 456 & $k_{1}v_{k_{1}} = def \mapsto xyz \mapsto 456$ \\ 28 | atKey(M, abc) = 123 \\ 29 | atKey(M, def) = xyz \mapsto 456 \\ 30 | atKey(M, foo) = \emptyset 31 | \end{argue} 32 | \end{document} 33 | -------------------------------------------------------------------------------- /docs/operations/kv/dissociate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/kv/dissociate.pdf -------------------------------------------------------------------------------- /docs/operations/kv/dissociate.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Dissociate} 4 | The operation $dissociate$ will remove some $k \mapsto v$ from $KV$ given $k \in KV$ 5 | \begin{schema}{Dissociate[KV, K]} 6 | m?, m! : KV \\ 7 | k? : K \\ 8 | dissociate~\_ : KV \cross K \surj KV 9 | \where 10 | m! = dissociate(m?, k?) @ m! = m? \ndres ~k? \implies \\ 11 | \t1 (\dom ~m! = \dom ~(~m? \setminus ~k?)) ~\land \\ 12 | \t1 (~m? \setminus ~m! = k? \iff k? \in m?) ~\land \\ 13 | \t1 (~m? \setminus ~m! = \emptyset \iff k? \not \in m? \implies m? = m!) ~\land \\ 14 | \t1 ((k?, m?_{k?}) \not \in m!) 15 | \end{schema} 16 | such that every mapping in $m?$ is also in $m!$ except for $k? \mapsto m?_{k?}$. 17 | \begin{argue} 18 | M = \ldata k_{0}v_{k_{0}}, k_{1}v_{k_{1}} \rdata \\ 19 | \t1 k_{0} = abc \ \land v_{k_{0}} = 123 & $k_{0}v_{k_{0}} = abc \mapsto 123$ \\ 20 | \t1 k_{1} = def \ \land v_{k_{1}} = xyz \mapsto 456 & $k_{1}v_{k_{1}} = def \mapsto xyz \mapsto 456$ \\ 21 | dissociate(M, abc) = \ldata def \mapsto xyz \mapsto 456 \rdata \\ 22 | dissociate(M, def) = \ldata abc \mapsto 123 \rdata \\ 23 | dissociate(M, xyz) = M & $xyz \not \in M$ 24 | \end{argue} 25 | \end{document} 26 | -------------------------------------------------------------------------------- /docs/operations/kv/map?.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/kv/map?.pdf -------------------------------------------------------------------------------- /docs/operations/kv/map?.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Map?} 4 | The operation $map?$ will return a boolean which indicates if the passed in argument is a $KV$ 5 | \begin{schema}{Map?[V]} 6 | m? : V \\ 7 | bol! : Boolean \\ 8 | map?~\_ : V \fun Boolean 9 | \where 10 | bol! = map?(m?) @ bol! = true \iff m? : KV \implies V \hide (Scalar, Collection) 11 | \end{schema} 12 | where $V \hide (Scalar, Collection)$ is used to indicate that $m?$ is of type $V$ 13 | \begin{zed} 14 | V ::= Scalar ~| ~Collection ~| ~KV 15 | \end{zed} 16 | but in order for $bol! = true$, $m?$ must not be of type $Scalar ~\lor Collection$ such that 17 | \begin{argue} 18 | X = \ldata x_{0}, x_{1}, x_{2}, x_{3}, x_{4} \rdata \\ 19 | \t1 x_{0} = 0 \\ 20 | \t1 x_{1} = foo \\ 21 | \t1 x_{2} = \langle baz, \ qux \rangle \\ 22 | \t1 x_{3} = \ldata abc \mapsto 123, \ def \mapsto 456 \rdata \\ 23 | \t1 x_{4} = \langle \ldata ghi \mapsto 789, \ jkl \mapsto 101112 \rdata, \ \ldata ghi \mapsto 131415, \ jkl \mapsto 161718 \rdata \rangle \\ 24 | map?(X) = true & KV by definition\\ 25 | map?(x_{3}) = true & KV \\ 26 | map?(x_{2}) = false & Collection \\ 27 | map?(x_{4}) = false & Collection of maps\\ 28 | map?(x_{0}) = false & Scalar \\ 29 | map?(x_{1}) = false & String 30 | \end{argue} 31 | \end{document} 32 | -------------------------------------------------------------------------------- /docs/operations/util/isoToUnix.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/util/isoToUnix.pdf -------------------------------------------------------------------------------- /docs/operations/util/isoToUnix.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Iso To Unix Epoch} 4 | The $isoToUnix$ operation converts an ISO 8601 Timestamp (see the \href{https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Data.md#timestamps}{xAPI Specification}) 5 | to the number of seconds that have elapsed since January 1, 1970 6 | \begin{schema}{IsoToUnix} 7 | Timestamp \\ 8 | seconds! : \nat \\ 9 | isoToUnix~\_ : \finset_1 \fun \nat \\ 10 | \where 11 | seconds! = isoToUnix(timestamp) 12 | \end{schema} 13 | \begin{argue} 14 | ts = 2015-11-18T12:17:00+00:00 \equiv 2015-11-18T12:17:00Z \\ 15 | isoToUnixEpoch(ts) = 1447849020 & ISO 8601 $\to$ Epoch time 16 | \end{argue} 17 | \end{document} 18 | -------------------------------------------------------------------------------- /docs/operations/util/map.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/util/map.pdf -------------------------------------------------------------------------------- /docs/operations/util/map.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | 4 | \subsubsection{Map} 5 | The $map$ operation takes in a function $fn?$, Collection $coll?$ and additional Arguments $args?$ (as necessary) 6 | and returns a modified Collection $coll!$ with members $fn!_{n}$. The ordering of $coll?$ is maintained within $coll!$ 7 | \begin{schema}{Map[(\_~\pfun~\_), Collection, V]} 8 | fn? : (\_~\pfun~\_) \\ 9 | args? : V \\ 10 | coll?, coll! : Collection \\ 11 | map~\_ : (\_~\pfun~\_) \cross Collection \cross V \surj Collection 12 | \where 13 | coll! = map(fn?, coll?, args?) @ \\ 14 | \t3 \langle ~\forall n : i~..~j \in coll? ~|~ i \leq n \leq j ~\land ~j = ~\# ~coll? @ \\ 15 | \t4 \exists_1 ~fn!_{n} : V ~|~ fn!_{n} = \\ 16 | \t5 (fn?(coll?_{n}, args?) \iff args? \not = \emptyset) ~\lor \\ 17 | \t5 (fn?(coll?_{n}) \iff args? = \emptyset) \rangle \implies fn!_{i} \cat fn!_{n} \cat fn!_{j} \\ 18 | \end{schema} 19 | Above, $fn!_{n}$ is introduced to handle the case where $fn?$ only requires a single argument. 20 | Additional arguments may be necessary but if they are not ($args? = \emptyset$) then only $coll?_{n}$ is passed to $fn?$. 21 | \begin{argue} 22 | X = \langle 1, 2, 3 \rangle \\ 23 | \t1 map~(succ, X) = \langle 2, 3, 4 \rangle & increment each member of $X$ \\ 24 | \t1 map~(+, X, 2) = \langle 3, 4, 5 \rangle & add 2 to each member of $X$ 25 | \end{argue} 26 | 27 | \end{document} 28 | -------------------------------------------------------------------------------- /docs/operations/util/rateOf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/util/rateOf.pdf -------------------------------------------------------------------------------- /docs/operations/util/rateOf.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | 4 | \subsection{Rate Of} 5 | The Operation $rateOf$ calculates the number of times something occurs 6 | within an interval of time given a unit of time. 7 | $$rateOf(nOccurances, start, end, unit)$$ 8 | Where the output translates to: the rate of occurrence per unit within interval 9 | \begin{itemize} 10 | \item $nOccurances$ is the number of times something happened and should be an Integer (called $nO?$ bellow) 11 | \item $start$ is an ISO 8601 timestamp which serves as the first timestamp within the interval 12 | \item $end$ is an ISO 8601 timestamp which servers as the last timestamp within the interval 13 | \item $unit$ is a String Enum representing the unit of time 14 | \end{itemize} 15 | This can be seen in the definition of $rateOf$ bellow. 16 | \begin{schema}{RateOf[\nat, TIMESTAMP, TIMESTAMP, TIMEUNIT]} 17 | nO? : \nat \\ 18 | rate! : \num \\ 19 | start?, end? : TIMESTAMP \\ 20 | unit? : TIMEUNIT \\ 21 | rateOf~\_ : \nat \cross TIMESTAMP \cross TIMESTAMP \cross TIMEUNIT \fun \num 22 | \where 23 | rate! = rateOf(nO?, start?, end?, unit?) @ \\ 24 | \t1 let \ \ ~~ interval == isoToUnix(end) - isoToUnix(start) \\ 25 | \t2 unitS == toSeconds(unit?) \\ 26 | \t1 \ = nO? \div (interval \div units) 27 | \end{schema} 28 | The only other functionality required by $rateOf$ is supplied via basic arithmetic 29 | \begin{argue} 30 | start = 2015-11-18T12:17:00Z \\ 31 | end = 2015-11-18T14:17:00Z \\ 32 | unit = second \\ 33 | nO? = 10 \\ 34 | \t1 startN = isoToUnix(start) = 1447849020 \\ 35 | \t1 endN = isoToUnix(end) = 1447856220 \\ 36 | \t1 interval = endN - StartN = 7200\\ 37 | \t1 unitN = toSeconds(unit) = 60 \\ 38 | 0.001389 = rateOf(nO?, start, end, unit) \implies 10 \div (7200 \div 60) \\ 39 | 5 = rateOf(nO?, start, end, hour) \implies 10 \div (7200 \div 3600) 40 | \end{argue} 41 | \end{document} 42 | -------------------------------------------------------------------------------- /docs/operations/util/timeUnitToNumberOfSeconds.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/operations/util/timeUnitToNumberOfSeconds.pdf -------------------------------------------------------------------------------- /docs/operations/util/timeUnitToNumberOfSeconds.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../../main.tex]{subfiles} 2 | \begin{document} 3 | \subsubsection{Timeunit To Number of Seconds} 4 | 5 | The operation $toSeconds$ will return the number of seconds corresponding to the input $Timeunit$ 6 | \begin{zed} 7 | Timeunit ::= second ~| ~ minute ~| ~hour ~| ~day ~| ~week ~| ~month ~| ~year 8 | \end{zed} 9 | such that the following schema defines $toSeconds$ 10 | \begin{schema}{ToSeconds[Timeunit]} 11 | t? : Timeunit \\ 12 | toSeconds~\_ : Timeunit \pfun \nat 13 | \where 14 | toSeconds(t?) = 1 \iff t? = second \\ 15 | toSeconds(t?) = 60 \iff t? = minute \\ 16 | toSeconds(t?) = 3600 \iff t? = hour \\ 17 | toSeconds(t?) = 86400 \iff t? = day \\ 18 | toSeconds(t?) = 604800 \iff t? = week \\ 19 | toSeconds(t?) = 2629743 \iff t? = month \\ 20 | toSeconds(t?) = 31556926 \iff t? = year 21 | \end{schema} 22 | \end{document} 23 | -------------------------------------------------------------------------------- /docs/primitives/atJsonPath.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/primitives/atJsonPath.pdf -------------------------------------------------------------------------------- /docs/primitives/atJsonPath.tex: -------------------------------------------------------------------------------- 1 | \documentclass[../main.tex]{subfiles} 2 | \begin{document} 3 | 4 | \subsection{At JSONPath} 5 | Performs a lookup at $path$ within $source$ similar to atKey 6 | $$atJsonPath(source, path)$$ 7 | such that the fundamental functionality of JSONPath is covered in this definition. 8 | \begin{itemize} 9 | \item A more complete definition will come at a future date if/as necessary 10 | \end{itemize} 11 | 12 | \subsubsection{Arguments} 13 | \begin{itemize} 14 | \item $source$ is an object Scalar, KV, Statement or an Algorithm State 15 | \item $path$ is a \href{https://goessner.net/articles/JsonPath/index.html#e2}{JSONPath string} which adheres to the 16 | \href{https://github.com/adlnet/xapi-profiles/blob/master/xapi-profiles-structure.md#81-statement-template-rules}{additional requirements, clarifications, and additions} placed on JSONPath by the \href{https://github.com/adlnet/xapi-profiles/blob/master/xapi-profiles-structure.md#part-two}{xAPI Profile Specification} 17 | \end{itemize} 18 | 19 | \subsubsection{Relevant Operations} 20 | The primitive $atJsonPath$ uses the operations 21 | \begin{itemize} 22 | \item atKey 23 | \item atIndex 24 | \item append 25 | \item count 26 | \end{itemize} 27 | 28 | \subsubsection{Summary} 29 | $atJsonPath$ will return a $v$ found within $source$ after converting 30 | $$path \to $$ 31 | such that if 32 | $$path = \$.a.b$$ 33 | then 34 | $$path \to $$ 35 | so that 36 | $$atJsonPath(, \$.a.b) = 123$$ 37 | 38 | \subsubsection{Usage of Operations} 39 | In order to convert 40 | $$path \to $$ 41 | an empty Collection $keyState$ is introduced 42 | $$keyState = <>$$ 43 | so that the relevant $k$'(s) can be stored in $keyState$ during iteration over $path$ 44 | $$\forall n : i..j \ \bullet i = 0 \ \land j = count(path) - 1$$ 45 | and the number of stored keys can be tracked using $curKeyStateIndex$ 46 | $$curKeyStateIndex = count(keyState) - 1$$ 47 | such that the current $path_{n}$ can be retrieved 48 | $$curKey = atIndex(path, n)$$ 49 | and $keepKey?$ can indicate the relevance of $path_{n}$ 50 | $$keepKey? = true \iff curKey \not= \$ \ \land curKey \not= . $$ 51 | such that during each iteration $n$, $keyState$ will be updated if necessary 52 | $$keyState = append(keyState, \ curKey, \ curKeyStateIndex) \iff keepKey? = true$$ 53 | so at the end of the loop 54 | $$keyState = $$ 55 | which provides the Collection of Key(s) necessary for calling $atKey$ 56 | $$valueInSource = atKey(source, keyState)$$ 57 | such that 58 | $$atJsonPath(source,path) \equiv atKey(source, keyState)$$ 59 | 60 | \subsubsection{Example output} 61 | Given an example $source$ 62 | $$source = , d \mapsto foo>$$ 63 | then 64 | $$atJsonPath(source, \$.a) = $$ 65 | and 66 | $$atJsonPath(source, \$.a.b) = 123$$ 67 | and 68 | $$atJsonPath(source, \$.a.c) = 456$$ 69 | and 70 | $$atJsonPath(source, \$.d) = foo$$ 71 | 72 | \end{document} 73 | -------------------------------------------------------------------------------- /docs/primitives/walk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/primitives/walk.pdf -------------------------------------------------------------------------------- /docs/z/Z-notation reference manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/z/Z-notation reference manual.pdf -------------------------------------------------------------------------------- /docs/z/introduction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/z/introduction.pdf -------------------------------------------------------------------------------- /docs/z/xapi.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/z/xapi.pdf -------------------------------------------------------------------------------- /docs/z/zed-csp-documentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yetanalytics/dave/7a71c2017889862b2fb567edc8196b4382d01beb/docs/z/zed-csp-documentation.pdf -------------------------------------------------------------------------------- /figwheel-main.edn: -------------------------------------------------------------------------------- 1 | ;; Figwheel-main configuration options see: https://figwheel.org/config-options 2 | ;; these will be overriden by the metadata config options in dev.cljs.edn build file 3 | { 4 | ;; Set the server port https://figwheel.org/config-options#ring-server-options 5 | ;; :ring-server-options {:port 9500} 6 | 7 | ;; Target directory https://figwheel.org/config-options#target-dir 8 | ;; you may want to set this to resources if you are using Leiningen 9 | ;; :target-dir "resources" 10 | 11 | ;; Server Ring Handler (optional) https://figwheel.org/docs/ring-handler.html 12 | ;; If you want to embed a ring handler into the figwheel server, this 13 | ;; is for simple ring servers 14 | ;; :ring-handler hello_world.server/handler 15 | 16 | ;; To be able to open files in your editor from the heads up display 17 | ;; you will need to put a script on your path. This script will have 18 | ;; to take a file path and a line number ie. 19 | ;; in ~/bin/myfile-opener: 20 | ;; 21 | ;; #! /bin/sh 22 | ;; emacsclient -n +$2:$3 $1 23 | ;; 24 | ;; :open-file-command "myfile-opener" 25 | 26 | ;; if you are using emacsclient you can just use 27 | ;; :open-file-command "emacsclient" 28 | 29 | ;; Logging output gets printed to the REPL, if you want to redirect it to a file: 30 | ;; :log-file "figwheel-main.log" 31 | } 32 | -------------------------------------------------------------------------------- /prod.cljs.edn: -------------------------------------------------------------------------------- 1 | ^{:open-url "http://localhost:[[server-port]]/prod_index.html"} 2 | {:closure-defines {"goog.DEBUG" false} 3 | :main com.yetanalytics.dave.ui.core 4 | :install-deps true 5 | :npm-deps {"material-components-web" "0.41.1"}} 6 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_alert.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Base styles 3 | // 4 | 5 | .alert { 6 | position: relative; 7 | padding: $alert-padding-y $alert-padding-x; 8 | margin-bottom: $alert-margin-bottom; 9 | border: $alert-border-width solid transparent; 10 | @include border-radius($alert-border-radius); 11 | } 12 | 13 | // Headings for larger alerts 14 | .alert-heading { 15 | // Specified to prevent conflicts of changing $headings-color 16 | color: inherit; 17 | } 18 | 19 | // Provide class for links that match alerts 20 | .alert-link { 21 | font-weight: $alert-link-font-weight; 22 | } 23 | 24 | 25 | // Dismissible alerts 26 | // 27 | // Expand the right padding and account for the close button's positioning. 28 | 29 | .alert-dismissible { 30 | padding-right: ($close-font-size + $alert-padding-x * 2); 31 | 32 | // Adjust close link position 33 | .close { 34 | position: absolute; 35 | top: 0; 36 | right: 0; 37 | padding: $alert-padding-y $alert-padding-x; 38 | color: inherit; 39 | } 40 | } 41 | 42 | 43 | // Alternate styles 44 | // 45 | // Generate contextual modifier classes for colorizing the alert. 46 | 47 | @each $color, $value in $theme-colors { 48 | .alert-#{$color} { 49 | @include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_badge.scss: -------------------------------------------------------------------------------- 1 | // Base class 2 | // 3 | // Requires one of the contextual, color modifier classes for `color` and 4 | // `background-color`. 5 | 6 | .badge { 7 | display: inline-block; 8 | padding: $badge-padding-y $badge-padding-x; 9 | font-size: $badge-font-size; 10 | font-weight: $badge-font-weight; 11 | line-height: 1; 12 | text-align: center; 13 | white-space: nowrap; 14 | vertical-align: baseline; 15 | @include border-radius($badge-border-radius); 16 | 17 | // Empty badges collapse automatically 18 | &:empty { 19 | display: none; 20 | } 21 | } 22 | 23 | // Quick fix for badges in buttons 24 | .btn .badge { 25 | position: relative; 26 | top: -1px; 27 | } 28 | 29 | // Pill badges 30 | // 31 | // Make them extra rounded with a modifier to replace v3's badges. 32 | 33 | .badge-pill { 34 | padding-right: $badge-pill-padding-x; 35 | padding-left: $badge-pill-padding-x; 36 | @include border-radius($badge-pill-border-radius); 37 | } 38 | 39 | // Colors 40 | // 41 | // Contextual variations (linked badges get darker on :hover). 42 | 43 | @each $color, $value in $theme-colors { 44 | .badge-#{$color} { 45 | @include badge-variant($value); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_breadcrumb.scss: -------------------------------------------------------------------------------- 1 | .breadcrumb { 2 | display: flex; 3 | flex-wrap: wrap; 4 | padding: $breadcrumb-padding-y $breadcrumb-padding-x; 5 | margin-bottom: $breadcrumb-margin-bottom; 6 | list-style: none; 7 | background-color: $breadcrumb-bg; 8 | @include border-radius($breadcrumb-border-radius); 9 | } 10 | 11 | .breadcrumb-item { 12 | // The separator between breadcrumbs (by default, a forward-slash: "/") 13 | + .breadcrumb-item { 14 | padding-left: $breadcrumb-item-padding; 15 | 16 | &::before { 17 | display: inline-block; // Suppress underlining of the separator in modern browsers 18 | padding-right: $breadcrumb-item-padding; 19 | color: $breadcrumb-divider-color; 20 | content: $breadcrumb-divider; 21 | } 22 | } 23 | 24 | // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built 25 | // without `
    `s. The `::before` pseudo-element generates an element 26 | // *within* the .breadcrumb-item and thereby inherits the `text-decoration`. 27 | // 28 | // To trick IE into suppressing the underline, we give the pseudo-element an 29 | // underline and then immediately remove it. 30 | + .breadcrumb-item:hover::before { 31 | text-decoration: underline; 32 | } 33 | // stylelint-disable-next-line no-duplicate-selectors 34 | + .breadcrumb-item:hover::before { 35 | text-decoration: none; 36 | } 37 | 38 | &.active { 39 | color: $breadcrumb-active-color; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_close.scss: -------------------------------------------------------------------------------- 1 | .close { 2 | float: right; 3 | font-size: $close-font-size; 4 | font-weight: $close-font-weight; 5 | line-height: 1; 6 | color: $close-color; 7 | text-shadow: $close-text-shadow; 8 | opacity: .5; 9 | 10 | &:not(:disabled):not(.disabled) { 11 | 12 | @include hover-focus { 13 | color: $close-color; 14 | text-decoration: none; 15 | opacity: .75; 16 | } 17 | 18 | // Opinionated: add "hand" cursor to non-disabled .close elements 19 | cursor: pointer; 20 | } 21 | } 22 | 23 | // Additional properties for button version 24 | // iOS requires the button element instead of an anchor tag. 25 | // If you want the anchor version, it requires `href="#"`. 26 | // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile 27 | 28 | // stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type 29 | button.close { 30 | padding: 0; 31 | background-color: transparent; 32 | border: 0; 33 | -webkit-appearance: none; 34 | } 35 | // stylelint-enable 36 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_code.scss: -------------------------------------------------------------------------------- 1 | // Inline code 2 | code { 3 | font-size: $code-font-size; 4 | color: $code-color; 5 | word-break: break-word; 6 | 7 | // Streamline the style when inside anchors to avoid broken underline and more 8 | a > & { 9 | color: inherit; 10 | } 11 | } 12 | 13 | // User input typically entered via keyboard 14 | kbd { 15 | padding: $kbd-padding-y $kbd-padding-x; 16 | font-size: $kbd-font-size; 17 | color: $kbd-color; 18 | background-color: $kbd-bg; 19 | @include border-radius($border-radius-sm); 20 | @include box-shadow($kbd-box-shadow); 21 | 22 | kbd { 23 | padding: 0; 24 | font-size: 100%; 25 | font-weight: $nested-kbd-font-weight; 26 | @include box-shadow(none); 27 | } 28 | } 29 | 30 | // Blocks of code 31 | pre { 32 | display: block; 33 | font-size: $code-font-size; 34 | color: $pre-color; 35 | 36 | // Account for some code outputs that place code tags in pre tags 37 | code { 38 | font-size: inherit; 39 | color: inherit; 40 | word-break: normal; 41 | } 42 | } 43 | 44 | // Enable scrollable blocks of code 45 | .pre-scrollable { 46 | max-height: $pre-scrollable-max-height; 47 | overflow-y: scroll; 48 | } 49 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_functions.scss: -------------------------------------------------------------------------------- 1 | // Bootstrap functions 2 | // 3 | // Utility mixins and functions for evaluating source code across our variables, maps, and mixins. 4 | 5 | // Ascending 6 | // Used to evaluate Sass maps like our grid breakpoints. 7 | @mixin _assert-ascending($map, $map-name) { 8 | $prev-key: null; 9 | $prev-num: null; 10 | @each $key, $num in $map { 11 | @if $prev-num == null { 12 | // Do nothing 13 | } @else if not comparable($prev-num, $num) { 14 | @warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !"; 15 | } @else if $prev-num >= $num { 16 | @warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !"; 17 | } 18 | $prev-key: $key; 19 | $prev-num: $num; 20 | } 21 | } 22 | 23 | // Starts at zero 24 | // Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0. 25 | @mixin _assert-starts-at-zero($map) { 26 | $values: map-values($map); 27 | $first-value: nth($values, 1); 28 | @if $first-value != 0 { 29 | @warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}."; 30 | } 31 | } 32 | 33 | // Replace `$search` with `$replace` in `$string` 34 | // Used on our SVG icon backgrounds for custom forms. 35 | // 36 | // @author Hugo Giraudel 37 | // @param {String} $string - Initial string 38 | // @param {String} $search - Substring to replace 39 | // @param {String} $replace ('') - New value 40 | // @return {String} - Updated string 41 | @function str-replace($string, $search, $replace: "") { 42 | $index: str-index($string, $search); 43 | 44 | @if $index { 45 | @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); 46 | } 47 | 48 | @return $string; 49 | } 50 | 51 | // Color contrast 52 | @function color-yiq($color) { 53 | $r: red($color); 54 | $g: green($color); 55 | $b: blue($color); 56 | 57 | $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000; 58 | 59 | @if ($yiq >= $yiq-contrasted-threshold) { 60 | @return $yiq-text-dark; 61 | } @else { 62 | @return $yiq-text-light; 63 | } 64 | } 65 | 66 | // Retrieve color Sass maps 67 | @function color($key: "blue") { 68 | @return map-get($colors, $key); 69 | } 70 | 71 | @function theme-color($key: "primary") { 72 | @return map-get($theme-colors, $key); 73 | } 74 | 75 | @function gray($key: "100") { 76 | @return map-get($grays, $key); 77 | } 78 | 79 | // Request a theme color level 80 | @function theme-color-level($color-name: "primary", $level: 0) { 81 | $color: theme-color($color-name); 82 | $color-base: if($level > 0, $black, $white); 83 | $level: abs($level); 84 | 85 | @return mix($color-base, $color, $level * $theme-color-interval); 86 | } 87 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_grid.scss: -------------------------------------------------------------------------------- 1 | // Container widths 2 | // 3 | // Set the container width, and override it for fixed navbars in media queries. 4 | 5 | @if $enable-grid-classes { 6 | .container { 7 | @include make-container(); 8 | @include make-container-max-widths(); 9 | } 10 | } 11 | 12 | // Fluid container 13 | // 14 | // Utilizes the mixin meant for fixed width containers, but with 100% width for 15 | // fluid, full width layouts. 16 | 17 | @if $enable-grid-classes { 18 | .container-fluid { 19 | @include make-container(); 20 | } 21 | } 22 | 23 | // Row 24 | // 25 | // Rows contain and clear the floats of your columns. 26 | 27 | @if $enable-grid-classes { 28 | .row { 29 | @include make-row(); 30 | } 31 | 32 | // Remove the negative margin from default .row, then the horizontal padding 33 | // from all immediate children columns (to prevent runaway style inheritance). 34 | .no-gutters { 35 | margin-right: 0; 36 | margin-left: 0; 37 | 38 | > .col, 39 | > [class*="col-"] { 40 | padding-right: 0; 41 | padding-left: 0; 42 | } 43 | } 44 | } 45 | 46 | // Columns 47 | // 48 | // Common styles for small and large grid columns 49 | 50 | @if $enable-grid-classes { 51 | @include make-grid-columns(); 52 | } 53 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_images.scss: -------------------------------------------------------------------------------- 1 | // Responsive images (ensure images don't scale beyond their parents) 2 | // 3 | // This is purposefully opt-in via an explicit class rather than being the default for all ``s. 4 | // We previously tried the "images are responsive by default" approach in Bootstrap v2, 5 | // and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps) 6 | // which weren't expecting the images within themselves to be involuntarily resized. 7 | // See also https://github.com/twbs/bootstrap/issues/18178 8 | .img-fluid { 9 | @include img-fluid; 10 | } 11 | 12 | 13 | // Image thumbnails 14 | .img-thumbnail { 15 | padding: $thumbnail-padding; 16 | background-color: $thumbnail-bg; 17 | border: $thumbnail-border-width solid $thumbnail-border-color; 18 | @include border-radius($thumbnail-border-radius); 19 | @include box-shadow($thumbnail-box-shadow); 20 | 21 | // Keep them at most 100% wide 22 | @include img-fluid; 23 | } 24 | 25 | // 26 | // Figures 27 | // 28 | 29 | .figure { 30 | // Ensures the caption's text aligns with the image. 31 | display: inline-block; 32 | } 33 | 34 | .figure-img { 35 | margin-bottom: ($spacer / 2); 36 | line-height: 1; 37 | } 38 | 39 | .figure-caption { 40 | font-size: $figure-caption-font-size; 41 | color: $figure-caption-color; 42 | } 43 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_jumbotron.scss: -------------------------------------------------------------------------------- 1 | .jumbotron { 2 | padding: $jumbotron-padding ($jumbotron-padding / 2); 3 | margin-bottom: $jumbotron-padding; 4 | background-color: $jumbotron-bg; 5 | @include border-radius($border-radius-lg); 6 | 7 | @include media-breakpoint-up(sm) { 8 | padding: ($jumbotron-padding * 2) $jumbotron-padding; 9 | } 10 | } 11 | 12 | .jumbotron-fluid { 13 | padding-right: 0; 14 | padding-left: 0; 15 | @include border-radius(0); 16 | } 17 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_media.scss: -------------------------------------------------------------------------------- 1 | .media { 2 | display: flex; 3 | align-items: flex-start; 4 | } 5 | 6 | .media-body { 7 | flex: 1; 8 | } 9 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Toggles 2 | // 3 | // Used in conjunction with global variables to enable certain theme features. 4 | 5 | // Utilities 6 | @import "mixins/breakpoints"; 7 | @import "mixins/hover"; 8 | @import "mixins/image"; 9 | @import "mixins/badge"; 10 | @import "mixins/resize"; 11 | @import "mixins/screen-reader"; 12 | @import "mixins/size"; 13 | @import "mixins/reset-text"; 14 | @import "mixins/text-emphasis"; 15 | @import "mixins/text-hide"; 16 | @import "mixins/text-truncate"; 17 | @import "mixins/visibility"; 18 | 19 | // // Components 20 | @import "mixins/alert"; 21 | @import "mixins/buttons"; 22 | @import "mixins/caret"; 23 | @import "mixins/pagination"; 24 | @import "mixins/lists"; 25 | @import "mixins/list-group"; 26 | @import "mixins/nav-divider"; 27 | @import "mixins/forms"; 28 | @import "mixins/table-row"; 29 | 30 | // // Skins 31 | @import "mixins/background-variant"; 32 | @import "mixins/border-radius"; 33 | @import "mixins/box-shadow"; 34 | @import "mixins/gradients"; 35 | @import "mixins/transition"; 36 | 37 | // // Layout 38 | @import "mixins/clearfix"; 39 | @import "mixins/grid-framework"; 40 | @import "mixins/grid"; 41 | @import "mixins/float"; 42 | -------------------------------------------------------------------------------- /resources/dave/ui/sass/bootstrap/_nav.scss: -------------------------------------------------------------------------------- 1 | // Base class 2 | // 3 | // Kickstart any navigation component with a set of style resets. Works with 4 | // `