Repository: arturo-lang/grafito Branch: main Commit: cdbeb8b76ea2 Files: 72 Total size: 734.5 KB Directory structure: gitextract_hq975k_i/ ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ ├── release.yml │ ├── test.yml │ └── todos.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── examples/ │ ├── sample1.art │ ├── sample10.art │ ├── sample11.art │ ├── sample12.art │ ├── sample2.art │ ├── sample3.art │ ├── sample4.art │ ├── sample4b.art │ ├── sample4c.art │ ├── sample4d.art │ ├── sample5.art │ ├── sample6.art │ ├── sample7.art │ ├── sample8.art │ └── sample9.art ├── grafito.art ├── info.art ├── logo.txt ├── sql/ │ ├── filters/ │ │ ├── edgePropertyWithValue.sql │ │ ├── edgeWithAny.sql │ │ ├── edgeWithProperties.sql │ │ ├── edgeWithSource.sql │ │ ├── edgeWithTarget.sql │ │ ├── hasEdge.sql │ │ ├── hasProperty.sql │ │ └── nodePropertyWithValue.sql │ ├── pragmas/ │ │ ├── caseInsensitiveLike.sql │ │ └── caseSensitiveLike.sql │ ├── procs/ │ │ ├── countEdges.sql │ │ ├── countNodes.sql │ │ ├── createEdge.sql │ │ ├── createNode.sql │ │ ├── deleteEdge.sql │ │ ├── deleteEdgeById.sql │ │ ├── deleteNode.sql │ │ ├── deleteNodeEdges.sql │ │ ├── fetchNodes.sql │ │ ├── fetchNodes.withEdges.sql │ │ ├── getAllNodeTags.sql │ │ ├── getMaxNodeId.sql │ │ ├── getNode.sql │ │ ├── getRelatedNodes.sql │ │ ├── updateEdge.sql │ │ ├── updateNode.sql │ │ ├── updateNodeProperties.sql │ │ └── updateNodeProperty.sql │ └── schema.sql └── ui/ ├── index.html ├── palettes/ │ ├── default.art │ ├── earthy.art │ ├── inferno.art │ ├── light.art │ ├── magma.art │ ├── pastel.art │ ├── playful.art │ ├── rainbow.art │ ├── vibrant.art │ └── viridis.art ├── scripts/ │ ├── ace/ │ │ ├── ace.js │ │ ├── modes/ │ │ │ └── grafito.js │ │ └── themes/ │ │ └── monokai.js │ └── app.js └── styles/ └── app.less ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ *.art linguist-language=Red *.art linguist-vendored ================================================ FILE: .github/FUNDING.yml ================================================ github: [drkameleon] ================================================ FILE: .github/workflows/release.yml ================================================ name: "Release" on: push: tags: - 'v*.*.*' env: app-name: grafito defaults: run: shell: bash -l {0} jobs: package: runs-on: ${{ matrix.os }} strategy: matrix: os: - ubuntu-latest - macos-latest version: - full steps: - name: "Cancel similar actions in progress" uses: styfle/cancel-workflow-action@0.6.0 with: access_token: ${{ github.token }} - name: "Get Arturo" uses: actions/checkout@main with: repository: arturo-lang/arturo submodules: recursive - name: Install Nim run: | wget -qO - https://nim-lang.org/choosenim/init.sh | bash -s -- -y echo "$HOME/.nimble/bin" >> $GITHUB_PATH - name: Install dependencies if: matrix.os == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install libwebkit2gtk-4.0-dev - name: Verify dependecies run: | nim --version - name: "Checkout" uses: actions/checkout@main with: submodules: recursive path: "grafito" - name: Package binary run: | mv grafito/grafito.art grafito.art rm -rf grafito ./package grafito.art ls -la - name: Create artifact run: | install -m 0755 ./grafito . tar czf ${{ env.app-name }}-${{runner.os}}.tar.gz ${{ env.app-name }} README.md LICENSE - name: Upload Artifact uses: 'actions/upload-artifact@v1' with: name: ${{ env.app-name }}-${{runner.os}}.tar.gz path: ${{ env.app-name }}-${{runner.os}}.tar.gz upload: name: "Upload" runs-on: ubuntu-latest if: ${{ always() }} needs: - package steps: - uses: actions/download-artifact@v2 with: path: ./assets - name: Display structure of downloaded files run: ls -R - name: Create Release id: create-release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} release_name: ${{ github.ref }} body: | Official Release ${{ github.ref }} draft: false prerelease: false - name: Upload Release Assets id: upload-release-assets uses: dwenegar/upload-release-assets@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: release_id: ${{ steps.create-release.outputs.id }} assets_path: ./assets ================================================ FILE: .github/workflows/test.yml ================================================ name: "CI" on: push: branches: - master pull_request: types: [opened, synchronize] workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build: name: "Test" runs-on: ${{ (matrix.os == 'linux') && (matrix.arch == 'arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest') || (matrix.os == 'macos') && (matrix.arch == 'arm64' && 'macos-latest' || 'macOS-15-intel') || (matrix.os == 'windows') && 'windows-latest' || 'ubuntu-latest' }} # TODO(workflows/test) FreeBSD workflow gets stuck # Not sure if it has to do with the VM setup on GitHub Actions # or something related to the implementation of Grafito, # but we'll have to investigate this. # labels: workflows, bug strategy: fail-fast: false matrix: include: - {os: linux, arch: amd64} - {os: linux, arch: arm64} # - {os: freebsd, arch: amd64} - {os: macos, arch: amd64} - {os: macos, arch: arm64} - {os: windows, arch: amd64} defaults: run: shell: ${{ (matrix.os == 'freebsd') && 'freebsd {0}' || (matrix.os == 'windows') && 'msys2 {0}' || 'bash' }} steps: - name: "Checkout sources" uses: actions/checkout@v4 with: submodules: recursive - name: Setup Arturo uses: arturo-lang/setup-arturo@v2 with: token: ${{ secrets.GITHUB_TOKEN }} os: ${{ matrix.os }} arch: ${{ matrix.arch }} - name: Run unit tests run: | cd $GITHUB_WORKSPACE arturo -e "inspect sys\deps" arturo tests/test1.art ================================================ FILE: .github/workflows/todos.yml ================================================ name: "TODO -> Issue" on: push: branches: - 'main' tags-ignore: - '**' jobs: build: runs-on: "ubuntu-latest" steps: - uses: "actions/checkout@main" - name: "TODO to Issue generator" uses: "alstr/todo-to-issue-action@v4.5" id: "todo" with: TOKEN: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .gitignore ================================================ *.db *.graf test*.sql test*.nim test*.html testy.art test*.art ================================================ FILE: Dockerfile ================================================ FROM arturolang/arturo RUN apk update && apk upgrade RUN apk add --no-cache sqlite-dev RUN apk add sqlite ADD grafito.art /home/grafito.art WORKDIR /home ENTRYPOINT [ "/home/grafito.art" ] ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2024 Yanis Zafirópulos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================

Portable, Serverless & Lightweight
SQLite-based Graph Database


Language

--- * [At A Glance](#at-a-glance) * [Try Grafito](#try-grafito) * [Docker](#docker) * [Installation](#installation) * [As a Library](#as-a-library) * [As a Standalone tool](#as-a-standalone-tool) * [How To](#how-to) * [Create a simple Node](#create-a-simple-node) * [Create Relationships between Nodes](#create-relationships-between-nodes) * [Search Nodes](#search-nodes) * [Delete an existing Node](#delete-an-existing-node) * [Delete an existing Relationship](#delete-an-existing-relationship) * [Preview a Set of Nodes](#preview-a-set-of-nodes) * [More complex queries](#more-complex-queries) * [Reverse edge queries](#reverse-edge-queries) * [Using filters](#using-filters) * [Not just a query language!](#not-just-a-query-language) * [Command Reference](#command-reference) * [put](#put) * [unput](#unput) * [link](#link) * [unlink](#unlink) * [what](#what) * [fetch](#fetch) * [preview](#preview) * [Filter Reference](#filter-reference) * [contains](#contains) * [prefix](#prefix) * [suffix](#suffix) * [over](#over) * [under](#under) * [overOrEqual](#greaterOrEqual) * [underOrEqual](#underOrEqual) * [in](#in) * [not](#not) * [Community](#community) * [License](#license) --- ## At A Glance I know you really don't care about long explanations and want to have a look at working code right away, so... here you are (this is the code that creates the graph in the image above): ```red ;--------------------------------------------- ; Import Grafito ; and ... let's rock'n'roll! :) ;--------------------------------------------- do.import {grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample11" ;--------------------------------------------- graph .helpers: [person movie country book] .create .palette: 'default "sample11" [ unless dbExists? [ ;--------------------------------------------- ; Populate the database ;--------------------------------------------- uk: country.new [name: "United Kingdom"] au: country.new [name: "Australia"] us: country.new [name: "United States"] ca: country.new [name: "Canada"] fr: country.new [name: "France"] de: country.new [name: "Germany"] se: country.new [name: "Sweden"] es: country.new [name: "Spain"] pl: country.new [name: "Poland"] nolan: person.new [name: "Christopher Nolan" birthday: 1970 sex: "m"] pearce: person.new [name: "Guy Pearce" birthday: 1967 sex: "m"] hanson: person.new [name: "Curtis Hanson" birthday: 1945 sex: "m"] spacey: person.new [name: "Kevin Spacey" birthday: 1959 sex: "m"] dicaprio: person.new [name: "Leonardo DiCaprio" birthday: 1974 sex: "m"] hardy: person.new [name: "Tom Hardy" birthday: 1977 sex: "m"] cotillard: person.new [name: "Marion Cotillard" birthday: 1975 sex: "f"] moss: person.new [name: "Carrie-Ann Moss" birthday: 1967 sex: "f"] kidman: person.new [name: "Nicole Kidman" birthday: 1967 sex: "f"] cruise: person.new [name: "Tom Cruise" birthday: 1962 sex: "m"] kubrick: person.new [name: "Stanley Kubrick" birthday: 1928 died: 1999 sex: "m" alive: false] burton: person.new [name: "Tim Burton" birthday: 1958 sex: "m"] depp: person.new [name: "Johny Depp" birthday: 1965 sex: "m"] hallstrom: person.new [name: "Lasse Hallström" birthday: 1946 sex: "m"] scorsese: person.new [name: "Martin Scorsese" birthday: 1942 sex: "m"] sydow: person.new [name: "Max von Sydow" birthday: 1929 died: 2020 sex: "m" alive: false] binoche: person.new [name: "Juliette Binoche" birthday: 1964 sex: "f"] dench: person.new [name: "Judi Dench" birthday: 1934 sex: "f"] eastwood: person.new [name: "Clint Eastwood" birthday: 1930 sex: "m"] polanski: person.new [name: "Roman Polanski" birthday: 1933 sex: "m"] olin: person.new [name: "Lena Olin" birthday: 1955 sex: "f"] zimmer: person.new [name: "Hans Zimmer" birthday: 1957 sex: "m"] pook: person.new [name: "Jocelyn Pook" birthday: 1960 sex: "f"] lehane: person.new [name: "Dennis Lehane" birthday: 1965 sex: "m"] penn: person.new [name: "Sean Penn" birthday: 1960 sex: "m"] malick: person.new [name: "Terrence Malick" birthday: 1943 sex: "m"] brody: person.new [name: "Adrien Brody" birthday: 1973 sex: "m"] wach1: person.new [name: "Lana Wachowski" birthday: 1965 sex: "f"] wach2: person.new [name: "Lilly Wachowski" birthday: 1967 sex: "f"] memento: movie.new [title: "Memento" year: 2000] inception: movie.new [title: "Inception" year: 2010] laconfidential: movie.new [title: "L.A. Confidential" year: 1997] matrix: movie.new [title: "The Matrix" year: 1999] eyes: movie.new [title: "Eyes Wide Shut" year: 1999] bigfish: movie.new [title: "Big Fish" year: 2003] sleepyhollow: movie.new [title: "Sleepy Hollow" year: 1999] chocolat: movie.new [title: "Chocolat" year: 2000] jedgar: movie.new [title: "J. Edgar" year: 2011] ninthgate: movie.new [title: "The Ninth Gate" year: 1999] shutter: movie.new [title: "Shutter Island" year: 2010] mystic: movie.new [title: "Mystic River" year: 2003] redline: movie.new [title: "Thin Red Line" year: 1998] pianist: movie.new [title: "The Pianist" year: 2002] mysticB: book.new [title: "Mystic River" year: 2001 language: "en"] ;--------------------------------------------- ; Define the relationships ; between our nodes ;--------------------------------------------- [nolan hardy dench pook] ~> 'isFrom uk [pearce kidman] ~> 'isFrom au [malick brody hanson spacey dicaprio wach1 wach2 cruise kubrick burton depp eastwood scorsese lehane penn] ~> 'isFrom us moss ~> 'isFrom ca [cotillard binoche] ~> 'isFrom fr polanski ~> 'isFrom [fr pl] [hallstrom olin sydow] ~> 'isFrom se zimmer ~> 'isFrom de nolan ~> 'directed [memento inception] hanson ~> 'directed laconfidential [wach1 wach2] ~> 'directed matrix kubrick ~> 'directed eyes burton ~> 'directed [bigfish sleepyhollow] hallstrom ~> 'directed chocolat eastwood ~> 'directed [jedgar mystic] polanski ~> 'directed [pianist ninthgate] scorsese ~> 'directed shutter malick ~> 'directed [pianist redline] pearce ~> 'actedIn [memento laconfidential] spacey ~> 'actedIn laconfidential [dicaprio hardy cotillard] ~> 'actedIn inception [dicaprio sydow] ~> 'actedIn shutter cotillard ~> 'actedIn bigfish moss ~> 'actedIn [memento matrix chocolat] [cruise kidman] ~> 'actedIn eyes depp ~> 'actedIn [chocolat sleepyhollow] [binoche dench olin] ~> 'actedIn chocolat [dicaprio dench] ~> 'actedIn jedgar [depp olin] ~> 'actedIn ninthgate penn ~> 'actedIn [mystic redline] brody ~> 'actedIn [redline pianist] zimmer ~> 'composed inception pook ~> 'composed eyes nolan ~> 'written inception lehane ~> 'written mysticB mystic ~> 'basedOn mysticB [redline bigfish memento laconfidential jedgar shutter mystic] ~> 'origin us matrix ~> 'origin [us au] [inception eyes chocolat] ~> 'origin [uk us] sleepyhollow ~> 'origin [us de] ninthgate ~> 'origin [us fr es] pianist ~> 'origin [uk fr de pl] wach1 ~> 'sibling wach2 cruise ~> 'married kidman ] ;--------------------------------------------- ; Fetch every "person" & ; open the Desktop app for visualization ;--------------------------------------------- preview fetch 'person ø ] ] ``` ## Try Grafito! ### Docker The easiest way to try Grafito is using Docker (although, without support for the Desktop app - yet) ``` docker run -it arturolang/grafito ``` or, if you want to run a specific script: ``` docker run -it -v $(pwd):/home arturolang/grafito ``` ### Installation To install local, first you have to have installed the latest version of [Arturo](https://github.com/arturo-lang/arturo). Then, just clone this repo and simply go to the folder via your terminal. #### As a Library After having installed the latest version of Arturo, you can use Grafito from any Arturo script as a library. For example, here's how to run the above example: ``` arturo examples/sample11.art ``` #### As a Standalone tool Of course, you can also run Grafito as a tool on it own: ``` ./grafito.art ``` (If you pass a name, it will use it as your database file. If not, the database will be in-memory)

And you can see your lightweight graph engine in action! ## How To ### Create a simple Node ```red graph.create "mygraph" [ put'person [name: "John" sex: 'm] ] ``` The exact same thing using node helpers: ```red graph.create "mygraph" .helpers: [person] [ person.new [name: "John", sex: 'm] ] ``` ### Create Relationships between Nodes ```red graph.create "mygraph" [ john: put 'person [name: "John" sex: 'm] joan: put 'person [name: "Joan" sex: 'f] link john 'marriedTo joan ] ``` The exact same thing using node helpers and some syntactic sugar: ```red graph.create "mygraph" .helpers: [person] [ john: person.new [name: "John", sex: 'm] joan: person.new [name: "Joan", sex: 'f] john <~> 'marriedTo joan ] ``` ### Search Nodes ```red graph "mygraph" [ inspect fetch 'person [name: "Joan"] ] ``` The exact same thing using node helpers: ```red graph "mygraph" .helpers: [person] [ inspect person [name: "Joan"] ] ``` ### Delete an existing Node ```red graph "mygraph" [ unput fetch 'person [name: "John"] ] ``` ### Delete an existing Relationship ```red graph "mygraph" [ unlink fetch 'person [name: "John"] 'marriedTo fetch 'person [name: "Joan"] ] ``` ### Preview a Set of Nodes ```red graph "mygraph" [ preview fetch 'person ø ] ``` (If you run the `sample4` in the *examples* folder, you'll be a minimal movie database. Running the command `preview` will open up the Desktop app with the image you see above ;-)) ### More complex queries ```red graph "mygraph" [ inspect fetch'person [ sex: "m" marriedTo: fetch 'person [name: "Joan"] ] ] ``` The exact same thing using node helpers: ```red graph "mygraph" .helpers: [person] [ inspect person [ sex: "m" marriedTo: person [name: "Joan"] ] ] ``` #### Reverse edge queries ```red ; using our sample11.art graph movie [ directed: <| person "Clint Eastwood" ] ``` #### Using filters ```red graph "mygraph" [ fetch 'person [ surname:"Doe" age: -> over: 30 ] ] ``` ### Not just a query language! Now, let's be reminded that although Grafito may present itself as an easy-to-use Graph Query Language, actually it's a "shell" on top of Arturo. That is: you can use anything you would normally use in a full-blown programming language, *along with* the extra layer that is Grafito. Awesome, right? The above is a - very simple - example, but gives you definitely a rough idea (and no, [`union`](https://arturo-lang.io/documentation/library/sets/union/) has nothing to do with Grafito... it's just a normal command from Arturo's standard library) ```red union person [ sex: "m" birthday: -> under: 1960 ] person [ sex: "f isFrom: country "France" ] ``` (totally random example: Find all the men that were born before 1960 + all the women from... France!) ## Command Reference All of the following commands must run within a `graph` environment. In order to set it up, use: ```red graph [ ;; your code goes here ] ``` > ⚠️ The `graph` command is not needed when you run Grafito as a tool, since the "environment" is already set up for you. ;-) If you pass `null` (or `ø`) then the database will be *in-memory*. If you want to save to a file on disk, then pass a string with the desired database name. If the database already exists, it will be re-opened. If not, it will be created from scratch. > 💡 You may force the database to be re-created from scratch, regardless of whether it exists, by setting the `.create` attribute. E.g. > ``` > graph.create "mygraph" [ > ;; your code goes here > ] > ``` ### put #### Description Insert new node(s) to graph with given name and attributes. #### Usage
put name :literal, :string
    attributes :dictionary, :block
#### Returns - *:dictionary* (node) - *:block* (of nodes) #### Examples ```red put 'person [name: "John" surname: "Doe" birthday: 1986] ``` ### unput #### Description Remove given node(s) from graph. #### Usage
unput node :dictionary, :block
#### Examples ```red x: put 'person [name: "John" surname: "Doe" birthday: 1986] unput x ``` ### link #### Description Create a connection from source to target node with given name. #### Usage
link source :dictionary (node), :block (of nodes)
     name :literal, :string
     target :dictionary (node), :block (of nodes)
#### Returns - *:dictionary* (edge) #### Examples ```red link put 'person [name: "John" surname: "Doe" birthday: 1986] 'marriedTo put 'person [name: "Mary" surname: "Doe" birthday: 1986] ``` ### unlink #### Description Remove connection from source to target node with given name #### Usage
unlink source :dictionary (node), :block (of nodes)
       name :literal, :string
       target :dictionary (node), :block (of nodes)
#### Examples ```red x: put 'person [name: "John" surname: "Doe" birthday: 1986] y: put 'person [name: "Mary" surname: "Doe" birthday: 1986] link 'marriedTo x y unlink 'marriedTo x y ``` ### fetch #### Description Retrieves nodes with name that match all given attributes. #### Usage
fetch name :literal, :string
      properties :block :dictionary :null
#### Returns - *:block* of *:dictionary* (node) #### Examples ```red print fetch 'person [surname: "Doe"] print fetch 'person [ surname: "Doe" marriedTo: fetch'person [name: "Mary"] ] ``` ### preview #### Description Preview given array of nodes in Desktop app. #### Usage
preview nodes :block
#### Examples ```red preview fetch 'person [surname: "Doe"] ``` ## Filter Reference When querying - e.g. with `fetch` or `what` - you can search for results, not only for exact matches, but also using one of the filters below. ```red fetch'person [ surname: "Doe" ; here, we are looking for an exact match ; that is: people with the surname Doe ] ``` ```red fetch'person [ surname: [ contains: "D" ; here, we are using the 'contains filter ; that is: people whose surname contains the letter D ] ] ``` (The above, using Arturo's powerful syntax, could also be written like: ```red fetch'person [ surname: -> contains: "D" ] ``` ### contains Get rows that *contain* the given text. ### prefix Get rows that start with, or "have as prefix", the given text. ### suffix Get rows that end with, or "have as suffix", the given text. ### over Get rows with a numeric value *greater than* the given one. ### under Get rows with a numeric value *less than* the given one. ### overOrEqual Get rows with a numeric value *greater than or equal to* the given one. ### underOrEqual Get rows with a numeric value *less than or equal to* the given one. ### in Get rows with a numeric value *equal* to *one of those in* the given block. ### not Get rows with a value *not equal to* the given one (or block of given values). Community ------------------------------ In case you want to ask a question, suggest an idea, or practically anything related to Grafito (or Arturo) - feel free! Everything and everyone is welcome. For that, the most convenient place for me would be the [GitHub Issues](https://github.com/arturo-lang/grafito/issues) page. [![Stargazers over time](https://starchart.cc/arturo-lang/grafito.svg)](https://starchart.cc/arturo-lang/grafito) ## License MIT License Copyright (c) 2023 Yanis Zafirópulos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: examples/sample1.art ================================================ ;; Just run this with: ;; arturo sample.art ;; ;; This will create a local sample.db ;; along with the corresponding dot file ;; and its visualization as sample.png ;; - provided GraphViz is installed ;; ;; Have fun! do.import "grafito.art" do [ graph.create "sample1" [ john: put 'person [s: "John" sex: 'm] joan: put 'person [s: "Joan" sex: 'f] bob: put 'person [s: "Bob" sex: 'm] jill: put 'person [s: "Jill" sex: 'f] link'marriedTo john joan link'childOf @[bob jill] @[john joan] ] ] do [ benchmark [ graph.verbose "sample1" [ print "getting first person named Joan..." joan: what'person [s: "Joan"] inspect joan print "getting all male people married to Joan..." husband: what 'person [sex: 'm marriedTo: joan] inspect husband ; inspect fetch 'person [ ; marriedTo: what 'person [s: "Joan"] ; ] preview fetch 'person ø ] ] ] ; do [ ; graph "sample1" [ ; preview fetch 'person ø ; ] ; ] ; execute ~"dot -Tpng sample.dot -o sample.png" ================================================ FILE: examples/sample10.art ================================================ do.import {grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample4" ;--------------------------------------------- graph.create "sample10" [ j: put 'person [name: "John" age: 35] n: put 'person [name: "Jane" age: 41] link 'likes j n preview fetch 'person ø ] ] ================================================ FILE: examples/sample11.art ================================================ ;--------------------------------------------- ; Import Grafito ; and ... let's rock'n'roll! :) ;--------------------------------------------- import ./{../grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample11" ;--------------------------------------------- graph .helpers: [person movie country book] .create .palette: 'default "sample11" [ unless dbExists? [ ;--------------------------------------------- ; Populate the database ;--------------------------------------------- uk: country.new [name: "United Kingdom"] au: country.new [name: "Australia"] us: country.new [name: "United States"] ca: country.new [name: "Canada"] fr: country.new [name: "France"] de: country.new [name: "Germany"] se: country.new [name: "Sweden"] es: country.new [name: "Spain"] pl: country.new [name: "Poland"] nolan: person.new [name: "Christopher Nolan" birthday: 1970 sex: "m"] pearce: person.new [name: "Guy Pearce" birthday: 1967 sex: "m"] hanson: person.new [name: "Curtis Hanson" birthday: 1945 sex: "m"] spacey: person.new [name: "Kevin Spacey" birthday: 1959 sex: "m"] dicaprio: person.new [name: "Leonardo DiCaprio" birthday: 1974 sex: "m"] hardy: person.new [name: "Tom Hardy" birthday: 1977 sex: "m"] cotillard: person.new [name: "Marion Cotillard" birthday: 1975 sex: "f"] moss: person.new [name: "Carrie-Ann Moss" birthday: 1967 sex: "f"] kidman: person.new [name: "Nicole Kidman" birthday: 1967 sex: "f"] cruise: person.new [name: "Tom Cruise" birthday: 1962 sex: "m"] kubrick: person.new [name: "Stanley Kubrick" birthday: 1928 died: 1999 sex: "m" alive: false] burton: person.new [name: "Tim Burton" birthday: 1958 sex: "m"] depp: person.new [name: "Johny Depp" birthday: 1965 sex: "m"] hallstrom: person.new [name: "Lasse Hallström" birthday: 1946 sex: "m"] scorsese: person.new [name: "Martin Scorsese" birthday: 1942 sex: "m"] sydow: person.new [name: "Max von Sydow" birthday: 1929 died: 2020 sex: "m" alive: false] binoche: person.new [name: "Juliette Binoche" birthday: 1964 sex: "f"] dench: person.new [name: "Judi Dench" birthday: 1934 sex: "f"] eastwood: person.new [name: "Clint Eastwood" birthday: 1930 sex: "m"] polanski: person.new [name: "Roman Polanski" birthday: 1933 sex: "m"] olin: person.new [name: "Lena Olin" birthday: 1955 sex: "f"] zimmer: person.new [name: "Hans Zimmer" birthday: 1957 sex: "m"] pook: person.new [name: "Jocelyn Pook" birthday: 1960 sex: "f"] lehane: person.new [name: "Dennis Lehane" birthday: 1965 sex: "m"] penn: person.new [name: "Sean Penn" birthday: 1960 sex: "m"] malick: person.new [name: "Terrence Malick" birthday: 1943 sex: "m"] brody: person.new [name: "Adrien Brody" birthday: 1973 sex: "m"] wach1: person.new [name: "Lana Wachowski" birthday: 1965 sex: "f"] wach2: person.new [name: "Lilly Wachowski" birthday: 1967 sex: "f"] memento: movie.new [title: "Memento" year: 2000] inception: movie.new [title: "Inception" year: 2010] laconfidential: movie.new [title: "L.A. Confidential" year: 1997] matrix: movie.new [title: "The Matrix" year: 1999] eyes: movie.new [title: "Eyes Wide Shut" year: 1999] bigfish: movie.new [title: "Big Fish" year: 2003] sleepyhollow: movie.new [title: "Sleepy Hollow" year: 1999] chocolat: movie.new [title: "Chocolat" year: 2000] jedgar: movie.new [title: "J. Edgar" year: 2011] ninthgate: movie.new [title: "The Ninth Gate" year: 1999] shutter: movie.new [title: "Shutter Island" year: 2010] mystic: movie.new [title: "Mystic River" year: 2003] redline: movie.new [title: "Thin Red Line" year: 1998] pianist: movie.new [title: "The Pianist" year: 2002] mysticB: book.new [title: "Mystic River" year: 2001 language: "en"] ;--------------------------------------------- ; Define the relationships ; between our nodes ;--------------------------------------------- [nolan hardy dench pook] ~> 'isFrom uk [pearce kidman] ~> 'isFrom au [malick brody hanson spacey dicaprio wach1 wach2 cruise kubrick burton depp eastwood scorsese lehane penn] ~> 'isFrom us moss ~> 'isFrom ca [cotillard binoche] ~> 'isFrom fr polanski ~> 'isFrom [fr pl] [hallstrom olin sydow] ~> 'isFrom se zimmer ~> 'isFrom de nolan ~> 'directed [memento inception] hanson ~> 'directed laconfidential [wach1 wach2] ~> 'directed matrix kubrick ~> 'directed eyes burton ~> 'directed [bigfish sleepyhollow] hallstrom ~> 'directed chocolat eastwood ~> 'directed [jedgar mystic] polanski ~> 'directed [pianist ninthgate] scorsese ~> 'directed shutter malick ~> 'directed [pianist redline] pearce ~> 'actedIn [memento laconfidential] spacey ~> 'actedIn laconfidential [dicaprio hardy cotillard] ~> 'actedIn inception [dicaprio sydow] ~> 'actedIn shutter cotillard ~> 'actedIn bigfish moss ~> 'actedIn [memento matrix chocolat] [cruise kidman] ~> 'actedIn eyes depp ~> 'actedIn [chocolat sleepyhollow] [binoche dench olin] ~> 'actedIn chocolat [dicaprio dench] ~> 'actedIn jedgar [depp olin] ~> 'actedIn ninthgate penn ~> 'actedIn [mystic redline] brody ~> 'actedIn [redline pianist] zimmer ~> 'composed inception pook ~> 'composed eyes nolan ~> 'written inception lehane ~> 'written mysticB mystic ~> 'basedOn mysticB [redline bigfish memento laconfidential jedgar shutter mystic] ~> 'origin us matrix ~> 'origin [us au] [inception eyes chocolat] ~> 'origin [uk us] sleepyhollow ~> 'origin [us de] ninthgate ~> 'origin [us fr es] pianist ~> 'origin [uk fr de pl] wach1 ~> 'sibling wach2 cruise ~> 'married kidman ] ;--------------------------------------------- ; Fetch every "person" & ; open the Desktop app for visualization ;--------------------------------------------- preview fetch 'person ø ] ] ================================================ FILE: examples/sample12.art ================================================ do.import {grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample11" ;--------------------------------------------- graph .helpers: [word] .create .palette: 'default "sample12" [ unless dbExists? [ 'word [name: "for" lang: "en"] {for_en}: put'word [name: {for}, lang: "en"] {Because, as, since.}: put'sense [name: {Because, as, since.}] [ {parce que_fr}, {car_fr}, {da_de}, {weil_de}, {denn_de}, {διότι_el}, {επειδή_el}, {γιατί_el}, {perché_it}, {poiché_it}, {porque_pt}, {pentru că_ro}, {căci_ro}, {porque_es}, {pues_es}, {como_es} ]: put.many 'word [ [name:{parce que}, lang:{fr}], [name:{car}, lang:{fr}], [name:{da}, lang:{de}], [name:{weil}, lang:{de}], [name:{denn}, lang:{de}], [name:{διότι}, lang:{el}], [name:{επειδή}, lang:{el}], [name:{γιατί}, lang:{el}], [name:{perché}, lang:{it}], [name:{poiché}, lang:{it}], [name:{porque}, lang:{pt}], [name:{pentru că}, lang:{ro}], [name:{căci}, lang:{ro}], [name:{porque}, lang:{es}], [name:{pues}, lang:{es}], [name:{como}, lang:{es}] ] link [var{parce que_fr} var{car_fr} var{da_de} var{weil_de} var{denn_de} var{διότι_el} var{επειδή_el} var{γιατί_el} var{perché_it} var{poiché_it} var{porque_pt} var{pentru că_ro} var{căci_ro} var{porque_es} var{pues_es} var{como_es} var{for_en}] 'means var{Because, as, since.} {Towards; in the direction of.}: put'sense [name: {Towards; in the direction of.}] [ {pour_fr}, {zu_de}, {nach_de}, {για_el}, {per_it}, {verso_it}, {a_pt}, {para_pt}, {pentru_ro}, {a_es}, {hacia_es} ]: put.many 'word [ [name:{pour}, lang:{fr}], [name:{zu}, lang:{de}], [name:{nach}, lang:{de}], [name:{για}, lang:{el}], [name:{per}, lang:{it}], [name:{verso}, lang:{it}], [name:{a}, lang:{pt}], [name:{para}, lang:{pt}], [name:{pentru}, lang:{ro}], [name:{a}, lang:{es}], [name:{hacia}, lang:{es}] ] link [var{parce que_fr} var{car_fr} var{da_de} var{weil_de} var{denn_de} var{διότι_el} var{επειδή_el} var{γιατί_el} var{perché_it} var{poiché_it} var{porque_pt} var{pentru că_ro} var{căci_ro} var{porque_es} var{pues_es} var{como_es} var{pour_fr} var{zu_de} var{nach_de} var{για_el} var{per_it} var{verso_it} var{a_pt} var{para_pt} var{pentru_ro} var{a_es} var{hacia_es} var{for_en}] 'means var{Towards; in the direction of.} {Directed at; intended to belong to.}: put'sense [name: {Directed at; intended to belong to.}] [ {pour_fr}, {für_de}, {για_el}, {per_it}, {para_pt}, {pentru_ro}, {para_es} ]: put.many 'word [ [name:{pour}, lang:{fr}], [name:{für}, lang:{de}], [name:{για}, lang:{el}], [name:{per}, lang:{it}], [name:{para}, lang:{pt}], [name:{pentru}, lang:{ro}], [name:{para}, lang:{es}] ] link [var{parce que_fr} var{car_fr} var{da_de} var{weil_de} var{denn_de} var{διότι_el} var{επειδή_el} var{γιατί_el} var{perché_it} var{poiché_it} var{porque_pt} var{pentru că_ro} var{căci_ro} var{porque_es} var{pues_es} var{como_es} var{pour_fr} var{zu_de} var{nach_de} var{για_el} var{per_it} var{verso_it} var{a_pt} var{para_pt} var{pentru_ro} var{a_es} var{hacia_es} var{pour_fr} var{für_de} var{για_el} var{per_it} var{para_pt} var{pentru_ro} var{para_es} var{for_en}] 'means var{Directed at; intended to belong to.} {In order to help, benefit, gratify, honor etc. (someone or something).}: put'sense [name: {In order to help, benefit, gratify, honor etc. (someone or something).}] {To be used or treated in a stated way, or with a stated purpose.}: put'sense [name: {To be used or treated in a stated way, or with a stated purpose.}] {Supporting, in favour of.}: put'sense [name: {Supporting, in favour of.}] [ {pour_fr}, {für_de}, {υπέρ_el}, {pro_it}, {a favor de_pt}, {pentru_ro}, {por_es} ]: put.many 'word [ [name:{pour}, lang:{fr}], [name:{für}, lang:{de}], [name:{υπέρ}, lang:{el}], [name:{pro}, lang:{it}], [name:{a favor de}, lang:{pt}], [name:{pentru}, lang:{ro}], [name:{por}, lang:{es}] ] link [var{parce que_fr} var{car_fr} var{da_de} var{weil_de} var{denn_de} var{διότι_el} var{επειδή_el} var{γιατί_el} var{perché_it} var{poiché_it} var{porque_pt} var{pentru că_ro} var{căci_ro} var{porque_es} var{pues_es} var{como_es} var{pour_fr} var{zu_de} var{nach_de} var{για_el} var{per_it} var{verso_it} var{a_pt} var{para_pt} var{pentru_ro} var{a_es} var{hacia_es} var{pour_fr} var{für_de} var{για_el} var{per_it} var{para_pt} var{pentru_ro} var{para_es} var{pour_fr} var{für_de} var{υπέρ_el} var{pro_it} var{a favor de_pt} var{pentru_ro} var{por_es} var{for_en}] 'means var{Supporting, in favour of.} {Because of.}: put'sense [name: {Because of.}] [ {pour_fr}, {wegen_de}, {για_el}, {λόγω_el}, {per_it}, {por causa de_pt}, {por_pt}, {por_es} ]: put.many 'word [ [name:{pour}, lang:{fr}], [name:{wegen}, lang:{de}], [name:{για}, lang:{el}], [name:{λόγω}, lang:{el}], [name:{per}, lang:{it}], [name:{por causa de}, lang:{pt}], [name:{por}, lang:{pt}], [name:{por}, lang:{es}] ] link [var{parce que_fr} var{car_fr} var{da_de} var{weil_de} var{denn_de} var{διότι_el} var{επειδή_el} var{γιατί_el} var{perché_it} var{poiché_it} var{porque_pt} var{pentru că_ro} var{căci_ro} var{porque_es} var{pues_es} var{como_es} var{pour_fr} var{zu_de} var{nach_de} var{για_el} var{per_it} var{verso_it} var{a_pt} var{para_pt} var{pentru_ro} var{a_es} var{hacia_es} var{pour_fr} var{für_de} var{για_el} var{per_it} var{para_pt} var{pentru_ro} var{para_es} var{pour_fr} var{für_de} var{υπέρ_el} var{pro_it} var{a favor de_pt} var{pentru_ro} var{por_es} var{pour_fr} var{wegen_de} var{για_el} var{λόγω_el} var{per_it} var{por causa de_pt} var{por_pt} var{por_es} var{for_en}] 'means var{Because of.} {Intended to cure, remove or counteract; in order to cure, remove or counteract.}: put'sense [name: {Intended to cure, remove or counteract; in order to cure, remove or counteract.}] {Over (a period of time).}: put'sense [name: {Over (a period of time).}] [ {depuis_fr}, {pendant_fr}, {seit_de}, {lang_de}, {-lang_de}, {tagelang etc._de}, {durante_it}, {por_pt}, {durante_pt}, {por_es}, {durante_es} ]: put.many 'word [ [name:{depuis}, lang:{fr}], [name:{pendant}, lang:{fr}], [name:{seit}, lang:{de}], [name:{lang}, lang:{de}], [name:{-lang}, lang:{de}], [name:{tagelang etc.}, lang:{de}], [name:{durante}, lang:{it}], [name:{por}, lang:{pt}], [name:{durante}, lang:{pt}], [name:{por}, lang:{es}], [name:{durante}, lang:{es}] ] link [var{parce que_fr} var{car_fr} var{da_de} var{weil_de} var{denn_de} var{διότι_el} var{επειδή_el} var{γιατί_el} var{perché_it} var{poiché_it} var{porque_pt} var{pentru că_ro} var{căci_ro} var{porque_es} var{pues_es} var{como_es} var{pour_fr} var{zu_de} var{nach_de} var{για_el} var{per_it} var{verso_it} var{a_pt} var{para_pt} var{pentru_ro} var{a_es} var{hacia_es} var{pour_fr} var{für_de} var{για_el} var{per_it} var{para_pt} var{pentru_ro} var{para_es} var{pour_fr} var{für_de} var{υπέρ_el} var{pro_it} var{a favor de_pt} var{pentru_ro} var{por_es} var{pour_fr} var{wegen_de} var{για_el} var{λόγω_el} var{per_it} var{por causa de_pt} var{por_pt} var{por_es} var{depuis_fr} var{pendant_fr} var{seit_de} var{lang_de} var{-lang_de} var{tagelang etc._de} var{durante_it} var{por_pt} var{durante_pt} var{por_es} var{durante_es} var{for_en}] 'means var{Over (a period of time).} {Throughout or across (a distance in space).}: put'sense [name: {Throughout or across (a distance in space).}] {Used to introduce a subject within a to-infinitive clause.}: put'sense [name: {Used to introduce a subject within a to-infinitive clause.}] {On behalf of.}: put'sense [name: {On behalf of.}] {In the role or capacity of; instead of; in place of.}: put'sense [name: {In the role or capacity of; instead of; in place of.}] {In exchange for; in correspondence or equivalence with.}: put'sense [name: {In exchange for; in correspondence or equivalence with.}] {In order to obtain or acquire.}: put'sense [name: {In order to obtain or acquire.}] [ {pour_fr}, {für_de}, {por_pt}, {por_es} ]: put.many 'word [ [name:{pour}, lang:{fr}], [name:{für}, lang:{de}], [name:{por}, lang:{pt}], [name:{por}, lang:{es}] ] link [var{parce que_fr} var{car_fr} var{da_de} var{weil_de} var{denn_de} var{διότι_el} var{επειδή_el} var{γιατί_el} var{perché_it} var{poiché_it} var{porque_pt} var{pentru că_ro} var{căci_ro} var{porque_es} var{pues_es} var{como_es} var{pour_fr} var{zu_de} var{nach_de} var{για_el} var{per_it} var{verso_it} var{a_pt} var{para_pt} var{pentru_ro} var{a_es} var{hacia_es} var{pour_fr} var{für_de} var{για_el} var{per_it} var{para_pt} var{pentru_ro} var{para_es} var{pour_fr} var{für_de} var{υπέρ_el} var{pro_it} var{a favor de_pt} var{pentru_ro} var{por_es} var{pour_fr} var{wegen_de} var{για_el} var{λόγω_el} var{per_it} var{por causa de_pt} var{por_pt} var{por_es} var{depuis_fr} var{pendant_fr} var{seit_de} var{lang_de} var{-lang_de} var{tagelang etc._de} var{durante_it} var{por_pt} var{durante_pt} var{por_es} var{durante_es} var{pour_fr} var{für_de} var{por_pt} var{por_es} var{for_en}] 'means var{In order to obtain or acquire.} {By the standards of, usually with the implication of those standards being lower than one might otherwise expect.}: put'sense [name: {By the standards of, usually with the implication of those standards being lower than one might otherwise expect.}] [ {für_de}, {para_pt}, {para ser_es} ]: put.many 'word [ [name:{für}, lang:{de}], [name:{para}, lang:{pt}], [name:{para ser}, lang:{es}] ] link [var{parce que_fr} var{car_fr} var{da_de} var{weil_de} var{denn_de} var{διότι_el} var{επειδή_el} var{γιατί_el} var{perché_it} var{poiché_it} var{porque_pt} var{pentru că_ro} var{căci_ro} var{porque_es} var{pues_es} var{como_es} var{pour_fr} var{zu_de} var{nach_de} var{για_el} var{per_it} var{verso_it} var{a_pt} var{para_pt} var{pentru_ro} var{a_es} var{hacia_es} var{pour_fr} var{für_de} var{για_el} var{per_it} var{para_pt} var{pentru_ro} var{para_es} var{pour_fr} var{für_de} var{υπέρ_el} var{pro_it} var{a favor de_pt} var{pentru_ro} var{por_es} var{pour_fr} var{wegen_de} var{για_el} var{λόγω_el} var{per_it} var{por causa de_pt} var{por_pt} var{por_es} var{depuis_fr} var{pendant_fr} var{seit_de} var{lang_de} var{-lang_de} var{tagelang etc._de} var{durante_it} var{por_pt} var{durante_pt} var{por_es} var{durante_es} var{pour_fr} var{für_de} var{por_pt} var{por_es} var{für_de} var{para_pt} var{para ser_es} var{for_en}] 'means var{By the standards of, usually with the implication of those standards being lower than one might otherwise expect.} {To be, or as being.}: put'sense [name: {To be, or as being.}] {Despite, in spite of.}: put'sense [name: {Despite, in spite of.}] {Indicating something desired or anticipated.}: put'sense [name: {Indicating something desired or anticipated.}] {Introducing the first item(s) in a potential sequence.}: put'sense [name: {Introducing the first item(s) in a potential sequence.}] {In honor of; after.}: put'sense [name: {In honor of; after.}] {Due or facing (a certain outcome or fate).}: put'sense [name: {Due or facing (a certain outcome or fate).}] {Out of; used to indicate a fraction, a ratio}: put'sense [name: {Out of; used to indicate a fraction, a ratio}] {Used as part of a score to indicate the number of wickets that have fallen.}: put'sense [name: {Used as part of a score to indicate the number of wickets that have fallen.}] {Indicating that in prevention of which, or through fear of which, anything is done.}: put'sense [name: {Indicating that in prevention of which, or through fear of which, anything is done.}] {Used in various more-or-less idiomatic ways to construe individual verbs, indicating various semantic relationships such as target, purpose, result, etc.; see also the entries for individual phrasal verbs, e.g. ask for, look for, stand for, etc.}: put'sense [name: {Used in various more-or-less idiomatic ways to construe individual verbs, indicating various semantic relationships such as target, purpose, result, etc.; see also the entries for individual phrasal verbs, e.g. ask for, look for, stand for, etc.}] {So (that), in order to}: put'sense [name: {So (that), in order to}] {To, the particle for marking the following verb as an infinitive.}: put'sense [name: {To, the particle for marking the following verb as an infinitive.}] {desertification_en}: put'word [name: {desertification}, lang: "en"] {The process by which a geographic region becomes a desert, resulting from natural changes in climate or by human activity.}: put'sense [name: {The process by which a geographic region becomes a desert, resulting from natural changes in climate or by human activity.}] [ {désertification_fr}, {Desertifikation_de}, {fortschreitende Wüstenbildung_de}, {ερημοποίηση_el}, {desertificazione_it}, {desertificação_pt}, {desertificación_es} ]: put.many 'word [ [name:{désertification}, lang:{fr}], [name:{Desertifikation}, lang:{de}], [name:{fortschreitende Wüstenbildung}, lang:{de}], [name:{ερημοποίηση}, lang:{el}], [name:{desertificazione}, lang:{it}], [name:{desertificação}, lang:{pt}], [name:{desertificación}, lang:{es}] ] link [var{désertification_fr} var{Desertifikation_de} var{fortschreitende Wüstenbildung_de} var{ερημοποίηση_el} var{desertificazione_it} var{desertificação_pt} var{desertificación_es} var{desertification_en}] 'means var{The process by which a geographic region becomes a desert, resulting from natural changes in climate or by human activity.} {acute_en}: put'word [name: {acute}, lang: "en"] {Brief, quick, short.}: put'sense [name: {Brief, quick, short.}] {High or shrill.}: put'sense [name: {High or shrill.}] {Intense, sensitive, sharp.}: put'sense [name: {Intense, sensitive, sharp.}] [ {aigu_fr}, {aiguë_fr}, {scharf_de}, {οξύς_el}, {agudo_pt}, {agudo_es}, {perspicaz_es}, {sagaz_es} ]: put.many 'word [ [name:{aigu}, lang:{fr}], [name:{aiguë}, lang:{fr}], [name:{scharf}, lang:{de}], [name:{οξύς}, lang:{el}], [name:{agudo}, lang:{pt}], [name:{agudo}, lang:{es}], [name:{perspicaz}, lang:{es}], [name:{sagaz}, lang:{es}] ] link [var{aigu_fr} var{aiguë_fr} var{scharf_de} var{οξύς_el} var{agudo_pt} var{agudo_es} var{perspicaz_es} var{sagaz_es} var{acute_en}] 'means var{Intense, sensitive, sharp.} {Urgent.}: put'sense [name: {Urgent.}] [ {urgente_pt}, {grave_es} ]: put.many 'word [ [name:{urgente}, lang:{pt}], [name:{grave}, lang:{es}] ] link [var{aigu_fr} var{aiguë_fr} var{scharf_de} var{οξύς_el} var{agudo_pt} var{agudo_es} var{perspicaz_es} var{sagaz_es} var{urgente_pt} var{grave_es} var{acute_en}] 'means var{Urgent.} {With the sides meeting directly to form an acute angle (at an apex or base).}: put'sense [name: {With the sides meeting directly to form an acute angle (at an apex or base).}] {Of an angle: less than 90 degrees.}: put'sense [name: {Of an angle: less than 90 degrees.}] [ {aigu_fr}, {spitz_de}, {οξύς_el}, {acuto_it}, {agudo_pt}, {ascuțit_ro}, {agudo_es} ]: put.many 'word [ [name:{aigu}, lang:{fr}], [name:{spitz}, lang:{de}], [name:{οξύς}, lang:{el}], [name:{acuto}, lang:{it}], [name:{agudo}, lang:{pt}], [name:{ascuțit}, lang:{ro}], [name:{agudo}, lang:{es}] ] link [var{aigu_fr} var{aiguë_fr} var{scharf_de} var{οξύς_el} var{agudo_pt} var{agudo_es} var{perspicaz_es} var{sagaz_es} var{urgente_pt} var{grave_es} var{aigu_fr} var{spitz_de} var{οξύς_el} var{acuto_it} var{agudo_pt} var{ascuțit_ro} var{agudo_es} var{acute_en}] 'means var{Of an angle: less than 90 degrees.} {Of a triangle: having all three interior angles measuring less than 90 degrees.}: put'sense [name: {Of a triangle: having all three interior angles measuring less than 90 degrees.}] {Of an accent or tone: generally higher than others.}: put'sense [name: {Of an accent or tone: generally higher than others.}] {Of an abnormal condition of recent or sudden onset, in contrast to delayed onset; this sense does not imply severity, unlike the common usage.}: put'sense [name: {Of an abnormal condition of recent or sudden onset, in contrast to delayed onset; this sense does not imply severity, unlike the common usage.}] [ {aigu_fr}, {akut_de}, {agudo_pt} ]: put.many 'word [ [name:{aigu}, lang:{fr}], [name:{akut}, lang:{de}], [name:{agudo}, lang:{pt}] ] link [var{aigu_fr} var{aiguë_fr} var{scharf_de} var{οξύς_el} var{agudo_pt} var{agudo_es} var{perspicaz_es} var{sagaz_es} var{urgente_pt} var{grave_es} var{aigu_fr} var{spitz_de} var{οξύς_el} var{acuto_it} var{agudo_pt} var{ascuțit_ro} var{agudo_es} var{aigu_fr} var{akut_de} var{agudo_pt} var{acute_en}] 'means var{Of an abnormal condition of recent or sudden onset, in contrast to delayed onset; this sense does not imply severity, unlike the common usage.} {Of a short-lived condition, in contrast to a chronic condition; this sense also does not imply severity.}: put'sense [name: {Of a short-lived condition, in contrast to a chronic condition; this sense also does not imply severity.}] [ {aigu_fr}, {οξύς_el}, {agudo_pt} ]: put.many 'word [ [name:{aigu}, lang:{fr}], [name:{οξύς}, lang:{el}], [name:{agudo}, lang:{pt}] ] link [var{aigu_fr} var{aiguë_fr} var{scharf_de} var{οξύς_el} var{agudo_pt} var{agudo_es} var{perspicaz_es} var{sagaz_es} var{urgente_pt} var{grave_es} var{aigu_fr} var{spitz_de} var{οξύς_el} var{acuto_it} var{agudo_pt} var{ascuțit_ro} var{agudo_es} var{aigu_fr} var{akut_de} var{agudo_pt} var{aigu_fr} var{οξύς_el} var{agudo_pt} var{acute_en}] 'means var{Of a short-lived condition, in contrast to a chronic condition; this sense also does not imply severity.} {After a letter of the alphabet: having an acute accent.}: put'sense [name: {After a letter of the alphabet: having an acute accent.}] [ {aigu_fr} ]: put.many 'word [ [name:{aigu}, lang:{fr}] ] link [var{aigu_fr} var{aiguë_fr} var{scharf_de} var{οξύς_el} var{agudo_pt} var{agudo_es} var{perspicaz_es} var{sagaz_es} var{urgente_pt} var{grave_es} var{aigu_fr} var{spitz_de} var{οξύς_el} var{acuto_it} var{agudo_pt} var{ascuțit_ro} var{agudo_es} var{aigu_fr} var{akut_de} var{agudo_pt} var{aigu_fr} var{οξύς_el} var{agudo_pt} var{aigu_fr} var{acute_en}] 'means var{After a letter of the alphabet: having an acute accent.} {A person who has the acute form of a disorder, such as schizophrenia.}: put'sense [name: {A person who has the acute form of a disorder, such as schizophrenia.}] {An accent or tone higher than others.}: put'sense [name: {An accent or tone higher than others.}] {An acute accent (´).}: put'sense [name: {An acute accent (´).}] {To give an acute sound to.}: put'sense [name: {To give an acute sound to.}] {To make acute; to sharpen, to whet.}: put'sense [name: {To make acute; to sharpen, to whet.}] {humble_en}: put'word [name: {humble}, lang: "en"] {Not pretentious or magnificent; unpretending; unassuming.}: put'sense [name: {Not pretentious or magnificent; unpretending; unassuming.}] {Having a low opinion of oneself; not proud, arrogant, or assuming; modest.}: put'sense [name: {Having a low opinion of oneself; not proud, arrogant, or assuming; modest.}] [ {humble_fr}, {demütig_de}, {bescheiden_de}, {umile_it}, {modesto_it}, {humilde_pt}, {umil_ro}, {modesto_es}, {humilde_es} ]: put.many 'word [ [name:{humble}, lang:{fr}], [name:{demütig}, lang:{de}], [name:{bescheiden}, lang:{de}], [name:{umile}, lang:{it}], [name:{modesto}, lang:{it}], [name:{humilde}, lang:{pt}], [name:{umil}, lang:{ro}], [name:{modesto}, lang:{es}], [name:{humilde}, lang:{es}] ] link [var{humble_fr} var{demütig_de} var{bescheiden_de} var{umile_it} var{modesto_it} var{humilde_pt} var{umil_ro} var{modesto_es} var{humilde_es} var{humble_en}] 'means var{Having a low opinion of oneself; not proud, arrogant, or assuming; modest.} {To defeat or reduce the power, independence, or pride of}: put'sense [name: {To defeat or reduce the power, independence, or pride of}] {To make humble or lowly; to make less proud or arrogant; to make meek and submissive.}: put'sense [name: {To make humble or lowly; to make less proud or arrogant; to make meek and submissive.}] [ {erniedrigen_de}, {demütig machen_de}, {umili_ro} ]: put.many 'word [ [name:{erniedrigen}, lang:{de}], [name:{demütig machen}, lang:{de}], [name:{umili}, lang:{ro}] ] link [var{humble_fr} var{demütig_de} var{bescheiden_de} var{umile_it} var{modesto_it} var{humilde_pt} var{umil_ro} var{modesto_es} var{humilde_es} var{erniedrigen_de} var{demütig machen_de} var{umili_ro} var{humble_en}] 'means var{To make humble or lowly; to make less proud or arrogant; to make meek and submissive.} {An arrest based on weak evidence intended to demean or punish the subject.}: put'sense [name: {An arrest based on weak evidence intended to demean or punish the subject.}] {To hum.}: put'sense [name: {To hum.}] {Alternative form of hummel.}: put'sense [name: {Alternative form of hummel.}] {Alternative form of hummel.}: put'sense [name: {Alternative form of hummel.}] {million_en}: put'word [name: {million}, lang: "en"] {The cardinal number 1,000,000: 10⁶; a thousand thousand.}: put'sense [name: {The cardinal number 1,000,000: 10⁶; a thousand thousand.}] [ {million_fr}, {Million_de}, {εκατομμύριο_el}, {milione_it}, {milhão_pt}, {milion_ro}, {millón_es} ]: put.many 'word [ [name:{million}, lang:{fr}], [name:{Million}, lang:{de}], [name:{εκατομμύριο}, lang:{el}], [name:{milione}, lang:{it}], [name:{milhão}, lang:{pt}], [name:{milion}, lang:{ro}], [name:{millón}, lang:{es}] ] link [var{million_fr} var{Million_de} var{εκατομμύριο_el} var{milione_it} var{milhão_pt} var{milion_ro} var{millón_es} var{million_en}] 'means var{The cardinal number 1,000,000: 10⁶; a thousand thousand.} {An unspecified very large number.}: put'sense [name: {An unspecified very large number.}] {before_en}: put'word [name: {before}, lang: "en"] {Earlier than (in time).}: put'sense [name: {Earlier than (in time).}] [ {avant_fr}, {avant que_fr}, {vor_de}, {πριν_el}, {prima_it}, {innanzi_it}, {antes de_pt}, {înainte_ro}, {anterior_ro}, {antes de_es}, {antes que_es} ]: put.many 'word [ [name:{avant}, lang:{fr}], [name:{avant que}, lang:{fr}], [name:{vor}, lang:{de}], [name:{πριν}, lang:{el}], [name:{prima}, lang:{it}], [name:{innanzi}, lang:{it}], [name:{antes de}, lang:{pt}], [name:{înainte}, lang:{ro}], [name:{anterior}, lang:{ro}], [name:{antes de}, lang:{es}], [name:{antes que}, lang:{es}] ] link [var{avant_fr} var{avant que_fr} var{vor_de} var{πριν_el} var{prima_it} var{innanzi_it} var{antes de_pt} var{înainte_ro} var{anterior_ro} var{antes de_es} var{antes que_es} var{before_en}] 'means var{Earlier than (in time).} {In front of in space.}: put'sense [name: {In front of in space.}] [ {devant_fr}, {vor_de}, {μπροστά σε_el}, {μπροστά από_el}, {davanti_it}, {innanzi_it}, {ante_pt}, {em frente a_pt}, {na frente de_pt}, {diante de_pt}, {înainte_ro}, {în față_ro}, {ante_es}, {frente a_es}, {enfrente de_es} ]: put.many 'word [ [name:{devant}, lang:{fr}], [name:{vor}, lang:{de}], [name:{μπροστά σε}, lang:{el}], [name:{μπροστά από}, lang:{el}], [name:{davanti}, lang:{it}], [name:{innanzi}, lang:{it}], [name:{ante}, lang:{pt}], [name:{em frente a}, lang:{pt}], [name:{na frente de}, lang:{pt}], [name:{diante de}, lang:{pt}], [name:{înainte}, lang:{ro}], [name:{în față}, lang:{ro}], [name:{ante}, lang:{es}], [name:{frente a}, lang:{es}], [name:{enfrente de}, lang:{es}] ] link [var{avant_fr} var{avant que_fr} var{vor_de} var{πριν_el} var{prima_it} var{innanzi_it} var{antes de_pt} var{înainte_ro} var{anterior_ro} var{antes de_es} var{antes que_es} var{devant_fr} var{vor_de} var{μπροστά σε_el} var{μπροστά από_el} var{davanti_it} var{innanzi_it} var{ante_pt} var{em frente a_pt} var{na frente de_pt} var{diante de_pt} var{înainte_ro} var{în față_ro} var{ante_es} var{frente a_es} var{enfrente de_es} var{before_en}] 'means var{In front of in space.} {In the presence of.}: put'sense [name: {In the presence of.}] {Under consideration, judgment, authority of (someone).}: put'sense [name: {Under consideration, judgment, authority of (someone).}] {In store for, in the future of (someone).}: put'sense [name: {In store for, in the future of (someone).}] {In front of, according to a formal system of ordering items.}: put'sense [name: {In front of, according to a formal system of ordering items.}] [ {avant_fr}, {vor_de}, {antes de_pt}, {antes de_es} ]: put.many 'word [ [name:{avant}, lang:{fr}], [name:{vor}, lang:{de}], [name:{antes de}, lang:{pt}], [name:{antes de}, lang:{es}] ] link [var{avant_fr} var{avant que_fr} var{vor_de} var{πριν_el} var{prima_it} var{innanzi_it} var{antes de_pt} var{înainte_ro} var{anterior_ro} var{antes de_es} var{antes que_es} var{devant_fr} var{vor_de} var{μπροστά σε_el} var{μπροστά από_el} var{davanti_it} var{innanzi_it} var{ante_pt} var{em frente a_pt} var{na frente de_pt} var{diante de_pt} var{înainte_ro} var{în față_ro} var{ante_es} var{frente a_es} var{enfrente de_es} var{avant_fr} var{vor_de} var{antes de_pt} var{antes de_es} var{before_en}] 'means var{In front of, according to a formal system of ordering items.} {At a higher or greater position than, in a ranking.}: put'sense [name: {At a higher or greater position than, in a ranking.}] {At an earlier time.}: put'sense [name: {At an earlier time.}] [ {avant_fr}, {zuvor_de}, {vorher_de}, {prima_it}, {antes_pt}, {înainte_ro} ]: put.many 'word [ [name:{avant}, lang:{fr}], [name:{zuvor}, lang:{de}], [name:{vorher}, lang:{de}], [name:{prima}, lang:{it}], [name:{antes}, lang:{pt}], [name:{înainte}, lang:{ro}] ] link [var{avant_fr} var{avant que_fr} var{vor_de} var{πριν_el} var{prima_it} var{innanzi_it} var{antes de_pt} var{înainte_ro} var{anterior_ro} var{antes de_es} var{antes que_es} var{devant_fr} var{vor_de} var{μπροστά σε_el} var{μπροστά από_el} var{davanti_it} var{innanzi_it} var{ante_pt} var{em frente a_pt} var{na frente de_pt} var{diante de_pt} var{înainte_ro} var{în față_ro} var{ante_es} var{frente a_es} var{enfrente de_es} var{avant_fr} var{vor_de} var{antes de_pt} var{antes de_es} var{avant_fr} var{zuvor_de} var{vorher_de} var{prima_it} var{antes_pt} var{înainte_ro} var{before_en}] 'means var{At an earlier time.} {In advance.}: put'sense [name: {In advance.}] [ {eher_de}, {im Voraus_de}, {primeiro_pt}, {în avans_ro} ]: put.many 'word [ [name:{eher}, lang:{de}], [name:{im Voraus}, lang:{de}], [name:{primeiro}, lang:{pt}], [name:{în avans}, lang:{ro}] ] link [var{avant_fr} var{avant que_fr} var{vor_de} var{πριν_el} var{prima_it} var{innanzi_it} var{antes de_pt} var{înainte_ro} var{anterior_ro} var{antes de_es} var{antes que_es} var{devant_fr} var{vor_de} var{μπροστά σε_el} var{μπροστά από_el} var{davanti_it} var{innanzi_it} var{ante_pt} var{em frente a_pt} var{na frente de_pt} var{diante de_pt} var{înainte_ro} var{în față_ro} var{ante_es} var{frente a_es} var{enfrente de_es} var{avant_fr} var{vor_de} var{antes de_pt} var{antes de_es} var{avant_fr} var{zuvor_de} var{vorher_de} var{prima_it} var{antes_pt} var{înainte_ro} var{eher_de} var{im Voraus_de} var{primeiro_pt} var{în avans_ro} var{before_en}] 'means var{In advance.} {At the front end.}: put'sense [name: {At the front end.}] [ {vorn_de}, {vorne_de} ]: put.many 'word [ [name:{vorn}, lang:{de}], [name:{vorne}, lang:{de}] ] link [var{avant_fr} var{avant que_fr} var{vor_de} var{πριν_el} var{prima_it} var{innanzi_it} var{antes de_pt} var{înainte_ro} var{anterior_ro} var{antes de_es} var{antes que_es} var{devant_fr} var{vor_de} var{μπροστά σε_el} var{μπροστά από_el} var{davanti_it} var{innanzi_it} var{ante_pt} var{em frente a_pt} var{na frente de_pt} var{diante de_pt} var{înainte_ro} var{în față_ro} var{ante_es} var{frente a_es} var{enfrente de_es} var{avant_fr} var{vor_de} var{antes de_pt} var{antes de_es} var{avant_fr} var{zuvor_de} var{vorher_de} var{prima_it} var{antes_pt} var{înainte_ro} var{eher_de} var{im Voraus_de} var{primeiro_pt} var{în avans_ro} var{vorn_de} var{vorne_de} var{before_en}] 'means var{At the front end.} {In advance of the time when.}: put'sense [name: {In advance of the time when.}] [ {avant que_fr}, {bevor_de}, {prima_it}, {antes de que_es} ]: put.many 'word [ [name:{avant que}, lang:{fr}], [name:{bevor}, lang:{de}], [name:{prima}, lang:{it}], [name:{antes de que}, lang:{es}] ] link [var{avant_fr} var{avant que_fr} var{vor_de} var{πριν_el} var{prima_it} var{innanzi_it} var{antes de_pt} var{înainte_ro} var{anterior_ro} var{antes de_es} var{antes que_es} var{devant_fr} var{vor_de} var{μπροστά σε_el} var{μπροστά από_el} var{davanti_it} var{innanzi_it} var{ante_pt} var{em frente a_pt} var{na frente de_pt} var{diante de_pt} var{înainte_ro} var{în față_ro} var{ante_es} var{frente a_es} var{enfrente de_es} var{avant_fr} var{vor_de} var{antes de_pt} var{antes de_es} var{avant_fr} var{zuvor_de} var{vorher_de} var{prima_it} var{antes_pt} var{înainte_ro} var{eher_de} var{im Voraus_de} var{primeiro_pt} var{în avans_ro} var{vorn_de} var{vorne_de} var{avant que_fr} var{bevor_de} var{prima_it} var{antes de que_es} var{before_en}] 'means var{In advance of the time when.} {Rather or sooner than.}: put'sense [name: {Rather or sooner than.}] [ {bevor_de} ]: put.many 'word [ [name:{bevor}, lang:{de}] ] link [var{avant_fr} var{avant que_fr} var{vor_de} var{πριν_el} var{prima_it} var{innanzi_it} var{antes de_pt} var{înainte_ro} var{anterior_ro} var{antes de_es} var{antes que_es} var{devant_fr} var{vor_de} var{μπροστά σε_el} var{μπροστά από_el} var{davanti_it} var{innanzi_it} var{ante_pt} var{em frente a_pt} var{na frente de_pt} var{diante de_pt} var{înainte_ro} var{în față_ro} var{ante_es} var{frente a_es} var{enfrente de_es} var{avant_fr} var{vor_de} var{antes de_pt} var{antes de_es} var{avant_fr} var{zuvor_de} var{vorher_de} var{prima_it} var{antes_pt} var{înainte_ro} var{eher_de} var{im Voraus_de} var{primeiro_pt} var{în avans_ro} var{vorn_de} var{vorne_de} var{avant que_fr} var{bevor_de} var{prima_it} var{antes de que_es} var{bevor_de} var{before_en}] 'means var{Rather or sooner than.} {overall_en}: put'word [name: {overall}, lang: "en"] {All-encompassing, all around.}: put'sense [name: {All-encompassing, all around.}] [ {global_fr}, {total_fr}, {Gesamt-_de}, {complessivo_it}, {globale_it}, {generale_it}, {abrangente_pt}, {geral_pt}, {total_es}, {completo_es}, {general_es} ]: put.many 'word [ [name:{global}, lang:{fr}], [name:{total}, lang:{fr}], [name:{Gesamt-}, lang:{de}], [name:{complessivo}, lang:{it}], [name:{globale}, lang:{it}], [name:{generale}, lang:{it}], [name:{abrangente}, lang:{pt}], [name:{geral}, lang:{pt}], [name:{total}, lang:{es}], [name:{completo}, lang:{es}], [name:{general}, lang:{es}] ] link [var{global_fr} var{total_fr} var{Gesamt-_de} var{complessivo_it} var{globale_it} var{generale_it} var{abrangente_pt} var{geral_pt} var{total_es} var{completo_es} var{general_es} var{overall_en}] 'means var{All-encompassing, all around.} {Generally; with everything considered.}: put'sense [name: {Generally; with everything considered.}] [ {en général_fr}, {insgesamt_de}, {tutto sommato_it}, {in generale_it}, {complessivamente_it}, {nell'insieme_it}, {em geral_pt}, {sobretodo_es}, {totalmente_es}, {completamente_es} ]: put.many 'word [ [name:{en général}, lang:{fr}], [name:{insgesamt}, lang:{de}], [name:{tutto sommato}, lang:{it}], [name:{in generale}, lang:{it}], [name:{complessivamente}, lang:{it}], [name:{nell'insieme}, lang:{it}], [name:{em geral}, lang:{pt}], [name:{sobretodo}, lang:{es}], [name:{totalmente}, lang:{es}], [name:{completamente}, lang:{es}] ] link [var{global_fr} var{total_fr} var{Gesamt-_de} var{complessivo_it} var{globale_it} var{generale_it} var{abrangente_pt} var{geral_pt} var{total_es} var{completo_es} var{general_es} var{en général_fr} var{insgesamt_de} var{tutto sommato_it} var{in generale_it} var{complessivamente_it} var{nell'insieme_it} var{em geral_pt} var{sobretodo_es} var{totalmente_es} var{completamente_es} var{overall_en}] 'means var{Generally; with everything considered.} {A garment worn over other clothing to protect it; a coverall or boiler suit. A garment, for manual labor or for casual wear, often made of a single piece of fabric, with long legs and a bib upper, supported from the shoulders with straps, and having several large pockets and loops for carrying tools.}: put'sense [name: {A garment worn over other clothing to protect it; a coverall or boiler suit. A garment, for manual labor or for casual wear, often made of a single piece of fabric, with long legs and a bib upper, supported from the shoulders with straps, and having several large pockets and loops for carrying tools.}] [ {blouse_fr}, {combinaison_fr}, {salopette_fr}, {Overall_de}, {Latzhose_de}, {blusa_it}, {tuta da lavoro_it}, {macacão_pt}, {braga_es}, {mono_es}, {overol_es} ]: put.many 'word [ [name:{blouse}, lang:{fr}], [name:{combinaison}, lang:{fr}], [name:{salopette}, lang:{fr}], [name:{Overall}, lang:{de}], [name:{Latzhose}, lang:{de}], [name:{blusa}, lang:{it}], [name:{tuta da lavoro}, lang:{it}], [name:{macacão}, lang:{pt}], [name:{braga}, lang:{es}], [name:{mono}, lang:{es}], [name:{overol}, lang:{es}] ] link [var{global_fr} var{total_fr} var{Gesamt-_de} var{complessivo_it} var{globale_it} var{generale_it} var{abrangente_pt} var{geral_pt} var{total_es} var{completo_es} var{general_es} var{en général_fr} var{insgesamt_de} var{tutto sommato_it} var{in generale_it} var{complessivamente_it} var{nell'insieme_it} var{em geral_pt} var{sobretodo_es} var{totalmente_es} var{completamente_es} var{blouse_fr} var{combinaison_fr} var{salopette_fr} var{Overall_de} var{Latzhose_de} var{blusa_it} var{tuta da lavoro_it} var{macacão_pt} var{braga_es} var{mono_es} var{overol_es} var{overall_en}] 'means var{A garment worn over other clothing to protect it; a coverall or boiler suit. A garment, for manual labor or for casual wear, often made of a single piece of fabric, with long legs and a bib upper, supported from the shoulders with straps, and having several large pockets and loops for carrying tools.} {A garment, worn for manual labor, with an integral covering extending to the chest, supported by straps.}: put'sense [name: {A garment, worn for manual labor, with an integral covering extending to the chest, supported by straps.}] {do_en}: put'word [name: {do}, lang: "en"] {A syntactic marker.}: put'sense [name: {A syntactic marker.}] {A syntactic marker.}: put'sense [name: {A syntactic marker.}] [ {_fr}, {_de}, {_it}, {_pt}, {_es} ]: put.many 'word [ [name:{}, lang:{fr}], [name:{}, lang:{de}], [name:{}, lang:{it}], [name:{}, lang:{pt}], [name:{}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{do_en}] 'means var{A syntactic marker.} {A syntactic marker.}: put'sense [name: {A syntactic marker.}] [ {schon_de}, {sim_pt}, {sí_es} ]: put.many 'word [ [name:{schon}, lang:{de}], [name:{sim}, lang:{pt}], [name:{sí}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{do_en}] 'means var{A syntactic marker.} {A syntactic marker.}: put'sense [name: {A syntactic marker.}] [ {_fr}, {_de}, {_it}, {_pt}, {_es} ]: put.many 'word [ [name:{}, lang:{fr}], [name:{}, lang:{de}], [name:{}, lang:{it}], [name:{}, lang:{pt}], [name:{}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{do_en}] 'means var{A syntactic marker.} {To perform; to execute.}: put'sense [name: {To perform; to execute.}] [ {faire_fr}, {tun_de}, {machen_de}, {κάμνω_el}, {κάνω_el}, {fare_it}, {fazer_pt}, {realizar_pt}, {face_ro}, {hacer_es}, {fazer_pt} ]: put.many 'word [ [name:{faire}, lang:{fr}], [name:{tun}, lang:{de}], [name:{machen}, lang:{de}], [name:{κάμνω}, lang:{el}], [name:{κάνω}, lang:{el}], [name:{fare}, lang:{it}], [name:{fazer}, lang:{pt}], [name:{realizar}, lang:{pt}], [name:{face}, lang:{ro}], [name:{hacer}, lang:{es}], [name:{fazer}, lang:{pt}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{do_en}] 'means var{To perform; to execute.} {To cause, make (someone) (do something).}: put'sense [name: {To cause, make (someone) (do something).}] {To suffice.}: put'sense [name: {To suffice.}] [ {aller_fr}, {reichen_de}, {servir_pt}, {valer_es} ]: put.many 'word [ [name:{aller}, lang:{fr}], [name:{reichen}, lang:{de}], [name:{servir}, lang:{pt}], [name:{valer}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{do_en}] 'means var{To suffice.} {To be reasonable or acceptable.}: put'sense [name: {To be reasonable or acceptable.}] [ {aller_fr}, {andare_it}, {servir_pt}, {valer_es} ]: put.many 'word [ [name:{aller}, lang:{fr}], [name:{andare}, lang:{it}], [name:{servir}, lang:{pt}], [name:{valer}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{do_en}] 'means var{To be reasonable or acceptable.} {To have (as an effect).}: put'sense [name: {To have (as an effect).}] [ {fazer_pt} ]: put.many 'word [ [name:{fazer}, lang:{pt}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{do_en}] 'means var{To have (as an effect).} {To fare, perform (well or poorly).}: put'sense [name: {To fare, perform (well or poorly).}] [ {ir_pt} ]: put.many 'word [ [name:{ir}, lang:{pt}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{do_en}] 'means var{To fare, perform (well or poorly).} {To have as one's job.}: put'sense [name: {To have as one's job.}] [ {fazer_pt}, {hacer_es} ]: put.many 'word [ [name:{fazer}, lang:{pt}], [name:{hacer}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{fazer_pt} var{hacer_es} var{do_en}] 'means var{To have as one's job.} {To perform the tasks or actions associated with (something).}: put'sense [name: {To perform the tasks or actions associated with (something).}] {To cook.}: put'sense [name: {To cook.}] [ {fazer_pt}, {preparar_pt}, {hacer_es} ]: put.many 'word [ [name:{fazer}, lang:{pt}], [name:{preparar}, lang:{pt}], [name:{hacer}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{fazer_pt} var{hacer_es} var{fazer_pt} var{preparar_pt} var{hacer_es} var{do_en}] 'means var{To cook.} {To travel in, to tour, to make a circuit of.}: put'sense [name: {To travel in, to tour, to make a circuit of.}] {To treat in a certain way.}: put'sense [name: {To treat in a certain way.}] {To work for or on, by way of caring for, looking after, preparing, cleaning, keeping in order, etc.}: put'sense [name: {To work for or on, by way of caring for, looking after, preparing, cleaning, keeping in order, etc.}] {To act or behave in a certain manner; to conduct oneself.}: put'sense [name: {To act or behave in a certain manner; to conduct oneself.}] {To spend (time) in jail. (See also do time)}: put'sense [name: {To spend (time) in jail. (See also do time)}] [ {passar_pt} ]: put.many 'word [ [name:{passar}, lang:{pt}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{fazer_pt} var{hacer_es} var{fazer_pt} var{preparar_pt} var{hacer_es} var{passar_pt} var{do_en}] 'means var{To spend (time) in jail. (See also do time)} {To impersonate or depict.}: put'sense [name: {To impersonate or depict.}] {To copy or emulate the actions or behaviour that is associated with the person or thing mentioned.}: put'sense [name: {To copy or emulate the actions or behaviour that is associated with the person or thing mentioned.}] {To kill.}: put'sense [name: {To kill.}] {To deal with for good and all; to finish up; to undo; to ruin; to do for.}: put'sense [name: {To deal with for good and all; to finish up; to undo; to ruin; to do for.}] {To punish for a misdemeanor.}: put'sense [name: {To punish for a misdemeanor.}] {To have sex with. (See also do it)}: put'sense [name: {To have sex with. (See also do it)}] [ {se faire_fr}, {comer_pt}, {coger_es}, {culear_es}, {joder_es} ]: put.many 'word [ [name:{se faire}, lang:{fr}], [name:{comer}, lang:{pt}], [name:{coger}, lang:{es}], [name:{culear}, lang:{es}], [name:{joder}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{fazer_pt} var{hacer_es} var{fazer_pt} var{preparar_pt} var{hacer_es} var{passar_pt} var{se faire_fr} var{comer_pt} var{coger_es} var{culear_es} var{joder_es} var{do_en}] 'means var{To have sex with. (See also do it)} {To cheat or swindle.}: put'sense [name: {To cheat or swindle.}] {To convert into a certain form; especially, to translate.}: put'sense [name: {To convert into a certain form; especially, to translate.}] {To finish.}: put'sense [name: {To finish.}] {To work as a domestic servant (with for).}: put'sense [name: {To work as a domestic servant (with for).}] {Used to form the present progressive of verbs.}: put'sense [name: {Used to form the present progressive of verbs.}] {To cash or to advance money for, as a bill or note.}: put'sense [name: {To cash or to advance money for, as a bill or note.}] {To make or provide.}: put'sense [name: {To make or provide.}] {To injure (one's own body part).}: put'sense [name: {To injure (one's own body part).}] {To take drugs.}: put'sense [name: {To take drugs.}] [ {nehmen_de}, {usar_pt} ]: put.many 'word [ [name:{nehmen}, lang:{de}], [name:{usar}, lang:{pt}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{fazer_pt} var{hacer_es} var{fazer_pt} var{preparar_pt} var{hacer_es} var{passar_pt} var{se faire_fr} var{comer_pt} var{coger_es} var{culear_es} var{joder_es} var{nehmen_de} var{usar_pt} var{do_en}] 'means var{To take drugs.} {To exist with a purpose or for a reason.}: put'sense [name: {To exist with a purpose or for a reason.}] [ {fazer_pt}, {hacer_es} ]: put.many 'word [ [name:{fazer}, lang:{pt}], [name:{hacer}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{fazer_pt} var{hacer_es} var{fazer_pt} var{preparar_pt} var{hacer_es} var{passar_pt} var{se faire_fr} var{comer_pt} var{coger_es} var{culear_es} var{joder_es} var{nehmen_de} var{usar_pt} var{fazer_pt} var{hacer_es} var{do_en}] 'means var{To exist with a purpose or for a reason.} {A party, celebration, social function.}: put'sense [name: {A party, celebration, social function.}] {A hairdo.}: put'sense [name: {A hairdo.}] [ {penteado_pt} ]: put.many 'word [ [name:{penteado}, lang:{pt}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{fazer_pt} var{hacer_es} var{fazer_pt} var{preparar_pt} var{hacer_es} var{passar_pt} var{se faire_fr} var{comer_pt} var{coger_es} var{culear_es} var{joder_es} var{nehmen_de} var{usar_pt} var{fazer_pt} var{hacer_es} var{penteado_pt} var{do_en}] 'means var{A hairdo.} {Something that can or should be done (usually in the phrase dos and don'ts).}: put'sense [name: {Something that can or should be done (usually in the phrase dos and don'ts).}] {Ado; bustle; stir; to-do; A period of confusion or argument.}: put'sense [name: {Ado; bustle; stir; to-do; A period of confusion or argument.}] {A cheat; a swindler.}: put'sense [name: {A cheat; a swindler.}] {An act of swindling; a fraud or deception.}: put'sense [name: {An act of swindling; a fraud or deception.}] {A syllable used in solfège to represent the first and eighth tonic of a major scale.}: put'sense [name: {A syllable used in solfège to represent the first and eighth tonic of a major scale.}] [ {do_fr}, {ντο_el}, {dó_pt}, {do_es} ]: put.many 'word [ [name:{do}, lang:{fr}], [name:{ντο}, lang:{el}], [name:{dó}, lang:{pt}], [name:{do}, lang:{es}] ] link [var{_fr} var{_de} var{_it} var{_pt} var{_es} var{schon_de} var{sim_pt} var{sí_es} var{_fr} var{_de} var{_it} var{_pt} var{_es} var{faire_fr} var{tun_de} var{machen_de} var{κάμνω_el} var{κάνω_el} var{fare_it} var{fazer_pt} var{realizar_pt} var{face_ro} var{hacer_es} var{fazer_pt} var{aller_fr} var{reichen_de} var{servir_pt} var{valer_es} var{aller_fr} var{andare_it} var{servir_pt} var{valer_es} var{fazer_pt} var{ir_pt} var{fazer_pt} var{hacer_es} var{fazer_pt} var{preparar_pt} var{hacer_es} var{passar_pt} var{se faire_fr} var{comer_pt} var{coger_es} var{culear_es} var{joder_es} var{nehmen_de} var{usar_pt} var{fazer_pt} var{hacer_es} var{penteado_pt} var{do_fr} var{ντο_el} var{dó_pt} var{do_es} var{do_en}] 'means var{A syllable used in solfège to represent the first and eighth tonic of a major scale.} {Abbreviation of ditto.}: put'sense [name: {Abbreviation of ditto.}] {The cardinal number occurring after el and before do one in a duodecimal system. Written 10, decimal value 12.}: put'sense [name: {The cardinal number occurring after el and before do one in a duodecimal system. Written 10, decimal value 12.}] {literature_en}: put'word [name: {literature}, lang: "en"] {The body of all written works.}: put'sense [name: {The body of all written works.}] [ {littérature_fr}, {Literatur_de}, {λογοτεχνία_el}, {βιβλιογραφία_el}, {letteratura_it}, {literatura_pt}, {literatură_ro}, {literatura_es} ]: put.many 'word [ [name:{littérature}, lang:{fr}], [name:{Literatur}, lang:{de}], [name:{λογοτεχνία}, lang:{el}], [name:{βιβλιογραφία}, lang:{el}], [name:{letteratura}, lang:{it}], [name:{literatura}, lang:{pt}], [name:{literatură}, lang:{ro}], [name:{literatura}, lang:{es}] ] link [var{littérature_fr} var{Literatur_de} var{λογοτεχνία_el} var{βιβλιογραφία_el} var{letteratura_it} var{literatura_pt} var{literatură_ro} var{literatura_es} var{literature_en}] 'means var{The body of all written works.} {The collected creative writing of a nation, people, group, or culture.}: put'sense [name: {The collected creative writing of a nation, people, group, or culture.}] [ {literatura_pt}, {literatura_es} ]: put.many 'word [ [name:{literatura}, lang:{pt}], [name:{literatura}, lang:{es}] ] link [var{littérature_fr} var{Literatur_de} var{λογοτεχνία_el} var{βιβλιογραφία_el} var{letteratura_it} var{literatura_pt} var{literatură_ro} var{literatura_es} var{literatura_pt} var{literatura_es} var{literature_en}] 'means var{The collected creative writing of a nation, people, group, or culture.} {All the papers, treatises, etc. published in academic journals on a particular subject.}: put'sense [name: {All the papers, treatises, etc. published in academic journals on a particular subject.}] [ {littérature_fr}, {letteratura_it}, {literatura_pt}, {literatura_es} ]: put.many 'word [ [name:{littérature}, lang:{fr}], [name:{letteratura}, lang:{it}], [name:{literatura}, lang:{pt}], [name:{literatura}, lang:{es}] ] link [var{littérature_fr} var{Literatur_de} var{λογοτεχνία_el} var{βιβλιογραφία_el} var{letteratura_it} var{literatura_pt} var{literatură_ro} var{literatura_es} var{literatura_pt} var{literatura_es} var{littérature_fr} var{letteratura_it} var{literatura_pt} var{literatura_es} var{literature_en}] 'means var{All the papers, treatises, etc. published in academic journals on a particular subject.} {Written fiction of a high standard.}: put'sense [name: {Written fiction of a high standard.}] {sufficient_en}: put'word [name: {sufficient}, lang: "en"] {An adequate quantity of; enough.}: put'sense [name: {An adequate quantity of; enough.}] {A quantity (of something) that is as large as is needed.}: put'sense [name: {A quantity (of something) that is as large as is needed.}] {Of a type or kind that suffices, that satisfies requirements or needs.}: put'sense [name: {Of a type or kind that suffices, that satisfies requirements or needs.}] {Possessing adequate talents or accomplishments; of competent power or ability; qualified; fit.}: put'sense [name: {Possessing adequate talents or accomplishments; of competent power or ability; qualified; fit.}] [ {appropriato_it}, {suficiente_pt}, {autosuffisant_fr}, {autosufficiente_it} ]: put.many 'word [ [name:{appropriato}, lang:{it}], [name:{suficiente}, lang:{pt}], [name:{autosuffisant}, lang:{fr}], [name:{autosufficiente}, lang:{it}] ] link [var{appropriato_it} var{suficiente_pt} var{autosuffisant_fr} var{autosufficiente_it} var{sufficient_en}] 'means var{Possessing adequate talents or accomplishments; of competent power or ability; qualified; fit.} {Capable of meeting obligations; responsible.}: put'sense [name: {Capable of meeting obligations; responsible.}] [ {idoneo_it} ]: put.many 'word [ [name:{idoneo}, lang:{it}] ] link [var{appropriato_it} var{suficiente_pt} var{autosuffisant_fr} var{autosufficiente_it} var{idoneo_it} var{sufficient_en}] 'means var{Capable of meeting obligations; responsible.} {Having enough money to meet obligations and live comfortably.}: put'sense [name: {Having enough money to meet obligations and live comfortably.}] {modernism_en}: put'word [name: {modernism}, lang: "en"] {Modern or contemporary ideas, thought, practices, etc.}: put'sense [name: {Modern or contemporary ideas, thought, practices, etc.}] {Anything that is characteristic of modernity.}: put'sense [name: {Anything that is characteristic of modernity.}] {Any of several styles of art, architecture, literature, philosophy, etc., that flourished in the 20th century.}: put'sense [name: {Any of several styles of art, architecture, literature, philosophy, etc., that flourished in the 20th century.}] [ {modernisme_fr}, {Modernismus_de}, {νεωτερισμός_el}, {modernismo_it}, {modernismo_pt}, {modernismo_es} ]: put.many 'word [ [name:{modernisme}, lang:{fr}], [name:{Modernismus}, lang:{de}], [name:{νεωτερισμός}, lang:{el}], [name:{modernismo}, lang:{it}], [name:{modernismo}, lang:{pt}], [name:{modernismo}, lang:{es}] ] link [var{modernisme_fr} var{Modernismus_de} var{νεωτερισμός_el} var{modernismo_it} var{modernismo_pt} var{modernismo_es} var{modernism_en}] 'means var{Any of several styles of art, architecture, literature, philosophy, etc., that flourished in the 20th century.} {A religious movement in the early 20th century that tried to reconcile Roman Catholic dogma with modern science and philosophy.}: put'sense [name: {A religious movement in the early 20th century that tried to reconcile Roman Catholic dogma with modern science and philosophy.}] {midnight_en}: put'word [name: {midnight}, lang: "en"] {The middle of the night: the sixth temporal hour, equidistant between sunset and sunrise.}: put'sense [name: {The middle of the night: the sixth temporal hour, equidistant between sunset and sunrise.}] [ {medianoche_es}, {madrugada_es} ]: put.many 'word [ [name:{medianoche}, lang:{es}], [name:{madrugada}, lang:{es}] ] link [var{medianoche_es} var{madrugada_es} var{midnight_en}] 'means var{The middle of the night: the sixth temporal hour, equidistant between sunset and sunrise.} {Twelve o'clock at night exactly.}: put'sense [name: {Twelve o'clock at night exactly.}] [ {minuit_fr}, {Mitternacht_de}, {μεσάνυχτα_el}, {mezzanotte_it}, {meia-noite_pt}, {miezul nopții_ro}, {miez de noapte_ro}, {mijloc de noapte_ro}, {medianoche_es} ]: put.many 'word [ [name:{minuit}, lang:{fr}], [name:{Mitternacht}, lang:{de}], [name:{μεσάνυχτα}, lang:{el}], [name:{mezzanotte}, lang:{it}], [name:{meia-noite}, lang:{pt}], [name:{miezul nopții}, lang:{ro}], [name:{miez de noapte}, lang:{ro}], [name:{mijloc de noapte}, lang:{ro}], [name:{medianoche}, lang:{es}] ] link [var{medianoche_es} var{madrugada_es} var{minuit_fr} var{Mitternacht_de} var{μεσάνυχτα_el} var{mezzanotte_it} var{meia-noite_pt} var{miezul nopții_ro} var{miez de noapte_ro} var{mijloc de noapte_ro} var{medianoche_es} var{midnight_en}] 'means var{Twelve o'clock at night exactly.} {boxcars}: put'sense [name: {boxcars}] {Utterly dark or black.}: put'sense [name: {Utterly dark or black.}] {able_en}: put'word [name: {able}, lang: "en"] {Having the necessary powers or the needed resources to accomplish a task.}: put'sense [name: {Having the necessary powers or the needed resources to accomplish a task.}] {Free from constraints preventing completion of task; permitted to; not prevented from.}: put'sense [name: {Free from constraints preventing completion of task; permitted to; not prevented from.}] [ {capable_fr}, {imstande_de}, {fähig_de}, {δυνάμενος_el}, {μπορώ να_el}, {είμαι ικανός να_el}, {capace_it}, {possível_pt}, {permitido_pt}, {capaz_es} ]: put.many 'word [ [name:{capable}, lang:{fr}], [name:{imstande}, lang:{de}], [name:{fähig}, lang:{de}], [name:{δυνάμενος}, lang:{el}], [name:{μπορώ να}, lang:{el}], [name:{είμαι ικανός να}, lang:{el}], [name:{capace}, lang:{it}], [name:{possível}, lang:{pt}], [name:{permitido}, lang:{pt}], [name:{capaz}, lang:{es}] ] link [var{capable_fr} var{imstande_de} var{fähig_de} var{δυνάμενος_el} var{μπορώ να_el} var{είμαι ικανός να_el} var{capace_it} var{possível_pt} var{permitido_pt} var{capaz_es} var{able_en}] 'means var{Free from constraints preventing completion of task; permitted to; not prevented from.} {Gifted with skill, intelligence, knowledge, or competence.}: put'sense [name: {Gifted with skill, intelligence, knowledge, or competence.}] [ {capable_fr}, {expérimenté_fr}, {fähig_de}, {tüchtig_de}, {ικανός_el}, {abile_it}, {capaz_pt}, {abil_ro}, {capabil_ro}, {diestro_es}, {hábil_es}, {capaz_es} ]: put.many 'word [ [name:{capable}, lang:{fr}], [name:{expérimenté}, lang:{fr}], [name:{fähig}, lang:{de}], [name:{tüchtig}, lang:{de}], [name:{ικανός}, lang:{el}], [name:{abile}, lang:{it}], [name:{capaz}, lang:{pt}], [name:{abil}, lang:{ro}], [name:{capabil}, lang:{ro}], [name:{diestro}, lang:{es}], [name:{hábil}, lang:{es}], [name:{capaz}, lang:{es}] ] link [var{capable_fr} var{imstande_de} var{fähig_de} var{δυνάμενος_el} var{μπορώ να_el} var{είμαι ικανός να_el} var{capace_it} var{possível_pt} var{permitido_pt} var{capaz_es} var{capable_fr} var{expérimenté_fr} var{fähig_de} var{tüchtig_de} var{ικανός_el} var{abile_it} var{capaz_pt} var{abil_ro} var{capabil_ro} var{diestro_es} var{hábil_es} var{capaz_es} var{able_en}] 'means var{Gifted with skill, intelligence, knowledge, or competence.} {Legally qualified or competent.}: put'sense [name: {Legally qualified or competent.}] [ {habilité_fr}, {kompetent_de}, {αρτιμελής_el}, {έχων σώας τας φρένας_el}, {competente_pt}, {abilitat_ro}, {competent_ro}, {competente_es} ]: put.many 'word [ [name:{habilité}, lang:{fr}], [name:{kompetent}, lang:{de}], [name:{αρτιμελής}, lang:{el}], [name:{έχων σώας τας φρένας}, lang:{el}], [name:{competente}, lang:{pt}], [name:{abilitat}, lang:{ro}], [name:{competent}, lang:{ro}], [name:{competente}, lang:{es}] ] link [var{capable_fr} var{imstande_de} var{fähig_de} var{δυνάμενος_el} var{μπορώ να_el} var{είμαι ικανός να_el} var{capace_it} var{possível_pt} var{permitido_pt} var{capaz_es} var{capable_fr} var{expérimenté_fr} var{fähig_de} var{tüchtig_de} var{ικανός_el} var{abile_it} var{capaz_pt} var{abil_ro} var{capabil_ro} var{diestro_es} var{hábil_es} var{capaz_es} var{habilité_fr} var{kompetent_de} var{αρτιμελής_el} var{έχων σώας τας φρένας_el} var{competente_pt} var{abilitat_ro} var{competent_ro} var{competente_es} var{able_en}] 'means var{Legally qualified or competent.} {Capable of performing all the requisite duties; as an able seaman.}: put'sense [name: {Capable of performing all the requisite duties; as an able seaman.}] {Having the physical strength; robust; healthy.}: put'sense [name: {Having the physical strength; robust; healthy.}] {Easy to use.}: put'sense [name: {Easy to use.}] {Suitable; competent.}: put'sense [name: {Suitable; competent.}] {Liable to.}: put'sense [name: {Liable to.}] {Rich; well-to-do.}: put'sense [name: {Rich; well-to-do.}] {To make ready.}: put'sense [name: {To make ready.}] {To make capable; to enable.}: put'sense [name: {To make capable; to enable.}] {To dress.}: put'sense [name: {To dress.}] {To give power to; to reinforce; to confirm.}: put'sense [name: {To give power to; to reinforce; to confirm.}] {To vouch for; to guarantee.}: put'sense [name: {To vouch for; to guarantee.}] {The letter "A" in Navy Phonetic Alphabet.}: put'sense [name: {The letter "A" in Navy Phonetic Alphabet.}] {signal_en}: put'word [name: {signal}, lang: "en"] {A sequence of states representing an encoded message in a communication channel.}: put'sense [name: {A sequence of states representing an encoded message in a communication channel.}] {Any variation of a quantity or change in an entity over time that conveys information upon detection.}: put'sense [name: {Any variation of a quantity or change in an entity over time that conveys information upon detection.}] {A sign made to give notice of some occurrence, command, or danger, or to indicate the start of a concerted action.}: put'sense [name: {A sign made to give notice of some occurrence, command, or danger, or to indicate the start of a concerted action.}] [ {signal_fr}, {Signal_de}, {σήμα_el}, {segnale_it}, {sinal_pt}, {semnal_ro}, {señal_es} ]: put.many 'word [ [name:{signal}, lang:{fr}], [name:{Signal}, lang:{de}], [name:{σήμα}, lang:{el}], [name:{segnale}, lang:{it}], [name:{sinal}, lang:{pt}], [name:{semnal}, lang:{ro}], [name:{señal}, lang:{es}] ] link [var{signal_fr} var{Signal_de} var{σήμα_el} var{segnale_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{signal_en}] 'means var{A sign made to give notice of some occurrence, command, or danger, or to indicate the start of a concerted action.} {An on-off light, semaphore, or other device used to give an indication to another person.}: put'sense [name: {An on-off light, semaphore, or other device used to give an indication to another person.}] {An electromagnetic action, normally a voltage that is a function of time, that conveys the information of the radio or TV program or of communication with another party.}: put'sense [name: {An electromagnetic action, normally a voltage that is a function of time, that conveys the information of the radio or TV program or of communication with another party.}] [ {segnale_it}, {campo_it}, {sinal_pt}, {semnal_ro}, {señal_es} ]: put.many 'word [ [name:{segnale}, lang:{it}], [name:{campo}, lang:{it}], [name:{sinal}, lang:{pt}], [name:{semnal}, lang:{ro}], [name:{señal}, lang:{es}] ] link [var{signal_fr} var{Signal_de} var{σήμα_el} var{segnale_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{segnale_it} var{campo_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{signal_en}] 'means var{An electromagnetic action, normally a voltage that is a function of time, that conveys the information of the radio or TV program or of communication with another party.} {An action, change or process done to convey information and thus reduce uncertainty.}: put'sense [name: {An action, change or process done to convey information and thus reduce uncertainty.}] {A token; an indication; a foreshadowing; a sign.}: put'sense [name: {A token; an indication; a foreshadowing; a sign.}] [ {sinal_pt} ]: put.many 'word [ [name:{sinal}, lang:{pt}] ] link [var{signal_fr} var{Signal_de} var{σήμα_el} var{segnale_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{segnale_it} var{campo_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{sinal_pt} var{signal_en}] 'means var{A token; an indication; a foreshadowing; a sign.} {Useful information, as opposed to noise.}: put'sense [name: {Useful information, as opposed to noise.}] [ {sinal_pt} ]: put.many 'word [ [name:{sinal}, lang:{pt}] ] link [var{signal_fr} var{Signal_de} var{σήμα_el} var{segnale_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{segnale_it} var{campo_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{sinal_pt} var{sinal_pt} var{signal_en}] 'means var{Useful information, as opposed to noise.} {A simple interprocess communication used to notify a process or thread of an occurrence.}: put'sense [name: {A simple interprocess communication used to notify a process or thread of an occurrence.}] [ {signal_fr} ]: put.many 'word [ [name:{signal}, lang:{fr}] ] link [var{signal_fr} var{Signal_de} var{σήμα_el} var{segnale_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{segnale_it} var{campo_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{sinal_pt} var{sinal_pt} var{signal_fr} var{signal_en}] 'means var{A simple interprocess communication used to notify a process or thread of an occurrence.} {A signalling interaction between cells}: put'sense [name: {A signalling interaction between cells}] {To indicate; to convey or communicate by a signal.}: put'sense [name: {To indicate; to convey or communicate by a signal.}] [ {signaler_fr}, {signalisieren_de}, {segnalare_it}, {indicare_it}, {señalar_es} ]: put.many 'word [ [name:{signaler}, lang:{fr}], [name:{signalisieren}, lang:{de}], [name:{segnalare}, lang:{it}], [name:{indicare}, lang:{it}], [name:{señalar}, lang:{es}] ] link [var{signal_fr} var{Signal_de} var{σήμα_el} var{segnale_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{segnale_it} var{campo_it} var{sinal_pt} var{semnal_ro} var{señal_es} var{sinal_pt} var{sinal_pt} var{signal_fr} var{signaler_fr} var{signalisieren_de} var{segnalare_it} var{indicare_it} var{señalar_es} var{signal_en}] 'means var{To indicate; to convey or communicate by a signal.} {To communicate with (a person or system) by a signal.}: put'sense [name: {To communicate with (a person or system) by a signal.}] {Standing above others in rank, importance, or achievement.}: put'sense [name: {Standing above others in rank, importance, or achievement.}] {weapon_en}: put'word [name: {weapon}, lang: "en"] {An instrument of attack or defense in combat or hunting, e.g. most guns, missiles, or swords; arm.}: put'sense [name: {An instrument of attack or defense in combat or hunting, e.g. most guns, missiles, or swords; arm.}] [ {arme_fr}, {Waffe_de}, {όπλο_el}, {arma_it}, {arma_pt}, {armă_ro}, {arma_es} ]: put.many 'word [ [name:{arme}, lang:{fr}], [name:{Waffe}, lang:{de}], [name:{όπλο}, lang:{el}], [name:{arma}, lang:{it}], [name:{arma}, lang:{pt}], [name:{armă}, lang:{ro}], [name:{arma}, lang:{es}] ] link [var{arme_fr} var{Waffe_de} var{όπλο_el} var{arma_it} var{arma_pt} var{armă_ro} var{arma_es} var{weapon_en}] 'means var{An instrument of attack or defense in combat or hunting, e.g. most guns, missiles, or swords; arm.} {An instrument or other means of harming or exerting control over another.}: put'sense [name: {An instrument or other means of harming or exerting control over another.}] [ {όπλο_el} ]: put.many 'word [ [name:{όπλο}, lang:{el}] ] link [var{arme_fr} var{Waffe_de} var{όπλο_el} var{arma_it} var{arma_pt} var{armă_ro} var{arma_es} var{όπλο_el} var{weapon_en}] 'means var{An instrument or other means of harming or exerting control over another.} {A tool of any kind.}: put'sense [name: {A tool of any kind.}] {An idiot, an oaf, a fool, a tool; a contemptible or incompetent person.}: put'sense [name: {An idiot, an oaf, a fool, a tool; a contemptible or incompetent person.}] {Any very skilled, competent, or capable person or thing worthy of awe.}: put'sense [name: {Any very skilled, competent, or capable person or thing worthy of awe.}] {To equip with a weapon; to arm.}: put'sense [name: {To equip with a weapon; to arm.}] {devastation_en}: put'word [name: {devastation}, lang: "en"] {The act of devastating, or the state of being devastated; a laying waste.}: put'sense [name: {The act of devastating, or the state of being devastated; a laying waste.}] [ {dévastation_fr}, {Verwüstung_de}, {Zerstörung_de}, {αφανισμός_el}, {συντριβή_el}, {καταστροφή_el}, {devastação_pt}, {devastare_ro}, {devastación_es}, {asolamiento_es}, {arrasamiento_es}, {quebranto_es} ]: put.many 'word [ [name:{dévastation}, lang:{fr}], [name:{Verwüstung}, lang:{de}], [name:{Zerstörung}, lang:{de}], [name:{αφανισμός}, lang:{el}], [name:{συντριβή}, lang:{el}], [name:{καταστροφή}, lang:{el}], [name:{devastação}, lang:{pt}], [name:{devastare}, lang:{ro}], [name:{devastación}, lang:{es}], [name:{asolamiento}, lang:{es}], [name:{arrasamiento}, lang:{es}], [name:{quebranto}, lang:{es}] ] link [var{dévastation_fr} var{Verwüstung_de} var{Zerstörung_de} var{αφανισμός_el} var{συντριβή_el} var{καταστροφή_el} var{devastação_pt} var{devastare_ro} var{devastación_es} var{asolamiento_es} var{arrasamiento_es} var{quebranto_es} var{devastation_en}] 'means var{The act of devastating, or the state of being devastated; a laying waste.} {Waste or misapplication of the assets of a deceased person by an executor or administrator; devastavit.}: put'sense [name: {Waste or misapplication of the assets of a deceased person by an executor or administrator; devastavit.}] {solidary_en}: put'word [name: {solidary}, lang: "en"] {Having community of interests and responsibilities.}: put'sense [name: {Having community of interests and responsibilities.}] {itself_en}: put'word [name: {itself}, lang: "en"] {it; A thing as the object of a verb or preposition that also appears as the subject}: put'sense [name: {it; A thing as the object of a verb or preposition that also appears as the subject}] [ {se_fr}, {von selbst_de}, {von allein_de}, {selbst_de}, {sich selbst_de}, {sé_it}, {se_pt}, {a si mesmo_pt}, {se_es}, {solo_es}, {a si mismo_es}, {por si mismo_es} ]: put.many 'word [ [name:{se}, lang:{fr}], [name:{von selbst}, lang:{de}], [name:{von allein}, lang:{de}], [name:{selbst}, lang:{de}], [name:{sich selbst}, lang:{de}], [name:{sé}, lang:{it}], [name:{se}, lang:{pt}], [name:{a si mesmo}, lang:{pt}], [name:{se}, lang:{es}], [name:{solo}, lang:{es}], [name:{a si mismo}, lang:{es}], [name:{por si mismo}, lang:{es}] ] link [var{se_fr} var{von selbst_de} var{von allein_de} var{selbst_de} var{sich selbst_de} var{sé_it} var{se_pt} var{a si mesmo_pt} var{se_es} var{solo_es} var{a si mismo_es} var{por si mismo_es} var{itself_en}] 'means var{it; A thing as the object of a verb or preposition that also appears as the subject} {it; used to intensify the subject, especially to emphasize that it is the only participant in the predicate}: put'sense [name: {it; used to intensify the subject, especially to emphasize that it is the only participant in the predicate}] [ {soi-même_fr}, {se stesso_it}, {sé stesso_it}, {ele/ela mesmo_pt}, {próprio_pt}, {própria_pt}, {sí mismo_es}, {mismo_es} ]: put.many 'word [ [name:{soi-même}, lang:{fr}], [name:{se stesso}, lang:{it}], [name:{sé stesso}, lang:{it}], [name:{ele/ela mesmo}, lang:{pt}], [name:{próprio}, lang:{pt}], [name:{própria}, lang:{pt}], [name:{sí mismo}, lang:{es}], [name:{mismo}, lang:{es}] ] link [var{se_fr} var{von selbst_de} var{von allein_de} var{selbst_de} var{sich selbst_de} var{sé_it} var{se_pt} var{a si mesmo_pt} var{se_es} var{solo_es} var{a si mismo_es} var{por si mismo_es} var{soi-même_fr} var{se stesso_it} var{sé stesso_it} var{ele/ela mesmo_pt} var{próprio_pt} var{própria_pt} var{sí mismo_es} var{mismo_es} var{itself_en}] 'means var{it; used to intensify the subject, especially to emphasize that it is the only participant in the predicate} {it; used to refer back to an earlier subject}: put'sense [name: {it; used to refer back to an earlier subject}] {audience_en}: put'word [name: {audience}, lang: "en"] {A group of people within hearing; specifically, a large gathering of people listening to or watching a performance, speech, etc.}: put'sense [name: {A group of people within hearing; specifically, a large gathering of people listening to or watching a performance, speech, etc.}] [ {assistance_fr}, {public_fr}, {auditoire_fr}, {Publikum_de}, {Zuschauer_de}, {Audienzen_de}, {ακροατήριο_el}, {κοινό_el}, {pubblico_it}, {uditorio_it}, {público_pt}, {plateia_pt}, {asistență_ro}, {audiencia_es}, {público_es} ]: put.many 'word [ [name:{assistance}, lang:{fr}], [name:{public}, lang:{fr}], [name:{auditoire}, lang:{fr}], [name:{Publikum}, lang:{de}], [name:{Zuschauer}, lang:{de}], [name:{Audienzen}, lang:{de}], [name:{ακροατήριο}, lang:{el}], [name:{κοινό}, lang:{el}], [name:{pubblico}, lang:{it}], [name:{uditorio}, lang:{it}], [name:{público}, lang:{pt}], [name:{plateia}, lang:{pt}], [name:{asistență}, lang:{ro}], [name:{audiencia}, lang:{es}], [name:{público}, lang:{es}] ] link [var{assistance_fr} var{public_fr} var{auditoire_fr} var{Publikum_de} var{Zuschauer_de} var{Audienzen_de} var{ακροατήριο_el} var{κοινό_el} var{pubblico_it} var{uditorio_it} var{público_pt} var{plateia_pt} var{asistență_ro} var{audiencia_es} var{público_es} var{audience_en}] 'means var{A group of people within hearing; specifically, a large gathering of people listening to or watching a performance, speech, etc.} {Hearing; the condition or state of hearing or listening.}: put'sense [name: {Hearing; the condition or state of hearing or listening.}] {A widespread or nationwide viewing or listening public, as of a TV or radio network or program.}: put'sense [name: {A widespread or nationwide viewing or listening public, as of a TV or radio network or program.}] {A formal meeting with a state or religious dignitary.}: put'sense [name: {A formal meeting with a state or religious dignitary.}] [ {audience_fr}, {Audienz_de}, {ακρόαση_el}, {udienza_it}, {audiência_pt}, {audiență_ro}, {audiencia_es} ]: put.many 'word [ [name:{audience}, lang:{fr}], [name:{Audienz}, lang:{de}], [name:{ακρόαση}, lang:{el}], [name:{udienza}, lang:{it}], [name:{audiência}, lang:{pt}], [name:{audiență}, lang:{ro}], [name:{audiencia}, lang:{es}] ] link [var{assistance_fr} var{public_fr} var{auditoire_fr} var{Publikum_de} var{Zuschauer_de} var{Audienzen_de} var{ακροατήριο_el} var{κοινό_el} var{pubblico_it} var{uditorio_it} var{público_pt} var{plateia_pt} var{asistență_ro} var{audiencia_es} var{público_es} var{audience_fr} var{Audienz_de} var{ακρόαση_el} var{udienza_it} var{audiência_pt} var{audiență_ro} var{audiencia_es} var{audience_en}] 'means var{A formal meeting with a state or religious dignitary.} {The readership of a book or other written publication.}: put'sense [name: {The readership of a book or other written publication.}] [ {lectorat_fr}, {Publikum_de}, {κοινό_el}, {pubblico_it}, {público_pt}, {público-alvo_pt}, {leitorado_pt}, {público_es} ]: put.many 'word [ [name:{lectorat}, lang:{fr}], [name:{Publikum}, lang:{de}], [name:{κοινό}, lang:{el}], [name:{pubblico}, lang:{it}], [name:{público}, lang:{pt}], [name:{público-alvo}, lang:{pt}], [name:{leitorado}, lang:{pt}], [name:{público}, lang:{es}] ] link [var{assistance_fr} var{public_fr} var{auditoire_fr} var{Publikum_de} var{Zuschauer_de} var{Audienzen_de} var{ακροατήριο_el} var{κοινό_el} var{pubblico_it} var{uditorio_it} var{público_pt} var{plateia_pt} var{asistență_ro} var{audiencia_es} var{público_es} var{audience_fr} var{Audienz_de} var{ακρόαση_el} var{udienza_it} var{audiência_pt} var{audiență_ro} var{audiencia_es} var{lectorat_fr} var{Publikum_de} var{κοινό_el} var{pubblico_it} var{público_pt} var{público-alvo_pt} var{leitorado_pt} var{público_es} var{audience_en}] 'means var{The readership of a book or other written publication.} {A following.}: put'sense [name: {A following.}] [ {κοινό_el}, {público_pt}, {audiencia_es} ]: put.many 'word [ [name:{κοινό}, lang:{el}], [name:{público}, lang:{pt}], [name:{audiencia}, lang:{es}] ] link [var{assistance_fr} var{public_fr} var{auditoire_fr} var{Publikum_de} var{Zuschauer_de} var{Audienzen_de} var{ακροατήριο_el} var{κοινό_el} var{pubblico_it} var{uditorio_it} var{público_pt} var{plateia_pt} var{asistență_ro} var{audiencia_es} var{público_es} var{audience_fr} var{Audienz_de} var{ακρόαση_el} var{udienza_it} var{audiência_pt} var{audiență_ro} var{audiencia_es} var{lectorat_fr} var{Publikum_de} var{κοινό_el} var{pubblico_it} var{público_pt} var{público-alvo_pt} var{leitorado_pt} var{público_es} var{κοινό_el} var{público_pt} var{audiencia_es} var{audience_en}] 'means var{A following.} {An audiencia (judicial court of the Spanish empire), or the territory administered by it.}: put'sense [name: {An audiencia (judicial court of the Spanish empire), or the territory administered by it.}] {diary_en}: put'word [name: {diary}, lang: "en"] {A daily log of experiences, especially those of the writer.}: put'sense [name: {A daily log of experiences, especially those of the writer.}] [ {journal intime_fr}, {Tagebuch_de}, {ημερολόγιο_el}, {diario_it}, {diário_pt}, {jurnal intim_ro}, {diario_es} ]: put.many 'word [ [name:{journal intime}, lang:{fr}], [name:{Tagebuch}, lang:{de}], [name:{ημερολόγιο}, lang:{el}], [name:{diario}, lang:{it}], [name:{diário}, lang:{pt}], [name:{jurnal intim}, lang:{ro}], [name:{diario}, lang:{es}] ] link [var{journal intime_fr} var{Tagebuch_de} var{ημερολόγιο_el} var{diario_it} var{diário_pt} var{jurnal intim_ro} var{diario_es} var{diary_en}] 'means var{A daily log of experiences, especially those of the writer.} {A personal organizer or appointment diary.}: put'sense [name: {A personal organizer or appointment diary.}] {Lasting for one day.}: put'sense [name: {Lasting for one day.}] {To keep a diary or journal.}: put'sense [name: {To keep a diary or journal.}] ] preview fetch 'word ø ] ] ================================================ FILE: examples/sample2.art ================================================ do.import {grafito.art} do [ graph.create "sample2" [ honorEnN: put'Pos [p:"noun"] honorEsN: put'Pos [p:"noun"] dishonorEnN: put'Pos [p:"noun"] tokenS: put'Sense [s:"token of praise or respect"] link'has (put'Lemma [w:"honor" l:"en"]) honorEnN link'has (put'Lemma [w:"honor" l:"es"]) honorEsN link'has (put'Lemma [w:"dishonor" l:"en"]) dishonorEnN link'means honorEnN tokenS link'means honorEsN tokenS link'antonym dishonorEnN honorEnN preview fetch 'Pos ø ]] ================================================ FILE: examples/sample3.art ================================================ do.import {grafito.art} do [ graph.create "sample3" [ nick: put'person [name: "Nick", sex: "m", birth: 1957] eleftheria: put'person [name: "Eleftheria", sex: "f", birth: 1960] angela: put'person [name: "Angela", sex: "f", birth: 1999] john: put'person [name: "John", sex: "m", birth: 1986] niovi: put'person [name: "Niovi", sex: "f", birth: 1928] johnA: put'person [name: "John", sex: "m", birth: 1933] tatie: put'person [name: "Tatie", sex: "m", birth: 1958] spaghetti: put'food [name: "Spaghetti"] pizza: put'food [name: "Pizza"] steak: put'food [name: "Steak"] link'marriedTo nick eleftheria link'marriedTo johnA niovi link'childOf @[angela john] @[nick eleftheria] link'childOf @[nick tatie] @[johnA niovi] link'likes @[john angela niovi] @[spaghetti] link'likes @[eleftheria johnA nick] @[pizza] link'likes @[john tatie nick] @[steak] preview fetch 'person ø ] ] ================================================ FILE: examples/sample4.art ================================================ ;--------------------------------------------- ; Import Grafito ; and ... let's rock'n'roll! :) ;--------------------------------------------- do.import {grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample4" ;--------------------------------------------- graph.create "sample4" [ ;--------------------------------------------- ; Populate the database ;--------------------------------------------- uk: put'country [name: "United Kingdom"] au: put'country [name: "Australia"] us: put'country [name: "United States"] ca: put'country [name: "Canada"] nolan: put'person [name: "Christopher Nolan" birthday: 1970 sex: "m"] pearce: put'person [name: "Guy Pearce" birthday: 1967 sex: "m"] hanson: put'person [name: "Curtis Hanson" birthday: 1945 sex: "m"] spacey: put'person [name: "Kevin Spacey" birthday: 1959 sex: "m"] dicaprio: put'person [name: "Leonardo DiCaprio" birthday: 1974 sex: "m"] moss: put'person [name: "Carrie-Ann Moss" birthday: 1967 sex: "f"] wach1: put'person [name: "Lana Wachowski" birthday: 1965 sex: "f"] wach2: put'person [name: "Lilly Wachowski" birthday: 1967 sex: "f"] memento: put'movie [title: "Memento" year: 2000] inception: put'movie [title: "Inception" year: 2010] laconfidential: put'movie [title: "L.A. Confidential" year: 1997] matrix: put'movie [title: "The Matrix" year: 1999] ;--------------------------------------------- ; Define the relationships ; between our nodes ;--------------------------------------------- link'isFrom nolan uk link'isFrom pearce au link'isFrom @[hanson spacey dicaprio wach1 wach2] us link'isFrom moss ca link'directed nolan @[memento inception] link'directed hanson laconfidential link'directed @[wach1 wach2] matrix link'actedIn pearce @[memento laconfidential] link'actedIn spacey laconfidential link'actedIn dicaprio inception link'actedIn moss @[memento matrix] ;--------------------------------------------- ; Fetch every "person" & ; open the Desktop app for visualization ;--------------------------------------------- preview fetch 'person ø ] ] ================================================ FILE: examples/sample4b.art ================================================ ;--------------------------------------------- ; Import Grafito ; and ... let's rock'n'roll! :) ;--------------------------------------------- do.import {grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample4" ;--------------------------------------------- graph.create "sample4b" [ ;--------------------- ; HELPERS ;--------------------- country: function [block] -> put 'country block person: function [block] -> put 'person block movie: function [block] -> put 'movie block country?: function [block] -> fetch 'country block person?: function [block] -> fetch 'person block movie?: function [block] -> fetch 'movie block ;--------------------------------------------- ; Populate the database ;--------------------------------------------- uk: country [name: "United Kingdom"] au: country [name: "Australia"] us: country [name: "United States"] ca: country [name: "Canada"] nolan: person [name: "Christopher Nolan" birthday: 1970 sex: "m"] pearce: person [name: "Guy Pearce" birthday: 1967 sex: "m"] hanson: person [name: "Curtis Hanson" birthday: 1945 sex: "m"] spacey: person [name: "Kevin Spacey" birthday: 1959 sex: "m"] dicaprio: person [name: "Leonardo DiCaprio" birthday: 1974 sex: "m"] moss: person [name: "Carrie-Ann Moss" birthday: 1967 sex: "f"] wach1: person [name: "Lana Wachowski" birthday: 1965 sex: "f"] wach2: person [name: "Lilly Wachowski" birthday: 1967 sex: "f"] memento: movie [title: "Memento" year: 2000] inception: movie [title: "Inception" year: 2010] laconfidential: movie [title: "L.A. Confidential" year: 1997] matrix: movie [title: "The Matrix" year: 1999] ;--------------------------------------------- ; Define the relationships ; between our nodes ;--------------------------------------------- link'isFrom nolan uk link'isFrom pearce au link'isFrom @[hanson spacey dicaprio wach1 wach2] us link'isFrom moss ca link'directed nolan @[memento inception] link'directed hanson laconfidential link'directed @[wach1 wach2] matrix link'actedIn pearce @[memento laconfidential] link'actedIn spacey laconfidential link'actedIn dicaprio inception link'actedIn moss @[memento matrix] ;--------------------------------------------- ; Fetch every "person" & ; open the Desktop app for visualization ;--------------------------------------------- ; person? [isFrom: first country? -> name: "United States" name: -> contains: "d" ; ] ; returns DiCaprio ; person? [ ; isFrom: country? "United States" ; name: -> contains: "d" ; ] ; should return DiCaprio ; pythonic (potentially) ; person? ; isFrom: country? ; name: ; contains: "United" ; person? [ ; isFrom: country? [ ; name: [ ; contains: "United" ; ] ; ] ; name: [ ; contains: "w" ; ] ; ] preview fetch 'person ø ] ] ================================================ FILE: examples/sample4c.art ================================================ ;--------------------------------------------- ; Import Grafito ; and ... let's rock'n'roll! :) ;--------------------------------------------- do.import {grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample4" ;--------------------------------------------- graph .create .helpers: [person movie country] "sample4c" [ ;--------------------------------------------- ; Populate the database ;--------------------------------------------- uk: country.new [name: "United Kingdom"] au: country.new [name: "Australia"] us: country.new [name: "United States"] ca: country.new [name: "Canada"] nolan: person.new [name: "Christopher Nolan" birthday: 1970 sex: "m"] pearce: person.new [name: "Guy Pearce" birthday: 1967 sex: "m"] hanson: person.new [name: "Curtis Hanson" birthday: 1945 sex: "m"] spacey: person.new [name: "Kevin Spacey" birthday: 1959 sex: "m"] dicaprio: person.new [name: "Leonardo DiCaprio" birthday: 1974 sex: "m"] moss: person.new [name: "Carrie-Ann Moss" birthday: 1967 sex: "f"] kidman: person.new [name: "Nicole Kidman" birthday: 1967 sex: "f"] cruise: person.new [name: "Tom Cruise" birthday: 1962 sex: "m"] kubrick: person.new [name: "Stanley Kubrick" birthday: 1928 sex: "m"] wach1: person.new [name: "Lana Wachowski" birthday: 1965 sex: "f"] wach2: person.new [name: "Lilly Wachowski" birthday: 1967 sex: "f"] memento: movie.new [title: "Memento" year: 2000] inception: movie.new [title: "Inception" year: 2010] laconfidential: movie.new [title: "L.A. Confidential" year: 1997] matrix: movie.new [title: "The Matrix" year: 1999] eyes: movie.new [title: "Eyes Wide Shut" year: 1999] ;--------------------------------------------- ; Define the relationships ; between our nodes ;--------------------------------------------- link'isFrom nolan uk link'isFrom @[pearce kidman] au link'isFrom @[hanson spacey dicaprio wach1 wach2 cruise kubrick] us link'isFrom moss ca link'directed nolan @[memento inception] link'directed hanson laconfidential link'directed @[wach1 wach2] matrix link'directed kubrick eyes link'actedIn pearce @[memento laconfidential] link'actedIn spacey laconfidential link'actedIn dicaprio inception link'actedIn moss @[memento matrix] link'actedIn @[cruise kidman] eyes link'origin memento us link'origin laconfidential us link'origin matrix @[us au] link'origin @[inception eyes] @[uk us] link'sibling wach1 wach2 link'married cruise kidman ;--------------------------------------------- ; Fetch every "person" & ; open the Desktop app for visualization ;--------------------------------------------- preview fetch 'person ø ] ] ================================================ FILE: examples/sample4d.art ================================================ ;--------------------------------------------- ; Import Grafito ; and ... let's rock'n'roll! :) ;--------------------------------------------- do.import {grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample4" ;--------------------------------------------- graph.create "sample4b" [ ;--------------------- ; HELPERS ;--------------------- newCountry: function [block] -> put 'country block newPerson: function [block] -> put 'person block newMovie: function [block] -> put 'movie block country: function [block] -> fetch 'country block person: function [block] -> fetch 'person block movie: function [block] -> fetch 'movie block ;--------------------------------------------- ; Populate the database ;--------------------------------------------- uk: newCountry [name: "United Kingdom"] au: newCountry [name: "Australia"] us: newCountry [name: "United States"] ca: newCountry [name: "Canada"] nolan: newPerson [name: "Christopher Nolan" birthday: 1970 sex: "m"] pearce: newPerson [name: "Guy Pearce" birthday: 1967 sex: "m"] hanson: newPerson [name: "Curtis Hanson" birthday: 1945 sex: "m"] spacey: newPerson [name: "Kevin Spacey" birthday: 1959 sex: "m"] dicaprio: newPerson [name: "Leonardo DiCaprio" birthday: 1974 sex: "m"] moss: newPerson [name: "Carrie-Ann Moss" birthday: 1967 sex: "f"] wach1: newPerson [name: "Lana Wachowski" birthday: 1965 sex: "f"] wach2: newPerson [name: "Lilly Wachowski" birthday: 1967 sex: "f"] memento: newMovie [title: "Memento" year: 2000] inception: newMovie [title: "Inception" year: 2010] laconfidential: newMovie [title: "L.A. Confidential" year: 1997] matrix: newMovie [title: "The Matrix" year: 1999] ;--------------------------------------------- ; Define the relationships ; between our nodes ;--------------------------------------------- link'isFrom nolan uk link'isFrom pearce au link'isFrom @[hanson spacey dicaprio wach1 wach2] us link'isFrom moss ca link'directed nolan @[memento inception] link'directed hanson laconfidential link'directed @[wach1 wach2] matrix link'actedIn pearce @[memento laconfidential] link'actedIn spacey laconfidential link'actedIn dicaprio inception link'actedIn moss @[memento matrix] ;--------------------------------------------- ; Fetch every "person" & ; open the Desktop app for visualization ;--------------------------------------------- ; person? [isFrom: first country? -> name: "United States" name: -> contains: "d" ; ] ; returns DiCaprio ; person? [ ; isFrom: country? "United States" ; name: -> contains: "d" ; ] ; should return DiCaprio ; pythonic (potentially) ; person? ; isFrom: country? ; name: ; contains: "United" ; person? [ ; isFrom: country? [ ; name: [ ; contains: "United" ; ] ; ] ; name: [ ; contains: "w" ; ] ; ] preview person ø ] ] ================================================ FILE: examples/sample5.art ================================================ do.import {grafito.art} do [ graph.create "sample5" [ lemma8b257cd027: put 'lemma [w: {book} l: {en}] pos3722df1028: put'pos [p: {noun}] link'is lemma8b257cd027 pos3722df1028 sensef86f08d2e2: put'sense [s:{collection of sheets of paper bound together containing printed or written material}] link'means pos3722df1028 sensef86f08d2e2 lemma493be85c29: put'lemma [w: {كتاب} l: {apc}] pose499631911: put'pos [p: {noun}] link'is lemma493be85c29 pose499631911 link'means pose499631911 sensef86f08d2e2 lemma693a742816: put'lemma [w: {ᏗᎪᏪᎵ} l: {chr}] pos22d786790a: put'pos [p: {noun}] link'is lemma693a742816 pos22d786790a link'means pos22d786790a sensef86f08d2e2 lemma26fd5156d7: put'lemma [w: {書} l: {gan}] posf6b3172996: put'pos [p: {noun}] link'is lemma26fd5156d7 posf6b3172996 link'means posf6b3172996 sensef86f08d2e2 lemma9a3a17ffe8: put'lemma [w: {书} l: {gan}] pos9b9ff30210: put'pos [p: {noun}] link'is lemma9a3a17ffe8 pos9b9ff30210 link'means pos9b9ff30210 sensef86f08d2e2 lemma3027ada842: put'lemma [w: {書} l: {cjy}] pose7e0f1482c: put'pos [p: {noun}] link'is lemma3027ada842 pose7e0f1482c link'means pose7e0f1482c sensef86f08d2e2 lemmafb0ebfc12a: put'lemma [w: {书} l: {cjy}] pos83a0d216aa: put'pos [p: {noun}] link'is lemmafb0ebfc12a pos83a0d216aa link'means pos83a0d216aa sensef86f08d2e2 lemmafdf3beed04: put'lemma [w: {書} l: {mnp}] pos49fb33a5c6: put'pos [p: {noun}] link'is lemmafdf3beed04 pos49fb33a5c6 link'means pos49fb33a5c6 sensef86f08d2e2 lemmae8ba2100e7: put'lemma [w: {书} l: {mnp}] pos45b2f78257: put'pos [p: {noun}] link'is lemmae8ba2100e7 pos45b2f78257 link'means pos45b2f78257 sensef86f08d2e2 lemmabfb684d055: put'lemma [w: {書} l: {hsn}] pos21c619ca73: put'pos [p: {noun}] link'is lemmabfb684d055 pos21c619ca73 link'means pos21c619ca73 sensef86f08d2e2 lemma49e788e226: put'lemma [w: {书} l: {hsn}] pos53828a28f1: put'pos [p: {noun}] link'is lemma49e788e226 pos53828a28f1 link'means pos53828a28f1 sensef86f08d2e2 lemma3de6f10595: put'lemma [w: {𞤣𞤫𞤬𞤼𞤫𞤪𞤫} l: {ff}] pos61a1c07120: put'pos [p: {noun}] link'is lemma3de6f10595 pos61a1c07120 link'means pos61a1c07120 sensef86f08d2e2 lemmadd03b675a5: put'lemma [w: {deftere} l: {ff}] pos2ba9f770dd: put'pos [p: {noun}] link'is lemmadd03b675a5 pos2ba9f770dd link'means pos2ba9f770dd sensef86f08d2e2 lemmab6adde549d: put'lemma [w: {ブック} l: {ja}] posefc5173c6e: put'pos [p: {noun}] link'is lemmab6adde549d posefc5173c6e link'means posefc5173c6e sensef86f08d2e2 lemma979bc5909e: put'lemma [w: {buku} l: {jv}] pos53c5fefdd3: put'pos [p: {noun}] link'is lemma979bc5909e pos53c5fefdd3 link'means pos53c5fefdd3 sensef86f08d2e2 lemma77d51b75ed: put'lemma [w: {layang} l: {jv}] pose41277bf28: put'pos [p: {noun}] link'is lemma77d51b75ed pose41277bf28 link'means pose41277bf28 sensef86f08d2e2 lemmada9979caf2: put'lemma [w: {serat} l: {jv}] pos89453006b2: put'pos [p: {noun}] link'is lemmada9979caf2 pos89453006b2 link'means pos89453006b2 sensef86f08d2e2 lemmaf9128c3a63: put'lemma [w: {hun} l: {tr}] posc360a20e09: put'pos [p: {noun}] link'is lemmaf9128c3a63 posc360a20e09 link'means posc360a20e09 sensef86f08d2e2 senseb2f79ce965: put'sense [s:{record of betting}] link'means pos3722df1028 senseb2f79ce965 sensee629d8b849: put'sense [s:{convenient collection of small paper items, such as stamps}] link'means pos3722df1028 sensee629d8b849 sense92e15899d7: put'sense [s:{major division of a published work, larger than a chapter}] link'means pos3722df1028 sense92e15899d7 sensea5f1ab78b7: put'sense [s:{script of a musical}] link'means pos3722df1028 sensea5f1ab78b7 sense310968d56f: put'sense [s:{usually in plural: records of the accounts of a business}] link'means pos3722df1028 sense310968d56f pos7f8fc0a70a: put'pos [p: {verb}] link'is lemma8b257cd027 pos7f8fc0a70a senseda38a026ab: put'sense [s:{to reserve}] link'means pos7f8fc0a70a senseda38a026ab lemma5ffab7eaf1: put'lemma [w: {حَجَزَ} l: {ar}] pos8f96b36193: put'pos [p: {verb}] link'is lemma5ffab7eaf1 pos8f96b36193 link'means pos8f96b36193 senseda38a026ab lemmab052952b74: put'lemma [w: {запазвам} l: {bg}] pos400e2c04fa: put'pos [p: {verb}] link'is lemmab052952b74 pos400e2c04fa link'means pos400e2c04fa senseda38a026ab lemmac68abfa48d: put'lemma [w: {reservar} l: {ca}] pos718825f926: put'pos [p: {verb}] link'is lemmac68abfa48d pos718825f926 link'means pos718825f926 senseda38a026ab lemma99b2986739: put'lemma [w: {預訂} l: {cmn}] pos4cd050d838: put'pos [p: {verb}] link'is lemma99b2986739 pos4cd050d838 link'means pos4cd050d838 senseda38a026ab lemmafa2b938743: put'lemma [w: {预订} l: {cmn}] posb4eb4eba86: put'pos [p: {verb}] link'is lemmafa2b938743 posb4eb4eba86 link'means posb4eb4eba86 senseda38a026ab lemma0f0d44abcf: put'lemma [w: {rezervovat} l: {cs}] pos162f335187: put'pos [p: {verb}] link'is lemma0f0d44abcf pos162f335187 link'means pos162f335187 senseda38a026ab lemmaef137e0718: put'lemma [w: {zarezervovat} l: {cs}] posf6d7b3a598: put'pos [p: {verb}] link'is lemmaef137e0718 posf6d7b3a598 link'means posf6d7b3a598 senseda38a026ab lemma2692b18099: put'lemma [w: {zabukovat} l: {cs}] poscc0eb62b54: put'pos [p: {verb}] link'is lemma2692b18099 poscc0eb62b54 link'means poscc0eb62b54 senseda38a026ab lemma1654d11c38: put'lemma [w: {reservere} l: {da}] pos9f550e3669: put'pos [p: {verb}] link'is lemma1654d11c38 pos9f550e3669 link'means pos9f550e3669 senseda38a026ab lemma3eb280bc1c: put'lemma [w: {bestille} l: {da}] pos269495d662: put'pos [p: {verb}] link'is lemma3eb280bc1c pos269495d662 link'means pos269495d662 senseda38a026ab lemmaa5e7be2c82: put'lemma [w: {boeken} l: {nl}] pos9fb854c050: put'pos [p: {verb}] link'is lemmaa5e7be2c82 pos9fb854c050 link'means pos9fb854c050 senseda38a026ab lemmac9f87cbf24: put'lemma [w: {reserveren} l: {nl}] pos66b6ed688a: put'pos [p: {verb}] link'is lemmac9f87cbf24 pos66b6ed688a link'means pos66b6ed688a senseda38a026ab lemmabbc5f17f49: put'lemma [w: {rezervi} l: {eo}] pos37d07f5e83: put'pos [p: {verb}] link'is lemmabbc5f17f49 pos37d07f5e83 link'means pos37d07f5e83 senseda38a026ab lemmab7f16f3b0b: put'lemma [w: {varata} l: {fi}] pos810ea59d98: put'pos [p: {verb}] link'is lemmab7f16f3b0b pos810ea59d98 link'means pos810ea59d98 senseda38a026ab lemmaea73a2348c: put'lemma [w: {tehdä varaus} l: {fi}] pos8c953c4fbb: put'pos [p: {verb}] link'is lemmaea73a2348c pos8c953c4fbb link'means pos8c953c4fbb senseda38a026ab lemmaa6e05310a1: put'lemma [w: {réserver} l: {fr}] posdb48c2f6f9: put'pos [p: {verb}] link'is lemmaa6e05310a1 posdb48c2f6f9 link'means posdb48c2f6f9 senseda38a026ab lemma57ee34b617: put'lemma [w: {reservar} l: {gl}] posedc5b0780b: put'pos [p: {verb}] link'is lemma57ee34b617 posedc5b0780b link'means posedc5b0780b senseda38a026ab lemma20e6bcda51: put'lemma [w: {რეგისტრირება} l: {ka}] posa462660823: put'pos [p: {verb}] link'is lemma20e6bcda51 posa462660823 link'means posa462660823 senseda38a026ab lemmab7b174e6b7: put'lemma [w: {რეგისტრაციაში გატარება} l: {ka}] pos7f7fb6d403: put'pos [p: {verb}] link'is lemmab7b174e6b7 pos7f7fb6d403 link'means pos7f7fb6d403 senseda38a026ab lemmad0bd3f2e5f: put'lemma [w: {დაბრონვა} l: {ka}] pos217871f31e: put'pos [p: {verb}] link'is lemmad0bd3f2e5f pos217871f31e link'means pos217871f31e senseda38a026ab lemma419efd5922: put'lemma [w: {ბრონირება} l: {ka}] pos8f34f3db49: put'pos [p: {verb}] link'is lemma419efd5922 pos8f34f3db49 link'means pos8f34f3db49 senseda38a026ab lemma9ce011469e: put'lemma [w: {buchen} l: {de}] posbc3dcacdaa: put'pos [p: {verb}] link'is lemma9ce011469e posbc3dcacdaa link'means posbc3dcacdaa senseda38a026ab lemma4adc255247: put'lemma [w: {reservieren} l: {de}] posabf9ceb9e3: put'pos [p: {verb}] link'is lemma4adc255247 posabf9ceb9e3 link'means posabf9ceb9e3 senseda38a026ab lemma8142abc97f: put'lemma [w: {κρατώ} l: {el}] pos29eb57cafc: put'pos [p: {verb}] link'is lemma8142abc97f pos29eb57cafc link'means pos29eb57cafc senseda38a026ab lemma64c115b11d: put'lemma [w: {προκρατ} l: {el}] posf6043dbd1d: put'pos [p: {verb}] link'is lemma64c115b11d posf6043dbd1d link'means posf6043dbd1d senseda38a026ab lemma0c080e4747: put'lemma [w: {κλείνω} l: {el}] pos9be526592e: put'pos [p: {verb}] link'is lemma0c080e4747 pos9be526592e link'means pos9be526592e senseda38a026ab lemma1445c3359b: put'lemma [w: {रिज़र्व करना} l: {hi}] pos2652d23622: put'pos [p: {verb}] link'is lemma1445c3359b pos2652d23622 link'means pos2652d23622 senseda38a026ab lemmad879fb0956: put'lemma [w: {lefoglal} l: {hu}] posfa7a7ccc22: put'pos [p: {verb}] link'is lemmad879fb0956 posfa7a7ccc22 link'means posfa7a7ccc22 senseda38a026ab lemmad3a1fe2739: put'lemma [w: {foglal} l: {hu}] posc4b80a955a: put'pos [p: {verb}] link'is lemmad3a1fe2739 posc4b80a955a link'means posc4b80a955a senseda38a026ab lemmaf9d257fe1b: put'lemma [w: {megvált} l: {hu}] pos8272261f05: put'pos [p: {verb}] link'is lemmaf9d257fe1b pos8272261f05 link'means pos8272261f05 senseda38a026ab lemma0628303c25: put'lemma [w: {vált} l: {hu}] pos91a5d1faa1: put'pos [p: {verb}] link'is lemma0628303c25 pos91a5d1faa1 link'means pos91a5d1faa1 senseda38a026ab lemmad664047b50: put'lemma [w: {előjegyez} l: {hu}] pos172fda6753: put'pos [p: {verb}] link'is lemmad664047b50 pos172fda6753 link'means pos172fda6753 senseda38a026ab lemma0fcd290db9: put'lemma [w: {pesan} l: {id}] pos3fc7440682: put'pos [p: {verb}] link'is lemma0fcd290db9 pos3fc7440682 link'means pos3fc7440682 senseda38a026ab lemma285918e9d7: put'lemma [w: {reservar} l: {ia}] pos71e7aa6831: put'pos [p: {verb}] link'is lemma285918e9d7 pos71e7aa6831 link'means pos71e7aa6831 senseda38a026ab lemmab388c1d5f4: put'lemma [w: {cuir in áirithe} l: {ga}] posc087fab3ae: put'pos [p: {verb}] link'is lemmab388c1d5f4 posc087fab3ae link'means posc087fab3ae senseda38a026ab lemma50000a8536: put'lemma [w: {prenotare} l: {it}] pos95467c3689: put'pos [p: {verb}] link'is lemma50000a8536 pos95467c3689 link'means pos95467c3689 senseda38a026ab lemmae07803f170: put'lemma [w: {riservare} l: {it}] pos6a7ad647ae: put'pos [p: {verb}] link'is lemmae07803f170 pos6a7ad647ae link'means pos6a7ad647ae senseda38a026ab lemma4452d5f6db: put'lemma [w: {予約する} l: {ja}] pos454ca32c7b: put'pos [p: {verb}] link'is lemma4452d5f6db pos454ca32c7b link'means pos454ca32c7b senseda38a026ab lemma8fcd8726fe: put'lemma [w: {예약하다} l: {ko}] pos4a5a86c7bd: put'pos [p: {verb}] link'is lemma8fcd8726fe pos4a5a86c7bd link'means pos4a5a86c7bd senseda38a026ab lemma2433e61607: put'lemma [w: {豫約} l: {ko}] pos6473e71a0d: put'pos [p: {verb}] link'is lemma2433e61607 pos6473e71a0d link'means pos6473e71a0d senseda38a026ab lemma0b78bda757: put'lemma [w: {하다} l: {ko}] pos1a5ff82ae5: put'pos [p: {verb}] link'is lemma0b78bda757 pos1a5ff82ae5 link'means pos1a5ff82ae5 senseda38a026ab lemma9c4463e264: put'lemma [w: {резерви́ра} l: {mk}] pos53276c2faa: put'pos [p: {verb}] link'is lemma9c4463e264 pos53276c2faa link'means pos53276c2faa senseda38a026ab lemma00530c554d: put'lemma [w: {закажува} l: {mk}] pos40bedcde3d: put'pos [p: {verb}] link'is lemma00530c554d pos40bedcde3d link'means pos40bedcde3d senseda38a026ab lemma34f6b2ffdd: put'lemma [w: {tempah} l: {ms}] pos2d7cbe1793: put'pos [p: {verb}] link'is lemma34f6b2ffdd pos2d7cbe1793 link'means pos2d7cbe1793 senseda38a026ab lemmad6f29905b6: put'lemma [w: {tāpui} l: {mi}] pos23a68a8d2b: put'pos [p: {verb}] link'is lemmad6f29905b6 pos23a68a8d2b link'means pos23a68a8d2b senseda38a026ab lemmaf698af452b: put'lemma [w: {ukaɗimia} l: {zdj}] pos6e1ac881a5: put'pos [p: {verb}] link'is lemmaf698af452b pos6e1ac881a5 link'means pos6e1ac881a5 senseda38a026ab lemmac034b1f0e8: put'lemma [w: {boutchi} l: {nrf}] pos712ca843ca: put'pos [p: {verb}] link'is lemmac034b1f0e8 pos712ca843ca link'means pos712ca843ca senseda38a026ab lemma77255589bd: put'lemma [w: {bestille} l: {no}] posd2ec255c53: put'pos [p: {verb}] link'is lemma77255589bd posd2ec255c53 link'means posd2ec255c53 senseda38a026ab lemma0536ef5117: put'lemma [w: {reservere} l: {no}] pos93c775435f: put'pos [p: {verb}] link'is lemma0536ef5117 pos93c775435f link'means pos93c775435f senseda38a026ab lemmafc32ea3c6b: put'lemma [w: {رزرو کردن} l: {fa}] pos75d89b17a4: put'pos [p: {verb}] link'is lemmafc32ea3c6b pos75d89b17a4 link'means pos75d89b17a4 senseda38a026ab lemma0d1a467c92: put'lemma [w: {rezerwować} l: {pl}] pos6b76db03c3: put'pos [p: {verb}] link'is lemma0d1a467c92 pos6b76db03c3 link'means pos6b76db03c3 senseda38a026ab lemma30625f22fd: put'lemma [w: {zarezerwować} l: {pl}] pos283289ef18: put'pos [p: {verb}] link'is lemma30625f22fd pos283289ef18 link'means pos283289ef18 senseda38a026ab lemma7bd6f153d5: put'lemma [w: {bukować} l: {pl}] pos6e5c9329a8: put'pos [p: {verb}] link'is lemma7bd6f153d5 pos6e5c9329a8 link'means pos6e5c9329a8 senseda38a026ab lemma5e6b1a766b: put'lemma [w: {zabukować} l: {pl}] pos002a1fcd8e: put'pos [p: {verb}] link'is lemma5e6b1a766b pos002a1fcd8e link'means pos002a1fcd8e senseda38a026ab lemma26b0f4e842: put'lemma [w: {reservar} l: {pt}] pos12c0f1ee7a: put'pos [p: {verb}] link'is lemma26b0f4e842 pos12c0f1ee7a link'means pos12c0f1ee7a senseda38a026ab lemma879ebd4b4c: put'lemma [w: {rezerva} l: {ro}] pos926bdd0d33: put'pos [p: {verb}] link'is lemma879ebd4b4c pos926bdd0d33 link'means pos926bdd0d33 senseda38a026ab lemmace2406de31: put'lemma [w: {брони́ровать} l: {ru}] posb84f90110d: put'pos [p: {verb}] link'is lemmace2406de31 posb84f90110d link'means posb84f90110d senseda38a026ab lemmae4ed260f84: put'lemma [w: {заброни́ровать} l: {ru}] pose74deb4481: put'pos [p: {verb}] link'is lemmae4ed260f84 pose74deb4481 link'means pose74deb4481 senseda38a026ab lemma8f820f7a26: put'lemma [w: {резерви́ровать} l: {ru}] pos0347e3dc8e: put'pos [p: {verb}] link'is lemma8f820f7a26 pos0347e3dc8e link'means pos0347e3dc8e senseda38a026ab lemma708016700d: put'lemma [w: {зарезерви́ровать} l: {ru}] pos1390c3be31: put'pos [p: {verb}] link'is lemma708016700d pos1390c3be31 link'means pos1390c3be31 senseda38a026ab lemma530ab298bb: put'lemma [w: {зака́зывать} l: {ru}] pos7067c6efa1: put'pos [p: {verb}] link'is lemma530ab298bb pos7067c6efa1 link'means pos7067c6efa1 senseda38a026ab lemma2b81adebcc: put'lemma [w: {заказа́ть} l: {ru}] poseafb3e54d8: put'pos [p: {verb}] link'is lemma2b81adebcc poseafb3e54d8 link'means poseafb3e54d8 senseda38a026ab lemma27f3081168: put'lemma [w: {predbilježiti} l: {sh}] pos2e39921f77: put'pos [p: {verb}] link'is lemma27f3081168 pos2e39921f77 link'means pos2e39921f77 senseda38a026ab lemmac390608b64: put'lemma [w: {rezervirati} l: {sh}] pos7ca2e7b7a1: put'pos [p: {verb}] link'is lemmac390608b64 pos7ca2e7b7a1 link'means pos7ca2e7b7a1 senseda38a026ab lemma0fa6291cae: put'lemma [w: {rezervovať} l: {sk}] pos27093a6607: put'pos [p: {verb}] link'is lemma0fa6291cae pos27093a6607 link'means pos27093a6607 senseda38a026ab lemma9b51132bd5: put'lemma [w: {zarezervovať} l: {sk}] pos3afcdc8775: put'pos [p: {verb}] link'is lemma9b51132bd5 pos3afcdc8775 link'means pos3afcdc8775 senseda38a026ab lemmadade0190a1: put'lemma [w: {reservar} l: {es}] pos1a3816d253: put'pos [p: {verb}] link'is lemmadade0190a1 pos1a3816d253 link'means pos1a3816d253 senseda38a026ab lemmabe96b9eda9: put'lemma [w: {boka} l: {sv}] pos8abf78a031: put'pos [p: {verb}] link'is lemmabe96b9eda9 pos8abf78a031 link'means pos8abf78a031 senseda38a026ab lemma66f4963c8f: put'lemma [w: {yer ayırma} l: {tr}] pos3b7b578927: put'pos [p: {verb}] link'is lemma66f4963c8f pos3b7b578927 link'means pos3b7b578927 senseda38a026ab lemma1befa0db9f: put'lemma [w: {kitap} l: {tr}] pos5945f4a88c: put'pos [p: {verb}] link'is lemma1befa0db9f pos5945f4a88c link'means pos5945f4a88c senseda38a026ab lemmab0303cee06: put'lemma [w: {cadw} l: {cy}] pos36d8a0e63e: put'pos [p: {verb}] link'is lemmab0303cee06 pos36d8a0e63e link'means pos36d8a0e63e senseda38a026ab sense8095a9e6b4: put'sense [s:{to write down, register, record}] link'means pos7f8fc0a70a sense8095a9e6b4 lemmad852354987: put'lemma [w: {записвам} l: {bg}] pos8819b3eae4: put'pos [p: {verb}] link'is lemmad852354987 pos8819b3eae4 link'means pos8819b3eae4 sense8095a9e6b4 lemmab005141cd0: put'lemma [w: {anotar} l: {ca}] pos97495274a8: put'pos [p: {verb}] link'is lemmab005141cd0 pos97495274a8 link'means pos97495274a8 sense8095a9e6b4 lemma0e15b367cc: put'lemma [w: {nedskrive} l: {da}] pos97d056b11a: put'pos [p: {verb}] link'is lemma0e15b367cc pos97d056b11a link'means pos97d056b11a sense8095a9e6b4 lemmacdefb85839: put'lemma [w: {notere} l: {da}] posfdd3b63753: put'pos [p: {verb}] link'is lemmacdefb85839 posfdd3b63753 link'means posfdd3b63753 sense8095a9e6b4 lemmaa25f253805: put'lemma [w: {bogføre} l: {da}] posade3600c74: put'pos [p: {verb}] link'is lemmaa25f253805 posade3600c74 link'means posade3600c74 sense8095a9e6b4 lemma304f17307c: put'lemma [w: {te boek stellen} l: {nl}] posd31eb16f3f: put'pos [p: {verb}] link'is lemma304f17307c posd31eb16f3f link'means posd31eb16f3f sense8095a9e6b4 lemma755a870552: put'lemma [w: {noteren} l: {nl}] pos6fc05d6155: put'pos [p: {verb}] link'is lemma755a870552 pos6fc05d6155 link'means pos6fc05d6155 sense8095a9e6b4 lemma8b3d7ecf85: put'lemma [w: {kirjoittaa ylös} l: {fi}] pos3c91c6d9bc: put'pos [p: {verb}] link'is lemma8b3d7ecf85 pos3c91c6d9bc link'means pos3c91c6d9bc sense8095a9e6b4 lemma2c97454540: put'lemma [w: {kirjata} l: {fi}] posc1827b1993: put'pos [p: {verb}] link'is lemma2c97454540 posc1827b1993 link'means posc1827b1993 sense8095a9e6b4 lemma7e3ca6f4f8: put'lemma [w: {kirjoittaa muistiin} l: {fi}] pos9e0e710234: put'pos [p: {verb}] link'is lemma7e3ca6f4f8 pos9e0e710234 link'means pos9e0e710234 sense8095a9e6b4 lemma26cbdd3150: put'lemma [w: {rekisteröidä} l: {fi}] posf3119d023c: put'pos [p: {verb}] link'is lemma26cbdd3150 posf3119d023c link'means posf3119d023c sense8095a9e6b4 lemmaf68d609965: put'lemma [w: {anotar} l: {gl}] pos84cd315e51: put'pos [p: {verb}] link'is lemmaf68d609965 pos84cd315e51 link'means pos84cd315e51 sense8095a9e6b4 lemma0de80bc46e: put'lemma [w: {notieren} l: {de}] pos84a5f64c2e: put'pos [p: {verb}] link'is lemma0de80bc46e pos84a5f64c2e link'means pos84a5f64c2e sense8095a9e6b4 lemmaa10d262aaa: put'lemma [w: {schreiben} l: {de}] pos5b1b03041e: put'pos [p: {verb}] link'is lemmaa10d262aaa pos5b1b03041e link'means pos5b1b03041e sense8095a9e6b4 lemma540a841c3d: put'lemma [w: {γράφω} l: {el}] pos48be3a8c62: put'pos [p: {verb}] link'is lemma540a841c3d pos48be3a8c62 link'means pos48be3a8c62 sense8095a9e6b4 lemma7fd4b6db6a: put'lemma [w: {καταχωρώ} l: {el}] posdc3280615b: put'pos [p: {verb}] link'is lemma7fd4b6db6a posdc3280615b link'means posdc3280615b sense8095a9e6b4 lemmab7b990a4b0: put'lemma [w: {σημειώνω} l: {el}] pos70c93fbb47: put'pos [p: {verb}] link'is lemmab7b990a4b0 pos70c93fbb47 link'means pos70c93fbb47 sense8095a9e6b4 lemmaa6b4c7bca1: put'lemma [w: {könyvel} l: {hu}] posb4d1705702: put'pos [p: {verb}] link'is lemmaa6b4c7bca1 posb4d1705702 link'means posb4d1705702 sense8095a9e6b4 lemmab43710f26b: put'lemma [w: {elkönyvel} l: {hu}] pos0ae342613c: put'pos [p: {verb}] link'is lemmab43710f26b pos0ae342613c link'means pos0ae342613c sense8095a9e6b4 lemma0511896480: put'lemma [w: {lekönyvel} l: {hu}] pos3b3b44fb1a: put'pos [p: {verb}] link'is lemma0511896480 pos3b3b44fb1a link'means pos3b3b44fb1a sense8095a9e6b4 lemmabce991bde2: put'lemma [w: {annotare} l: {it}] pos5ef4098e1e: put'pos [p: {verb}] link'is lemmabce991bde2 pos5ef4098e1e link'means pos5ef4098e1e sense8095a9e6b4 lemma2d43e6f98b: put'lemma [w: {trascrivere} l: {it}] pos939a70c95b: put'pos [p: {verb}] link'is lemma2d43e6f98b pos939a70c95b link'means pos939a70c95b sense8095a9e6b4 lemmaa37bb862d6: put'lemma [w: {記入する} l: {ja}] posbac3839f97: put'pos [p: {verb}] link'is lemmaa37bb862d6 posbac3839f97 link'means posbac3839f97 sense8095a9e6b4 lemma8544784707: put'lemma [w: {внесува} l: {mk}] pos70ca5d74c6: put'pos [p: {verb}] link'is lemma8544784707 pos70ca5d74c6 link'means pos70ca5d74c6 sense8095a9e6b4 lemma875e7a5bda: put'lemma [w: {запишува} l: {mk}] pose2a009c635: put'pos [p: {verb}] link'is lemma875e7a5bda pose2a009c635 link'means pose2a009c635 sense8095a9e6b4 lemmaee5012657d: put'lemma [w: {заведува} l: {mk}] posa54755bcaa: put'pos [p: {verb}] link'is lemmaee5012657d posa54755bcaa link'means posa54755bcaa sense8095a9e6b4 lemmad70262d4ea: put'lemma [w: {notere} l: {no}] pos358f613c8a: put'pos [p: {verb}] link'is lemmad70262d4ea pos358f613c8a link'means pos358f613c8a sense8095a9e6b4 lemma02aa35731c: put'lemma [w: {nedskrive} l: {no}] posa8ec1ffe68: put'pos [p: {verb}] link'is lemma02aa35731c posa8ec1ffe68 link'means posa8ec1ffe68 sense8095a9e6b4 lemma01516d0d30: put'lemma [w: {spisać} l: {pl}] pos12ec563702: put'pos [p: {verb}] link'is lemma01516d0d30 pos12ec563702 link'means pos12ec563702 sense8095a9e6b4 lemma2611d0acb7: put'lemma [w: {anotar} l: {pt}] pos869ad4d4c8: put'pos [p: {verb}] link'is lemma2611d0acb7 pos869ad4d4c8 link'means pos869ad4d4c8 sense8095a9e6b4 lemma115333dd6b: put'lemma [w: {zaznačiť} l: {sk}] pos78a01b223a: put'pos [p: {verb}] link'is lemma115333dd6b pos78a01b223a link'means pos78a01b223a sense8095a9e6b4 lemma096b64d995: put'lemma [w: {zaknihovať} l: {sk}] posfe3151ea95: put'pos [p: {verb}] link'is lemma096b64d995 posfe3151ea95 link'means posfe3151ea95 sense8095a9e6b4 lemma55e473797a: put'lemma [w: {anotar} l: {es}] pos6734388ceb: put'pos [p: {verb}] link'is lemma55e473797a pos6734388ceb link'means pos6734388ceb sense8095a9e6b4 lemmaa06d6a035f: put'lemma [w: {bokföra} l: {sv}] pos82f6ae7130: put'pos [p: {verb}] link'is lemmaa06d6a035f pos82f6ae7130 link'means pos82f6ae7130 sense8095a9e6b4 lemmaef47e75a55: put'lemma [w: {skriva in} l: {sv}] pos9e5da87289: put'pos [p: {verb}] link'is lemmaef47e75a55 pos9e5da87289 link'means pos9e5da87289 sense8095a9e6b4 sensee218329346: put'sense [s:{to record the details of an offender}] link'means pos7f8fc0a70a sensee218329346 lemmad643753534: put'lemma [w: {rekisteröidä} l: {fi}] pos5b8591e2bc: put'pos [p: {verb}] link'is lemmad643753534 pos5b8591e2bc link'means pos5b8591e2bc sensee218329346 lemmab34798aa49: put'lemma [w: {felír} l: {hu}] pos76ca843a7f: put'pos [p: {verb}] link'is lemmab34798aa49 pos76ca843a7f link'means pos76ca843a7f sensee218329346 lemma2384d799e8: put'lemma [w: {調書を取る} l: {ja}] pos76f69059ac: put'pos [p: {verb}] link'is lemma2384d799e8 pos76f69059ac link'means pos76f69059ac sensee218329346 lemma74800b8ba1: put'lemma [w: {multar} l: {pt}] posd2e6f18ffd: put'pos [p: {verb}] link'is lemma74800b8ba1 posd2e6f18ffd link'means posd2e6f18ffd sensee218329346 sense5524244560: put'sense [s:{sports: to issue with a caution}] link'means pos7f8fc0a70a sense5524244560 lemmac7b383a3e1: put'lemma [w: {varoittaa} l: {fi}] pos0b9995cd5d: put'pos [p: {verb}] link'is lemmac7b383a3e1 pos0b9995cd5d link'means pos0b9995cd5d sense5524244560 lemmaa86e7b94de: put'lemma [w: {antaa varoitus} l: {fi}] pos236b000aa1: put'pos [p: {verb}] link'is lemmaa86e7b94de pos236b000aa1 link'means pos236b000aa1 sense5524244560 lemmaeca039bc89: put'lemma [w: {sárga lapot ad} l: {hu}] pos583dbbd7c1: put'pos [p: {verb}] link'is lemmaeca039bc89 pos583dbbd7c1 link'means pos583dbbd7c1 sense5524244560 lemmae0276b43f4: put'lemma [w: {ammonire} l: {it}] pos8cff370755: put'pos [p: {verb}] link'is lemmae0276b43f4 pos8cff370755 link'means pos8cff370755 sense5524244560 sense90edbe61b4: put'sense [s:{slang: to travel very fast}] link'means pos7f8fc0a70a sense90edbe61b4 lemma126c5a7bbb: put'lemma [w: {boeken} l: {nl}] posbb935ff58b: put'pos [p: {verb}] link'is lemma126c5a7bbb posbb935ff58b link'means posbb935ff58b sense90edbe61b4 lemmab64af5f571: put'lemma [w: {vlammen} l: {nl}] pos8ef07ad582: put'pos [p: {verb}] link'is lemmab64af5f571 pos8ef07ad582 link'means pos8ef07ad582 sense90edbe61b4 lemmadc7c5c24bd: put'lemma [w: {luukuttaa} l: {fi}] posc384af9d73: put'pos [p: {verb}] link'is lemmadc7c5c24bd posc384af9d73 link'means posc384af9d73 sense90edbe61b4 lemmaf7717609a3: put'lemma [w: {rasen} l: {de}] pos7b4bf047a5: put'pos [p: {verb}] link'is lemmaf7717609a3 pos7b4bf047a5 link'means pos7b4bf047a5 sense90edbe61b4 lemma8df31a6b61: put'lemma [w: {száguld} l: {hu}] posdf53c51b96: put'pos [p: {verb}] link'is lemma8df31a6b61 posdf53c51b96 link'means posdf53c51b96 sense90edbe61b4 lemmac38cd89073: put'lemma [w: {スピードを出す} l: {ja}] pos52af984c8e: put'pos [p: {verb}] link'is lemmac38cd89073 pos52af984c8e link'means pos52af984c8e sense90edbe61b4 lemma43a341aeb4: put'lemma [w: {飛ばす} l: {ja}] pos4a27143545: put'pos [p: {verb}] link'is lemma43a341aeb4 pos4a27143545 link'means pos4a27143545 sense90edbe61b4 sense4ece92bfd9: put'sense [s:{to record bets as bookmaker}] link'means pos7f8fc0a70a sense4ece92bfd9 lemmafaa9c8acee: put'lemma [w: {pitää kirjaa} l: {fi}] pos00f8e8942b: put'pos [p: {verb}] link'is lemmafaa9c8acee pos00f8e8942b link'means pos00f8e8942b sense4ece92bfd9 sense6ea9e80c3d: put'sense [s:{to receive the highest grade in a class}] link'means pos7f8fc0a70a sense6ea9e80c3d lemmabb32c98866: put'lemma [w: {legjobbként végez} l: {hu}] posb87fd52a1b: put'pos [p: {verb}] link'is lemmabb32c98866 posb87fd52a1b link'means posb87fd52a1b sense6ea9e80c3d sense7b57751785: put'sense [s:{slang: to leave}] link'means pos7f8fc0a70a sense7b57751785 lemma37504a71c2: put'lemma [w: {nostaa kytkintä} l: {fi}] pos79f54bd342: put'pos [p: {verb}] link'is lemma37504a71c2 pos79f54bd342 link'means pos79f54bd342 sense7b57751785 lemma1e895e7987: put'lemma [w: {lelép} l: {hu}] posdf6ca3c753: put'pos [p: {verb}] link'is lemma1e895e7987 posdf6ca3c753 link'means posdf6ca3c753 sense7b57751785 pos7f8fc0a70a: put'pos [p: {verb}] link'is lemma8b257cd027 pos7f8fc0a70a lemmaceac518675: put 'lemma #[w: {book} l: {li}] posf68c8817db: put'pos [p: {noun}] link'is lemmaceac518675 posf68c8817db lemmac1a1a27858: put 'lemma #[w: {book} l: {enm}] pos0ff9e0a13a: put'pos [p: {noun}] link'is lemmac1a1a27858 pos0ff9e0a13a pos0ff9e0a13a: put'pos [p: {noun}] link'is lemmac1a1a27858 pos0ff9e0a13a lemma3af60c7721: put 'lemma #[w: {book} l: {nb}] pos35c7f973f2: put'pos [p: {verb}] link'is lemma3af60c7721 pos35c7f973f2 preview fetch'pos ø ] ] ================================================ FILE: examples/sample6.art ================================================ do.import {grafito.art} do [ graph "sample6" [ put'person [name: "John" surname: "Doe" age: 34] put'person [name: "Jane" surname: "doe" age: 24] put'person [name: "Bill" surname: "Jones" age: 44] ; let's find all the people who are ; more than 30 years old inspect fetch'person [ age: -> greater: 30 ] ] ] ================================================ FILE: examples/sample7.art ================================================ do.import {grafito.art} do [ graph.create "sample7" [ put'country [name: "United States"] put'country [name: "Australia"] john: put'person [name: "John" surname: "Doe" age: 34 country: "United States"] jane: put'person [name: "Jane" surname: "doe" age: 24 country: "United States"] put'person [name: "Bill" surname: "Jones" age: 44 country: "Australia"] link'marriedTo john jane ; let's find all the people who are ; more than 30 years old inspect fetch'person [ age: -> greater: 30 surname: "Doe" ] ] ] ================================================ FILE: examples/sample8.art ================================================ do.import {grafito.art} do [ graph.create "sample8" [ ;--------------------------------------------- ; Populate the database ;--------------------------------------------- us: put'country [name: "United States"] au: put'country [name: "Australia"] john: put'person [name: "John" surname: "Doe" age: 34] jane: put'person [name: "Jane" surname: "doe" age: 24] bill: put'person [name: "Bill" surname: "Jones" age: 44] mary: put'person [name: "Mary" age: 54] link'marriedTo john jane link'marriedTo bill mary link'isFrom @[john mary] us link'isFrom @[jane bill] au ;--------------------------------------------- ; Let's perform some interesting queries! ;--------------------------------------------- ; fetch all people inspect fetch'person ø ; fetch all people that have a surname inspect fetch'person [surname: true] ; fetch all people that have the name John inspect fetch'person [name: "John"] ; fetch all people that are over 40 years old inspect fetch'person [age: -> greater: 40] ; fetch all people that are over 40 years old ; and have the surname "Jones" inspect fetch'person [ age: -> greater: 40 surname: "Jones" ] ; fetch all people that have the name John ; and are married to someone/anyone inspect fetch'person [ name:"John" marriedTo: ø ] ; fetch all people that have the name John ; and are married to someone with the name Joan inspect fetch'person [ name:"John" marriedTo: what'person [name:"Joan"] ] ; fetch all people that have either the name "John" ; or the surname "Jones" inspect fetch'person .any [ name:"John" surname:"Jones" ] ] ] ================================================ FILE: examples/sample9.art ================================================ ;--------------------------------------------- ; Import Grafito ; and ... let's rock'n'roll! :) ;--------------------------------------------- do.import {grafito.art} do [ ;--------------------------------------------- ; Set up a new graph environment ; with a local database named "sample4" ;--------------------------------------------- graph.create "sample9" [ ArithmeticObj: put'modl [name: "Arithmetic"] arraysObj: put'modl [name: "arrays"] arturoObj: put'modl [name: "arturo"] benchmarkObj: put'modl [name: "benchmark"] bignumObj: put'modl [name: "bignum"] BinaryObj: put'modl [name: "Binary"] bytecodeObj: put'modl [name: "bytecode"] CollectionsObj: put'modl [name: "Collections"] ComparisonObj: put'modl [name: "Comparison"] ConvertersObj: put'modl [name: "Converters"] CoreObj: put'modl [name: "Core"] CryptoObj: put'modl [name: "Crypto"] csvObj: put'modl [name: "csv"] databaseObj: put'modl [name: "database"] DatabasesObj: put'modl [name: "Databases"] datasourceObj: put'modl [name: "datasource"] DatesObj: put'modl [name: "Dates"] debugObj: put'modl [name: "debug"] envObj: put'modl [name: "env"] errorsObj: put'modl [name: "errors"] evalObj: put'modl [name: "eval"] execObj: put'modl [name: "exec"] ffiObj: put'modl [name: "ffi"] FilesObj: put'modl [name: "Files"] globalsObj: put'modl [name: "globals"] helperObj: put'modl [name: "helper"] htmlObj: put'modl [name: "html"] IoObj: put'modl [name: "Io"] IteratorsObj: put'modl [name: "Iterators"] jsonobjectObj: put'modl [name: "jsonobject"] libObj: put'modl [name: "lib"] LogicObj: put'modl [name: "Logic"] markdownObj: put'modl [name: "markdown"] mathsObj: put'modl [name: "maths"] md4cObj: put'modl [name: "md4c"] minizObj: put'modl [name: "miniz"] NetObj: put'modl [name: "Net"] NumbersObj: put'modl [name: "Numbers"] parseObj: put'modl [name: "parse"] pathObj: put'modl [name: "path"] PathsObj: put'modl [name: "Paths"] ReflectionObj: put'modl [name: "Reflection"] replObj: put'modl [name: "repl"] SetsObj: put'modl [name: "Sets"] stackObj: put'modl [name: "stack"] stringsObj: put'modl [name: "strings"] StringsObj: put'modl [name: "Strings"] SystemObj: put'modl [name: "System"] templatesObj: put'modl [name: "templates"] tomlObj: put'modl [name: "toml"] UiObj: put'modl [name: "Ui"] unisortObj: put'modl [name: "unisort"] urlObj: put'modl [name: "url"] valueObj: put'modl [name: "value"] versionObj: put'modl [name: "version"] vmObj: put'modl [name: "vm"] webviewObj: put'modl [name: "webview"] link'rel valueObj bignumObj link'rel errorsObj stringsObj link'rel valueObj errorsObj link'rel envObj valueObj link'rel evalObj debugObj link'rel globalsObj errorsObj link'rel globalsObj valueObj link'rel bytecodeObj globalsObj link'rel bytecodeObj valueObj link'rel evalObj bytecodeObj link'rel evalObj globalsObj link'rel evalObj valueObj link'rel parseObj errorsObj link'rel parseObj valueObj link'rel stackObj valueObj link'rel execObj bytecodeObj link'rel execObj errorsObj link'rel execObj evalObj link'rel execObj globalsObj link'rel execObj parseObj link'rel execObj stackObj link'rel execObj valueObj link'rel vmObj envObj link'rel vmObj errorsObj link'rel vmObj evalObj link'rel vmObj execObj link'rel vmObj globalsObj link'rel vmObj parseObj link'rel vmObj stackObj link'rel vmObj valueObj link'rel vmObj versionObj link'rel libObj globalsObj link'rel libObj errorsObj link'rel libObj stackObj link'rel libObj valueObj link'rel ArithmeticObj libObj link'rel vmObj ArithmeticObj link'rel BinaryObj libObj link'rel vmObj BinaryObj link'rel arraysObj valueObj link'rel CollectionsObj arraysObj link'rel unisortObj valueObj link'rel CollectionsObj unisortObj link'rel CollectionsObj libObj link'rel vmObj CollectionsObj link'rel ComparisonObj libObj link'rel vmObj ComparisonObj link'rel ConvertersObj bignumObj link'rel urlObj valueObj link'rel datasourceObj urlObj link'rel ConvertersObj datasourceObj link'rel ConvertersObj stringsObj link'rel ConvertersObj libObj link'rel ConvertersObj errorsObj link'rel ConvertersObj execObj link'rel ConvertersObj parseObj link'rel vmObj ConvertersObj link'rel CoreObj datasourceObj link'rel ffiObj errorsObj link'rel ffiObj valueObj link'rel CoreObj ffiObj link'rel CoreObj libObj link'rel CoreObj envObj link'rel CoreObj errorsObj link'rel CoreObj evalObj link'rel CoreObj execObj link'rel CoreObj parseObj link'rel vmObj CoreObj link'rel CryptoObj libObj link'rel vmObj CryptoObj link'rel databaseObj valueObj link'rel DatabasesObj databaseObj link'rel DatabasesObj libObj link'rel vmObj DatabasesObj link'rel DatesObj libObj link'rel vmObj DatesObj link'rel htmlObj valueObj ; link'rel markdownObj md4cObj ; link'rel markdownObj valueObj ; link'rel tomlObj valueObj ; link'rel FilesObj minizObj ; link'rel FilesObj htmlObj ; link'rel FilesObj markdownObj ; link'rel FilesObj tomlObj ; link'rel csvObj valueObj ; link'rel FilesObj csvObj ; link'rel FilesObj datasourceObj ; link'rel jsonobjectObj valueObj ; link'rel FilesObj jsonobjectObj ; link'rel FilesObj libObj ; link'rel vmObj FilesObj ; link'rel replObj valueObj ; link'rel IoObj replObj ; link'rel IoObj libObj ; link'rel IoObj evalObj ; link'rel IoObj execObj ; link'rel vmObj IoObj ; link'rel IteratorsObj libObj ; link'rel IteratorsObj errorsObj ; link'rel IteratorsObj evalObj ; link'rel IteratorsObj execObj ; link'rel vmObj IteratorsObj ; link'rel LogicObj libObj ; link'rel LogicObj execObj ; link'rel vmObj LogicObj ; link'rel NetObj webviewObj ; link'rel NetObj libObj ; link'rel NetObj envObj ; link'rel NetObj execObj ; link'rel vmObj NetObj ; link'rel NumbersObj bignumObj ; link'rel mathsObj bignumObj ; link'rel mathsObj valueObj ; link'rel NumbersObj mathsObj ; link'rel NumbersObj libObj ; link'rel vmObj NumbersObj ; link'rel pathObj valueObj ; link'rel PathsObj pathObj ; link'rel PathsObj urlObj ; link'rel PathsObj libObj ; link'rel PathsObj envObj ; link'rel vmObj PathsObj ; link'rel ReflectionObj benchmarkObj ; link'rel helperObj globalsObj ; link'rel helperObj valueObj ; link'rel ReflectionObj helperObj ; link'rel ReflectionObj libObj ; link'rel ReflectionObj envObj ; link'rel ReflectionObj execObj ; link'rel vmObj ReflectionObj ; link'rel SetsObj libObj ; link'rel vmObj SetsObj ; link'rel StringsObj stringsObj ; link'rel templatesObj execObj ; link'rel templatesObj parseObj ; link'rel templatesObj stackObj ; link'rel templatesObj valueObj ; link'rel StringsObj templatesObj ; link'rel StringsObj libObj ; link'rel vmObj StringsObj ; link'rel SystemObj libObj ; link'rel SystemObj errorsObj ; link'rel SystemObj execObj ; link'rel vmObj SystemObj ; link'rel UiObj libObj ; link'rel UiObj jsonobjectObj ; link'rel UiObj urlObj ; link'rel UiObj webviewObj ; link'rel UiObj envObj ; link'rel UiObj execObj ;link'rel vmObj UiObj ;link'rel arturoObj versionObj link'rel arturoObj valueObj link'rel arturoObj vmObj preview fetch 'modl ø ] ] ================================================ FILE: grafito.art ================================================ #!/usr/bin/env arturo ;======================================================== ; Grafito ; ; SQLite-based Graph Database ; in Arturo ;-------------------------------------------------------- ;; name: grafito ;; version: 0.2.12 ;; author: drkameleon ;; website: « https://github.com/arturo-lang/grafito ;; category: database ;; embed: [ ;; "ui" "sql" ;; ".art" ".sql" ".html" ".less" ".js" ;; ] ;======================================================== ;-------------------------- ; The main library ;-------------------------- Grafito: #[ ; version Version: 0.2.12 ; configuration Debug?: false verbose?: true caseSensitive?: true ; colors Palette: "" ] ; ; Define custom objects ;-------------------------- define :edgeFilter [direction, content, properties] ;---------------------------------------------- graph: function [ dbpath :string :null body :block ][ ;; description: « initiate a new graph environment with given name and body ;; options: [ ;; create: « recreate database from scratch, even if it exists ;; case: « queries should be case-sensitive ;; verbose: « show messages regarding database operations ;; palette: :string :literal « select color palette (current: default) ;; ] ;; returns: :any ;; example: { ;; graph "mydb" [ ;; ; do sth with this graph database ;; ] ;; .......... ;; ; in memory database ;; graph ø [ ;; ; do sth with this graph database ;; ] ;; } ;========================================== ; CONSTANTS ;========================================== ; Global SQL scripts schemaSQL: split.by:";" read.file ./"sql/schema.sql" createNodeSQL: read.file ./"sql/procs/createNode.sql" updateNodeSQL: read.file ./"sql/procs/updateNode.sql" updateNodePropertySQL: read.file ./"sql/procs/updateNodeProperty.sql" updateNodePropertiesSQL: read.file ./"sql/procs/updateNodeProperties.sql" deleteNodeSQL: read.file ./"sql/procs/deleteNode.sql" deleteNodeEdgesSQL: read.file ./"sql/procs/deleteNodeEdges.sql" getNodeSQL: read.file ./"sql/procs/getNode.sql" getRelatedNodesSQL: read.file ./"sql/procs/getRelatedNodes.sql" getMaxNodeIdSQL: read.file ./"sql/procs/getMaxNodeId.sql" createEdgeSQL: read.file ./"sql/procs/createEdge.sql" updateEdgeSQL: read.file ./"sql/procs/updateEdge.sql" deleteEdgeSQL: read.file ./"sql/procs/deleteEdge.sql" deleteEdgeByIdSQL: read.file ./"sql/procs/deleteEdgeById.sql" fetchNodesSQL: read.file ./"sql/procs/fetchNodes.sql" fetchNodesWithEdgesSQL: read.file ./"sql/procs/fetchNodes.withEdges.sql" countNodesSQL: read.file ./"sql/procs/countNodes.sql" countEdgesSQL: read.file ./"sql/procs/countEdges.sql" ; Global SQL filters hasEdgeFilter: read.file ./"sql/filters/hasEdge.sql" hasPropertyFilter: read.file ./"sql/filters/hasProperty.sql" edgeWithTargetFilter: read.file ./"sql/filters/edgeWithTarget.sql" edgeWithSourceFilter: read.file ./"sql/filters/edgeWithSource.sql" edgeWithAnyFilter: read.file ./"sql/filters/edgeWithAny.sql" edgeWithPropertiesFilter: read.file ./"sql/filters/edgeWithProperties.sql" nodePropertyWithValueFilter: read.file ./"sql/filters/nodePropertyWithValue.sql" edgePropertyWithValueFilter: read.file ./"sql/filters/edgePropertyWithValue.sql" ; Global SQL pragmas caseInsensitiveLikePragma: read.file ./"sql/pragmas/caseInsensitiveLike.sql" caseSensitiveLikePragma: read.file ./"sql/pragmas/caseSensitiveLike.sql" ; Global UI template app: read.file ./"ui/index.html" ; Color palettes ; for graph nodes colorPalettes: #.raw flatten.once map list ./"ui/palettes" 'pal [ @[extract.filename pal, to :block read.file pal] ] ;========================================== ; HELPERS ;========================================== ; ; Perform query ;-------------------------- performQuery: function [ctx, qu, params][ if and? [Grafito\Debug?][null? attr 'noDebug] [ context: to :string ctx prepend: " | " print color.bold #gray ">: " ++ context queryString: qu if block? qu [ queryString: join.with:"\n" qu ] print color #gray prepend ++ join.with:"\n"++prepend split.lines queryString inspect params print "" ] (not? null? params)? [ query db .with: params qu ][ query db qu ] ] ; ; Print message ;-------------------------- printDebug: function [msg][ print color #cyan ":: " ++ msg ] ; ; Format size ;-------------------------- formatSize: function [sz][ if sz < 1024 -> return sz if sz < 1024*1024 -> return sz --> 'kB if sz < 1024*1024*1024 -> return sz --> 'MB if sz < 1024*1024*1024*1024 -> return sz --> 'GB return @[] ] ; ; Get db analytics ;-------------------------- analytics: function [][ nodeCount: to :integer first first performQuery 'analytics countNodesSQL ø edgeCount: to :integer first first performQuery 'analytics countEdgesSQL ø avgDegree: edgeCount // nodeCount filename: dbPath filesize: 0 if not? empty? filename [ prefilesize: formatSize volume filename filesize: #[ number: to :string scalar prefilesize units: to :string units prefilesize ] ] prememory: formatSize process\memory\occupied mem: #[ number: to :string scalar prememory units: to :string units prememory ] return #[ database: #[ nodes: nodeCount edges: edgeCount degree: to :floating to :string .format: ".2f" avgDegree ] memory: mem disk: #[ path: filename size: filesize ] ] ] ; ; Get suitable fg color ; depending on node bg ; for better contrast ;-------------------------- idealForeground: function [back][ rgbs: values extract back lrgbs: map rgbs 'rgb [ C: rgb // 255 (C =< 0.03928)? -> C: C // 12.92 -> C: ((C+0.055)//1.055) ^ 2.4 C ] L: (lrgbs\0*0.2126) + (lrgbs\1*0.7152) + (lrgbs\2*0.0722) if L > 0.189 [ return #black ] return #white ] ; ; Safe SQLite-compatible ; value codification ; including Unicode strings ;-------------------------- codifySafe: function [val][ (string? val)? [ return {"} ++ (escape.json val) ++ {"} ][ return express val ] ] ; ; Get styled node ; ready for use in the ; graph view ;-------------------------- styleNode: function [nodeId, nodeTag, nodeProps][ if not? key? Grafito\nodeColors nodeTag [ cpal: Grafito\Palette cpal: colorPalettes\[cpal] nodeColor: sample cpal existingColors: map values Grafito\nodeColors => first while [contains? existingColors nodeColor] -> nodeColor: sample cpal Grafito\nodeColors\[nodeTag]: @[ nodeColor idealForeground nodeColor ] updateMeta 'colors Grafito\nodeColors ] bg: to :string Grafito\nodeColors\[nodeTag]\0 fg: to :string Grafito\nodeColors\[nodeTag]\1 nodeLabel: first values nodeProps highlightField: #[ border: express darken to :color bg 0.2 background: bg ] return #[ id: to :integer nodeId tag: nodeTag properties: nodeProps label: truncate nodeLabel 10 fullLabel: nodeLabel color: #[ border: bg background: bg hover: bg highlight: highlightField ] font: #[ color: fg ] ] ] ; ; Create new edge ;-------------------------- edge: function [ src :integer :dictionary name :literal :string tgt :integer :dictionary ][ ;; description: « create edge from source to target node with given name ;; returns: :dictionary srcId: src tgtId: tgt props: (attr "") ?? #[] unless dictionary? props -> props: # props if dictionary? srcId -> srcId: src\id if dictionary? tgtId -> tgtId: tgt\id edgeId: performQuery.id 'edge createEdgeSQL @[name, write.compact.json props ø, srcId, tgtId] #[ id: edgeId tag: name properties: props source: src target: tgt ] ] ; ; Delete existing edge ;-------------------------- unedge: function [ src :integer name :literal :string tgt :integer ][ ;; description: « delete edge from source to target node with given name performQuery 'unedge deleteEdgeSQL @[name, src, tgt] ] ; ; Delete existing edge ; by id ;-------------------------- unedgeById: function [ eid :integer ][ ;; description: « delete edge with given id performQuery 'unedgeById deleteEdgeByIdSQL @[eid] ] ; ; Update single property ; by id ;-------------------------- editProperty: function [ nid :integer prop :literal :string val :any ][ ;; description: « set or update single node property performQuery 'editProperty updateNodePropertySQL @[~"$.|prop|", write.compact.json val ø, nid] ] ; ; Update meta value ;-------------------------- updateMeta: function [ prop :literal :string val :any ][ ;; description: « update a single meta value editProperty 1 prop val ] ; ; Re-tag existing edge ; by id ;-------------------------- retagEdge: function [ eid :integer tag :literal :string ][ ;; description: « update edge with given tag performQuery 'retag updateEdgeSQL @[tag, eid] ] ; ; Get node with properties ; from ID ;-------------------------- nodeFromId: function [nid][ results: performQuery 'nodeFromId getNodeSQL @[nid] if empty? results -> return ø return #[ id: nid tag: first first results properties: read.json last first results ] ] ; ; Get nodeset ; for graph visualization ;-------------------------- nodeFromIds: function [nodes][ nodeset: nodes if not? block? nodeset -> nodeset: @[nodeset] nodeElements: map nodeset 'nd -> styleNode nd\id nd\tag nd\properties edgeElements: new [] loop nodeset [nd][ rezu: performQuery 'nodeFromIds getRelatedNodesSQL @[nd\id, nd\id, nd\id] loop rezu [rez][ 'nodeElements ++ styleNode rez\0 rez\1 read.json rez\2 'edgeElements ++ #[ id: ~"|rez\3|+|rez\4|+|rez\5|" dbId: rez\6 label: rez\5 properties: read.json rez\7 from: to :integer rez\3 to: to :integer rez\4 ] ] ] unique 'nodeElements unique 'edgeElements return #[ nodes: nodeElements edges: edgeElements ] ] ; ; Generate access helper ;-------------------------- generateHelper: function [id,block][ (not? null? attr 'new)? [ put id block ][ fetch id block ] ] ;========================================== ; REPL ;========================================== ; ; Switch verbosity on/off ;-------------------------- verbose: function [] [ Grafito\verbose?: not? Grafito\verbose? ] ;========================================== ; METHODS ;========================================== ; ; Create new node ;-------------------------- put: function [ name :literal :string attributes :string :block :dictionary ][ ;; description: « insert new node(s) to graph with given name and attributes ;; options: [ ;; unique: « add only if node doesn't already exist ;; many: « add multiple nodes at once ;; ] ;; returns: :dictionary :block if attr "unique" [ found: fetch name attributes if not? empty? found -> return found ] result: new [] (not? null? attr 'many)? [ lastId: to :integer first first performQuery 'put getMaxNodeIdSQL ø queries: new [] vals: new [] loop attributes 'nd [ lastId: lastId + 1 att: nd (block? att)? -> att: # att [ (string? att)? -> att: #[ name: att ] [] ] 'queries ++ createNodeSQL 'vals ++ @[name, write.compact.json att ø] 'result ++ #[ id: lastId tag: name properties: att ] ] performQuery 'put queries vals if Grafito\verbose? -> printDebug ~{created |size attributes| nodes} ] [ att: attributes (block? att)? -> att: # att [ (string? att)? -> att: #[ name: att ] [] ] nodeId: performQuery.id 'put createNodeSQL @[name, write.compact.json att ø] result: #[ id: nodeId tag: name properties: att ] if Grafito\verbose? -> printDebug ~{created 1 node (@|nodeId|) with |size att| propert|(1 = size att)? -> "y" -> "ies"|} ] return result ] ; ; Update existing node ;-------------------------- edit: function [ nd :dictionary :block attributes :block :dictionary ][ ;; description: « update given node(s) with attributes ;; options: [ ;; tag: :literal :string « also set new tag ;; replace: « replace entire object properties with given ones ;; ] ;; returns: :nothing toUpdate: ø (dictionary? nd)? -> toUpdate: @[nd] -> toUpdate: new nd doReplace?: not? null? attr 'replace withTag: attr 'tag additional: attributes if block? additional -> additional: # additional loop toUpdate 'updateable [ newAttributes: ø (doReplace?)? -> newAttributes: additional -> newAttributes: extend updateable\properties additional updateable\properties: newAttributes (null? withTag)? -> performQuery 'edit updateNodePropertiesSQL @[write.compact.json newAttributes ø, updateable\id] -> performQuery 'edit updateNodeSQL @[withTag, write.compact.json newAttributes ø, updateable\id] ] ] ; ; Delete existing node ;-------------------------- unput: function [ nd :integer :dictionary :block ][ ;; description: « remove given node(s) from graph ;; returns: :nothing toDelete: ø (block? nd)? -> toDelete: new nd -> toDelete: @[nd] loop toDelete 'deletable [ nodeId: (dictionary? deletable) ? -> deletable\id -> deletable performQuery 'unput @[ deleteNodeSQL, deleteNodeEdgesSQL ] @[ nodeId, nodeId, nodeId ] ] ] ; ; Link nodes with edges ;-------------------------- link: function [ src :block :dictionary name :literal :string tgt :block :dictionary ] [ ;; description: « create a connection from source to target node with given name ;; returns: :block :dictionary edgeId: 0 (:dictionary = type tgt)? [ edges: new [] if :dictionary = type src [ ret: edge src name tgt return ret ] sr: @ src loop sr [s]-> 'edges ++ edge s name tgt if Grafito\verbose? -> printDebug ~"created |size edges| edges" return edges ][ edges: new [] tg: @ tgt (:dictionary = type src)? [ loop tg [t][ 'edges ++ edge src name t ] ][ sr: @ src loop sr [s] [ loop tg [t]-> 'edges ++ edge s name t ] ] if Grafito\verbose? -> printDebug ~"created |size edges| edges" return edges ] ] reverseLink: function [ tgt :block :dictionary name :literal :string src :block :dictionary ][ link src name tgt ] reciprocalLink: function [ src :block :dictionary name :literal :string tgt :block :dictionary ][ link src name tgt link tgt name src ] ; ; Delete node edges ;-------------------------- unlink: function [ src :integer :dictionary :block name :literal :string tgt :integer :dictionary :block ][ ;; description: « remove connection from source to target node with given name nodesFrom: new [] nodesTo: new [] ;case [(type src)=] (dictionary? src)? -> nodesFrom: @[src\id] [ (integer? src)? -> nodesFrom: @[src] [ nodesFrom: new map src 'n [ (dictionary? n)? -> n\id -> n ] ] ] ; when? -> :dictionary -> nodesFrom: @[src\id] ; when? -> :integer -> nodesFrom: @[src] ; else -> nodesFrom: new map src 'n [ ; if? dictionary? n -> n\id ; else -> n ; ] (dictionary? tgt)? -> nodesFrom: @[tgt\id] [ (integer? tgt)? -> nodesFrom: @[tgt] [ nodesFrom: new map tgt 'n [ (dictionary? n)? -> n\id -> n ] ] ] ; if?case [(type tgt)=] ; when? -> :dictionary -> nodesTo: @[tgt\id] ; when? -> :integer -> nodesTo: @[tgt] ; else -> nodesTo: new map tgt 'n [ ; if? dictionary? n -> n\id ; else -> n ; ] loop nodesFrom 'nf [ loop nodesTo 'nt [ unedge nf name nt ] ] if Grafito\verbose? [ totalEdges: mul size nodesFrom size nodesTo edgeLabel: (totalEdges = 1) ? -> "edge" -> "edges" printDebug ~"removed |totalEdges| |edgeLabel|" ] ] ; ; Check node type ;-------------------------- isA?: function [ls,nd][ nd\tag = to :string ls ] ; ; Helpers ; for edge filters ;-------------------------- edgeFilterRight: function [cnt, props][ pp: props if block? pp -> pp: # pp to :edgeFilter @[1, cnt, pp] ] edgeFilterLeft: function [cnt, props][ pp: props if block? pp -> pp: # pp to :edgeFilter @[2, cnt, pp] ] edgeFilterAny: function [cnt, props][ pp: props if block? pp -> pp: # pp to :edgeFilter @[3, cnt, pp] ] ; ; Fetch all results for tag ; with given properties ; and edges ;-------------------------- fetch: function [ name :literal :string attributes :null :string :block :dictionary ][ ;; description: « retrieves nodes with name that match all given attributes ;; options: [ ;; .any « try matching any of the attributes ;; ] ;; returns: :block ;; setup main variables catchAny?: false if not? null? attr "any" -> catchAny?: true collator: "" if not? Grafito\caseSensitive? -> collator: " COLLATE NOCASE" propertyFilters: new [] edgeFilters: new [] qvals: new @[name] qpropvals: new [] qedgevals: new [] att: new attributes (string? att)? [ [collate,symb,val]: @[collator, "=", codifySafe att] ; add it once (to check for `name`) 'propertyFilters ++ ~nodePropertyWithValueFilter 'qpropvals ++ @[~"$.name"] ; add it once more (to check for `title`) 'propertyFilters ++ ~nodePropertyWithValueFilter 'qpropvals ++ @[~"$.title"] ; we won't it to be valid when any of the two criteria above is true ; so we'll have to forcefully set `catchAny?` to true catchAny?: true ] [ if and? not? dictionary? att not? null? att -> att: # att ; ; HACK - to solve ; remove.key 'att 'n ; remove.key 'att 'a if not? empty? att [ loop att [k,v][ if null? v [ ; it's an edge filter without criteria 'edgeFilters ++ hasEdgeFilter 'qedgevals ++ @[k] continue ] if dictionary? v [ ; it's an edge filter searchForProperties: "" 'edgeFilters ++ ~edgeWithTargetFilter 'qedgevals ++ @[k, v\id] continue ] if is? :edgeFilter v [ ; it's a directed edge filter if dictionary? v\content [ searchForProperties: "" subfilters: [] subvals: [] if not? empty? v\properties [ collator: "" if not? Grafito\caseSensitive? -> collator: " COLLATE NOCASE" subfilters: new [] loop v\properties [kk,vv][ [collate,symb,val]: @[collator, "=", codifySafe vv] subvals: subvals ++ ~"$.|kk|" subfilters: subfilters ++ ~edgePropertyWithValueFilter ] subfilters: join.with:" AND " subfilters searchForProperties: ~"AND (|subfilters|)" ] (v\direction = 1)? [ 'edgeFilters ++ ~edgeWithTargetFilter 'qedgevals ++ @[k, v\content\id] ++ subvals ][ (v\direction = 2)? [ 'edgeFilters ++ ~edgeWithSourceFilter 'qedgevals ++ @[k, v\content\id] ++ subvals ][ (v\direction = 3)? [ 'edgeFilters ++ ~edgeWithAnyFilter 'qedgevals ++ @[k, v\content\id, v\content\id] ++ subvals ][ print "Shouldn't have reached here!" ] ] ] ] if all? @[ block? v\content or? and? [0 < size v\content] [:dictionary = type first v\content] not? empty? v\properties ][ searchForProperties: "" subfilters: [] subvals: [] if not? empty? v\properties [ collator: "" if not? Grafito\caseSensitive? -> collator: " COLLATE NOCASE" subfilters: new [] loop v\properties [kk,vv][ [collate,symb,val]: @[collator, "=", codifySafe vv] subvals: subvals ++ ~"$.|kk|" subfilters: subfilters ++ ~edgePropertyWithValueFilter ] subfilters: join.with:" AND " subfilters searchForProperties: ~"AND (|subfilters|)" ] orCriteria: new [] (0 < size v\content)? [ loop v\content [edgef][ (v\direction = 1)? [ 'orCriteria ++ ~edgeWithTargetFilter 'qedgevals ++ @[k, edgef\id] ++ subvals ][ (v\direction = 2)? [ 'orCriteria ++ ~edgeWithSourceFilter 'qedgevals ++ @[k, edgef\id] ++ subvals ][ (v\direction = 3)? [ 'orCriteria ++ ~edgeWithAnyFilter 'qedgevals ++ @[k, edgef\id, edgef\id] ++ subvals ][ print "Shouldn't have reached here!" ] ] ] ] ][ 'orCriteria ++ ~edgeWithPropertiesFilter 'qedgevals ++ @[k] ++ subvals ] 'edgeFilters ++ "(" ++ (join.with:" OR " orCriteria) ++ ")" ] continue ] if block? v [ (and? 0 < size v :dictionary = type first v)? [ ; it's an array of edge filters orCriteria: new [] loop v [edgef][ searchForProperties: "" 'orCriteria ++ ~edgeWithTargetFilter 'qedgevals ++ @[k, edgef\id] ] 'edgeFilters ++ "(" ++ (join.with:" OR " orCriteria) ++ ")" ] [ ; it's a complex property filter loop # v [filt,rg][ [collate,symb,val]: @[collator, "=", v] requiresCodification: true (filt = "contains")? -> [collate,symb,val]: @["", "LIKE", ~"%|rg|%"] [ (filt = "prefix")? -> [collate,symb,val]: @["", "LIKE", ~"|rg|%"] [ (filt = "suffix")? -> [collate,symb,val]: @["", "LIKE", ~"%|rg|"] [ (filt = "under")? -> [collate,symb,val]: @["", "<", rg] [ (filt = "over")? -> [collate,symb,val]: @["", ">", rg] [ (filt = "underOrEqual")? -> [collate,symb,val]: @["", "<=", rg] [ (filt = "overOrEqual")? -> [collate,symb,val]: @["", ">=", rg] [ (filt = "in")? [ [collate,symb,val]: @[collator, "IN", "(" ++ (join.with:", " map rg [x][codifySafe x]) ++ ")"] requiresCodification: false ][ (filt = "not")? [ (block? rg)? [ [collate,symb,val]: @[collator, "NOT IN", "(" ++ (join.with:", " map rg [x][codifySafe x]) ++ ")"] requiresCodification: false ] -> [collate,symb,val]: @[collator, "!=", rg] ] [ panic.code: 1 ~"filter: |filt| not recognized" ] ] ] ] ] ] ] ] ] ; case [equal? filt] ; when? ["contains"] -> [collate,symb,val]: @["", "LIKE", ~"%|rg|%"] ; when? ["prefix"] -> [collate,symb,val]: @["", "LIKE", ~"|rg|%"] ; when? ["suffix"] -> [collate,symb,val]: @["", "LIKE", ~"%|rg|"] ; when? ["under"] -> [collate,symb,val]: @["", "<", rg] ; when? ["over"] -> [collate,symb,val]: @["", ">", rg] ; when? ["underOrEqual"] -> [collate,symb,val]: @["", "<=", rg] ; when? ["overOrEqual"] -> [collate,symb,val]: @["", ">=", rg] ; when? ["in"] -> [collate,symb,val]: @[collator, "IN", ~{(|join.with:", " map rg [x]["'" ++ (to :string x) ++ "'"]|)}] ; when? ["not"][ ; if? block? rg -> [collate,symb,val]: @[collator, "NOT IN", ~{(|join.with:", " map rg [x]["'" ++ (to :string x) ++ "'"]|)}] ; else -> [collate,symb,val]: @[collator, "!=", rg] ; ] ; else [ ; panic.code: 1 ~"filter: |filt| not recognized" ; ] if requiresCodification -> val: codifySafe val 'propertyFilters ++ ~nodePropertyWithValueFilter 'qpropvals ++ @[~"$.|k|"] ] ] continue ] if logical? v [ ; it's a simple property filter without criteria 'propertyFilters ++ hasPropertyFilter 'qpropvals ++ @[~"$.|k|"] continue ] ; it's a simple property filter [collate,symb,val]: @[collator, "=", codifySafe v] 'propertyFilters ++ ~nodePropertyWithValueFilter 'qpropvals ++ @[~"$.|k|"] ] ] ] qr: "" propies: "" linker: " AND " edgeLimit: ~" = |size edgeFilters|" if catchAny? [ linker: " OR " edgeLimit: " >= 1" ] if not? empty? propertyFilters [ propies: ~{!sql AND (|join.with: linker propertyFilters|)} 'qvals ++ qpropvals ] (not? empty? edgeFilters)? [ edgies: join.with: " OR " edgeFilters 'qvals ++ qedgevals qr: ~fetchNodesWithEdgesSQL ] [ qr: ~fetchNodesSQL ] return map performQuery 'fetch qr qvals 'x [ #[ id: x\0 tag: x\1 properties: read.json x\2 ] ] ] ; ; Visualize given nodeset ;-------------------------- preview: function [ nodeset :block ][ ;; description: « preview given set of nodes in Grafito's UI ;; options: [ ;; server: « start Grafito as a server ;; ] currentNodes: new nodeset currentDataset: new nodeFromIds currentNodes Versions: #[ engine: to :version first split.by:" " execute "sqlite3 --version" system: Grafito\Version arturo: strip replace execute "arturo -v" ["arturo" "v/"] "" ] routes: [ GET "/" [ render.template app ] POST "/startup" [ write.json #[ title: cleanpath data: currentDataset rows: currentNodes versions: Versions caseSensitive: Grafito\caseSensitive? palettes: colorPalettes activePalette: Grafito\Palette ] ø ] POST "/exec" $[command][ err: try [ if Grafito\verbose? -> printDebug "<== " ++ command currentNodes: "" bench: benchmark.get [ currentNodes: new do command ] if Grafito\verbose? -> printDebug ~"==> OK (|bench|)" (or? [not? block? currentNodes] [and? [0 < size currentNodes][not? dictionary? first currentNodes]])?[ "empty" ] [ currentDataset: new nodeFromIds currentNodes write.json #[ data: currentDataset rows: currentNodes timeTaken: scalar bench ] ø ] ] ] POST "/nodeFromId" $[ndid][ newNodes: new nodeFromIds @[nodeFromId ndid] write.json newNodes ø ] POST "/changePalette" $[newpalette, ndids][ Grafito\Palette: newpalette Grafito\nodeColors: #[] newNodes: new nodeFromIds map split.by:"," ndids => nodeFromId updateMeta 'palette Grafito\Palette updateMeta 'colors Grafito\nodeColors write.json newNodes ø ] POST "/deleteNode" $[ndid][ unput to :integer ndid "" ] POST "/updateNode" $[ndid,newtag,props][ nd: nodeFromId ndid edit.replace.tag:newtag nd read.json props "" ] POST "/createNode" $[newtag,props][ created: put newtag read.json props write.json new nodeFromIds created ø ] POST "/linkNodes" $[newtag,src,tgt][ srcid: to :integer src tgtid: to :integer tgt edge srcid newtag tgtid "" ] POST "/updateEdge" $[egid,newtag][ eid: to :integer egid retagEdge eid newtag "" ] POST "/deleteEdge" $[egid][ edgeParts: split.by:"+" egid unlink to :integer edgeParts\0 edgeParts\2 to :integer edgeParts\1 "" ] POST "/updateEngine" $[caseSensitive][ (to :logical caseSensitive)? [ Grafito\caseSensitive?: true performQuery 'main caseSensitiveLikePragma ø ] [ Grafito\caseSensitive?: false performQuery 'main caseInsensitiveLikePragma ø ] "" ] POST "/analytics" [ write.json analytics ø ] GET "/styles/(?.+)" $[file][ read.file ./ ~"ui/styles/|file|" ] GET "/scripts/(?.+)" $[file][ (file = "ace/modes/grafito.js")? -> replace read.file ./"ui/scripts/ace/modes/grafito.js" "CUSTOM_HELPERS" join.with:"|" entities -> read.file ./ ~"ui/scripts/|file|" ] GET "/exit" [ printDebug "Shutting down" close db exit ] ] (null? attr 'server)? [ serve.chrome routes ] [ serve.verbose routes ] ] ;========================================== ; INITIALIZATION ;========================================== ; basic setup Grafito\verbose?: not? null? attr 'verbose Grafito\caseSensitive?: null? attr 'nocase dbPath: "" cleanpath: "in-memory" dbExisted: false if not? null? dbpath [ cleanpath: extract.filename dbpath dbPath: ~"|cleanpath|.graf" dbExisted: exists? ~"|cleanpath|.graf" ] ; setup color palettes Grafito\Palette: attr 'palette if null? Grafito\Palette -> Grafito\Palette: "default" Grafito\nodeColors: #[] ; define aliases alias.infix {~>} 'link alias.infix {<~} 'reverseLink alias.infix {<~>} 'reciprocalLink alias {|>} 'edgeFilterRight alias {<|} 'edgeFilterLeft alias {<|>} 'edgeFilterAny ; open the database printDebug ~"DB = |cleanpath|" db: open dbPath dbExists?: true ; get helpers entities: attr "helpers" if null? entities -> entities: [] ; and initialize it ; with the given schema (if necessary) (or? not? null? attr "create" not? dbExisted)? [ dbExists?: false printDebug "creating database from scratch" performQuery.noDebug 'main schemaSQL ø metas: #[] set metas 'version "undefined" set metas 'mode "json" set metas 'version Grafito\Version set metas 'palette Grafito\Palette set metas 'entities write.json entities ø put'meta metas discard unstack 1 ][ printDebug "using existing database" meta: first fetch'meta [] Grafito\nodeColors: read.json meta\properties\colors Grafito\Palette: meta\properties\palette entities: read.json meta\properties\entities ] ; setup pragmas if Grafito\caseSensitive? -> performQuery 'main caseSensitiveLikePragma ø ; create helpers, if any ei: new 0 while [ei < size entities] [ entity: to :literal entities\[ei] let entity function [block] with 'entity -> generateHelper entity block inc 'ei ] ; process body result: do body ; close the database close db ; and that was it :) return result ] ;-------------------------- ; The main entry point ;-------------------------- if standalone? [ ; helpers & templates Versions: #[ engine: to :version first split.by:" " execute "sqlite3 --version" system: script\version ] BR: "\n" logoTxt: read.file ./"logo.txt" GrafitoHeader: join @[ print color #magenta replace logoTxt {/#(.+)/} (color #white "$1") ++ color.keep #magenta "" print " " color #gray "-------------------------------------" BR color #gray ~" system: v/|Versions\system|, engine: v/|Versions\engine|" BR color #gray "-------------------------------------" BR ] ; methods launchTerminal: function [][ completions: ["fetch" "put" "unput" "link" "unlink" "edge" "unedge"] historyPath: join.path @[path\home ".arturo" "grafito-history.lst"] print "" print color #orange "## Tip: Type `verbose` to switch info messages on/off" print color #orange "## Launching Grafito console - rock on! 🤘" print "" while ø [ Got: null indentation: "" inp: input .repl .history: historyPath .complete: completions "$> " while [suffix? inp " "][ if suffix? strip inp "[" [ indentation: indentation ++ "\t" ] inp: inp ++ input ".. " ++ indentation ] err: try.verbose [ try.verbose to :block inp StackSize: size stack if StackSize > 0 -> Got: unstack 1 if Got <> null -> print color #gray ~"=> |Got|" print "" ] ] ] ; startup print GrafitoHeader if 1 < size arg -> panic "Too many arguments given!" dbInput: ø if 1 = size arg -> dbInput: arg\0 graph dbInput [ launchTerminal ] ] ;========================================== ; This is the end, ; my only friend, the end... ;========================================== ================================================ FILE: info.art ================================================ entry: {grafito} executable: {grafito} depends: [] requires: [> 0.9.83] ================================================ FILE: logo.txt ================================================ __ _ _ / _(_) | __ _ _ __ __ _| |_ _| |_ ___ / _` | '__/ _` | _| | __/ _ \ | (_| | | | (_| | | | | || (_) | \__, |_| \__,_|_| |_|\__\___/ __/ | #(c) 2024 |___/ #Yanis Zafirópulos ================================================ FILE: sql/filters/edgePropertyWithValue.sql ================================================ (json_extract(edges.properties, ?)|collate| |symb| |val|) ================================================ FILE: sql/filters/edgeWithAny.sql ================================================ (edges.tag=? AND (edges.target=? OR edges.source=?) |searchForProperties|) ================================================ FILE: sql/filters/edgeWithProperties.sql ================================================ (edges.tag=? AND |searchForProperties|) ================================================ FILE: sql/filters/edgeWithSource.sql ================================================ (edges.tag=? AND edges.source=? |searchForProperties|) ================================================ FILE: sql/filters/edgeWithTarget.sql ================================================ (edges.tag=? AND edges.target=? |searchForProperties|) ================================================ FILE: sql/filters/hasEdge.sql ================================================ (edges.tag=?) ================================================ FILE: sql/filters/hasProperty.sql ================================================ (json_extract(nodes.properties, ?)!='') ================================================ FILE: sql/filters/nodePropertyWithValue.sql ================================================ (json_extract(nodes.properties, ?)|collate| |symb| |val|) ================================================ FILE: sql/pragmas/caseInsensitiveLike.sql ================================================ PRAGMA case_sensitive_like = 0 ================================================ FILE: sql/pragmas/caseSensitiveLike.sql ================================================ PRAGMA case_sensitive_like = 1 ================================================ FILE: sql/procs/countEdges.sql ================================================ SELECT COUNT(id) FROM edges ================================================ FILE: sql/procs/countNodes.sql ================================================ SELECT COUNT(id) FROM nodes ================================================ FILE: sql/procs/createEdge.sql ================================================ INSERT INTO edges (tag, properties, source, target) VALUES (?, ?, ?, ?) ================================================ FILE: sql/procs/createNode.sql ================================================ INSERT INTO nodes (tag, properties) VALUES (?, ?) ================================================ FILE: sql/procs/deleteEdge.sql ================================================ DELETE FROM edges WHERE tag=? AND source=? AND target=? ================================================ FILE: sql/procs/deleteEdgeById.sql ================================================ DELETE FROM edges WHERE id=? ================================================ FILE: sql/procs/deleteNode.sql ================================================ DELETE FROM nodes WHERE id=? ================================================ FILE: sql/procs/deleteNodeEdges.sql ================================================ DELETE FROM edges WHERE source=? OR target=? ================================================ FILE: sql/procs/fetchNodes.sql ================================================ SELECT nodes.id, nodes.tag, nodes.properties FROM nodes WHERE nodes.tag=? |propies| ================================================ FILE: sql/procs/fetchNodes.withEdges.sql ================================================ SELECT nodes.id, nodes.tag, nodes.properties FROM nodes INNER JOIN edges ON edges.source=nodes.id OR edges.target=nodes.id WHERE nodes.tag=? |propies| GROUP BY nodes.id HAVING COUNT( CASE WHEN |edgies| THEN 1 END ) |edgeLimit| ================================================ FILE: sql/procs/getAllNodeTags.sql ================================================ SELECT DISTINCT tag FROM nodes ================================================ FILE: sql/procs/getMaxNodeId.sql ================================================ SELECT MAX(id) FROM nodes ================================================ FILE: sql/procs/getNode.sql ================================================ SELECT nodes.tag, nodes.properties FROM nodes WHERE nodes.id=? ================================================ FILE: sql/procs/getRelatedNodes.sql ================================================ SELECT nodes.id, nodes.tag, nodes.properties, source, target, edges.tag, edges.id AS label, edges.properties FROM edges INNER JOIN nodes ON nodes.id=edges.source OR nodes.id=edges.target WHERE (source=? OR target=?) AND (nodes.id<>?) ================================================ FILE: sql/procs/updateEdge.sql ================================================ UPDATE edges SET tag=? WHERE id=? ================================================ FILE: sql/procs/updateNode.sql ================================================ UPDATE nodes SET tag=?, properties=? WHERE id=? ================================================ FILE: sql/procs/updateNodeProperties.sql ================================================ UPDATE nodes SET properties=? WHERE id=? ================================================ FILE: sql/procs/updateNodeProperty.sql ================================================ UPDATE nodes SET properties = json_set(properties, ?, ?) WHERE id=? ================================================ FILE: sql/schema.sql ================================================ PRAGMA encoding="UTF-8"; DROP TABLE IF EXISTS nodes; CREATE TABLE nodes ( id INTEGER PRIMARY KEY, tag TEXT, properties JSON NOT NULL ); CREATE INDEX IF NOT EXISTS node_index ON nodes(id); CREATE INDEX IF NOT EXISTS node_tag_index ON nodes(tag); DROP TABLE IF EXISTS edges; CREATE TABLE edges ( id INTEGER PRIMARY KEY, tag TEXT, properties JSON NOT NULL, source INTEGER, target INTEGER, FOREIGN KEY (source) REFERENCES nodes(id), FOREIGN KEY (target) REFERENCES nodes(id) ); CREATE INDEX IF NOT EXISTS edges_index ON edges(id); CREATE INDEX IF NOT EXISTS edges_source_index ON edges(source); CREATE INDEX IF NOT EXISTS edges_target_index ON edges(target); ================================================ FILE: ui/index.html ================================================ Grafito
{{tableKey}}
{{tableRow[tableKey]}}

Grafito {{config.versions.system}}

 running at /localhost:18966

  • backend: Arturo v/{{config.versions.arturo}}
  • engine: SQLite v/{{config.versions.engine}}

Database

{{analytics.disk.path}}

{{analytics.database.nodes}}

Nodes

{{analytics.database.edges}}

Edges

{{analytics.database.degree}}

Avg. Degree

Performance

{{analytics.memory.number}} {{analytics.memory.units}}

Memory

Size

General

Engine

Graph View

Table View

{{graph.selected.node[0].tag}} {{graph.selected.edge[0].label}} info
================================================ FILE: ui/palettes/default.art ================================================ #130075 #3d0075 #bd8ed1 #75250e #756c10 #567513 #A5D180 #00752B #005f73 #0a9396 #94d2bd #e9d8a6 #d1ad94 #ee9b00 #ca6702 #bb3e03 #ae2012 #9b2226 #750041 ================================================ FILE: ui/palettes/earthy.art ================================================ #c27e88 #a9505c #c3887d #aa5d4e #7a4238 #b2c77a #94b049 #6a7d34 #90b1b1 #679292 #496868 #ae9d92 #8f786a #66564b #3d332d ================================================ FILE: ui/palettes/inferno.art ================================================ #fcffa4 #f2ea69 #f8cd37 #fcb014 #fa9407 #f47918 #e9612b #d94d3d #c63d4d #b0315b #982766 #801f6c #69166e #510e6c #380962 ================================================ FILE: ui/palettes/light.art ================================================ #a0bfe8 #6698da #3072c9 #22518f #143156 #eabd9e #de9563 #ce6d2b #934e1f #582e12 #edac9b #e27a5e #d44a25 #97351a #5a1f10 #cfc0b8 #b3998d #957364 #6a5247 #40312a #b7d0ca #8cb4ab #62978a #466c63 #2a403b ================================================ FILE: ui/palettes/magma.art ================================================ #f0f921 #fada24 #febd2a #fba238 #f48849 #e97158 #db5c68 #cc4778 #b83289 #a31e9a #8b0aa5 #6f00a8 #5302a3 #350498 #0d0887 ================================================ FILE: ui/palettes/pastel.art ================================================ #3bb2d0 #3887be #8a8acb #56b881 #50667f #41afa5 #f9886c #e55e5e #ed6498 #fbb03b ================================================ FILE: ui/palettes/playful.art ================================================ #7ac70c #8ee000 #faa918 #ffc715 #d33131 #e53838 #1cb0f6 #14d4f4 #8549ba #a560e8 #4c4c4c #6f6f6f ================================================ FILE: ui/palettes/rainbow.art ================================================ #4aae20 #6cc751 #225f1e #f8cc07 #ff9300 #e44436 #cd3292 #37aef3 #0076ba #005888 #8732cd ================================================ FILE: ui/palettes/vibrant.art ================================================ #ff6050 #ff0e83 #d54262 #813867 #66336e #5677fc #341539 #9013fe #ffc208 #00cc99 ================================================ FILE: ui/palettes/viridis.art ================================================ #fde725 #d0e11c #a0da39 #73d056 #4ac16d #2db27d #1fa187 #21918c #277f8e #2e6e8e #365c8d #3f4788 #46327e #481b6d #440154 ================================================ FILE: ui/scripts/ace/ace.js ================================================ (function(){var t=function(){return this}();var n=function(e,t,r){"string"==typeof e?(2==arguments.length&&(r=t),n.modules||(n.modules={},n.payloads={}),n.payloads[e]=r,n.modules[e]=null):n.original?n.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace())},r=function(e,t,n){if("[object Array]"===Object.prototype.toString.call(t)){for(var i=[],o=0,u=t.length;ot.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(t){t=r.exec.call(this,t);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t}))}),ace.define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function H(e){return(e=+e)!=e?e=0:0!==e&&e!==1/0&&e!==-1/0&&(e=(0>>0;if("[object Function]"!=a(t))throw new TypeError;for(;++s>>0,s=Array(i),o=arguments[1];if("[object Function]"!=a(t))throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],u=arguments[1];if("[object Function]"!=a(t))throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if("[object Function]"!=a(t))throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if("[object Function]"!=a(t))throw new TypeError(t+" is not a function");for(var o=0;o>>0;if("[object Function]"!=a(t))throw new TypeError(t+" is not a function");if(!i&&1==arguments.length)throw new TypeError("reduce of empty array with no initial value");var o,s=0;if(2<=arguments.length)o=arguments[1];else for(;;){if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}for(;s>>0;if("[object Function]"!=a(t))throw new TypeError(t+" is not a function");if(!i&&1==arguments.length)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(2<=arguments.length)s=arguments[1];else for(;;){if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}for(;o in this&&(s=t.call(void 0,s,r[o],o,n)),o--;);return s}),Array.prototype.indexOf&&-1==[0,1].indexOf(1,2)||(Array.prototype.indexOf=function(t){var n=g&&"[object String]"==a(this)?this.split(""):F(this),r=n.length>>>0;if(!r)return-1;for(var i=0,i=0<=(i=1>>0;if(!r)return-1;for(var i=r-1,i=0<=(i=1=n.lastRow||t.end.row<=n.firstRow)&&this.renderer.scrollSelectionIntoView(this.selection.anchor,this.selection.lead)}"animate"==e.scrollIntoView&&this.renderer.animateScrolling(this.curOp.scrollTop)}this.prevOp=this.curOp,this.curOp=null}},this.$historyTracker=function(e){var t,n,r,i;this.$mergeUndoDeltas&&(n=["backspace","del","insertstring"],r=(t=this.prevOp).command&&e.command.name==t.command.name,"insertstring"==e.command.name?(i=e.args,void 0===this.mergeNextCommand&&(this.mergeNextCommand=!0),r=r&&this.mergeNextCommand&&(!/\s/.test(i)||/\s/.test(t.args)),this.mergeNextCommand=!0):r=r&&-1!==n.indexOf(e.command.name),(r="always"!=this.$mergeUndoDeltas&&2e3d.search(/\S|$/)&&(c=d.substr(i.column).search(/\S|$/),n.doc.removeInLine(i.row,i.column,i.column+c))),this.clearSelection();var f=i.column,l=n.getState(i.row),d=n.getLine(i.row),c=r.checkOutdent(l,d,e);n.insert(i,e);s&&s.selection&&(2==s.selection.length?this.selection.setSelectionRange(new p(i.row,f+s.selection[0],i.row,f+s.selection[1])):this.selection.setSelectionRange(new p(i.row+s.selection[0],s.selection[1],i.row+s.selection[2],s.selection[3]))),n.getDocument().isNewLine(e)&&(d=r.getNextLineIndent(l,d.slice(0,i.column),n.getTabString()),n.insert({row:i.row+1,column:0},d)),c&&r.autoOutdent(l,n,i.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.setOption("scrollSpeed",e)},this.getScrollSpeed=function(){return this.getOption("scrollSpeed")},this.setDragDelay=function(e){this.setOption("dragDelay",e)},this.getDragDelay=function(){return this.getOption("dragDelay")},this.setSelectionStyle=function(e){this.setOption("selectionStyle",e)},this.getSelectionStyle=function(){return this.getOption("selectionStyle")},this.setHighlightActiveLine=function(e){this.setOption("highlightActiveLine",e)},this.getHighlightActiveLine=function(){return this.getOption("highlightActiveLine")},this.setHighlightGutterLine=function(e){this.setOption("highlightGutterLine",e)},this.getHighlightGutterLine=function(){return this.getOption("highlightGutterLine")},this.setHighlightSelectedWord=function(e){this.setOption("highlightSelectedWord",e)},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.setReadOnly=function(e){this.setOption("readOnly",e)},this.getReadOnly=function(){return this.getOption("readOnly")},this.setBehavioursEnabled=function(e){this.setOption("behavioursEnabled",e)},this.getBehavioursEnabled=function(){return this.getOption("behavioursEnabled")},this.setWrapBehavioursEnabled=function(e){this.setOption("wrapBehavioursEnabled",e)},this.getWrapBehavioursEnabled=function(){return this.getOption("wrapBehavioursEnabled")},this.setShowFoldWidgets=function(e){this.setOption("showFoldWidgets",e)},this.getShowFoldWidgets=function(){return this.getOption("showFoldWidgets")},this.setFadeFoldWidgets=function(e){this.setOption("fadeFoldWidgets",e)},this.getFadeFoldWidgets=function(){return this.getOption("fadeFoldWidgets")},this.remove=function(i){this.selection.isEmpty()&&("left"==i?this.selection.selectLeft():this.selection.selectRight());var s,o,t=this.getSelectionRange();this.getBehavioursEnabled()&&(s=(o=this.session).getState(t.start.row),i=o.getMode().transformAction(s,"deletion",this,o,t),0!==t.end.column||"\n"==(s=o.getTextRange(t))[s.length-1]&&(o=o.getLine(t.end.row),/^\s+$/.test(o)&&(t.end.column=o.length)),i&&(t=i)),this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){var e,n,r,i;!this.selection.isEmpty()||0!==(i=(e=this.getCursorPosition()).column)&&(i=i<(n=this.session.getLine(e.row)).length?(r=n.charAt(i)+n.charAt(i-1),new p(e.row,i-1,e.row,i+1)):(r=n.charAt(i-1)+n.charAt(i-2),new p(e.row,i-2,e.row,i)),this.session.replace(i,r))},this.toLowerCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toLowerCase()),this.selection.setSelectionRange(e)},this.toUpperCase=function(){var e=this.getSelectionRange();this.selection.isEmpty()&&this.selection.selectWord();var t=this.getSelectionRange(),n=this.session.getTextRange(t);this.session.replace(t,n.toUpperCase()),this.selection.setSelectionRange(e)},this.indent=function(){var e=this.session,t=this.getSelectionRange();if(!(t.start.rowt.toLowerCase()?1:0});for(var r=new p(0,0,0,0),i=e.first;i<=e.last;i++){var s=t.getLine(i);r.start.row=i,r.end.row=i,r.end.column=s.length,t.replace(r,n[i-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.toggleBlockComment=function(){var e=this.getCursorPosition(),t=this.session.getState(e.row),n=this.getSelectionRange();this.session.getMode().toggleBlockComment(t,this.session,n,e)},this.getNumberAt=function(e,t){var n=/[\-]?[0-9]+(?:\.[0-9]+)?/g;n.lastIndex=0;for(var r=this.session.getLine(e);n.lastIndex=t)return{value:i[0],start:i.index,end:i.index+i[0].length}}return null},this.modifyNumber=function(e){var s,o,t=this.selection.getCursor().row,n=this.selection.getCursor().column,l=new p(t,n-1,t,n),f=this.session.getTextRange(l);isNaN(parseFloat(f))||!isFinite(f)||(s=this.getNumberAt(t,n))&&(o=0<=s.value.indexOf(".")?s.start+s.value.indexOf(".")+1:s.end,l=s.start+s.value.length-o,f=parseFloat(s.value),f*=Math.pow(10,l),o!==s.end&&n=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(s,t){var n=this.renderer,r=this.renderer.layerConfig,i=s*Math.floor(r.height/r.lineHeight);this.$blockScrolling++,!0===t?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):!1===t&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection()),this.$blockScrolling--;s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),null!=t&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var t=this.getSelectionRange(),t={row:Math.floor(t.start.row+(t.end.row-t.start.row)/2),column:Math.floor(t.start.column+(t.end.column-t.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),--this.$blockScrolling},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e){var t=this.getCursorPosition(),n=this.session.getBracketRange(t);if(!n){if(!(n=this.find({needle:/[{}()\[\]]/g,preventScroll:!0,start:{row:t.row,column:t.column-1}})))return;var r=n.start;r.row==t.row&&Math.abs(r.column-t.column)<2&&(n=this.session.getBracketRange(r))}(r=n&&n.cursor||r)&&(e?n&&n.isEqual(this.getSelectionRange())?this.clearSelection():this.selection.selectTo(r.row,r.column):this.selection.moveTo(r.row,r.column))},this.gotoLine=function(e,t,n){this.selection.clearSelection(),this.session.unfold({row:e-1,column:t||0}),this.$blockScrolling+=1,this.exitMultiSelectMode&&this.exitMultiSelectMode(),this.moveCursorTo(e-1,t||0),--this.$blockScrolling,this.isRowFullyVisible(e-1)||this.scrollToLine(e-1,!0,n)},this.navigateTo=function(e,t){this.selection.moveTo(e,t)},this.navigateUp=function(e){if(this.selection.isMultiLine()&&!this.selection.isBackwards()){var t=this.selection.anchor.getPosition();return this.moveCursorToPosition(t)}this.selection.clearSelection(),this.selection.moveCursorBy(-e||-1,0)},this.navigateDown=function(e){if(this.selection.isMultiLine()&&this.selection.isBackwards()){var t=this.selection.anchor.getPosition();return this.moveCursorToPosition(t)}this.selection.clearSelection(),this.selection.moveCursorBy(e||1,0)},this.navigateLeft=function(e){if(this.selection.isEmpty())for(e=e||1;e--;)this.selection.moveCursorLeft();else{var t=this.getSelectionRange().start;this.moveCursorToPosition(t)}this.clearSelection()},this.navigateRight=function(e){if(this.selection.isEmpty())for(e=e||1;e--;)this.selection.moveCursorRight();else{var t=this.getSelectionRange().end;this.moveCursorToPosition(t)}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){this.selection.moveCursorFileEnd(),this.clearSelection()},this.navigateFileStart=function(){this.selection.moveCursorFileStart(),this.clearSelection()},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(e,r){r&&this.$search.set(r);var n=this.$search.find(this.session),r=0;return n&&(this.$tryReplace(n,e)&&(r=1),null!==n&&(this.selection.setSelectionRange(n),this.renderer.scrollSelectionIntoView(n.start,n.end))),r},this.replaceAll=function(e,i){i&&this.$search.set(i);var n=this.$search.findAll(this.session),r=0;if(!n.length)return r;this.$blockScrolling+=1;i=this.getSelectionRange();this.selection.moveTo(0,0);for(var s=n.length-1;0<=s;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),--this.$blockScrolling,r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return null!==(t=this.$search.replace(n,t))?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(s,t,n){t=t||{},"string"==typeof s||s instanceof RegExp?t.needle=s:"object"==typeof s&&r.mixin(t,s);var i=this.selection.getRange();null==t.needle&&((s=this.session.getTextRange(i)||this.$search.$options.needle)||(i=this.session.getWordRange(i.start.row,i.start.column),s=this.session.getTextRange(i)),this.$search.set({needle:s})),this.$search.set(t),t.start||this.$search.set({start:i});s=this.$search.find(this.session);return t.preventScroll?s:s?(this.revealRange(s,n),s):(t.backwards?i.start=i.end:i.end=i.start,void this.selection.setRange(i))},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),--this.$blockScrolling;var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),!1!==t&&this.renderer.animateScrolling(n)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy(),this._signal("destroy",this)},this.setAutoScrollEditorIntoView=function(e){var t,n,r,i,s,o,u;e&&(r=!1,(n=this).$scrollAnchor||(this.$scrollAnchor=document.createElement("div")),(i=this.$scrollAnchor).style.cssText="position:absolute",this.container.insertBefore(i,this.container.firstChild),s=this.on("changeSelection",function(){r=!0}),o=this.renderer.on("beforeRender",function(){r&&(t=n.renderer.container.getBoundingClientRect())}),u=this.renderer.on("afterRender",function(){var s,o,u;r&&t&&n.isFocused()&&(s=(u=n.renderer).$cursorLayer.$pixelPos,o=u.layerConfig,u=s.top-o.offset,null!=(r=0<=s.top&&u+t.top<0||!(s.topwindow.innerHeight)&&null)&&(i.style.top=u+"px",i.style.left=s.left+"px",i.style.height=o.lineHeight+"px",i.scrollIntoView(r)),r=t=null)}),this.setAutoScrollEditorIntoView=function(e){e||(delete this.setAutoScrollEditorIntoView,this.removeEventListener("changeSelection",s),this.renderer.removeEventListener("afterRender",u),this.renderer.removeEventListener("beforeRender",o))})},this.$resetCursorStyle=function(){var e=this.$cursorStyle||"ace",t=this.renderer.$cursorLayer;t&&(t.setSmoothBlinking("smooth"==e),t.isBlinking=!this.$readOnly&&"wide"!=e)}}).call(y.prototype),g.defineOptions(y.prototype,"editor",{selectionStyle:{set:function(e){this.onSelectionChange(),this._signal("changeSelectionStyle",{data:e})},initialValue:"line"},highlightActiveLine:{set:function(){this.$updateHighlightActiveLine()},initialValue:!0},highlightSelectedWord:{set:function(e){this.$onSelectionChange()},initialValue:!0},readOnly:{set:function(e){this.$resetCursorStyle()},initialValue:!1},cursorStyle:{set:function(e){this.$resetCursorStyle()},values:["ace","slim","smooth","wide"],initialValue:"ace"},mergeUndoDeltas:{values:[!1,!0,"always"],initialValue:!0},behavioursEnabled:{initialValue:!0},wrapBehavioursEnabled:{initialValue:!0},autoScrollEditorIntoView:{set:function(e){this.setAutoScrollEditorIntoView(e)}},hScrollBarAlwaysVisible:"renderer",vScrollBarAlwaysVisible:"renderer",highlightGutterLine:"renderer",animatedScroll:"renderer",showInvisibles:"renderer",showPrintMargin:"renderer",printMarginColumn:"renderer",printMargin:"renderer",fadeFoldWidgets:"renderer",showFoldWidgets:"renderer",showLineNumbers:"renderer",showGutter:"renderer",displayIndentGuides:"renderer",fontSize:"renderer",fontFamily:"renderer",maxLines:"renderer",minLines:"renderer",scrollPastEnd:"renderer",fixedWidthGutter:"renderer",theme:"renderer",scrollSpeed:"$mouseHandler",dragDelay:"$mouseHandler",dragEnabled:"$mouseHandler",focusTimout:"$mouseHandler",tooltipFollowsMouse:"$mouseHandler",firstLineNumber:"session",overwrite:"session",newLineMode:"session",useWorker:"session",useSoftTabs:"session",tabSize:"session",wrap:"session",foldStyle:"session",mode:"session"}),t.Editor=y}),ace.define("ace/lib/lang",["require","exports","module"],function(e,t,n){t.last=function(e){return e[e.length-1]},t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){for(var n="";0>=1)&&(e+=e);return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var n,t={};for(n in e)t[n]=e[n];return t},t.copyArray=function(e){for(var t=[],n=0,r=e.length;nthis.$focusTimout)&&this.startSelect(this.mousedownEvent.getDocumentPosition())},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,i=n.session.getBracketRange(t);i?(i.isEmpty()&&(i.start.column--,i.end.column++),this.setState("select")):(i=n.selection.getWordRange(t.row,t.column),this.setState("selectByWords")),this.$clickSelection=i,this[this.state]&&this[this.state](e)},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState("selectByLines"),this.$clickSelection=n.selection.getLineRange(t.row),this[this.state]&&this[this.state](e)},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("selectAll")},this.onMouseWheel=function(e){if(!e.getAccelKey()){e.getShiftKey()&&e.wheelY&&!e.wheelX&&(e.wheelX=e.wheelY,e.wheelY=0);var t=e.domEvent.timeStamp,n=t-(this.$lastScrollTime||0),r=this.editor;return r.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed)||n<200?(this.$lastScrollTime=t,r.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.stop()):void 0}}}).call(u.prototype),t.DefaultHandlers=u}),ace.define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"],function(e,t,n){function a(e){o.call(this,e)}var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/event"),o=e("../tooltip").Tooltip;i.inherits(a,o),function(){this.setPosition=function(e,t){var n=window.innerWidth||document.documentElement.clientWidth,r=window.innerHeight||document.documentElement.clientHeight,i=this.getWidth(),s=this.getHeight();n<(e+=15)+i&&(e-=e+i-n),r<(t+=15)+s&&(t-=20+s),o.prototype.setPosition.call(this,e,t)}}.call(a.prototype),t.GutterHandler=function(e){function l(){var v=u.getDocumentPosition().row,d=n.$annotations[v];if(!d)return c();if(v==t.session.getLength()){var a=t.renderer.pixelToScreenCoordinates(0,u.y).row,l=u.$pos;if(a>t.session.documentToScreenRow(l.row,l.column))return c()}f!=d&&(f=d.text.join("
"),i.setHtml(f),i.show(),t.on("mousewheel",c),e.$tooltipFollowsMouse?h(u):(d=n.$cells[t.session.documentToScreenRow(v,0)].element.getBoundingClientRect(),(v=i.getElement().style).left=d.right+"px",v.top=d.bottom+"px"))}function c(){o=o&&clearTimeout(o),f&&(i.hide(),f=null,t.removeEventListener("mousewheel",c))}function h(e){i.setPosition(e.x,e.y)}var o,u,f,t=e.editor,n=t.renderer.$gutterLayer,i=new a(t.container);e.editor.setDefaultHandler("guttermousedown",function(r){if(t.isFocused()&&0==r.getButton()&&"foldWidgets"!=n.getRegion(r)){var s=r.getDocumentPosition().row,o=t.session.selection;if(r.getShiftKey())o.selectTo(s,0);else{if(2==r.domEvent.detail)return t.selectAll(),r.preventDefault();e.$clickSelection=t.selection.getLineRange(s)}return e.setState("selectByLines"),e.captureMouse(r),r.preventDefault()}}),e.editor.setDefaultHandler("guttermousemove",function(t){var n=t.domEvent.target||t.domEvent.srcElement;if(r.hasCssClass(n,"ace_fold-widget"))return c();f&&e.$tooltipFollowsMouse&&h(t),u=t,o=o||setTimeout(function(){o=null,(u&&!e.isMousePressed?l:c)()},50)}),s.addListener(t.renderer.$gutter,"mouseout",function(e){u=null,f&&!o&&(o=setTimeout(function(){o=null,c()},50))}),t.on("changeSession",c)}}),ace.define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"],function(e,t,n){function s(e){this.isOpen=!1,this.$element=null,this.$parentNode=e}e("./lib/oop");var i=e("./lib/dom");(function(){this.$init=function(){return this.$element=i.createElement("div"),this.$element.className="ace_tooltip",this.$element.style.display="none",this.$parentNode.appendChild(this.$element),this.$element},this.getElement=function(){return this.$element||this.$init()},this.setText=function(e){i.setInnerText(this.getElement(),e)},this.setHtml=function(e){this.getElement().innerHTML=e},this.setPosition=function(e,t){this.getElement().style.left=e+"px",this.getElement().style.top=t+"px"},this.setClassName=function(e){i.addCssClass(this.getElement(),e)},this.show=function(e,t,n){null!=e&&this.setText(e),null!=t&&null!=n&&this.setPosition(t,n),this.isOpen||(this.getElement().style.display="block",this.isOpen=!0)},this.hide=function(){this.isOpen&&(this.getElement().style.display="none",this.isOpen=!1)},this.getHeight=function(){return this.getElement().offsetHeight},this.getWidth=function(){return this.getElement().offsetWidth}}).call(s.prototype),t.Tooltip=s}),ace.define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"],function(e,s,n){var r=e("../lib/event"),i=e("../lib/useragent"),s=s.MouseEvent=function(e,t){this.domEvent=e,this.editor=t,this.x=this.clientX=e.clientX,this.y=this.clientY=e.clientY,this.$pos=null,this.$inSelection=null,this.propagationStopped=!1,this.defaultPrevented=!1};!function(){this.stopPropagation=function(){r.stopPropagation(this.domEvent),this.propagationStopped=!0},this.preventDefault=function(){r.preventDefault(this.domEvent),this.defaultPrevented=!0},this.stop=function(){this.stopPropagation(),this.preventDefault()},this.getDocumentPosition=function(){return this.$pos||(this.$pos=this.editor.renderer.screenToTextCoordinates(this.clientX,this.clientY),this.$pos)},this.inSelection=function(){if(null!==this.$inSelection)return this.$inSelection;var n,t=this.editor.getSelectionRange();return t.isEmpty()?this.$inSelection=!1:(n=this.getDocumentPosition(),this.$inSelection=t.contains(n.row,n.column)),this.$inSelection},this.getButton=function(){return r.getButton(this.domEvent)},this.getShiftKey=function(){return this.domEvent.shiftKey},this.getAccelKey=i.isMac?function(){return this.domEvent.metaKey}:function(){return this.domEvent.ctrlKey}}.call(s.prototype)}),ace.define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"],function(e,t,n){function f(e){function C(){var e=g;(function(e,s){var r=Date.now(),i=!s||e.row!=s.row,s=!s||e.column!=s.column;!S||i||s?(t.$blockScrolling+=1,t.moveCursorToPosition(e),--t.$blockScrolling,S=r,x={x:p,y:d}):5this.editor.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(){this.editor.container.draggable=!1,this.startSelect(this.mousedownEvent.getDocumentPosition()),this.selectEnd()},this.dragReadyEnd=function(e){this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()),this.editor.unsetStyle("ace_dragging"),this.dragWaitEnd()},this.startDrag=function(){this.cancelDrag=!1,this.editor.container.draggable=!0,this.editor.renderer.$cursorLayer.setBlinking(!1),this.editor.setStyle("ace_dragging"),this.setState("dragReady")},this.onMouseDrag=function(e){var t=this.editor.container;s.isIE&&"dragReady"==this.state&&3>1,s=e[i];if(se&&(e=t.screenWidth)}),this.lineWidgetWidth=e},this.$computeWidth=function(e){if(this.$modified||e){if(this.$modified=!1,this.$useWrapMode)return this.screenWidth=this.$wrapLimit;for(var t=this.doc.getAllLines(),n=this.$rowLengthCache,r=0,i=0,s=this.$foldData[i],o=s?s.start.row:1/0,u=t.length,a=0;ar&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.undoChanges=function(e,t){if(e.length){this.$fromUndo=!0;for(var n=null,r=e.length-1;-1!=r;r--){var i=e[r];"doc"==i.group?(this.doc.revertDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!0,n)):i.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n}},this.redoChanges=function(e,t){if(e.length){this.$fromUndo=!0;for(var n=null,r=0;rl.end.column&&(s.start.column+=u),s.end.row==l.end.row&&s.end.column>l.end.column&&(s.end.column+=u)),o&&s.start.row>=l.end.row&&(s.start.row+=o,s.end.row+=o)),s.end=this.insert(s.start,r),i.length&&(a=l.start,l=s.start,o=l.row-a.row,u=l.column-a.column,this.addFolds(i.map(function(e){return(e=e.clone()).start.row==a.row&&(e.start.column+=u),e.end.row==a.row&&(e.end.column+=u),e.start.row+=o,e.end.row+=o,e}))),s},this.indentRows=function(e,t,n){n=n.replace(/\t/g,this.getTabString());for(var r=e;r<=t;r++)this.insert({row:r,column:0},n)},this.outdentRows=function(e){for(var t=e.collapseRows(),n=new f(0,0,0,0),r=this.getTabSize(),i=t.start.row;i<=t.end.row;++i){var s=this.getLine(i);n.start.row=i,n.end.row=i;for(var o=0;othis.doc.getLength()-1)return 0;i=o-u}else{e=this.$clipRowToDocument(e);i=(u=this.$clipRowToDocument(u))-e+1}var o=new f(e,0,u,Number.MAX_VALUE),o=this.getFoldsInRange(o).map(function(e){return(e=e.clone()).start.row+=i,e.end.row+=i,e}),u=0==n?this.doc.getLines(e,u):this.doc.removeLines(e,u);return this.doc.insertLines(e+i,u),o.length&&this.addFolds(o),i},this.moveLinesUp=function(e,t){return this.$moveLines(e,t,-1)},this.moveLinesDown=function(e,t){return this.$moveLines(e,t,1)},this.duplicateLines=function(e,t){return this.$moveLines(e,t,0)},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){var n;return t=Math.max(0,t),t=e<0?e=0:(n=this.doc.getLength())<=e?this.doc.getLine(e=n-1).length:Math.min(this.doc.getLine(e).length,t),{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(t){t!=this.$useWrapMode&&(this.$useWrapMode=t,this.$modified=!0,this.$resetRowCache(0),t&&(t=this.getLength(),this.$wrapData=Array(t),this.$updateWrapData(0,t-1)),this._signal("changeWrapMode"))},this.getUseWrapMode=function(){return this.$useWrapMode},this.setWrapLimitRange=function(e,t){this.$wrapLimitRange.min===e&&this.$wrapLimitRange.max===t||(this.$wrapLimitRange={min:e,max:t},this.$modified=!0,this._signal("changeWrapMode"))},this.adjustWrapLimit=function(e,t){var r=this.$wrapLimitRange;r.max<0&&(r={min:t,max:t});r=this.$constrainWrapLimit(e,r.min,r.max);return r!=this.$wrapLimit&&1=u.row&&l.shiftRow(-n);s=i}else{var v=Array(n);v.unshift(i,0);var d=t?this.$wrapData:this.$rowLengthCache;d.splice.apply(d,v);f=this.$foldData,c=0;for((l=this.getFoldLine(i))&&(0==(v=l.range.compareInside(o.row,o.column))?((l=l.split(o.row,o.column)).shiftRow(n),l.addRemoveChars(s,0,u.column-o.column)):-1==v&&(l.addRemoveChars(i,0,u.column-o.column),l.shiftRow(n)),c=f.indexOf(l)+1);c=i&&l.shiftRow(n)}else{var l,n=Math.abs(e.data.range.start.column-e.data.range.end.column);-1!=r.indexOf("remove")&&(a=this.getFoldsInRange(e.data.range),this.removeFolds(a),n=-n),(l=this.getFoldLine(i))&&l.addRemoveChars(i,o.column,n)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),this.$updating=!1,t?this.$updateWrapData(i,s):this.$updateRowLengthCache(i,s),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var o,a,n=this.doc.getAllLines(),r=this.getTabSize(),i=this.$wrapData,s=this.$wrapLimit,f=e;for(t=Math.min(t,n.length-1);f<=t;)(a=this.getFoldLine(f,a))?(o=[],a.walk(function(e,t,r,i){var s;if(null!=e){(s=this.$getDisplayTokens(e,o.length))[0]=u;for(var a=1;a>2)),i-1);cv[m-1]):!m;for(var s,h=this.getLength()-1,p=this.getNextFoldLine(r),d=p?p.start.row:1/0;o<=e&&!(ea[l-1]):!l;for(var h=this.getNextFoldLine(u),p=h?h.start.row:1/0;u=v[m];)r++,m++;d=d.substring(v[m-1]||0,d.length)}}return{row:r,column:this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(this.$useWrapMode)for(var i=this.$wrapData.length,s=0,r=0,o=(t=this.$foldData[r++])?t.start.row:1/0;st.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.getRange().isEmpty()&&(this.$isEmpty=!0),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.moveTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.moveToPosition=function(e){this.clearSelection(),this.moveCursorToPosition(e)},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){var n;return void 0===t&&(e=(n=e||this.lead).row,t=n.column),this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var t=this.getCursor(),t=this.session.getAWordRange(t.row,t.column);this.setSelectionRange(t)},this.getLineRange=function(r,t){var n="number"==typeof r?r:this.lead.row,r=this.session.getFoldLine(n),r=r?(n=r.start.row,r.end.row):n;return!0===t?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var n,e=this.lead.getPosition();(n=this.session.getFoldAt(e.row,e.column,-1))?this.moveCursorTo(n.start.row,n.start.column):0==e.column?0=n.length)return this.moveCursorTo(e,n.length),this.moveCursorRight(),void(e ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return 0==this.compare(e,t)},this.compareRange=function(r){var t=r.end,r=r.start,t=this.compare(t.row,t.column);return 1==t?1==(t=this.compare(r.row,r.column))?2:0==t?1:0:-1==t?-2:-1==(t=this.compare(r.row,r.column))?-1:1==t?42:0},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return 0==this.comparePoint(e.start)&&0==this.comparePoint(e.end)},this.intersects=function(t){t=this.compareRange(t);return-1==t||0==t||1==t},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){"object"==typeof e?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){"object"==typeof e?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return 0==this.compare(e,t)&&(!this.isEnd(e,t)&&!this.isStart(e,t))},this.insideStart=function(e,t){return 0==this.compare(e,t)&&!this.isEnd(e,t)},this.insideEnd=function(e,t){return 0==this.compare(e,t)&&!this.isStart(e,t)},this.compare=function(e,t){return this.isMultiLine()||e!==this.start.row?ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row!==e||t<=this.end.column?0:1:tthis.end.column?1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){var n,r;return this.end.row>t?n={row:t+1,column:0}:this.end.rowt?r={row:t+1,column:0}:this.start.rowe.length&&(E=e.length)}),a==1/0&&(a=E,o=s=!1),l&&a%f!=0&&(a=Math.floor(a/f)*f),w(o?m:v)},this.toggleBlockComment=function(e,t,n,r){var i=this.blockComment;if(i){!i.start&&i[0]&&(i=i[0]);var c,h,o=(s=new a(t,r.row,r.column)).getCurrentToken(),l=(t.selection,t.selection.toOrientedRange());if(o&&/comment/.test(o.type)){for(;o&&/comment/.test(o.type);){if(-1!=(v=o.value.indexOf(i.start))){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v,p=new f(m,g,m,g+i.start.length);break}o=s.stepBackward()}for(var s,v,o=(s=new a(t,r.row,r.column)).getCurrentToken();o&&/comment/.test(o.type);){if(-1!=(v=o.value.indexOf(i.end))){var m=s.getCurrentTokenRow(),g=s.getCurrentTokenColumn()+v,d=new f(m,g,m,g+i.end.length);break}o=s.stepForward()}d&&t.remove(d),p&&(t.remove(p),c=p.start.row,h=-i.start.length)}else h=i.start.length,c=n.start.row,t.insert(n.end,i.end),t.insert(n.start,i.start);l.start.row==c&&(l.start.column+=h),l.end.row==c&&(l.end.column+=h),t.selection.fromOrientedRange(l)}},this.getNextLineIndent=function(e,t,n){return this.$getIndent(t)},this.checkOutdent=function(e,t,n){return!1},this.autoOutdent=function(e,t,n){},this.$getIndent=function(e){return e.match(/^\s*/)[0]},this.createWorker=function(e){return null},this.createModeDelegates=function(e){for(var t in this.$embeds=[],this.$modes={},e)e[t]&&(this.$embeds.push(t),this.$modes[t]=new e[t]);for(var n=["toggleBlockComment","toggleCommentLines","getNextLineIndent","checkOutdent","autoOutdent","transformAction","getCompletions"],t=0;tl&&(m=e.substring(l,v-d.length),c.type==h?c.value+=m:(c.type&&f.push(c),c={type:h,value:m}));for(var g=0;gr){for(;l=this.$rowTokens.length;){if(this.$row+=1,e=e||this.$session.getLength(),this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(void 0!==n)return n;for(n=0;0=t?(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length):e.row<0&&(e.row=0),e},this.insert=function(e,i){if(!i||0===i.length)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(i);var n=this.$split(i),r=n.splice(0,1)[0],i=0==n.length?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),null!==i&&(e=this.insertNewLine(e),e=this._insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){return e>=this.getLength()?this.insert({row:e,column:0},"\n"+t.join("\n")):this._insertLines(Math.max(e,0),t)},this._insertLines=function(e,t){if(0==t.length)return{row:e,column:0};for(;61440=this.getLength()?this.remove(new s(e,0,t+1,0)):this._removeLines(e,t)},this._removeLines=function(r,t){var i=new s(r,0,t+1,0),r=this.$lines.splice(r,t-r+1),i={action:"removeLines",range:i,nl:this.getNewLineCharacter(),lines:r};return this._signal("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),o=new s(e,t.length,e+1,0);this.$lines.splice(e,2,t+n);o={action:"removeText",range:o,text:this.getNewLineCharacter()};this._signal("change",{data:o})},this.replace=function(e,t){return e instanceof s||(e=s.fromPoints(e.start,e.end)),0==t.length&&e.isEmpty()?e.start:t==this.getTextRange(e)?e.end:(this.remove(e),t?this.insert(e.start,t):e.start)},this.applyDeltas=function(e){for(var t=0;tthis.row||o.start.row==this.row&&o.start.column>this.column||(r=this.row,i=this.column,s=o.start,o=o.end,"insertText"===t.action?s.row===r&&s.column<=i?s.column===i&&this.$insertRight||(s.row===o.row?i+=o.column-s.column:(i-=s.column,r+=o.row-s.row)):s.row!==o.row&&s.row=i?s.column:Math.max(0,i-(o.column-s.column)):s.row!==o.row&&s.row=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}.call(s.prototype)}),ace.define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(s,t,n){var r=s("./lib/oop"),i=s("./lib/event_emitter").EventEmitter,s=function(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var n=this;this.$worker=function(){if(n.running){for(var e=new Date,t=n.currentLine,r=-1,i=n.doc;n.lines[t];)t++;var s=t,o=i.getLength(),u=0;for(n.running=!1;te+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=r.tokens}}).call(s.prototype),t.BackgroundTokenizer=s}),ace.define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(o,t,n){var r=o("./lib/lang"),s=(o("./lib/oop"),o("./range").Range),o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){this.regExp+""!=e+""&&(this.regExp=e,this.cache=[])},this.update=function(e,t,n,i){if(this.regExp)for(var o=i.firstRow,u=i.lastRow,a=o;a<=u;a++){var f=this.cache[a];null==f&&(f=(f=(f=r.getMatchOffsets(n.getLine(a),this.regExp)).length>this.MAX_RANGES?f.slice(0,this.MAX_RANGES):f).map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:"");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i)}}}).call(o.prototype),t.SearchHighlight=o}),ace.define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"],function(e,t,n){var r=e("../range").Range,i=e("./fold_line").FoldLine,s=e("./fold").Fold,o=e("../token_iterator").TokenIterator;t.Folding=function(){this.getFoldAt=function(e,t,n){var r=this.getFoldLine(e);if(!r)return null;for(var i=r.folds,s=0;s=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;for(-1==(r=t?n.indexOf(t):r)&&(r=0);r=e)return i}return null},this.getFoldedRowCount=function(e,t){for(var n=this.$foldData,r=t-e+1,i=0;i=e){i=s.end.row;try{var o=this.addFold("...",s);o&&(o.collapseChildren=n)}catch(u){}}}}},this.$foldStyles={manual:1,markbegin:1,markbeginend:1},this.$foldStyle="markbegin",this.setFoldStyle=function(t){if(!this.$foldStyles[t])throw new Error("invalid fold style: "+t+"["+Object.keys(this.$foldStyles).join(", ")+"]");this.$foldStyle!=t&&("manual"==(this.$foldStyle=t)&&this.unfold(),t=this.$foldMode,this.$setFolding(null),this.$setFolding(t))},this.$setFolding=function(e){this.$foldMode!=e&&(this.$foldMode=e,this.removeListener("change",this.$updateFoldWidgets),this._emit("changeAnnotation"),e&&"manual"!=this.$foldStyle?(this.foldWidgets=[],this.getFoldWidget=e.getFoldWidget.bind(e,this,this.$foldStyle),this.getFoldWidgetRange=e.getFoldWidgetRange.bind(e,this,this.$foldStyle),this.$updateFoldWidgets=this.updateFoldWidgets.bind(this),this.on("change",this.$updateFoldWidgets)):this.foldWidgets=null)},this.getParentFoldRangeData=function(e,t){var n=this.foldWidgets;if(!n||t&&n[e])return{};for(var r=e-1;0<=r;){var s=n[r];if("start"==(s=null==s?n[r]=this.getFoldWidget(r):s)){var o=this.getFoldWidgetRange(r),i=i||o;if(o&&o.end.row>=e)break}r--}return{range:-1!==r&&o,firstRange:i}},this.onFoldWidgetClick=function(e,i){var n={children:(i=i.domEvent).shiftKey,all:i.ctrlKey||i.metaKey,siblings:i.altKey};this.$toggleFoldWidget(e,n)||(i=i.target||i.srcElement)&&/ace_fold-widget/.test(i.className)&&(i.className+=" ace_invalid")},this.$toggleFoldWidget=function(e,t){if(this.getFoldWidget){var s=this.getFoldWidget(e),o=this.getLine(e),u="end"===s?-1:1,s=this.getFoldAt(e,-1==u?0:o.length,u);if(s)t.children||t.all?this.removeFold(s):this.expandFold(s);else{var a,f,o=this.getFoldWidgetRange(e,!0);if(!o||o.isMultiLine()||!(s=this.getFoldAt(o.start.row,o.start.column,1))||!o.isEqual(s.range))return t.siblings?((u=this.getParentFoldRangeData(e)).range&&(a=u.range.start.row+1,f=u.range.end.row),this.foldAll(a,f,t.all?1e4:0)):t.children?(f=o?o.end.row:this.getLength(),this.foldAll(e+1,o.end.row,t.all?1e4:0)):o&&(t.all&&(o.collapseChildren=1e4),this.addFold("...",o)),o;this.removeFold(s)}}},this.toggleFoldWidget=function(e){var i=this.selection.getCursor().row;i=this.getRowFoldStart(i);var r,n=this.$toggleFoldWidget(i,{});n||(n=(r=this.getParentFoldRangeData(i,!0)).range||r.firstRange)&&(i=n.start.row,(i=this.getFoldAt(i,this.getLine(i).length,1))?this.removeFold(i):this.addFold("...",n))},this.updateFoldWidgets=function(r){var t=r.data,s=t.range,r=s.start.row,s=s.end.row-r;0==s?this.foldWidgets[r]=null:"removeText"==t.action||"removeLines"==t.action?this.foldWidgets.splice(r,1+s,null):((s=Array(1+s)).unshift(r,1),this.foldWidgets.splice.apply(this.foldWidgets,s))}}}),ace.define("ace/edit_session/fold_line",["require","exports","module","ace/range"],function(e,t,n){function i(n,t){this.foldData=n,Array.isArray(t)?this.folds=t:t=this.folds=[t];n=t[t.length-1];this.range=new r(t[0].start.row,t[0].start.column,n.end.row,n.end.column),this.start=this.range.start,this.end=this.range.end,this.folds.forEach(function(e){e.setFoldLine(this)},this)}var r=e("../range").Range;(function(){this.shiftRow=function(e){this.start.row+=e,this.end.row+=e,this.folds.forEach(function(t){t.start.row+=e,t.end.row+=e})},this.addFold=function(e){if(e.sameRow){if(e.start.rowthis.endRow)throw new Error("Can't add a fold to this FoldLine as it has no connection");this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),0=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var s,o,r=0,i=this.folds,a=!0;null==t&&(t=this.end.row,n=this.end.column);for(var f=0;ft||n[n.length-1].start.rowi)break;c.start.row==i&&c.start.column>=n.column&&(c.start.column!=n.column||!this.$insertRight)&&(c.start.column+=u,c.start.row+=o),c.end.row==i&&c.end.column>=n.column&&(c.end.column==n.column&&this.$insertRight||(c.end.column==n.column&&0c.start.column&&c.end.column==a[f+1].start.column&&(c.end.column-=u),c.end.column+=u,c.end.row+=o))}if(0!=o&&fv||(o.push(l=new s(c,v,c+a-1,m)),2E&&o[h].end.row==n.end.row;)h--;for(o=o.slice(g,h+1),g=0,h=o.length;g .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0 -12px 0 1px;display: none;width: 11px;vertical-align: top;background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;cursor: pointer;}.ace_folding-enabled .ace_fold-widget {display: inline-block; }.ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==");}.ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}/*** Dark version for fold widgets*/.ace_dark .ace_fold-widget {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC");}.ace_dark .ace_fold-widget.ace_end {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget.ace_closed {background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {-moz-transition: opacity 0.4s ease 0.05s;-webkit-transition: opacity 0.4s ease 0.05s;-o-transition: opacity 0.4s ease 0.05s;-ms-transition: opacity 0.4s ease 0.05s;transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {-moz-transition: opacity 0.05s ease 0.05s;-webkit-transition: opacity 0.05s ease 0.05s;-o-transition: opacity 0.05s ease 0.05s;-ms-transition: opacity 0.05s ease 0.05s;transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}.ace_error-marker {background-color: rgba(255, 0, 0,0.2);position: absolute;z-index: 9;}.ace_highlight-marker {background-color: rgba(255, 255, 0,0.2);position: absolute;z-index: 8;}',"ace_editor");g=function(e,r){var n=this;this.container=e||i.createElement("div"),this.$keepTextAreaAtCursor=!o.isOldIE,i.addCssClass(this.container,"ace_editor"),this.setTheme(r),this.$gutter=i.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=i.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=i.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.$gutterLayer=new u(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new a(this.content);r=this.$textLayer=new f(this.content);this.canvas=r.element,this.$markerFront=new a(this.content),this.$cursorLayer=new l(this.content),this.$horizScroll=!1,this.$vScroll=!1,this.scrollBar=this.scrollBarV=new h(this.container,this),this.scrollBarH=new c(this.container,this),this.scrollBarV.addEventListener("scroll",function(e){n.$scrollAnimation||n.session.setScrollTop(e.data-n.scrollMargin.top)}),this.scrollBarH.addEventListener("scroll",function(e){n.$scrollAnimation||n.session.setScrollLeft(e.data-n.scrollMargin.left)}),this.scrollTop=0,this.scrollLeft=0,this.cursorPos={row:0,column:0},this.$fontMetrics=new d(this.container,500),this.$textLayer.$setFontMetrics(this.$fontMetrics),this.$textLayer.addEventListener("changeCharacterSize",function(e){n.updateCharacterSize(),n.onResize(!0,n.gutterWidth,n.$size.width,n.$size.height),n._signal("changeCharacterSize",e)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0,$dirty:!0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:0,characterWidth:0,minHeight:1,maxHeight:1,offset:0,height:1,gutterOffset:1},this.scrollMargin={left:0,right:0,top:0,bottom:0,v:0,h:0},this.$loop=new p(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4),s.resetOptions(this),s._emit("renderer",this)};(function(){this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,v),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.layerConfig.characterWidth=this.characterWidth=this.$textLayer.getCharacterWidth(),this.layerConfig.lineHeight=this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session&&this.session.doc.off("changeNewLineMode",this.onChangeNewLineMode),(this.session=e)&&(this.scrollMargin.top&&e.getScrollTop()<=0&&e.setScrollTop(-this.scrollMargin.top),this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e),this.$loop.schedule(this.CHANGE_FULL),this.session.$setFontMetrics(this.$fontMetrics),this.onChangeNewLineMode=this.onChangeNewLineMode.bind(this),this.onChangeNewLineMode(),this.session.doc.on("changeNewLineMode",this.onChangeNewLineMode))},this.updateLines=function(e,t){void 0===t&&(t=1/0),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRowthis.layerConfig.lastRow||this.$changedLines.lastRows.height-r||(i=this.characterWidth,this.$composition&&(s=this.textarea.value.replace(/^\x01+/,""),i*=this.session.$getStringScreenWidth(s)[0]+2,r+=2,--t),(n-=this.scrollLeft)>this.$size.scrollerWidth-i&&(n=this.$size.scrollerWidth-i),n-=this.scrollBar.width,this.textarea.style.height=r+"px",this.textarea.style.width=i+"px",this.textarea.style.right=Math.max(0,this.$size.scrollerWidth-n-i)+"px",this.textarea.style.bottom=Math.max(0,this.$size.height-t-r)+"px"))},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(0===this.layerConfig.offset?0:1)},this.getLastFullyVisibleRow=function(){var e=Math.floor((this.layerConfig.height+this.layerConfig.offset)/this.layerConfig.lineHeight);return this.layerConfig.firstRow-1+e},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.setScrollMargin=function(e,t,n,r){var i=this.scrollMargin;i.top=0|e,i.bottom=0|t,i.right=0|r,i.left=0|n,i.v=i.top+i.bottom,i.h=i.left+i.right,i.top&&this.scrollTop<=0&&this.session&&this.session.setScrollTop(-i.top),this.updateFull()},this.getHScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.setOption("hScrollBarAlwaysVisible",e)},this.getVScrollBarAlwaysVisible=function(){return this.$hScrollBarAlwaysVisible},this.setVScrollBarAlwaysVisible=function(e){this.setOption("vScrollBarAlwaysVisible",e)},this.$updateScrollBarV=function(){this.scrollBarV.setScrollHeight(this.layerConfig.maxHeight+this.scrollMargin.v),this.scrollBarV.setScrollTop(this.scrollTop+this.scrollMargin.top)},this.$updateScrollBarH=function(){this.scrollBarH.setScrollWidth(this.layerConfig.width+2*this.$padding+this.scrollMargin.h),this.scrollBarH.setScrollLeft(this.scrollLeft+this.scrollMargin.left)},this.$frozen=!1,this.freeze=function(){this.$frozen=!0},this.unfreeze=function(){this.$frozen=!1},this.$renderChanges=function(e,n){if(this.$changes&&(e|=this.$changes,this.$changes=0),this.session&&this.container.offsetWidth&&!this.$frozen&&(e||n)){if(this.$size.$dirty)return this.$changes|=e,this.onResize(!0);this.lineHeight||this.$textLayer.checkForSizeChanges(),this._signal("beforeRender");n=this.layerConfig;(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL||e&this.CHANGE_H_SCROLL)&&(e|=this.$computeLayerConfig(),n=this.layerConfig,this.$updateScrollBarV(),e&this.CHANGE_H_SCROLL&&this.$updateScrollBarH(),this.$gutterLayer.element.style.marginTop=-n.offset+"px",this.content.style.marginTop=-n.offset+"px",this.content.style.width=n.width+2*this.$padding+"px",this.content.style.height=n.minHeight+"px"),e&this.CHANGE_H_SCROLL&&(this.content.style.marginLeft=-this.scrollLeft+"px",this.scroller.className=this.scrollLeft<=0?"ace_scroller":"ace_scroller ace_scroll-left"),e&this.CHANGE_FULL?(this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()):e&this.CHANGE_SCROLL?(e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(n):this.$textLayer.scrollLines(n),this.$showGutter&&this.$gutterLayer.update(n),this.$markerBack.update(n),this.$markerFront.update(n),this.$cursorLayer.update(n),this.$highlightGutterLine&&this.$updateGutterLineHighlight(),this.$moveTextAreaToCursor()):(e&this.CHANGE_TEXT?(this.$textLayer.update(n),this.$showGutter&&this.$gutterLayer.update(n)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.$showGutter)&&this.$gutterLayer.update(n):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.$showGutter&&this.$gutterLayer.update(n),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(n),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(n),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(n)),this._signal("afterRender")}else this.$changes|=e},this.$autosize=function(){var i=this.session.getScreenLength()*this.lineHeight,t=this.$maxLines*this.lineHeight,n=Math.max((this.$minLines||1)*this.lineHeight,Math.min(t,i))+this.scrollMargin.v+(this.$extraHeight||0),i=ti-t.scrollerHeight&&(i+=Math.min((t.scrollerHeight-this.lineHeight)*this.$scrollPastEnd,this.scrollTop-i+t.scrollerHeight));var b=!g&&(this.$vScrollBarAlwaysVisible||t.scrollerHeight-i<0),c=this.$vScroll!==b;c&&(this.$vScroll=b,this.scrollBarV.setVisible(b)),this.session.setScrollTop(Math.max(-this.scrollMargin.top,Math.min(this.scrollTop,i-t.scrollerHeight+this.scrollMargin.bottom))),this.session.setScrollLeft(Math.max(-this.scrollMargin.left,Math.min(this.scrollLeft,u+2*this.$padding-t.scrollerWidth+this.scrollMargin.right)));var v=Math.ceil(o/this.lineHeight)-1,d=(p=Math.max(0,Math.round((this.scrollTop-s)/this.lineHeight)))+v,g=this.lineHeight,p=e.screenToDocumentRow(p,0),b=e.getFoldLine(p);b&&(p=b.start.row);v=e.documentToScreenRow(p,0),b=e.getRowLength(p)*g,d=Math.min(e.screenToDocumentRow(d,0),e.getLength()-1),o=t.scrollerHeight+e.getRowLength(d)*g+b,s=this.scrollTop-v*g,b=0;return this.layerConfig.width!=u&&(b=this.CHANGE_H_SCROLL),(f||c)&&(b=this.$updateCachedSize(!0,this.gutterWidth,t.width,t.height),this._signal("scrollbarVisibilityChanged"),c&&(u=this.$getLongestLine())),this.layerConfig={width:u,padding:this.$padding,firstRow:p,firstRowScreen:v,lastRow:d,lineHeight:g,characterWidth:this.characterWidth,minHeight:o,maxHeight:i,offset:s,gutterOffset:Math.max(0,Math.ceil((s+t.height-t.scrollerHeight)/g)),height:this.$size.scrollerHeight},b},this.$updateLines=function(){var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(!(e>n.lastRow+1||t=1-this.scrollMargin.top||(0=1-this.scrollMargin.left||(0d+1;)p=this.$cells.pop(),this.element.removeChild(p.element);break}(p=this.$cells[++d])||((p={element:null,textNode:null,foldWidget:null}).element=r.createElement("div"),p.textNode=document.createTextNode(""),p.element.appendChild(p.textNode),this.element.appendChild(p.element),this.$cells[d]=p);var m="ace_gutter-cell ";a[v]&&(m+=a[v]),f[v]&&(m+=f[v]),this.$annotations[v]&&(m+=this.$annotations[v].className),p.element.className!=m&&(p.element.className=m);var y,b=t.getRowLength(v)*e.lineHeight+"px";b!=p.element.style.height&&(p.element.style.height=b),!u||null==(y=u[v])&&(y=u[v]=t.getFoldWidget(v)),y?(p.foldWidget||(p.foldWidget=r.createElement("span"),p.element.appendChild(p.foldWidget)),m="ace_fold-widget ace_"+y,"start"==y&&v==o&&vn.right-t.right?"foldWidgets":void 0}}).call(u.prototype),t.Gutter=u}),ace.define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(s,t,n){var r=s("../range").Range,i=s("../lib/dom"),s=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){if(e=e||this.config){this.config=e;var n,t=[];for(n in this.markers){var o,u,s,r=this.markers[n];r.range?(s=r.range.clipRows(e.firstRow,e.lastRow)).isEmpty()||(s=s.toScreenRange(this.session),r.renderer?(o=this.$getTop(s.start.row,e),u=this.$padding+s.start.column*e.characterWidth,r.renderer(t,s,u,o,e)):"fullLine"==r.type?this.drawFullLineMarker(t,s,r.clazz,e):"screenLine"==r.type?this.drawScreenLineMarker(t,s,r.clazz,e):s.isMultiLine()?"text"==r.type?this.drawTextMarker(t,s,r.clazz,e):this.drawMultiLineMarker(t,s,r.clazz,e):this.drawSingleLineMarker(t,s,r.clazz+" ace_start",e)):r.update(t,this,this.session,e)}this.element=i.setInnerHtml(this.element,t.join(""))}},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(e,t,n,i,s){var o=t.start.row,u=new r(o,t.start.column,o,this.session.getScreenLastRowColumn(o));for(this.drawSingleLineMarker(e,u,n+" ace_start",i,1,s),o=t.end.row,u=new r(o,0,o,t.end.column),this.drawSingleLineMarker(e,u,n,i,0,s),o=t.start.row+1;o");u=this.$getTop(t.end.row,r),f=t.end.column*r.characterWidth;e.push("
"),(o=(t.end.row-t.start.row-1)*r.lineHeight)<0||(u=this.$getTop(t.start.row+1,r),e.push("
"))},this.drawSingleLineMarker=function(e,t,n,f,a,s){var o=f.lineHeight,u=(t.end.column+(a||0)-t.start.column)*f.characterWidth,a=this.$getTop(t.start.row,f),f=this.$padding+t.start.column*f.characterWidth;e.push("
")},this.drawFullLineMarker=function(e,t,n,r,i){var s=this.$getTop(t.start.row,r),o=r.lineHeight;t.start.row!=t.end.row&&(o+=this.$getTop(t.end.row,r)-s),e.push("
")},this.drawScreenLineMarker=function(e,s,n,o,i){s=this.$getTop(s.start.row,o),o=o.lineHeight;e.push("
")}}).call(s.prototype),t.Marker=s}),ace.define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(a,t,n){var r=a("../lib/oop"),i=a("../lib/dom"),s=a("../lib/lang"),u=(a("../lib/useragent"),a("../lib/event_emitter").EventEmitter),a=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$updateEolChar=this.$updateEolChar.bind(this)};(function(){r.implement(this,u),this.EOF_CHAR="¶",this.EOL_CHAR_LF="¬",this.EOL_CHAR_CRLF="¤",this.EOL_CHAR=this.EOL_CHAR_LF,this.TAB_CHAR="→",this.SPACE_CHAR="·",this.$padding=0,this.$updateEolChar=function(){var e="\n"==this.session.doc.getNewLineCharacter()?this.EOL_CHAR_LF:this.EOL_CHAR_CRLF;if(this.EOL_CHAR!=e)return this.EOL_CHAR=e,!0},this.setPadding=function(e){this.$padding=e,this.element.style.padding="0 "+e+"px"},this.getLineHeight=function(){return this.$fontMetrics.$characterSize.height||0},this.getCharacterWidth=function(){return this.$fontMetrics.$characterSize.width||0},this.$setFontMetrics=function(e){this.$fontMetrics=e,this.$fontMetrics.on("changeCharacterSize",function(e){this._signal("changeCharacterSize",e)}.bind(this)),this.$pollSizeChanges()},this.checkForSizeChanges=function(){this.$fontMetrics.checkForSizeChanges()},this.$pollSizeChanges=function(){return this.$pollSizeChangesTimer=this.$fontMetrics.$pollSizeChanges()},this.setSession=function(e){this.session=e,this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles!=e&&(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides!=e&&(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;for(var r,i,o,u,a,t=this.$tabStrings=[0],n=1;n"+this.TAB_CHAR+s.stringRepeat(" ",n-1)+""):t.push(s.stringRepeat(" ",n));this.displayIndentGuides&&(this.$indentGuideRe=/\s\S| \t|\t |\s$/,r="ace_indent-guide",o=i="",a=this.showInvisibles?(r+=" ace_invisible",i=" ace_invisible_space",o=" ace_invisible_tab",u=s.stringRepeat(this.SPACE_CHAR,this.tabSize),this.TAB_CHAR+s.stringRepeat(" ",this.tabSize-1)):u=s.stringRepeat(" ",this.tabSize),this.$tabStrings[" "]=""+u+"",this.$tabStrings["\t"]=""+a+"")},this.updateLines=function(e,t,n){this.config.lastRow==e.lastRow&&this.config.firstRow==e.firstRow||this.scrollLines(e),this.config=e;for(var r=Math.max(t,e.firstRow),s=Math.min(n,e.lastRow),o=this.element.childNodes,u=0,a=e.firstRow;ae.lastRow)for(r=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);0t.lastRow&&(i=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow),n.appendChild(i))},this.$renderLinesFragment=function(e,t,n){for(var r=this.element.ownerDocument.createDocumentFragment(),s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:1/0;u"),this.$renderLine(t,s,!1,s==u&&o),this.$useLineGroups()&&t.push(""),s++;this.element=i.setInnerHtml(this.element,t.join(""))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var f,l,i=this,a=r.replace(/\t|&|<|( +)|([\x00-\x1f\x80-\xa0\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g,function(l,n,f,a,u){if(n)return i.showInvisibles?""+s.stringRepeat(i.SPACE_CHAR,l.length)+"":s.stringRepeat(" ",l.length);if("&"==l)return"&";if("<"==l)return"<";if("\t"==l){a=i.session.getScreenTabSize(t+a);return t+=a-1,i.$tabStrings[a]}if(" "!=l)return f?""+i.SPACE_CHAR+"":(t+=1,""+l+"");f=i.showInvisibles?"ace_cjk ace_invisible ace_invisible_space":"ace_cjk",l=i.showInvisibles?i.SPACE_CHAR:"";return t+=1,""+l+""});return this.$textToken[n.type]?e.push(a):(f="ace_"+n.type.replace(/\./g," ace_"),l="","fold"==n.type&&(l=" style='width:"+n.value.length*this.config.characterWidth+"px;' "),e.push("",a,"")),t+r.length},this.renderIndentGuide=function(e,t,n){var r=t.search(this.$indentGuideRe);return r<=0||n<=r?t:" "==t[0]?(r-=r%this.tabSize,e.push(s.stringRepeat(this.$tabStrings[" "],r/this.tabSize)),t.substr(r)):"\t"==t[0]?(e.push(s.stringRepeat(this.$tabStrings["\t"],r)),t.substr(r)):t},this.$renderWrappedLine=function(e,t,n,r){for(var i=0,s=0,o=n[0],u=0,a=0;a=o;)u=this.$renderToken(e,u,f,l.substring(0,o-i)),l=l.substring(o-i),i=o,r||e.push("","
"),u=0,o=n[++s]||Number.MAX_VALUE;0!=l.length&&(i+=l.length,u=this.$renderToken(e,u,f,l))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;(i=this.displayIndentGuides?this.renderIndentGuide(e,i):i)&&(n=this.$renderToken(e,n,r,i));for(var s=1;s"),i.length&&((s=this.session.getRowSplitData(t))&&s.length?this.$renderWrappedLine(e,i,s,n):this.$renderSimpleLine(e,i)),this.showInvisibles&&(r&&(t=r.end.row),e.push("",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,"")),n||e.push("
")},this.$getFoldLineTokens=function(e,t){var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){null!=e?r.push({type:"fold",value:e}):(s=a?n.getTokens(t):s).length&&function(e,t,n){for(var o,i=0,s=0;s+e[i].value.lengthn-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1);sn?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}(s,u,o)},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),ace.define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(s,t,n){var i,r=s("../lib/dom"),s=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),void 0===i&&(i="opacity"in this.element),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors"),this.$updateCursors=this.$updateVisibility.bind(this)};(function(){this.$updateVisibility=function(e){for(var t=this.cursors,n=t.length;n--;)t[n].style.visibility=e?"":"hidden"},this.$updateOpacity=function(e){for(var t=this.cursors,n=t.length;n--;)t[n].style.opacity=e?"":"0"},this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e==this.smoothBlinking||i||(this.smoothBlinking=e,r.setCssClass(this.element,"ace_smooth-blinking",e),this.$updateCursors(!0),this.$updateCursors=(e?this.$updateOpacity:this.$updateVisibility).bind(this),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(1e.height+e.offset||s.top<0)&&1r;)this.removeCursor();var u=this.session.getOverwrite();this.$setOverwrite(u),this.$pixelPos=s,this.restartTimer()},this.$setOverwrite=function(e){e!=this.overwrite&&((this.overwrite=e)?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(s.prototype),t.Cursor=s}),ace.define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(f,t,n){function u(e){this.element=i.createElement("div"),this.element.className="ace_scrollbar ace_scrollbar"+this.classSuffix,this.inner=i.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.setVisible(!1),this.skipEvent=!1,s.addListener(this.element,"scroll",this.onScroll.bind(this)),s.addListener(this.element,"mousedown",s.preventDefault)}var r=f("./lib/oop"),i=f("./lib/dom"),s=f("./lib/event"),o=f("./lib/event_emitter").EventEmitter;!function(){r.implement(this,o),this.setVisible=function(e){this.element.style.display=e?"":"none",this.isVisible=e}}.call(u.prototype);function a(e,t){u.call(this,e),this.scrollTop=0,t.$scrollbarWidth=this.width=i.scrollbarWidth(e.ownerDocument),this.inner.style.width=this.element.style.width=(this.width||15)+5+"px"}r.inherits(a,u),function(){this.classSuffix="-v",this.onScroll=function(){this.skipEvent||(this.scrollTop=this.element.scrollTop,this._emit("scroll",{data:this.scrollTop})),this.skipEvent=!1},this.getWidth=function(){return this.isVisible?this.width:0},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=function(e){this.inner.style.height=e+"px"},this.setScrollHeight=function(e){this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=this.element.scrollTop=e)}}.call(a.prototype);f=function(e,t){u.call(this,e),this.scrollLeft=0,this.height=t.$scrollbarWidth,this.inner.style.height=this.element.style.height=(this.height||15)+5+"px"};r.inherits(f,u),function(){this.classSuffix="-h",this.onScroll=function(){this.skipEvent||(this.scrollLeft=this.element.scrollLeft,this._emit("scroll",{data:this.scrollLeft})),this.skipEvent=!1},this.getHeight=function(){return this.isVisible?this.height:0},this.setWidth=function(e){this.element.style.width=e+"px"},this.setInnerWidth=function(e){this.inner.style.width=e+"px"},this.setScrollWidth=function(e){this.inner.style.width=e+"px"},this.setScrollLeft=function(e){this.scrollLeft!=e&&(this.skipEvent=!0,this.scrollLeft=this.element.scrollLeft=e)}}.call(f.prototype),t.ScrollBar=a,t.ScrollBarV=a,t.ScrollBarH=f,t.VScrollBar=a,t.HScrollBar=f}),ace.define("ace/renderloop",["require","exports","module","ace/lib/event"],function(i,t,n){var r=i("./lib/event"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){var t;this.changes=this.changes|e,!this.pending&&this.changes&&(this.pending=!0,r.nextFrame(function(){var e;for(t.pending=!1;e=t.changes;)t.changes=0,t.onRender(e)},(t=this).window))}}).call(i.prototype),t.RenderLoop=i}),ace.define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/event_emitter"],function(e,a,n){var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/event_emitter").EventEmitter,u=0,a=a.FontMetrics=function(e,t){this.el=i.createElement("div"),this.$setMeasureNodeStyles(this.el.style,!0),this.$main=i.createElement("div"),this.$setMeasureNodeStyles(this.$main.style),this.$measureNode=i.createElement("div"),this.$setMeasureNodeStyles(this.$measureNode.style),this.el.appendChild(this.$main),this.el.appendChild(this.$measureNode),e.appendChild(this.el),u||this.$testFractionalRect(),this.$measureNode.innerHTML=s.stringRepeat("X",u),this.$characterSize={width:0,height:0},this.checkForSizeChanges()};!function(){r.implement(this,o),this.$characterSize={width:0,height:0},this.$testFractionalRect=function(){var e=i.createElement("div");this.$setMeasureNodeStyles(e.style),e.style.width="0.2px",document.documentElement.appendChild(e);var t=e.getBoundingClientRect().width;u=0r.length||n.length<2||!n[1])return this.commands.exec("insertstring",this,e);for(var i=r.length;i--;){var s=r[i];s.isEmpty()||this.session.remove(s),this.session.insert(s.start,n[i])}}},this.findAll=function(e,t,n){(t=t||{}).needle=e||t.needle,this.$search.set(t);var r=this.$search.findAll(this.session);if(!r.length)return 0;this.$blockScrolling+=1;var i=this.multiSelect;n||i.toSingleRange(r[0]);for(var s=r.length;s--;)i.addRange(r[s],!0);return--this.$blockScrolling,r.length},this.selectMoreLines=function(e,t){var n=this.selection.toOrientedRange(),r=n.cursor==n.end,s=this.session.documentToScreenPosition(n.cursor);this.selection.$desiredColumn&&(s.column=this.selection.$desiredColumn);var a,f,l,o=this.session.screenToDocumentPosition(s.row+e,s.column);a=n.isEmpty()?o:(a=this.session.documentToScreenPosition(r?n.end:n.start),this.session.screenToDocumentPosition(a.row+e,a.column)),r?(f=i.fromPoints(o,a)).cursor=f.start:(f=i.fromPoints(a,o)).cursor=f.end,f.desiredColumn=s.column,this.selection.inMultiSelectMode?t&&(l=n.cursor):this.selection.addRange(n),this.selection.addRange(f),l&&this.selection.substractPoint(l)},this.transposeSelections=function(e){for(var t=this.session,n=t.multiSelect,r=n.ranges,i=r.length;i--;)(s=r[i]).isEmpty()&&(o=t.getWordRange(s.start.row,s.start.column),s.start.row=o.start.row,s.start.column=o.start.column,s.end.row=o.end.row,s.end.column=o.end.column);n.mergeOverlappingRanges();for(var u=[],i=r.length;i--;){var s=r[i];u.unshift(t.getTextRange(s))}e<0?u.unshift(u.pop()):u.push(u.shift());for(i=r.length;i--;){var o=(s=r[i]).clone();t.replace(s,u[i]),s.start.row=o.start.row,s.start.column=o.start.column}},this.selectMore=function(e,t){var n=this.session,i=n.multiSelect.toOrientedRange();i.isEmpty()&&((i=n.getWordRange(i.start.row,i.start.column)).cursor=-1==e?i.start:i.end,this.multiSelect.addRange(i));var o=n.getTextRange(i),o=function(e,t,n){return c.$options.wrap=!0,c.$options.needle=t,c.$options.backwards=-1==n,c.find(e)}(n,o,e);o&&(o.cursor=-1==e?o.start:o.end,this.$blockScrolling+=1,this.session.unfold(o),this.multiSelect.addRange(o),--this.$blockScrolling,this.renderer.scrollCursorIntoView(null,.5)),t&&this.multiSelect.substractPoint(i.cursor)},this.alignCursors=function(){var e=this.session,u=e.multiSelect,c=u.ranges;if(c.length){var h=-1,r=c.filter(function(e){return e.cursor.row==h||void(h=e.cursor.row)});u.$onRemoveRange(r);var d=0,v=1/0,m=c.map(function(i){var n=i.cursor,i=e.getLine(n.row).substr(n.column).search(/\S/g);return n.column>d&&(d=n.column),(i=-1==i?0:i)t[1].length&&(i=t[1].length),st[3].length&&(o=t[3].length)),t):[e]}).map(t?f:n?r?function(e){return e[2]?u(i+s-e[2].length)+e[2]+u(o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}:f:function(e){return e[2]?u(i)+e[2]+u(o)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]})}}).call(d.prototype),t.onSessionChange=function(n){var t=n.session;t.multiSelect||(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t.multiSelect;n=n.oldSession;n&&(n.multiSelect.removeEventListener("addRange",this.$onAddRange),n.multiSelect.removeEventListener("removeRange",this.$onRemoveRange),n.multiSelect.removeEventListener("multiSelect",this.$onMultiSelect),n.multiSelect.removeEventListener("singleSelect",this.$onSingleSelect)),t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m,e("./config").defineOptions(d.prototype,"editor",{enableMultiselect:{set:function(e){m(this),e?(this.on("changeSession",this.$multiselectOnSessionChange),this.on("mousedown",o)):(this.off("changeSession",this.$multiselectOnSessionChange),this.off("mousedown",o))},value:!0}})}),ace.define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event"],function(e,t,n){function i(e,t){return e.row==t.row&&e.column==t.column}var r=e("../lib/event");t.onMouseDown=function(e){var n=(p=e.domEvent).altKey,s=p.shiftKey,o=e.getAccelKey(),u=e.getButton();if(e.editor.inMultiSelectMode&&2==u)e.editor.textInput.onContextMenu(e.domEvent);else if(o||n){var E,S,a=e.editor,f=a.selection,l=a.inMultiSelectMode,c=e.getDocumentPosition(),g=f.getCursor(),p=e.inSelection()||f.isEmpty()&&i(c,g),d=e.x,v=e.y,g=function(){var e=a.renderer.pixelToScreenCoordinates(d,v),t=y.screenToDocumentPosition(e.row,e.column);i(w,e)&&i(t,f.selectionLead)||(w=e,a.selection.moveToPosition(t),a.renderer.scrollCursorIntoView(),a.removeSelectionMarkers(x),(x=f.rectangularRangeBlock(w,b)).forEach(a.addSelectionMarker,a),a.updateSelectionMarkers())},y=a.session,b=a.renderer.pixelToScreenCoordinates(d,v),w=b;if(!o||n||s||0!==u){if(n&&0===u){e.stop(),l&&!o?f.toSingleRange():!l&&o&&f.addRange();var x=[];s?(b=y.documentToScreenPosition(f.lead),g()):f.moveToPosition(c);var N=g;r.capture(a.container,function(e){d=e.clientX,v=e.clientY},function(e){clearInterval(C),a.removeSelectionMarkers(x);for(var t=0;tthis.$doc.getLength()>>1?this.call("setValue",[this.$doc.getValue()]):this.emit("change",{data:e}))},this.$workerBlob=function(s){var t="importScripts('"+i.qualifyURL(s)+"');";try{return new Blob([t],{type:"application/javascript"})}catch(n){s=new(window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder);return s.append(t),s.getBlob("application/javascript")}}}.call(u.prototype);function a(e,t,n){this.$sendDeltaQueue=this.$sendDeltaQueue.bind(this),this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var r=null,i=!1,u=Object.create(s),a=this;this.$worker={},this.$worker.terminate=function(){},this.$worker.postMessage=function(e){a.messageBuffer.push(e),r&&(i?setTimeout(f):f())},this.setEmitSync=function(e){i=e};var f=function(){var e=a.messageBuffer.shift();e.command?r[e.command].apply(r,e.args):e.event&&u._signal(e.event,e.data)};u.postMessage=function(e){a.onMessage({data:e})},u.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},u.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},o.loadModule(["worker",t],function(e){for(r=new e[n](u);a.messageBuffer.length;)f()})}a.prototype=u.prototype,t.UIWorkerClient=a,t.WorkerClient=u}),ace.define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(o,t,n){var r=o("./range").Range,i=o("./lib/event_emitter").EventEmitter,s=o("./lib/oop"),o=function(e,t,u,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=u;u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session,i=this.$pos;this.pos=t.createAnchor(i.row,i.column),this.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.pos.on("change",function(t){n.removeMarker(e.markerId),e.markerId=n.addMarker(new r(t.value.row,t.value.column,t.value.row,t.value.column+e.length),e.mainClass,null,!1)}),this.others=[],this.$others.forEach(function(r){r=t.createAnchor(r.row,r.column);e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){var e,t;this.othersActive||(e=this.session,(t=this).othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1),n.on("change",function(i){e.removeMarker(n.markerId),n.markerId=e.addMarker(new r(i.value.row,i.value.column,i.value.row,i.value.column+t.length),t.othersClass,null,!1)})}))},this.hideOtherMarkers=function(){if(this.othersActive){this.othersActive=!1;for(var e=0;e=this.pos.column&&n.start.column<=this.pos.column+this.length+1){var s=n.start.column-this.pos.column;if(this.length+=i,!this.session.$fromUndo){if("insertText"===t.action)for(var o=this.others.length-1;0<=o;o--){var a={row:(u=this.others[o]).row,column:u.column+s};u.row===n.start.row&&n.start.column=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e)))},this.detach=function(){this.session.removeMarker(this.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.pos.detach();for(var e=0;eo.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)}},this.closingBracketBlock=function(e,u,n,o,s){o={row:n,column:o},u=e.$findOpeningBracket(u,o);if(u)return u.column++,o.column--,r.fromPoints(u,o)}}.call(i.prototype)}),ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!1,t.cssClass="ace-tm",t.cssText='.ace-tm .ace_gutter {background: #f0f0f0;color: #333;}.ace-tm .ace_print-margin {width: 1px;background: #e8e8e8;}.ace-tm .ace_fold {background-color: #6B72E6;}.ace-tm {background-color: #FFFFFF;color: black;}.ace-tm .ace_cursor {color: black;}.ace-tm .ace_invisible {color: rgb(191, 191, 191);}.ace-tm .ace_storage,.ace-tm .ace_keyword {color: blue;}.ace-tm .ace_constant {color: rgb(197, 6, 11);}.ace-tm .ace_constant.ace_buildin {color: rgb(88, 72, 246);}.ace-tm .ace_constant.ace_language {color: rgb(88, 92, 246);}.ace-tm .ace_constant.ace_library {color: rgb(6, 150, 14);}.ace-tm .ace_invalid {background-color: rgba(255, 0, 0, 0.1);color: red;}.ace-tm .ace_support.ace_function {color: rgb(60, 76, 114);}.ace-tm .ace_support.ace_constant {color: rgb(6, 150, 14);}.ace-tm .ace_support.ace_type,.ace-tm .ace_support.ace_class {color: rgb(109, 121, 222);}.ace-tm .ace_keyword.ace_operator {color: rgb(104, 118, 135);}.ace-tm .ace_string {color: rgb(3, 106, 7);}.ace-tm .ace_comment {color: rgb(76, 136, 107);}.ace-tm .ace_comment.ace_doc {color: rgb(0, 102, 255);}.ace-tm .ace_comment.ace_doc.ace_tag {color: rgb(128, 159, 191);}.ace-tm .ace_constant.ace_numeric {color: rgb(0, 0, 205);}.ace-tm .ace_variable {color: rgb(49, 132, 149);}.ace-tm .ace_xml-pe {color: rgb(104, 104, 91);}.ace-tm .ace_entity.ace_name.ace_function {color: #0000A2;}.ace-tm .ace_heading {color: rgb(12, 7, 255);}.ace-tm .ace_list {color:rgb(185, 6, 144);}.ace-tm .ace_meta.ace_tag {color:rgb(0, 22, 142);}.ace-tm .ace_string.ace_regex {color: rgb(255, 0, 0)}.ace-tm .ace_marker-layer .ace_selection {background: rgb(181, 213, 255);}.ace-tm.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px white;border-radius: 2px;}.ace-tm .ace_marker-layer .ace_step {background: rgb(252, 255, 0);}.ace-tm .ace_marker-layer .ace_stack {background: rgb(164, 229, 101);}.ace-tm .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid rgb(192, 192, 192);}.ace-tm .ace_marker-layer .ace_active-line {background: rgba(0, 0, 0, 0.07);}.ace-tm .ace_gutter-active-line {background-color : #dcdcdc;}.ace-tm .ace_marker-layer .ace_selected-word {background: rgb(250, 250, 255);border: 1px solid rgb(200, 200, 250);}.ace-tm .ace_indent-guide {background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==") right repeat-y;}',e("../lib/dom").importCssString(t.cssText,t.cssClass)}),ace.define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"],function(e,t,n){function u(e,t,n){var r=e.getAnnotations().sort(s.comparePoints);if(r.length){var i=function(e,t,n){for(var r=0,i=e.length-1;r<=i;){var s=r+i>>1,o=n(t,e[s]);if(0=r.length-1?i=0"),p.appendChild(i.createElement("div"));function m(e,t,n){if(0===t&&("esc"===n||"return"===n))return h.destroy(),{command:"null"}}h.destroy=function(){e.$mouseHandler.isMousePressed||(e.keyBinding.removeKeyboardHandler(m),n.widgetManager.removeLineWidget(h),e.off("changeSelection",h.destroy),e.off("changeSession",h.destroy),e.off("mouseup",h.destroy),e.off("change",h.destroy))},e.keyBinding.addKeyboardHandler(m),e.on("changeSelection",h.destroy),e.on("changeSession",h.destroy),e.on("mouseup",h.destroy),e.on("change",h.destroy),e.session.widgetManager.addLineWidget(h),h.el.onmousedown=e.focus.bind(e),e.renderer.scrollCursorIntoView(null,.5,{bottom:h.el.offsetHeight})},i.importCssString(" .error_widget_wrapper { background: inherit; color: inherit; border:none } .error_widget { border-top: solid 2px; border-bottom: solid 2px; margin: 5px 0; padding: 10px 40px; white-space: pre-wrap; } .error_widget.ace_error, .error_widget_arrow.ace_error{ border-color: #ff5a5a } .error_widget.ace_warning, .error_widget_arrow.ace_warning{ border-color: #F1D817 } .error_widget.ace_info, .error_widget_arrow.ace_info{ border-color: #5a5a5a } .error_widget.ace_ok, .error_widget_arrow.ace_ok{ border-color: #5aaa5a } .error_widget_arrow { position: absolute; border: solid 5px; border-top-color: transparent!important; border-right-color: transparent!important; border-left-color: transparent!important; top: -5px; }","")}),ace.define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"],function(e,t,n){function o(e){this.session=e,(this.session.widgetManager=this).session.getRowLength=this.getRowLength,this.session.$getWidgetScreenLength=this.$getWidgetScreenLength,this.updateOnChange=this.updateOnChange.bind(this),this.renderWidgets=this.renderWidgets.bind(this),this.measureWidgets=this.measureWidgets.bind(this),this.session._changedWidgets=[],this.detach=this.detach.bind(this),this.session.on("change",this.updateOnChange)}e("./lib/oop");var i=e("./lib/dom");e("./range").Range;(function(){this.getRowLength=function(e){var t=this.lineWidgets&&this.lineWidgets[e]&&this.lineWidgets[e].rowCount||0;return this.$useWrapMode&&this.$wrapData[e]?this.$wrapData[e].length+1+t:1+t},this.$getWidgetScreenLength=function(){var e=0;return this.lineWidgets.forEach(function(t){t&&t.rowCount&&(e+=t.rowCount)}),e},this.attach=function(e){e.widgetManager&&e.widgetManager!=this&&e.widgetManager.detach(),this.editor!=e&&(this.detach(),this.editor=e,this.editor.on("changeSession",this.detach),e.widgetManager=this,e.setOption("enableLineWidgets",!0),e.renderer.on("beforeRender",this.measureWidgets),e.renderer.on("afterRender",this.renderWidgets))},this.detach=function(n){n&&n.session==this.session||(n=this.editor)&&(n.off("changeSession",this.detach),this.editor=null,n.widgetManager=null,n.renderer.off("beforeRender",this.measureWidgets),n.renderer.off("afterRender",this.renderWidgets),(n=this.session.lineWidgets)&&n.forEach(function(e){e&&e.el&&e.el.parentNode&&(e._inDocument=!1,e.el.parentNode.removeChild(e.el))}))},this.updateOnChange=function(i){var n,u,t=this.session.lineWidgets;t&&(i=(u=(n=i.data).range).start.row,0!=(u=u.end.row-i)&&("removeText"==n.action||"removeLines"==n.action?t.splice(i+1,u).forEach(function(e){e&&this.removeLineWidget(e)},this):((u=new Array(u)).unshift(i,0),t.splice.apply(t,u)),this.$updateRows()))},this.$updateRows=function(){var t,e=this.session.lineWidgets;e&&(t=!0,e.forEach(function(e,n){e&&(t=!1,e.row=n)}),t&&(this.session.lineWidgets=null))},this.addLineWidget=function(e){this.session.lineWidgets||(this.session.lineWidgets=new Array(this.session.getLength())),this.session.lineWidgets[e.row]=e;var t=this.editor.renderer;return e.html&&!e.el&&(e.el=i.createElement("div"),e.el.innerHTML=e.html),e.el&&(i.addCssClass(e.el,"ace_lineWidgetContainer"),e.el.style.position="absolute",e.el.style.zIndex=5,t.container.appendChild(e.el),e._inDocument=!0),e.coverGutter||(e.el.style.zIndex=3),e.pixelHeight||(e.pixelHeight=e.el.offsetHeight),null==e.rowCount&&(e.rowCount=e.pixelHeight/t.layerConfig.lineHeight),this.session._emit("changeFold",{data:{start:{row:e.row}}}),this.$updateRows(),this.renderWidgets(null,t),e},this.removeLineWidget=function(e){if(e._inDocument=!1,e.el&&e.el.parentNode&&e.el.parentNode.removeChild(e.el),e.editor&&e.editor.destroy)try{e.editor.destroy()}catch(t){}this.session.lineWidgets&&(this.session.lineWidgets[e.row]=void 0),this.session._emit("changeFold",{data:{start:{row:e.row}}}),this.$updateRows()},this.onWidgetChanged=function(e){this.session._changedWidgets.push(e),this.editor&&this.editor.renderer.updateFull()},this.measureWidgets=function(e,t){var n=this.session._changedWidgets,r=t.layerConfig;if(n&&n.length){for(var i=1/0,s=0;s|=>|\\||\\:\\:|[\\-]{3,})" }, { token: "keyword.operator", regex: "<\\:|\\-\\:|ø|@|#|\\+|\\||\\*|\\$|\\-|\\%|\\/|\\.\\.|\\^|~|=|<|>|\\\\|(?/, next: "start" }, { defaultToken: "string.tag" }], comment: [{ token: "comment", regex: /}/, next: "start" }, { defaultToken: "comment" }] } }; oop.inherits(GrafitoHighlightRules, TextHighlightRules), exports.GrafitoHighlightRules = GrafitoHighlightRules }), ace.define("ace/mode/folding/cstyle", ["require", "exports", "module", "ace/lib/oop", "ace/range", "ace/mode/folding/fold_mode"], function(BaseFoldMode, FoldMode, module) { "use strict"; var oop = BaseFoldMode("../../lib/oop"), Range = BaseFoldMode("../../range").Range, BaseFoldMode = BaseFoldMode("./fold_mode").FoldMode, FoldMode = FoldMode.FoldMode = function(commentRegex) { commentRegex && (this.foldingStartMarker = new RegExp(this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start)), this.foldingStopMarker = new RegExp(this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end))) }; oop.inherits(FoldMode, BaseFoldMode), function() { this.foldingStartMarker = /([\{\[\(])[^\}\]\)]*$|^\s*(\/\*)/, this.foldingStopMarker = /^[^\[\{\(]*([\}\]\)])|^[\s\*]*(\*\/)/, this.singleLineBlockCommentRe = /^\s*(\/\*).*\*\/\s*$/, this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/, this.startRegionRe = /^\s*(\/\*|\/\/)#?region\b/, this._getFoldWidgetBase = this.getFoldWidget, this.getFoldWidget = function(session, foldStyle, fw) { var line = session.getLine(fw); if (this.singleLineBlockCommentRe.test(line) && !this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) return ""; fw = this._getFoldWidgetBase(session, foldStyle, fw); return !fw && this.startRegionRe.test(line) ? "start" : fw }, this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { var line = session.getLine(row); if (this.startRegionRe.test(line)) return this.getCommentRegionBlock(session, line, row); var match = line.match(this.foldingStartMarker); if (match) { var i = match.index; if (match[1]) return this.openingBracketBlock(session, match[1], row, i); var range = session.getCommentFoldRange(row, i + match[0].length, 1); return range && !range.isMultiLine() && (forceMultiline ? range = this.getSectionRange(session, row) : "all" != foldStyle && (range = null)), range } if ("markbegin" !== foldStyle && (match = line.match(this.foldingStopMarker))) { i = match.index + match[0].length; return match[1] ? this.closingBracketBlock(session, match[1], row, i) : session.getCommentFoldRange(row, i, -1) } }, this.getSectionRange = function(session, row) { for (var startIndent = (line = session.getLine(row)).search(/\S/), startRow = row, startColumn = line.length, endRow = row += 1, maxRow = session.getLength(); ++row < maxRow;) { var line, indent = (line = session.getLine(row)).search(/\S/); if (-1 !== indent) { if (indent < startIndent) break; var subRange = this.getFoldWidgetRange(session, "all", row); if (subRange) { if (subRange.start.row <= startRow) break; if (subRange.isMultiLine()) row = subRange.end.row; else if (startIndent == indent) break } endRow = row } } return new Range(startRow, startColumn, endRow, session.getLine(endRow).length) }, this.getCommentRegionBlock = function(session, line, row) { for (var startColumn = line.search(/\s*$/), maxRow = session.getLength(), startRow = row, re = /^\s*(?:\/\*|\/\/|--)#?(end)?region\b/, depth = 1; ++row < maxRow;) { line = session.getLine(row); var m = re.exec(line); if (m && (m[1] ? depth-- : depth++, !depth)) break } if (startRow < row) return new Range(startRow, startColumn, row, line.length) } }.call(FoldMode.prototype) }), ace.define("ace/mode/matching_brace_outdent", ["require", "exports", "module", "ace/range"], function(MatchingBraceOutdent, exports, module) { "use strict"; var Range = MatchingBraceOutdent("../range").Range, MatchingBraceOutdent = function() {}; ! function() { this.checkOutdent = function(line, input) { return !!/^\s+$/.test(line) && /^\s*\}/.test(input) }, this.autoOutdent = function(doc, row) { var indent = doc.getLine(row).match(/^(\s*\})/); if (!indent) return 0; var column = indent[1].length, indent = doc.findMatchingBracket({ row: row, column: column }); if (!indent || indent.row == row) return 0; indent = this.$getIndent(doc.getLine(indent.row)); doc.replace(new Range(row, 0, row, column - 1), indent) }, this.$getIndent = function(line) { return line.match(/^\s*/)[0] } }.call(MatchingBraceOutdent.prototype), exports.MatchingBraceOutdent = MatchingBraceOutdent }), ace.define("ace/mode/grafito", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text", "ace/mode/grafito_highlight_rules", "ace/mode/folding/cstyle", "ace/mode/matching_brace_outdent", "ace/range"], function(Mode, exports, module) { "use strict"; var oop = Mode("../lib/oop"), TextMode = Mode("./text").Mode, GrafitoHighlightRules = Mode("./grafito_highlight_rules").GrafitoHighlightRules, GrafitoFoldMode = Mode("./folding/cstyle").FoldMode, MatchingBraceOutdent = Mode("./matching_brace_outdent").MatchingBraceOutdent, Mode = (Mode("../range").Range, function() { this.HighlightRules = GrafitoHighlightRules, this.foldingRules = new GrafitoFoldMode, this.$outdent = new MatchingBraceOutdent, this.$behaviour = this.$defaultBehaviour }); oop.inherits(Mode, TextMode), function() { this.lineCommentStart = ";", this.blockComment = { start: "comment {", end: "}" }, this.getNextLineIndent = function(state, line, tab) { var match, indent = this.$getIndent(line), endState = this.getTokenizer().getLineTokens(line, state), tokens = endState.tokens, endState = endState.state; if (tokens.length && "comment" == tokens[tokens.length - 1].type) return indent; if ("start" == state)(match = line.match(/^.*[\{\[\(]\s*$/)) && (indent += tab); else if ("doc-start" == state) { if ("start" == endState) return ""; (match = line.match(/^\s*(\/?)\*/)) && (match[1] && (indent += " "), indent += "* ") } return indent }, this.checkOutdent = function(state, line, input) { return this.$outdent.checkOutdent(line, input) }, this.autoOutdent = function(state, doc, row) { this.$outdent.autoOutdent(doc, row) }, this.$id = "ace/mode/grafito" }.call(Mode.prototype), exports.Mode = Mode }), ace.require(["ace/mode/grafito"], function(m) { "object" == typeof module && "object" == typeof exports && module && (module.exports = m) }); ================================================ FILE: ui/scripts/ace/themes/monokai.js ================================================ ace.define("ace/theme/monokai", ["require", "exports", "module", "ace/lib/dom"], function(e, t, n) { t.isDark = !0, t.cssClass = "ace-monokai", t.cssText = ` .ace-monokai .ace_gutter {background: #2F3129;color: #8F908A} .ace-monokai .ace_print-margin {width: 1px;background: #555651} .ace-monokai {background-color: #272822;color: #F8F8F2} .ace-monokai .ace_cursor {color: #F8F8F0} .ace-monokai .ace_marker-layer .ace_selection {background: #49483E} .ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;border-radius: 2px} .ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)} .ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E} .ace-monokai .ace_marker-layer .ace_active-line {background: #202020} .ace-monokai .ace_gutter-active-line {background-color: #272727} .ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E} .ace-monokai .ace_invisible {color: #52524d} .ace-monokai .ace_entity.ace_name.ace_tag, .ace-monokai .ace_keyword, .ace-monokai .ace_meta.ace_tag, .ace-monokai .ace_storage {color: #F92672} .ace-monokai .ace_punctuation, .ace-monokai .ace_punctuation.ace_tag {color: #fff} .ace-monokai .ace_constant.ace_character, .ace-monokai .ace_constant.ace_language, .ace-monokai .ace_constant.ace_numeric, .ace-monokai .ace_constant.ace_other {color: #AE81FF} .ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672} .ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF} .ace-monokai .ace_support.ace_constant, .ace-monokai .ace_support.ace_function {color: #66D9EF} .ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2} .ace-monokai .ace_storage.ace_type, .ace-monokai .ace_support.ace_class, .ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF} .ace-monokai .ace_entity.ace_name.ace_function, .ace-monokai .ace_entity.ace_other, .ace-monokai .ace_entity.ace_other.ace_attribute-name, .ace-monokai .ace_variable {color: #A6E22E} .ace-monokai .ace_helper {color: #FD971F} .ace-monokai .ace_variable.ace_parameter {color: #FD971F} .ace-monokai .ace_string {color: #E6DB74} .ace-monokai .ace_comment {color: #75715E} .ace-monokai .bold {font-weight: bold} .ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}`, e("../lib/dom").importCssString(t.cssText, t.cssClass) }); ================================================ FILE: ui/scripts/app.js ================================================ const toastSuccess = (msg)=>{ iziToast.success({title: 'OK', message: msg})}; const toastWarning = (msg)=>{ iziToast.warning({title: 'Hmm', message: msg})}; const toastError = (msg)=>{ iziToast.error({title: 'Ooops', message: msg})}; const toastInfo = (msg)=>{ iziToast.info({title: '', message: msg})}; const Grafito = { data() { return { performInitialSetup: false, config: { versions: {}, general: { darkTheme: {value: false, description: "Enable dark theme"}, askForConfirmation: {value: true, description: "Always request confirmation before deleting elements"} }, engine: { caseSensitive: {value: false, description: "Queries should be case-sensitive"} }, graphView: { showNodesOnDrag: {value: true, description: "Keep showing nodes when dragging"}, showEdgesOnDrag: {value: true, description: "Keep showing edges when dragging"}, showEdgesOnZoom: {value: false, description: "Keep showing edges when zooming"}, showEdgeLabels: {value: true, description: "Show edge labels"}, showDashedEdges: {value: false, description: "Show edges as dashed lines"} }, tableView: { prettifyJson: {value: true, description: "Prettify exported JSON data"} } }, working: false, multilineMode: false, editor: null, graph: { palettes: { active: "", list: [] }, dataset: {}, dataview: { nodes: [], edges: [] }, hovered: { node: null, edge: null }, linkMode: false, linker: { source: 0, target: 0 }, editOptions: { main: { visualization: [ {icon: "funnel-bold", tip: "Filter visible elements", action: this.showFilterDialog}, {icon: "arrows-clockwise-bold", tip: "Refresh view", action: this.refreshGraph} ], database: [ {icon: "plus-bold", tip: "Add new node", effect: "modifying", action: this.showAddNodeDialog}, {icon: "palette-bold", tip: "Color palette", effect: "modifying", action: this.showPaletteDialog} ] }, node: { visualization: [ {icon: "arrows-out-fill", tip: "Expand neighboring nodes", action: this.expandNodeNeighbors}, {icon: "eye-slash-bold", tip: "Hide node from graph view", action: this.removeNode} ], database: [ {icon: "pencil-fill", tip: "Edit selected node", effect: "modifying", action: this.showEditNodeDialog}, {icon: "link-bold", tip: "Link selected node", effect: "modifying", action: this.linkNodeMode}, {icon: "trash-fill", tip: "Delete selected node", effect: "destructive", action: this.deleteNode} ] }, nodes: { visualization: [ {icon: "arrows-out-fill", tip: "Expand neighboring nodes", action: this.expandNodeNeighbors}, {icon: "eye-slash-bold", tip: "Hide nodes from graph view", action: this.removeNode} ], database: [ {icon: "trash-fill", tip: "Delete selected nodes", effect: "destructive", action: this.deleteNode} ] }, edge: { visualization: [ {icon: "eye-slash-bold", tip: "Hide edge from graph view", action: this.removeEdge} ], database: [ {icon: "pencil-fill", tip: "Edit selected edge", effect: "modifying", action: this.showEditEdgeDialog}, {icon: "trash-fill", tip: "Delete selected edge", effect: "destructive", action: this.deleteEdge} ] }, edges: { visualization: [ {icon: "eye-slash-bold", tip: "Hide edges from graph view", action: this.removeEdge} ], database: [ {icon: "trash-fill", tip: "Delete selected edges", effect: "destructive", action: this.deleteEdge} ] }, all: { visualization: [ {icon: "eye-slash-bold", tip: "Hide elements from graph view", action: this.removeElement} ], database: [ {icon: "trash-fill", tip: "Delete selected elements", effect: "destructive", action: this.deleteElement} ] } }, view: {}, filter: { edges: {}, nodes: {} }, selected: { node: [], edge: [] }, data: { nodes: [], edges: [] }, initialized: false, config: { nodes: { shape: "circle", font: { face: "Source Sans Pro", align: "center" }, widthConstraint: 70, borderWidthSelected: 5 }, edges:{ arrows: { to: { enabled: true, scaleFactor: 0.5, type: "arrow" } }, dashes: false, font: { background: '#FFFFFF', face: "Source Sans Pro", size: 12, color: '#343434', strokeColor: '#f5f5f5' }, smooth: { type: 'dynamic' }, length: 3.0 }, interaction: { hover: true, hideEdgesOnZoom: true, hoverConnectedEdges: true, selectConnectedEdges: false, navigationButtons: true, multiselect: true }, layout: { }, manipulation: { enabled: false }, physics: { barnesHut: { springConstant: 0.03, avoidOverlap: 0.2 } } } }, table: { showSearchBuilder: false, datarows: [], keys: [], rows: [] }, history: { queries: [] }, analytics: { disk: { path: "", size: { number: 0, units: "" } }, memory: { number: 0, units: "" }, database: { nodes: 0, edges: 0, degree: 0 } }, command: { focused: false }, sidebar: { hovered: "", active: "graph", items: { "graph": { tip: "Graph View", action: null }, "table": { tip: "Table View", action: null }, "clock-counter-clockwise": { tip: "Query History", action: null }, "database": { tip: "Database Analytics", action: this.getAnalytics }, "sliders": { tip: "Global Settings", action: null } } }, modal: { active: false, title: "Some title", icon: "", mode: null, dropdownShowing: false, selectedPalette: "", accept: { button: "Yes, I accept it", style: "", action: ()=> {console.log("modal action clicked!");} }, fields: {}, tagOptions: [], showAdd: false, addField: "", addFieldType: "String", showAddActive: false, showCancel: true } } }, methods: { getInputTypeForValue(val){ if (typeof val == "boolean") return "text"; if (typeof val == "string") return "text"; return "number"; }, getInputIconForValue(key,val){ if (key == "tag") return "tag-bold"; if (typeof val == "boolean") return "question-bold"; if (typeof val == "string") return "text-aa-bold"; return "hash-bold"; }, processCommand(){ console.log("Grafito:: Processing command..."); this.working = true; let currentQuery = $(".command input").val(); var currentdate = new Date(); var datetime = currentdate.getDate() + "/" + (currentdate.getMonth()+1) + "/" + currentdate.getFullYear() + " @ " + currentdate.getHours() + ":" + currentdate.getMinutes() + ":" + currentdate.getSeconds(); $.post( "/exec", {command: currentQuery}, (data)=>{ if (data!="empty"){ if (data=="error"){ this.history.queries.unshift({ query: currentQuery, time: 0, last: datetime, worked: false }); toastError("Something went wrong. Check your syntax!"); } else { try { dd = JSON.parse(data); this.drawGraph(dd["data"], clean=true, firstDraw=true); this.drawTable(dd["rows"]); let timeTaken = dd["timeTaken"].toFixed(2); this.history.queries.unshift({ query: currentQuery, time: timeTaken, last: datetime, worked: true }); toastSuccess(`Query executed in ${timeTaken} ms`); } catch (e) { this.history.queries.unshift({ query: currentQuery, time: 0, last: datetime, worked: false }); console.log(e); toastError("Something went wrong!"); } } } else { toastSuccess("Query performed"); } this.working = false; }); }, copyQueryToClipboard(queryId){ navigator.clipboard.writeText(this.history.queries[queryId].query).then( ()=>toastInfo('The query has been copied to the clipboard!') ); }, rerunQuery(queryId){ this.sidebar.active = 'graph'; $(".command input").val(this.history.queries[queryId].query); this.processCommand(); }, toggleMultilineMode(){ this.multilineMode = !this.multilineMode; if (this.multilineMode){ this.modal.title = "New query"; this.modal.mode = "query"; this.modal.accept.button = "Execute"; this.modal.accept.action = ()=>{ $(".command input").val(this.editor.getValue().replaceAll(/\n[\s\t]+/g," ")); this.processCommand(); this.multilineMode = false; }; this.modal.accept.style = "is-modifying"; this.modal.showAdd = false; this.modal.showCancel = true; this.modal.icon = "arrow-circle-right"; this.modal.dropdownShowing = false; this.modal.active = true; if (this.editor==null){ setTimeout(()=>{ this.editor = ace.edit("editor"); this.editor.setTheme("ace/theme/monokai"); this.editor.session.setMode("ace/mode/grafito", ()=>{ }); }, 500); } } else { this.modal.active = false; } }, expandNodeNeighbors(nodeId=null){ let list = [nodeId]; if (nodeId==null) list = this.graph.selected.node.map((x)=> x.id); for (let node of list) $.post("/nodeFromId", {ndid: node }, (data)=>{ let dt = JSON.parse(data); console.log(dt); for (let subnode of dt.nodes){ this.graph.data.nodes.update(subnode); } for (let subedge of dt.edges){ this.graph.data.edges.update(subedge); } // FIX: Something weird going on with // graph.data & graph.dataview synchronization this.resetFilterData(nomatterwhat=false); // this.graph.dataview.nodes.refresh(); // this.graph.dataview.edges.refresh(); }); }, removeNode(nodeId=null){ let list = [nodeId]; if (nodeId==null) list = this.graph.selected.node.map((x)=> x.id); for (let node of list) this.graph.data.nodes.remove(node); this.graph.selected.node = this.graph.selected.node.filter((x)=> !list.includes(x.id)); }, deleteNode(nodeId=null, message="Delete selected node", andThen=null){ let doDelete = ()=>{ let list = [nodeId]; if (nodeId==null) list = this.graph.selected.node.map((x)=> x.id); let nodeCounter = 0 for (let node of list){ $.post("/deleteNode", {ndid: node }, ()=>{ this.removeNode(node); nodeCounter += 1; if (nodeCounter == list.length && andThen != null) andThen(); }); } } if ((this.graph.selected.node.length > 1) && (andThen==null)) message += "s"; if (this.config.general.askForConfirmation.value) this.showConfirmationDialog(message, doDelete); else doDelete(); }, removeEdge(edgeId=null){ let list = [edgeId]; if (edgeId==null) list = this.graph.selected.edge.map((x)=> x.id); for (let edge of list) this.graph.data.edges.remove(edge); this.graph.selected.edge = this.graph.selected.edge.filter((x)=> !list.includes(x.id)); }, deleteEdge(edgeId=null, message="Delete selected edge", showConfirmation=true){ let doDelete = ()=>{ let list = [edgeId]; if (edgeId==null) list = this.graph.selected.edge.map((x)=> x.id); for (let edge of list) $.post("/deleteEdge", {egid: edge }, ()=>{ this.removeEdge(edge); }); } if (this.graph.selected.edge.length > 1) message += "s"; if (this.config.general.askForConfirmation.value && showConfirmation) this.showConfirmationDialog(message, doDelete); else doDelete(); }, removeElement(){ this.removeNode(); this.removeEdge(); }, deleteElement(){ this.deleteNode(null, message="Delete selected elements", andThen=()=>{ this.deleteEdge(null, message="", showConfirmation=false); }); }, linkNodeMode(nodeId=null){ this.graph.linkMode = true; toastInfo("Now, select the target node or click anywhere else to cancel the operation"); }, addEdgeHandler(data, callback){ console.log('add edge', data); if (data.from == data.to) { var r = confirm("Do you want to connect the node to itself?"); if (r === true) { callback(data); } } else { callback(data); } // after each adding you will be back to addEdge mode //this.graph.view.disableEdgeMode(); //network.addEdgeMode(); }, showConfirmationDialog(title, callback, button="Delete", style="is-destructive"){ this.modal.title = title; this.modal.mode = "confirmation"; this.modal.accept.button = button; this.modal.accept.style = style; this.modal.accept.action = callback; this.modal.showAdd = false; this.modal.showCancel = true; this.modal.icon = "trash-fill"; this.modal.active = true; }, showFilterDialog(){ this.modal.title = "Filter elements"; this.modal.mode = "filter"; this.modal.accept.button = "Done" this.modal.accept.style = ""; this.modal.accept.action = ()=>{}; this.modal.showAdd = false; this.modal.showCancel = false; this.modal.icon = "funnel-bold"; this.modal.active = true; }, showAddNodeDialog(){ this.modal.title = "Add node"; this.modal.mode = "edit"; this.modal.accept.button = "Create"; this.modal.accept.action = ()=>{ let nodeTag = this.modal.fields.tag; delete this.modal.fields.tag; let props = this.modal.fields; $.post("/createNode", { newtag: nodeTag, props: JSON.stringify(props) }, (data)=>{ console.log(data); console.log("DONE ;-)");//this.graph.data.nodes.update(node); }); }; this.modal.accept.style = "is-modifying"; this.modal.showAdd = true; this.modal.addField = ""; this.modal.addFieldType = "String"; this.modal.showCancel = true; this.modal.dropdownShowing = false; this.modal.icon = "plus-bold"; this.modal.tagOptions = [...new Set(VM.graph.data.nodes.map((x)=>x.tag))].sort(); this.modal.fields = { tag: this.modal.tagOptions[0] }; this.modal.active = true; }, showPaletteDialog(){ this.modal.title = "Color palette"; this.modal.mode = "palette"; this.modal.accept.button = "Apply"; this.modal.selectedPalette = this.graph.palettes.active; this.modal.accept.action = ()=>{ console.log("Applying palette:", this.modal.selectedPalette); this.graph.palettes.active = this.modal.selectedPalette; $.post("/changePalette", { newpalette: this.graph.palettes.active, ndids: this.graph.data.nodes.map((x)=>x.id).join(",") }, (data)=>{ let dt = JSON.parse(data); for (let subnode of dt.nodes){ this.graph.data.nodes.update(subnode); } }); }; this.modal.accept.style = "is-modifying"; this.modal.showAdd = false; this.modal.showCancel = true; this.modal.dropdownShowing = false; this.modal.icon = "palette-bold"; this.modal.active = true; }, addNewNodeField(){ if (this.modal.addFieldType=='String') this.modal.fields[this.modal.addField]=''; else if (this.modal.addFieldType=='Number') this.modal.fields[this.modal.addField]=0; else this.modal.fields[this.modal.addField]=false; this.modal.showAddActive=false; this.modal.addField = ''; this.modal.addFieldType = 'String'; }, showEditNodeDialog(){ let nodeId = this.graph.selected.node[0].id; let node = this.graph.data.nodes.get(nodeId); this.modal.title = "Edit node"; this.modal.mode = "edit"; this.modal.accept.button = "Save"; // TODO(edit node) Fields appearing empty after closing modal // mainly the Name field; weird... // labels: bug, ui this.modal.accept.action = ()=>{ node.tag = this.modal.fields.tag; delete this.modal.fields.tag; node.properties = this.modal.fields; $.post("/updateNode", { ndid: nodeId, newtag: node.tag, props: JSON.stringify(node.properties) }, ()=>{ this.graph.data.nodes.update(node); }); }; this.modal.accept.style = "is-modifying"; this.modal.showAdd = true; this.modal.addField = ""; this.modal.addFieldType = "String"; this.modal.showCancel = true; this.modal.dropdownShowing = false; this.modal.icon = "pencil-fill"; this.modal.tagOptions = [...new Set(VM.graph.data.nodes.map((x)=>x.tag))].sort(); this.modal.fields = Object.assign({ tag: node.tag, }, node.properties); this.modal.active = true; }, showAddEdgeDialog(){ this.modal.title = "Link selected node"; this.modal.mode = "edit"; this.modal.accept.button = "Create"; this.modal.accept.action = ()=>{ $.post("/linkNodes", { newtag: this.modal.fields.tag, src: this.graph.linker.source, tgt: this.graph.linker.target }, ()=>{ // this.graph.data.edges.update(edge); }); }; this.modal.accept.style = "is-modifying"; this.modal.showAdd = false; this.modal.showCancel = true; this.modal.dropdownShowing = false; this.modal.icon = "pencil-fill"; this.modal.tagOptions = [...new Set(VM.graph.data.edges.map((x)=>x.label))].sort(); this.modal.fields = { tag: "" } this.modal.active = true; }, showEditEdgeDialog(){ let edgeId = this.graph.selected.edge[0].id; let edge = this.graph.data.edges.get(edgeId); console.log(edge); this.modal.title = "Edit edge"; this.modal.mode = "edit"; this.modal.accept.button = "Save"; this.modal.accept.action = ()=>{ edge.label = this.modal.fields.tag; $.post("/updateEdge", { egid: edge.dbId, newtag: edge.label, }, ()=>{ this.graph.data.edges.update(edge); }); }; this.modal.accept.style = "is-modifying"; this.modal.showAdd = false; this.modal.showCancel = true; this.modal.dropdownShowing = false; this.modal.icon = "pencil-fill"; this.modal.tagOptions = [...new Set(VM.graph.data.edges.map((x)=>x.label))].sort(); this.modal.fields = { tag: edge.label } this.modal.active = true; }, resetFilterData(nomatterwhat=false){ if (nomatterwhat) this.graph.filter.nodes = {}; for (var node of [...new Set(VM.graph.dataset.nodes.map((x) => x.tag))].sort()){ if (nomatterwhat) this.graph.filter.nodes[node] = true; else { if (!(node in this.graph.filter.nodes)) this.graph.filter.nodes[node] = true; } } if (nomatterwhat) this.graph.filter.edges = {}; for (var edge of [...new Set(VM.graph.dataset.edges.map((x) => x.label))].sort()){ if (nomatterwhat) this.graph.filter.edges[edge] = true; else { if (!(edge in this.graph.filter.edges)) this.graph.filter.edges[edge] = true; } } }, getAnalytics(){ $.post("/analytics", {}, (data)=>{ this.analytics = JSON.parse(data); $(".counter-number").counterUp({ delay: 10, time: 1000 }); }); }, drawGraph(dataset, clean=false, firstDraw=false){ // if we're re-drawing the graph, // let's first delete all previous data if (clean && this.graph.initialized){ this.graph.data.nodes.clear(); this.graph.data.edges.clear(); this.graph.view.destroy(); } // store dataset this.graph.dataset = dataset; // set filter data if (clean && firstDraw){ this.resetFilterData(); } // create an array with nodes let nodes = new vis.DataSet(dataset.nodes); // create an array with edges let edges = new vis.DataSet(dataset.edges); // create the graph let container = document.getElementById("graph"); this.graph.data = { nodes: nodes, edges: edges, }; // setup filter for nodes const nodeFilter = (node)=>{ if (typeof this.graph.filter.nodes === 'object') if (node.tag in this.graph.filter.nodes) return this.graph.filter.nodes[node.tag]; else return true; else return this.graph.filter.nodes; } // setup filter for edges const edgeFilter = (edge)=>{ if (typeof this.graph.filter.edges === 'object') if (edge.label in this.graph.filter.edges) return this.graph.filter.edges[edge.label]; else return true; else return this.graph.filter.edges; } this.graph.dataview = { nodes: new vis.DataView(nodes, { filter: nodeFilter }), edges: new vis.DataView(edges, { filter: edgeFilter }) }; this.graph.view = new vis.Network(container, this.graph.dataview, this.graph.config); const updateSelected = (x)=>{ if (this.graph.linkMode && !("previousSelection" in Object.keys(x)) && x.nodes.length ==1){ this.graph.linker.source = this.graph.selected.node[0].id; this.graph.linker.target = x.nodes[0]; this.showAddEdgeDialog(); } this.graph.selected.node = x.nodes.map((e) => this.graph.data.nodes.get(e)); this.graph.selected.edge = x.edges.map((e) => this.graph.data.edges.get(e)); this.graph.linkMode = false; } this.graph.view.on("selectNode", updateSelected); this.graph.view.on("deselectNode", updateSelected); this.graph.view.on("selectEdge", updateSelected); this.graph.view.on("deselectEdge", updateSelected); this.graph.view.on("doubleClick", (x)=>{ this.expandNodeNeighbors(x.nodes[0]); }); this.graph.view.on("hoverNode", (x)=>{ this.graph.hovered.node = nodes.get(x.node); this.graph.hovered.edge = null; }); this.graph.view.on("hoverEdge", (x)=>{ this.graph.hovered.edge = edges.get(x.edge); this.graph.hovered.node = null; }); this.graph.view.on("blurNode", ()=>{ this.graph.hovered.node = null; }); this.graph.view.on("blurEdge", ()=>{ this.graph.hovered.edge = null; }); }, drawTable(rows){ // store datarows this.table.datarows = rows; // get common property keys as table headers var keys = Object.keys(rows[0].properties); for (var row of rows){ keys = keys.filter(value => Object.keys(row.properties).includes(value)); } // add the missing ones for (var row of rows){ for (var prop of Object.keys(row.properties)){ if (!keys.includes(prop)){ keys.push(prop); } } } // let's remove "id" and "tag" // we do want them, but with our own preferred order keys.unshift("id"); keys.unshift("tag"); // set table header this.table.keys = keys; // set table rows this.table.rows = rows.map(row=> Object.assign({ tag: row.tag, id: row.id }, row.properties) ); }, refreshGraph() { this.drawGraph(this.graph.dataset, clean=true); }, updateGraphView() { console.log("Grafito:: updating graph view..."); this.graph.config.interaction.hideNodesOnDrag = !this.config.graphView.showNodesOnDrag.value; this.graph.config.interaction.hideEdgesOnDrag = !this.config.graphView.showEdgesOnDrag.value; this.graph.config.interaction.hideEdgesOnZoom = !this.config.graphView.showEdgesOnZoom.value; this.graph.config.edges.dashes = this.config.graphView.showDashedEdges.value; if (this.config.general.darkTheme.value){ this.graph.config.edges.font.background = '#2A2C33'; this.graph.config.edges.font.color = '#DDDDDD'; this.graph.config.edges.font.strokeColor = '#222222'; } else { this.graph.config.edges.font.background = '#ffffff'; this.graph.config.edges.font.color = '#343434'; this.graph.config.edges.font.strokeColor = '#F5F5F5'; } this.graph.config.edges.font.size = (this.config.graphView.showEdgeLabels.value) ? 12 : 0; this.graph.view.setOptions(this.graph.config); }, updateEngineSettings() { console.log("Grafito:: updating enging settings"); $.post("/updateEngine", { caseSensitive: this.config.engine.caseSensitive.value }, ()=>{ console.log("Grafito:: done") }); } }, mounted(){ console.log("Grafito:: App started"); $.post("/startup", {}, (dd)=>{ let obj = JSON.parse(dd); document.title = `Grafito @ ${obj.title}`; this.drawGraph(obj.data, clean=true, firstDraw=true); this.drawTable(obj.rows); this.config.versions = obj.versions; this.config.helpers = obj.helperEntities; this.performInitialSetup = true; this.config.engine.caseSensitive.value = obj.caseSensitive; this.graph.initialized = true; this.graph.palettes.list = obj.palettes this.graph.palettes.active = obj.activePalette }); // window.onbeforeunload = ()=>{ // $.post( "/exit", {}, ()=>{}); // return true; // }; }, updated(){ if (this.performInitialSetup){ let table = $("#table table").DataTable({ language: { lengthMenu: 'Display results', }, searchBuilder: true, buttons: [ { text: '', action: function ( e, dt, button, config ) { let bl = null; if (VM.config.tableView.prettifyJson.value) bl = JSON.stringify(VM.table.datarows, null, 4); else bl = JSON.stringify(VM.table.datarows); $.fn.dataTable.fileSave( new Blob([bl]), 'Export.json' ); } }, { extend: 'csvHtml5', text: '' }, { extend: 'excelHtml5', text: '' }, { extend: 'pdfHtml5', text: '' } ], dom: "fltip" }); table.buttons().container().appendTo($(".table-info")); table.searchBuilder.container().insertBefore($("table.dataTable")); let tooltips = ["Export as JSON", "Export as CSV spreadsheet", "Export as Excel spreadsheet", "Export as PDF"]; for (let [idx,elem] of $(".dt-button").toArray().entries()){ $(elem).attr({ "data-tippy-content": tooltips[idx], "data-tippy-placement": "top", "data-tippy-theme": "light" }); } $(".dtsb-searchBuilder").addClass("hidden"); let filterButton = $(` `); filterButton.change(()=>{ if ($("#filterSwitch").is(":checked")) $(".dtsb-searchBuilder").removeClass("hidden"); else { $(".dtsb-searchBuilder").addClass("hidden"); } }); filterButton.appendTo($(".dataTables_filter label")); tippy("[data-tippy-content]",{ offset: [0, 20], delay: [500, 0] }); this.performInitialSetup = false; } } } const App = Vue.createApp(Grafito); const VM = App.mount('#app'); ================================================ FILE: ui/styles/app.less ================================================ /**************************************************** Global variables ****************************************************/ // Measurements @mainTop: 50px; @mainPushDown: 89px; @sidebarWidth: 60px; @sidebarBorder: 1px; @infobarHeight: 39px; // Colors @grafitoPurple: #683A8F; @switchableBg: #06842C; @modifyingColor: green; @destructiveColor: #AA0000; @darkFg: #DDDDDD; @darkFgDarker: #BBB; @darkBg: #2A2C33; @darkBgDarker: #222222; @darkGrafitoPurple: mediumvioletred;//lighten(@grafitoPurple, 30%); /**************************************************** Global mixins ****************************************************/ .stretched { width: 100%; height: 100%; margin: 0px; padding: 0px; overflow: hidden; } .noselect { -webkit-touch-callout: none; /* iOS Safari */ -webkit-user-select: none; /* Safari */ -khtml-user-select: none; /* Konqueror HTML */ -moz-user-select: none; /* Old versions of Firefox */ -ms-user-select: none; /* Internet Explorer/Edge */ user-select: none; /* Non-prefixed version, currently supported by Chrome, Edge, Opera and Firefox */ } /**************************************************** Global styles ****************************************************/ * { font-family: 'Source Sans Pro', sans-serif !important; } html, body { margin: 0px; padding: 0px; overflow-x: hidden; overflow-y: hidden; } :focus, input:focus{ outline: none !important; } .switchable { position: relative; width: 1.8em; height: 1.8em; color: black; border: 1px solid gray; border-radius: 4px; appearance: none; outline: 0; cursor: pointer; transition: background 175ms cubic-bezier(0.1, 0.1, 0.25, 1); box-sizing: border-box; transform: scale(0.8); &::before { position: absolute; content: ''; display: block; top: 2px; left: 7px; width: 8px; height: 14px; border-style: solid; border-color: white; border-width: 0 2px 2px 0; transform: rotate(45deg); opacity: 0; box-sizing: border-box; } &:checked { color: white; border-color: @switchableBg; background: @switchableBg; &::before { opacity: 1; } } & + label { cursor: pointer; &.inactive { color: darkgray; } } } .dark .switchable { & + label { color: @darkFg; &.inactive { color: #666; } } } .switchable-wrapper { display: flex; flex-direction: row; label { margin-left: 0.5rem; } } .inline-switchable-container { pointer-events: auto !important; .switchable { border: 1px solid #dbdbdb !important; box-shadow: inset 0 0.0625em 0.125em rgb(10 10 10 / 5%) !important; border-radius: 4px; &:hover { border-color: #b5b5b5 !important; } &::before { border-color: #363636 !important; } &:checked { background: transparent !important; } } } .dark .inline-switchable-container { .switchable { border: 1px solid black !important; &::before { border-color: @darkFg !important; } &:checked { background: @darkBgDarker !important; } } } /**************************************************** Global animations ****************************************************/ @-webkit-keyframes rotating { from { -webkit-transform: rotate(0deg); -o-transform: rotate(0deg); transform: rotate(0deg); } to { -webkit-transform: rotate(360deg); -o-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes rotating { from { -ms-transform: rotate(0deg); -moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -o-transform: rotate(0deg); transform: rotate(0deg); } to { -ms-transform: rotate(360deg); -moz-transform: rotate(360deg); -webkit-transform: rotate(360deg); -o-transform: rotate(360deg); transform: rotate(360deg); } } .rotating { -webkit-animation: rotating 2s linear infinite; -moz-animation: rotating 2s linear infinite; -ms-animation: rotating 2s linear infinite; -o-animation: rotating 2s linear infinite; animation: rotating 2s linear infinite; } .slide-left-enter-active { transition: all 0.3s ease-out; } .slide-left-leave-active { transition: all 0.25s cubic-bezier(1, 0.5, 0.8, 1); } .slide-left-enter-from, .slide-left-leave-to { transform: translateX(50px); opacity: 0; } /**************************************************** Header ****************************************************/ .command { .prompt { position: fixed; left: 15px; top: 7px; font-size: 1.8rem; color: #888; cursor: pointer; } .multiline { position: fixed; right: 140px; top: 13px; font-size: 1rem; color: #888; cursor: pointer; &:hover { color: #666; } } input { left: 20px; top: 0px; right:0px; bottom: 52px; width:100%; font-size: 20px; border-top: 0; font-family: 'Fira Code' !important; border-bottom: 4px solid #AAA; border-left: 0; border-right: 0; padding: 10px; background-image: url('data:image/png;base64,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AAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADFCaUAAAAAAAAoTigFAAAAAABAcUIpAAAAAAAAihNKAQAAAAAAUJxQCgAAAAAAgOKEUgAAAAAAABQnlAIAAAAAAKA4oRQAAAAAAADF/eAWQ3Hna7zFn/06AQAAAACoTq/X+/+2RMjpgGOqHgAAAABJRU5ErkJggg=='); background-size: contain; background-repeat: no-repeat; background-position: calc(100% - 20px) center; padding-left: 65px; padding-right: 185px; color: #888; &:focus { border-bottom: 4px solid @grafitoPurple; outline: none; } &::selection { background: @grafitoPurple !important; color: white !important; } } &.focused { filter: drop-shadow(1px 2px 4px #D5D5D5); .prompt, input { color: black; } } } .dark .command { input { background-color: @darkBg; color: @darkFgDarker; border-color: @darkBgDarker; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABqUAAAMaCAYAAAAP6kykAAAACXBIWXMAAC4jAAAuIwF4pT92AAAgAElEQVR4nOzdT24jx/k//nIQoJfS7wSSeIGZz4pLKUDvRzmB5BNYAQ8w8gEI0ycYzQmi2TcQaclVZi5ASSf4jpZc6Ycelxx6/pISyarqfr2AQRLHdlc3/zS73vU89dPDw0PYhGk1OgshnIcQXg7n49uNHAQAAAAAAIAi/H3dg5xWo6MQwiSE8CL+pfa/H3s7AAAAAAAA9NfaKqWm1Wg/BlCvvvJ//2M4H195nwEAAAAAAPTTsyulptVoN4TQtup7/Z2/7SKEsO89BgAAAAAA0E9/e85ZT6vRaQjh9geBVGsv7jEFAAAAAABADz2pfV/cN+o8hHC4wj9231ZLDefjj95oAAAAAAAA/bJS+764b1QbRp084SrtxH9WxRQAAAAAAEDPLFUptbBv1FkMl57jYDgf33qjAQAAAAAA9McP95SaVqPjEML7uG/UcwOp1oX3FwAAAAAAQL98s1JqWo1ehhAmK+4btax/DufjS+81AAAAAACAfvhiT6nYqm/yxH2jltX++4VSAAAAAAAAPfGX9n3TatTuGXW74UCqtTetRufeZAAAAAAAAP3wqX3ftBodxb2e9rZ41vchhP3hfPzRew0AAAAAAKDb/jatRm0Y9Z8tB1KtndjGDwAAAAAAgI77W6yQSuVkWo1eepMBAAAAAAB029+G8/FVCOE64VmqlgIAAAAAAOi4v8XTO014mofTapTy+AAAAAAAAGzYp1BqOB/fhhB+T3ixz6fVaNeLDQAAAAAA0E1/Wzir8xDCfaKz3AshnHX1IgMAAAAAAPTdn6HUcD7+GIOpVM6m1Wi/7y8IAAAAAABAFy1WSrXB1CSE8CHRee6EECadvMoAAAAAAAA997evnH7KNnqvptXoKOHxAQAAAAAA2IAvQqnhfHwVQniX8GKrlgIAAAAAAOiYr1VKhcTVUi+m1eg04fEBAAAAAABYs6+GUsP5+DaE8GvCiz2ZVqPdhMcHAAAAAABgjb5VKRViG737RBd7J3G1FgAAAAAAAGv008PDwzf/bbGN3puEF/wgVm0BAAAAAABQsO9VSrVt/C5CCNcJT+8i4bEBAAAAAABYk++GUtF5wot9OK1GRwmPDwAAAAAAwBr8MJQazsdXIYS3CS+2aikAAAAAAIDCLVMpFWK11H2iU92bVqOzRMcGAAAAAABgDZYKpYbz8W0IYZLwgp9Pq9FuwuMDAAAAAADwDMtWSoUYSt0lutg7ife2AgAAAAAA4Bl+enh4WPqfnlaj4xDCvxNe8P8bzsfvEx4fAAAAAACAJ1ilUqpt43cZQrhOeKFTthAEAAAAAADgiVYKpaKzhBf7MFZrAQAAAAAAUJCVQ6nYPu9twlNULQUAAAAAAFCYp1RKhVgtdZ/oVPem1eg80bEBAAAAAAB4gieFUsP5+GMIIWUwdDatRvsJjw8AAAAAAMAKnlop1QZTbRu9u0QXeydxKAYAAAAAAMAKnhxKRacJL/bJtBodJTw+AAAAAAAAS3pWKDWcj69CCNcJL7ZqKQAAAAAAgAI8t1IqJK6WOpxWo5THBwAAAAAAYAnPDqWG8/FtCOH3hBf7fFqNdhMeHwAAAAAAgB9YR6VUiG307hNd7L0QwlmiYwMAAAAAALCEnx4eHtZynWIbvTcJL/pBrNoCAAAAAAAgM+uqlGrb+F2EED4kPL1JwmMDAAAAAADwHWsLpaKUbfReTavRUcLjAwAAAAAA8A1rDaWG8/FVCOFdwoutWgoAAAAAACBD666UComrpV7Eva0AAAAAAADIyNpDqeF8fBtC+DXhKU6m1Wg34fEBAAAAAAD4zCYqpUJso3eX6GLvhBDOEx0bAAAAAACAr/jp4eFhI9clttF7k/CiH8SqLQAAAAAAABLbVKVU28bvIoRwnfD0LhIeGwAAAAAAgAUbC6WilG30DqfV6Cjh8QEAAAAAAIg2GkoN5+OrEMLbhBdbtRQAAAAAAEAGNl0pFWK11H2iU92bVqOzRMcGAAAAAAAg2ngoNZyPb0MIk4QX/HxajXYTHh8AAAAAAKD3tlEp1QZTbbXUXaKLvZM4FAMAAAAAAOi9rYRSUco2eifTavQy4fEBAAAAAAB6bWuh1HA+vgwhXCe82KqlAAAAAAAAEtlmpVRIXC11OK1GxwmPDwAAAAAA0FtbDaWG8/H7EMLvCS/2ZFqNdhMeHwAAAAAAoJe2XSnVOg8h3Ce62HuJq7UAAAAAAAB6aeuh1HA+/hiDqVTOptVo39sdAAAAAABge1JUSrXB1CSEcJfodd5JHIoBAAAAAAD0TpJQKjpNeOyTaTU6Snh8AAAAAACAXkkWSg3n46sQwnXCi61aCgAAAAAAYEtSVkqFxNVSh9NqlPL4AAAAAAAAvZE0lBrOx7chhF8TDmEyrUa7CY8PAAAAAADQC6krpVqTEMJ9omPvhBDOEh0bAAAAAACgN356eHhIfq6xjd6bhEM4iFVbAAAAAAAAbEAOlVJtG7+LEMKHhEOYJDw2AAAAAABA52URSkUp2+i9mlajo4THBwAAAAAA6LRsQqnhfHwVQniXcAiqpQAAAAAAADYkp0qpEKul7hMd+8W0GqWs1gIAAAAAAOisrEKp4Xx8m7hi6XxajXYTHh8AAAAAAKCTcquUCjGUukt07J02mEp0bAAAAAAAgM766eHhIbtzm1aj0xDCm4RDOIhVWwAAAAAAAKxBjpVSbRu/ixDCdcIhXCQ8NgAAAAAAQOdkGUpFZwmPfTitRkcJjw8AAAAAANAp2YZSw/n4fQjhbcIhqJYCAAAAAABYk5wrpUKslrpPdOy9aTU6T3RsAAAAAACATsk6lBrOxx9DCJOEQzibVqPdhMcHAAAAAADohNwrpdpgqq1Wukt0+J3EoRgAAAAAAEAnZB9KRWcJj30yrUYvEx4fAAAAAACgeEWEUsP5+DKEcJ1wCKqlAAAAAAAAnqGUSqnWacJjH06rUcrjAwAAAAAAFK2YUGo4H9+GEH5POITzaTXaTXh8AAAAAACAYpVUKdU6DyHcJzr2XuK9rQAAAAAAAIpVVCg1nI8/xmAqlbNpNdpPexUAAAAAAADKU1qlVBtMTUIId4kOv5M4FAMAAAAAAChScaFUdJrw2CfTanSU8PgAAAAAAADFKTKUGs7HVyGEdwmHMEl4bAAAAAAAgOKUWinVOkt47BfTapSyWgsAAAAAAKAoxYZSw/n4NoTwa8IhTKbVaDfh8QEAAAAAAIpRcqVUiG307hMdeydxtRYAAAAAAEAxfnp4eCj61Ypt9N4kHMJBrNoCAAAAAADgG0qvlGrb+F2EED4kHMIk4bEBAAAAAACKUHwoFaVso/dqWo2OEh4fAAAAAAAge50IpYbz8VUI4W3CIVwkPDYAAAAAAED2ulIp1ToPIdwnOvbetBqlrNYCAAAAAADIWmdCqeF8fJt4f6fzaTXaTXh8AAAAAACAbHWpUirEUOou0bF3YrUWAAAAAAAAn/np4eGhU9dkWo2OQwj/TjiE/xvOx+8THh8AAAAAACA7XauUatv4XYYQrhMOIWULQQAAAAAAgCx1LpSKzhIe+zBWawEAAAAAABB1MpSK7fPeJhyCaikAAAAAAIAFXa2UCrFa6j7Rsfem1eg80bEBAAAAAACy09lQajgff0xcsXQ2rUa7CY8PAAAAAACQjS5XSrXBVFutdJfo8Dva+AEAAAAAAPyh06FUdJrw2CfTanSU8PgAAAAAAABZ6HwoNZyPr0II1wmHYG8pAAAAAACg9/pQKRUSV0sdTqtRyuMDAAAAAAAk14tQajgf34YQfk84hPNpNdpNeHwAAAAAAICk+lIpFWIbvftEx94LIZwlOjYAAAAAAEByvQmlhvPxx8T7O51Nq9F+wuMDAAAAAAAk06dKqTaYmoQQPiQ6/E4IYZLo2AAAAAAAAEn1KpSKUrbRezWtRkcJjw8AAAAAAJBE70Kp4Xx8FUJ4l3AIqqUAAAAAAIDe6WOlVEhcLfViWo1OEx4fAAAAAABg63oZSg3n49sQwq8JhzCZVqPdhMcHAAAAAADYqr5WSoXYRu8+0bF3EldrAQAAAAAAbNVPDw8Pvb3isY3em4RDOIhVWwAAAAAAAJ3W50qpto3fRQjhOuEQLhIeGwAAAAAAYGt6HUpF5wmPfTitRkcJjw8AAAAAALAVvQ+lhvPxVQjhbcIhqJYCAAAAAAA6r/ehVNRWS90nOvbetBqdJTo2AAAAAADAVgil/qiWug0hTBIO4XxajXYTHh8AAAAAAGCjhFLRcD5uq6XuEh1+J3EoBgAAAAAAsFFCqb9K2UbvZFqNXiY8PgAAAAAAwMYIpRYM5+PLEMJ1wiGolgIAAAAAADpJKPWllNVSh9NqdJzw+AAAAAAAABshlPrMcD5+H0J4m3AIqqUAAAAAAIDOEUp9XVstdZ/o2HvTanSe6NgAAAAAAAAbIZT6iuF8/DGEkDIYOptWo/2ExwcAAAAAAFgrodQ3DOfjto3eXaLD7yQOxQAAAAAAANZKKPV9pwmPfTKtRkcJjw8AAAAAALA2QqnvGM7HVyGE64RDUC0FAAAAAAB0glDqx1JWSx1Oq1HK4wMAAAAAAKyFUOoHhvPxbQjh94RDOJ9Wo92ExwcAAAAAAHg2odRy2jZ694mOvRdCOEt0bAAAAAAAgLX46eHhwZVcQmyj9ybhEA5i1RYAAAAAAEBxVEotaTgfX4QQPiQcwiThsQEAAAAAAJ5FKLWalG30Xk2r0VHC4wMAAAAAADyZUGoFw/n4KoTwLuEQVEsBAAAAAABFEkqtLmW11Iu4txUAAAAAAEBRhFIrGs7HtyGEXxMOYTKtRrsJjw8AAAAAALAyodTTtG307hIdeyeEcJ7o2AAAAAAAAE/y08PDgyv3BLGN3puEQziIVVsAAAAAAADZUyn1RMP5+CKEcJ1wCBcJjw0AAAAAALASodTzpGyjdzitRkcJjw8AAAAAALA0odQzDOfjqxDC24RDUC0FAAAAAAAUQSj1fGchhPtEx96bVqOU1VoAAAAAAABLEUo903A+/hhCmCQcwtm0Gu0mPD4AAAAAAMAPCaXWYDgft9VKd4kOv5M4FAMAAAAAAPghodT6nCU89sm0Gr1MeHwAAAAAAIDvEkqtyXA+vgwhXCccgmopAAAAAAAgW0Kp9UpZLXU4rUbHCY8PAAAAAADwTUKpNRrOx+9DCL8nHMJkWo12Ex4fAAAAAADgq4RS63ceQrhPdOy9xNVaAAAAAAAAXyWUWrPhfPwxBlOpnE2r0X5XricAAAAAANANQqkNGM7HkxDCXaLD7yQOxQAAAAAAAL4glNqc04THPplWo6OExwcAAAAAAPgLodSGDOfjqxDCdcIhqJYCAAAAAACyIZTarJTVUofTapTy+AAAAAAAAH8SSm3QcD6+DSH8mnAIk2k12k14fAAAAAAAgE+EUps3CSHcJzr2TgjhLNGxAQAAAAAA/vTTw8ODq7FhsY3em4RDOIhVWwAAAAAAAEmolNqC4Xx8EUL4kHAIk4THBgAAAAAAEEptUco2eq+m1ego4fEBAAAAAICeE0ptyXA+vgohvE04hIuExwYAAAAAAHpOKLVd5yGE+0TH3ptWo5TVWgAAAAAAQI8JpbZoOB/fJt7f6XxajXYTHh8AAAAAAOgpodT2taHUXaJj78RqLQAAAAAAgK366eHhwRXfsmk1Og0hvEk4hINYtQUAAAAAALAVKqUSGM7HFyGE64RDuEh4bAAAAAAAoIeEUumcJTz24bQaHae+AAAAAAAAQH8IpRIZzsfvQwhvEw5hkvQCAAAAAAAAvSKUSqutlrpPNIK9aTU6z+VCAAAAAAAA3SaUSmg4H39MXLF0Nq1Gu8kvBAAAAAAA0HlCqcSG83FbrXSXaBQ72vgBAAAAAADbIJTKw1nCUZxMq9HLnC4GAAAAAADQPUKpDAzn48sQwnXCkaiWAgAAAAAANkoolY/ThCM5nFajlMcHAAAAAAA6TiiVieF8fBtC+D3haM6n1Wg3q4sCAAAAAAB0hlAqL+chhPtEI9pLvLcVAAAAAADQYUKpjAzn448xmErlbFqN9vv+OgAAAAAAAOsnlMrMcD6ehBDuEo1qJ3EoBgAAAAAAdJRQKk+nCUd1Mq1GRzlfHAAAAAAAoDxCqQwN5+OrEMK7hCObZHtxAAAAAACAIgml8nWWcGQvptUoZbUWAAAAAADQMUKpTA3n49sQwq8JRzeZVqPdrC8SAAAAAABQDKFU3to2eveJRriTuFoLAAAAAADokJ8eHh68nhmLbfTeJBzhQazaAgAAAAAAeDKVUpkbzscXIYTrhKO8KOJCAQAAAAAAWRNKleE84SgPp9XoqKSLBQAAAAAA5EcoVYDhfHwVQnibcKSqpQAAAAAAgGcRSpWjrZa6TzTavWk1OivxogEAAAAAAHkQShViOB/fhhAmCUd7Pq1Gu0VdNAAAAAAAIBtCqbK0odRdohHvJN7bCgAAAAAAKNhPDw8PXr+CTKvRcQjh3wlH/H/D+fh9cRcOAAAAAABISqVUYYbz8WUI4TrhqFO2EAQAAAAAAAollCrTWcJRH8ZqLQAAAAAAgKUJpQoU2+e9TThy1VIAAAAAAMBKhFLlaqul7hONfm9ajc67cBEBAAAAAIDtEEoVajgff0xcsXQ2rUa7RV9EAAAAAABga4RSBRvOx2210l2iM9jRxg8AAAAAAFiWUKp8pwnP4GRajY66ciEBAErUNI3fYwAAABRBKFW44Xx8FUK4TngW9pYCAEgkBlKXTdNoqwwAAED2hFLdkLJa6nBajVIeHwCgz85jW+Vj7wIAAAByJ5TqgOF8fBtC+D3hmZxPq5HVuQAAWxSrpA7jEVWvAwAAkD2hVHe0ExH3ic5mL4Rw1sWLCgCQscVq9b2maVSvAwAAkDWhVEcM5+OPiVfIvp5Wo/1OXVQAgEw1TdP+7jr5bHRCKQAAALImlOqQ4Xw8CSF8SHhGk85dVACAPH1tMdJhbOkHAAAAWRJKdU/KNnqvptXIRAgAwAZ9o0rqkWopAAAAsiWU6pjhfHwVQniX8KxUSwEAbNb3gqeTGFoBAABAdoRS3ZSyWurFtBpZoQsAsAFN0+wu8Vsv5W9BAAAA+CahVAcN5+PbEMKvCc9sMq1Gu529wAAA6bSB084Pjn4awysAAADIilCqu9o2eneJzm7nG5tvAwDwPMtUpO+olgIAACBHPz08PHhhOiq20XuT8OwOYtUWTzS7mR0989p9HBwM3rv+AFC+pmlW+W13V9e1vaUAAKAnZjeztlvCy2+crTlCsiGU6rhpNboKIRwmOsvr4Xz83FClU2Y3s/bG0N4g9uOf1uI12vRrdR9CeLwB3cY/rfZ9EgYHg6vuXn0AKFvTNO19e2+Fk/i5rusLLzsAAJRhdjP72pzh52HTyyVaeq/ieuHvXZwvbOcQPwq0WDehVMdNq1H75fWfhGf5j+F83KugY+HmcbQQPq37ZrFp1ws3ofamc+vmAwDprFgl9ehDXdffWikJAAAksLBo/WghcNpfcQFaCo+L3c0Z8ixCqR6YVqN2hexJojO9G87HnW0dE28iRwvBU6qqtG25XrjpXLnpAMB2NE3z1Or3f9R1rRIaAAC2bKGd3uKfFx19HT4szhm2/zk4GHzMYFxkSCjVA9NqtB+/EFJV6vxrOB9PSr/S8UZyFP/0IYBa1vXCDefKDQcA1qtpmudUvl/Xda2dMgAAbNjC4vXHEKqrAdSy7h4DKovbWSSU6olpNToPIbxOdLZtaef+cD4uKqz4LIQ6ciNZ2oeFgOqykDEDQLaeUSX16KCu69vl/lYAAGAZCyHU45+Stu5I4f5xzlBI1W9CqR6ZVqNVN8dep7fD+fg096sdbybH8Y8Qaj3exZvN5eBgYEKMH2qapv0cFl9d+QRfa6+1+NduTSpD/8TvxP8+88Tf1nWd/e8wuq3H93ee56yu62InrAp737+v6/osg3F8IS7OgFJk+1ni+eIC9uOFECr3PaBy91hJdan7Ur/8ve8XoGfam+K/E53yybQaTYbzcXYPFLOb2fHCDcXNZP1exT+/zW5mH+KN5tJqCL5jt6ftMb92zn+pcG2a5vG/3sVezSGWwX9c2GhUeAXdso5JjZOmadqJXQ95pNTX+zvPs1v49fO+Xw/XEEhmdjPbX1jA7vtovdp52JP4p73W7xbmDT27dJhQqkeG8/HltBpdJ/wCncTgJ7mFIOpYae1WvYh/Xs9uZnfxRjNRQQUr21sI0b/4To/h1YcYVl3F/3wfV+35YQeFaJpm//EBbQ3acOvcaw8AAN+3EESd6qS0VY8L298IqLpNKNU/Z2toAfNUh9NqdNyGYykOHlvzncabioqo9NrX4Jf2T6ygumj/uNHA2jz+cP5LaNU0zf3jJqMLQZVgGPK0zhDprGmaiWAaAAC+tNCa70wQlYUvAqrBweCi7xelK4RSPdO2z5tWo7drXHW7quOYcm+FG0ox2tfmt9ji72280SQJL6EHdmJQ9WdY9VlQdVXXtb79kFjTNLtr/r22E38TeZADAIBooZtSqrlSfuxTQDW7mU0WFrXbFqRgQql+OkvQtq5t1XY6nI+3MtEZq6JSnCfP96mXbGzvN1E9BVuxGFS9ju3/roVUkNQmNsg+F0oBANB3sT3fafyjm1I5dha6Ll3HOUPPNwUSSvXQcD7+OK1G57EyZdPa1ffnw/l4so0rPbuZPd5QbDxYvr3PqqcmVkHAVi2GVPcxoPrUz1n7L9isWCW1iVBqr2ma47quVSMDANA7s5vZUZw3VBVVvk9zFrF6ahLnDc1VFOJvfb8AfRVDorsNn34bJOxvOpBqW/TNbmbns5tZuyfKG4FUJ7U/Fv47u5ldxR8QwHbtPPZyDiH8v6Zp3jdN0+5Ps+91gI043WCl9ybCLgAAyFa7iL2dUwoh/Ecg1Tntc9Prdq5idjO7iFVwZE4o1W+nGzr7tnzy/4bzcduub2MJ9WMYFUK4jV8+ym27rw0c/zO7mb2PPX+BNB73gbtpmuaqaZrTWNkBrMcmg6PDpmleep0AAOi6GEZZxN4fbeB4M7uZXVrUnjehVI/F/Z2u13gF2sqrfw7n46PhfLyxNmtfCaPsGdU/7YT4v1VOQRYO4w/826ZpLpqm8ZmEZ2hD3i0stFEtBQBAJ8V5w8UwyiL2/nkVF7WbN8yUUIp1VEu1e438GkJ4OZyPN7ZHgTCKrzh0k4Fs7MRVSf+J7f02VY0LXXe+hfM70X4TAICuiXvNvxdGES3OG+oWkRGhVM8N5+M24Pn9GVfhbQyjzjfVqk8YxRIebzJ6x0Ie2mrGN03TfGya5lxrP1hO0zTHW3x4Vi0FAEAnqIziBw7jXvXmDTMhlCLEFbn3K16Jtu3fP+K+UbebuooLKxyEUSyjrdJo95s6b8NMVwySe9xw9FY4BUvZZlBkLzgAAIrWds0RRrGCxz2nJuYN0xJKEWKF07KTIG149XPcN+pqU1cv3lSU2/IUj5PgbTh17ApCFoRT8ANxP7Ztbr68s6Y2zgAAsFVttUvbkq3tmmPekCf4pZ2fmN3MdI9IRCjFJ8P5+CKE8OEHV6PdN2o//r0bEW8qF/Gm8sKrwzO0P0r+PbuZXSrNhWz8GRrbcwq+sI29pD7nIQwAgGLELT4mbbXLlhd00T3t/MRvbVGEfeq3TyjFom9NTLwLIRxsct+o8MeN5Sy26jvxqrBGr2LVlIk3yMde3HPqqmkam43Se03T7Cd6qN4TEAMAUIK4xcdtrHKBdXmxsE+9ri5bIpTiT7Ed37uFv/Qh7ht1vOF9o17GVn2/2TeKDXlc/XClagqy8mmz0baln5eFnkv5GbBoAwCAbC206ntj3pANOokt/Sza2wKhFJ9rJybuQgj/Gs7HLze8b1RbcttOwvxXqz625FDVFGTpddM071VN0UexSipllfiLuJ8VAABkJc4batXHtrSh5xuL2jdPKMVftBVRw/m43TdqsskrE3t1vo97i8A2qZqCPL1QNUVP5fCet1gDAIBsLHRVMm9ICha1b5hQiq2Lqxz+E/cUgVQebzDHXgHIyuu415ReznRefJ/ncB96FSu2AAAgKV2VyIRF7RsklGJrrHIgQ+0N5t82M4TsfAqNtfOjB84y6ouvShEAgGTMG5Ipi9o3QCjFVsRyxyurHMjUSbzBmACHfLTVtG3FlB9+dFKsksqpHcSxCkUAAFIwb0jmLGpfM6EUG9V+UGc3s8u23DGjlcDwNe0E+H9nN7NTVwey8emHX9M0Ppd00XFmv4127C0FAMA2mTekMBa1r4lQio2JH9C27PaVq0xB3lj5ANl50zSN1mJ0TY7vaaEUAABbYd6QQj0uavfs9AxCKTYiVpv8N35QoTTtygcbGUJeXjdNc+E1oQti9V+Ov5F2VCYCALBpcULfvCEl+82i9qcTSrFWsey2nTR848pSuBexJPfICwnZOBFM0RE5V/6pSgQAYCM+a9cHpXtc1K6d34qEUqxNTIav4gcSuqDtZ/wfJbmQFcEURWua5ijzFaF7cYwAALA2ceL+Srs+OuZFDKY8Q61AKMVaxBvLbfwgQtf8FisAgTwIpihZCZVIqqUAAFib2c3sOAZS5g3pIovaVySU4tni/lFX8QMIXXUyu5m91ysWsnFi7xtKEyuQDgsY9mHTNFpQAADwbHGi/t/mDekBi9qXJJTiWWY3s/O4f5QbC33wQq9YyMobwRSFKWnlnFV+AAA8S5ygt38UfdIuar+yqP37hFI8WbyxvHYF6RnBFOTljYoOStA0zX5h/fNP4pgBAGAl7YR8OzFv33l66jDOHXqe+gahFCtzY4FPlYFXsXUlkN6VyXMKUOI+Te5zAACsJFaIXBXStho2pV3U/t6i9q8TSrESNxb4UxtMvRFMQRbaz+Nl0zTK48lSDE1LXMxz5nMFAMCy4gT8bZyQh77b0W3p64RSLG0hkHJjgf95EzftBNJq700TrwGZKvU+saNaCgCAZcSJ97U8yAAAACAASURBVCv7zsNftJ+H/1rU/ldCKZZipQN8129xjzUgrXYPHCExWYmVRiU/gPhMAQDwXbOb2bFACr5Lt6UFf89mJGTLSoetuovhX4jX/NHHtg/pigNpX7fHljv78U/QenFjTmY3szA4GLjBQFrnTdNc1XW96ncmbMpZ4b+h9pqmOa3r2uILAAC+ECfa37gyG3cdD/D5HOH7+NdWsThnuBv/d4hzh3vduFxZehPnDnv/bCWU4rsEUhvxIQZP7+N/fvrvg4PBqjeQH7n63v8/u5kdLdx4Hv+48TyPYArSa+9XFws/qiG1LlQancbPFQAA/EkgtXbXi3OFbdg0OBh8d37viX40Z/i4uP0xvDoSWK1N74OpIJTiewRSa/Eh3kTex+BpEzeSJ1kYy+XiPx/DqqN44zny+q9MMAXpvWia5ryu63OvBSm1FUYduY8eNk1zVNd1Nr9jAABISyD1bNdxvrD9jX07OBhk0+1jcDB4DMb+8vt/djNbXNx+ZIH7k/U+mBJK8VUCqSf7EK/bpz8bqH7auBhW/XnTie+Fx6DqVWnnk4hgCtJ73TTNpTZ+JNalYPT0RysqAQDoB4HUk1wvzBcW+bs6znM+zhtOwv+qqo4W/gipltPrYEooxRcEUiu5j5VG7fW6LDGE+pG4UuP9ws2m3bzy8Y/3yLcJpiA9bfxIJlZJdemB7CRWIN4u8fcCANBRAqml3T3OGQ4OBpdr+ndmJ1ZVXTy2+44h1bHF7UvpbTAllOIvBFJLuY9ftJ2+qXxLPOdP5y2g+iHBVPfdbWCflcfezY/a8vgXfb/QT9S28Tur63pS5OgpXRf2kvrceayYgq7bxP2dpxGE0/rVVQivMxjDsvr+enX6e0sg9UOPQdRFTu34timGVO0z+CS2+3ucNxRQfV0vg6mfHh4eMhgGOYhJ9nvhwlc9VkRd9jGIWkb8YeIm83VvBVPLa/ctCSH8p5DhXtd1fbStgzVNs7tQ+XO08J+Cq29rv7/367ruXCUr+Srse2wVPk88mfs7feR9z7o0TVPM5F1d1z9lMAw2QCD1TY9zhpO+BlHLWAiozsxffNXPfQqmVErxSfxiuBRIfeFDTPc72ZpvneIX50UMN0/jTcb76Q8qpliLOBH82Hv6ix7UTdO8XNh0tP1z6Mp/+h4672jVCvnq0l5Si3biZ6mr5wcAwFcIpL7qOlZEqa5eQpxXXZw7PIvzh+YO/9CriimhFI+B1JWU+i/eWuHwNLFMt52sOo8/Ws5tcviJYIqNq+v6cQ+4P8UVukdxRVJfv+d/aZpmYi8ctiF+5rocCJ8KpQAA+mN2MzsSSP3psSrqPM5/8QTx2rWh1Jm5w79og6nbwcHgi0XIXfO3rp8gSxFI/eE+9j4+aIMDgdTzten+4GDQrn74Z1xB0ndtMGUFDVtV1/VVXdfndV23lVP/X1sSHkJ418NXwSQ629L1xQd7TdNYYAEA0ANx73nbWPxvznA/zhkKpNZkYe7wH+YOP7mMn7tOE0r1XJwg73sgtXhjsdJhA9p9uAYHgyM3mE8EUyTTtv+r6/qiruvjhYCqL5/Jk6Zp9jMYBx0W32MnPXiNhbwAAB0XJ8avet5e7fM5Q1t7bEhbHWTu8JP283bV9WBKKNVjs5vZpCcTJ9/ixrJlCzeYdiL8rlcn/1dtMGVCj6QWAqr2M3kQ25Z2nc8dm9aX99hebFMIAEAH2XvenGEqwqlPduLeW7sZjGUjhFI9Fft1/tLjS+DGktBCae6/4o2+j17HzyEk1+61VNf1aaye+rXDn0vVUmxMj6qkHgl5AQA6aGHv+T7u8SOMysRn4dSHHl6CF7FiqpPBlFCqh2L5X183KHwX94xyY8nA4GDQVuu1k3i/9/QSvBFMkZNYPXUeP5ddrZw6y2AMdFPfvs8PhbwAAJ3U160+2mfgl+YM8xLDqZex61LfFra3n8NJBuNYO6FUz8xuZvtxtUPftK3i/jE4GBzbMyov7Y1+cDBoJ4n/r6crH970YQNDyhLDqdP4uexaufxp0zSdLYEnjfie6mPgqVoKAKBD4lYfr3r2mn6Ic4an5gzz1XZd6unC9k5uASKU6pGe9oP9VHbbtoprk/UMxsM3DA4G7+PKhz629Ov8BoaUqa7r93HPqS59Ltt74HEG46Bbznrab/9EyAsA0A093Orjcc7wpTnDMvR4YXvntgARSvXLpGflt9ePZbcZjIUlxZZ+L3u2meFOl/vEUr66rtvP5VGHfvRp4ce69fk95fMEAFC4Hm71Yc6wYAsL23/t0WlPurSgXSjVE7Ob2VmPNt9uVzr8q90MT9ltmdrXLW5m+K8enfZOnPSHLLVVU/E92oW9pl40TaM6kbVomua0p1VSj85USwEAlCsukO1LpZA5ww6JoWJfqqbaZ87LrixoF0r1wOxm1k4i/taT022/hI5itQ2Fi69jX24uPw8OBpcZjAO+aWGvqS70cO5U6TtJ9X11pZaYAABlu+rJIitzhh20UDXVh72m9uLWPMUTSnXcwj5SffB77AP7vu+ve5fE17Mr1Rnf8nPcsBGKUNd1W337c+Gvlkl0ni1WSe25kr0P5gAAijS7mfVlqw9zhh0X95r6Rw/2qT+c3cyKf/4SSnXfZQ9WO7RfNv+MXz50UNzI8DROgnft5iKQokh1XV8UHkztaeHHGqi4+0P7eRL0AgAUZHYza3+//dLx18ycYY8MDgZt1d9+D/apfx07oxVLKNVhMTU97PhpfogbE2p71gMxvGm/dO86crYCKYoWg6mSS+QFCjxZ0zRHPfidtQoP+gAAhZjdzNqJ+67PR5gz7KG4sP2oB+38it5fSijVUbObWbv6+3XHT/NtLL21MWGPxFLrl4WvergXSNEVsZXfu0JPR2UHz6Fl3V8dxqAOAID8db2z0tu4f5Q5w56K1XFd7Lj0aKfkLXuEUh3Uk32k/hXbudFDC6seStxn6j7+MBJI0SWnhVYwti3H9jMYB4WJrR9VSX3JbzMAgMz1YB+pT3OG7dxRBmMhoYWOS10Nptr9pYrsWCGU6qbzDm+6/dgLdpLBWEhsYZ+pUjwGUjbWpFPquv5YcNWRaimeQqu6rzsR9AIA5CvuQ9PVfaTMGfKFOAe3H9s5dtFvsWNaUYRSHdODm8uRXrAsiqseSijHFUjRaXVdt+/tXws8R+3GWEkMXU5ctW8S2AEAZCh2Vupq1xZzhnxTrJo7KnwrkO8p7nMtlOqQjt9cHjcnNKHPFwooxxVI0Qt1XZ8X2MZPKMWq7CX1fadN0xS74S4AQIdddLSz0gdzLvxI4VuB/MiL2c2sqOdUoVS3dLVt3webE/Ij8cdHjsGUQIq+Ka1KYifuDwQ/FMMWVVLft6NaCgAgL7ObWdu2/FUHXxaBFCuJW4F0MZh6XVIbP6FUR3S4bd/jzcXmhPzQQjCVS59YP47onbquLwssiRdKsSxhy3JOSxgkAEAfdLizkjlDnqTDwVQxn3OhVHe4uUBewZRAij4rbWNZLfz4oVglJZRazl7TNIIpAIA8TGI1e5eYM+RZOhpMFdPGTyjVAfHN1rW2fW4uPNnCBoapginvX3otVkuVtLfUfgZjIH9nHXyY3yQBHgBAYrGzUtfaT5tzYS06Gky1bfyyn+MQShUuvsled+y03Fx4toTBlPcv/KGkaqnDDMZA/lT+rOZF0zSqEAEAEulo2z5zLqxVR4Op7D/3QqnyubnANyQIprx/4X+Kuj81TWNfKb4ptqLrWlX6NqiWAgBI56xjv2HNubARHQymDmc3s6wXVf49gzHwRLOb2XHHVne7ubB27fspfhFfbbjtkvcvLKjr+mPTNO9CCK8KuS67GYyBfBXRlztDr5qm2a/r+rbvFwIAYJs62FnJnMsPTKvRyyWeaz8O52N7n39FG0zNbmahQ+0uJ7Ob2WWunxmhVNlK20j+e9xc2JjBweB97KO8qWDqbVxVAfzVZUGh1ON3BPxF0zTHqqSe5VzrQwCAretSZyVzhn+ETkdxP+T2z2MA9XLVea5pNXr8r/chhMeAqn0WbheS3Q7n494+F8dgaregeYzv2YnVklkusBRKFWp2Mzvv0ATJvZsLm7bBYEogBd9W0o9ZlVJ8ixZ0z3PSNM1ZWz1Z8kkAAJQizn10pbNSO2d43Lc5w2k12o8LJ49i8PRiA4fZWXif/Pl+iaHVhxhYtX+uelZd9dhtaRPXfNtez25mF4ODQXadK4RSBYqJbVcmSARSbE0Mptqby7/XdEyBFHxH27KraZoPhfyYs6cUX2iapksP9Cllu0IPAKCDulIl9Thn2PlW0NNq1M71Hi8EUakLEV7EPydxfPexE0ob1lwO5+POzuPGbUCOYiDXhYKQi/ieysrfchsQSznb8N4429SudtDLlK0ZHAzam+jPazieQAqWU8p3vEopvkaQsh6qzQAAtmB2MzvrUGel0y7PGbZB1LQanU6rUTtP9f9CCG9iCJTj67cTx9aO8f+1Y45j7+RzdCyeOI7BaOkOY8iWFaFUYTq2UeHPg4OB/TvYusHBoF0l8PszjiuQguWV8j3fhdJ81qhpmn1VUmuz0zSN+yYAwAbFzkpdWVT1r7iouHOm1eh4Wo0uFoKoEvcvevVZQHWcwZjWKgaiXTmv7L4XhFLl6crN5W0MBiCJwcGgXT309gnH/l0gBSvpfKsFOkuV1Hq5ngAAm9WVzkrtnOEkg3GsTayKOptWo9u4pcRJR04txIDq3+25TavReZeqp2Ixxb8yGMpzHcbtTLIhlCpIrJLqwpfWB5P6ZOIsbt64rJ9jmAUsqa7rYipim6bRwo9PYpVUlx4Uc7DXNE3nVlACAOSgQ/vPd2rOcFqN9qfVaBIXa/7WodaKX7MXu3u11VMX7bnnN8TVxYD0KYvac5PVIkGhVFm6sML0PsfN1ein2CP2aMkesT+r7oMnK6UP88sMxkAeVPVshoUdAACb0YUqqfuutEuLYVQ7h3QTQvilIxVsq2gX+N10KJxadVF7jvZyqpYSShWiQ1VSxzEIgCwsBFPfI5CC5+ns5rR0T6yYU9GzGYdN0wh/AQDWqENVUu2cYdHt32ObvvP4DKzzwl/DqWI7k8S5w9OCFtx+SzaLL4VS5ejCit1fYy9OyErcvPDnb4xJIAXQL6WtMr3LYAyrUC0FALBeXaiSKn7OcFqNTmObvtc9rIz6kTacuo2BXZHi3GHpzzLZVEsJpQrQkSqp68HBQCscshWDp897xAqkYD0sSKAIsUqqtAeNZdvQ5uIk7tkFAMAzdaRK6kPJc4bTavRyWo3awOKNMOq72mvzelqN2nCqyK1d4hzhuwyG8hxZfNaEUmUofYO/+w6cA/3w2CO2fc/+UyAF0DunhT1IXtd13a7GnGQwllX4XQgAsB6lV0kVu4/UQqu+/4YQXmQwpFLshRD+M61Gk0Jb+pXexq+tlkr+mRNKZa4jKx7OS+8JSz8s9Ig9GhwMLr3s0Dv2uqG031yPq9xKW0RxFqvSAAB4InOG6bTVUbEjyOvSxp6RX9q9t0qrmlqYOyxZ8u8NoVT+Slux+7m2bV9pq3fpsbZHbOwTC/SPSfIea5rmNK7aK8WHuq4/tcaM1VKft6DN2Y5qKQCAZzs2Z7h902p0pjpqbR6rpopq3xgXspfcxu9wdjNLGgYKpfJX8ooHbfsAgFKU1sf+8wf40h7oS1/VCwCQWsl7txc3Zxjb9bWLwn7LYDhd0+419b6wdn6lt/FL+vkTSmUs9ncsacXu57TtAwCy1zTNUWG/ue7quv5Ly766rtsq3+t0Q1rZXqxOAwBgReYMtyu262t/bx+WMuYCtZVnt6W08+tAG7+T2c1sP9XBhVJ5K/mN/UHbPgAKo3Vnf5W2yvRb4y1tbymhFADA05RcdV7UnOG0Gp3G/aNKDgFLsRPb+RXxnBDb+JW0MPBzya6zUCpTMal8VfApaMkCQGk+esX6J1ZJlbTisW0Rcfm1/yNWT91tf0hPdhivPwAAS4pzhiVX7BQzZxj3j3pT+N5dJXozrUalBJclL7RL9lkUSuWr5Df028HB4CqDcQAA/EhpC2kmdV1/L0C1txQAQLeV/PupmDnDaTW6sH9UUr/E1yBrsQ3lr4Ve453ZzSxJBiGUylepodS9yQUAPlPSZqX0SNM0JVam/yh0uihsw91X8XUAAGA5Jc8ZFtE2O4YhJxkMpe9OptXoclqNcp9TmBT2DLZIKMUfCt+scBI3egOARy9dCTJV2l5Sb39QJRXi///V9n4ZK+11AABIIs4ZltpKbhKrSrImkMpOu4jwKudgKs6Fl/pMcxhbgm6VUCpPx4WO+77AljEA8Miiih6J1TmlPWwu+6BT2gPRcdM0KioBAH6s5Cqp7OcMBVLZelFAMDUpbH/fRVv/XhFKZWZ2M9stOJQ6UyUFwFcUUSlV1/X7DIbB9pTWbvhdXddLrSyNf9/15oe0NjvaPwMAfF+cMyyt9fSj7OcMBVLZexFblees1GopoRSh1DLcu8HBIPvN5wBIotT2EnRUrMopbZXpqitLS3sgEkoBAHxfqVVS2c8ZCqSK8Sq+VlmK7/MSq6X2ZjezrS4mFkrlp9QqKXsBAPCFpmmOCrkqpZbZ8zRnhYWl13VdX63yD8S/v6T39U7TNKVOtAAAbEOpv5WynjOcVqNTgVRRTqbVKOdWkKXOkW91kaBQKiMFl+GqkgLgW7a+YeYTZb/hLusRq6RKq8p56kNXaQ9EFjkBAHzF7Ga2H9uXlSbrOcNpNWqLA95kMBRW80sME7NTcLXUVgtlhFJ5KbVKSiAFwLcUsZ9UCMGeiP1RWqvku7quL5/4z17GTaVLsVdQdSUAwDaZM1yzaTV6aU6zaG/ia5ijEhfb7cxuZlv7nhFK5aXEG8z9M1bvAtB9pYRS7zMYA9vRm+qhuq4/Fvg7TbUUAMCXSmzdl+2c4bQa7cYFXPY/LttVfC1zU9riwEdCqZ4qcWXoxeBgYHU5AN9yWMiV0b6vB+KeRXsFnel9XdfPXb1Z2urPw6ZpSmn7CQCwcQW37st5zvCisOcCvm4nBkBZie/7Eos4tpZNCKUyEcvjSkznVUkB8FVN05RUASyU6oe+7CX1p7qu2/f22/UNaStUSwEA/E+p7Y1zrZI6K3RPf77ucFqNcnx+KLE15N7sZraVbjdCqXyUeIN5NzgYmMQD4FuKubfVdX2VwTDYoLhXUUkrTNfZ7qS0B6IT1VIAAH8qcbuPLOcM4x5EFkB1z+tpNcpq/iG+/99lMJRVbaVVqFAqHyXeYGwGCMD3lHJvu8tgDGxeaQ+fl3FPqGeLoet12tNZWYn7JgAAbEKR231kMIavubCPVGddZLi/VIlz51v5vhFKZSD2hi2tj+nd4GCQXc9OAPIQq1JKube9z2AMbFB8P5ayv9mjdYdopT0QnTVNk+OmxQAAWzO7mR0VGKJkOWcYW7yVuDcXy9nLbSFi/ByUtgj2RcwqNkoolYcSVzwIpAD4npKqHIRS3Vda1c3buBfU2tR1fVHYA9FOoZ0EAADWqcTfQzkGUu0k++sMhsJm/ZJbG79C59A3fg2FUnko8QaT5WaFAKQXqxtKurfZT6rD4t5EJ4Wd4aZ+Z5VWLaXfPwDQd1r3rYctSPojtznrEufQhVI9UdoN5kOOmxUCkI2zklpMxP126K7Sgo3ruq43Vb1X2gPRXtM09pYCAHppdjPbLbDdXDtnmFUnimk1Oi6wlTdP92Jajc5yuX5xDv1DBkNZhVCq62Y3s5cF9oa1ugCAr4pVUtn8AFzCdfYj5MkKrZLaWIhW1/XHtjXgpv79GyKUAgD6SpXUeuj21D/n02qU0/60pc2l7216XymhVHovCxyz/aQA+JaiqqS07uu80gKNuy1U7pVWOXbYNE2JEzIAAM9lD/pnmlaj9rfvXk5jYit2Mlssa1+pzwil0tO6D4BOKLBKKgiluqvQ9+PGA6O6rm8LrBBULQUA9FFpC9mzmjOMlTKlPQ+wPq+n1Wij1T7L0sLvS3/f5L+cpZR2g1ElBcC3nBdWJXVvP6lOK61qr62S2lZbh0lhffVPmqY5j4EabMPLpmncH9J4X9e1CUSAP5S2D1Ju987SngdYv/OMFrhdFrZHnFCqqwrdsFAoBcAXYnutXwq7Mu5p3VbapObW+ozXdX3ZNM1dYa1Mzqx0ZYt2bIgOQEqzm5n9pJ5BlRTRSdvCcTgf57C4rZ1/eJ3BOJbV7iu1OzgYfNzEv1z7vrRKq5K6HxwM3mcwDgAyEtuklbZxZ9C6r7uapjktrWovwQbMpe0tdRq/awAA+sCc4fOokuJRFuFk/HzcZzCUVWzse0golVZpqx6sKAfgayaFbh7rvtZdpQUuk7quN7IC7TsuC3soym2zYgCATSotlMptwZ89SXl0GivnclDaHMTGsguhVFpuMAAUrWmadpL4pMBzeJcgBGALYpVUaSHp1isN4/u/tApHkwsAQF/Yg/6JptWoxOcBNmcno+eI0ubWVUp11H5hpyWUAuBPTdMchxB+K/SKlNhukOWUVk3ztq7rVD3Ot90y8Ln2YugIANB1pe1Bn9Ocoep6PpfLe0IoFQml0irpBnM3OBjksCkcABlomuZlwcHOfV3XWvd1UNM0RwU+wCdrNRjDsLepjv9EJhkAgE6b3cxK3E8qiznDaTV6WeDzAJu3N61Gx6mvc/yc3KUexwr2ZjezjbQ+FEolMruZlbaflCopAD6JgdRVwRvHqpLqrtL2krpOWCX1qLTPw4sYPgIAdJXOSk+nqp5vSR5KRe+zGMXyNhKSC6XSKe0GU9oHBoANiK2zSg6kQoEty1hCDEsPC7tWyUO0uq7bz/OH1ONYUWnhIwDAKuxB/3RCKb7lZFqNNlL1s6Let/ALQqmkhFIAFKVpmrZt1pvCA6l3GVSmsBmltXX7EAOhHJQW1B42TVPab2kAgGWVFkplMWcY27OV/KzK5uVQLVXaHPtGnruEUukUdYMZHAy07wPoqaZpdpumaVt8/daBK6BKqoNiQHFS2Jll816s67r9fN9nMJRVqJYCALoqh2qOpWU0Z5hLezbylcO+Ur2vlApCqaRKusGU1tIFgDWJe7e8L3DC/2tyqkxhvUoLKO5iEJST0gLbkzYwz2AcAADrVlJL6rsMxvBIKMWPvMqkhV9Jc+0qpTqmpBuM1n0APROro9pJ6v+EEPY6cvaqpDooBhOlhaY5hmglfj5Ka9kIAPBds5tZaYtucmnd91LrPpZ0lMGFKmlLgY3MBwmlWIa9NwB6pGma0/hw8UuHzjrHyhTWo7Rgom2Td5nBOP6iruuPIYS3GQ1pGWeqpQCAjrGf1NOokmJZ9pVa0exmtvbvpb9vetB8aXYzyyGRXYVWRwA9EFv1tdUSLzp4tvaf6aAYSJQWSk1iAJSjSWFVZzvxoVLgDAB0hUqppxFKsawc5uVL60q29u8llVIsQ6UUQIe1lVFN07yPrfq6GEhdq5LqrLMC23Rk2yavruv2e+A6g6GsQuAMAHRJaZVSyRdbxT2Cuvgcy2bsTavRRvZJWkFpc+1r/14SSqVRVKXU4GAglALomKZp9pumOW+apv2Of9PxH/EmrbvrtLAze5txldSj0vaW2muaxspYAIAEBgeDHLorlRbkkV7SufnBwaD3lVLa9/EjH1whgG6Irc6O40T+YU9e1nd1XWtD20Fx77ONbLq6QdkHpHVdXzZNc1fYtT3LcZ8uAIAnKClguc9gDKG0xf9kIYfPWUnPXEKpjkhdIriK3FfzAvAdTdO8jD/Sj3sURD26L3C/IZZXWgVcG5CWUn3eVkv9lsE4lnXYftfF9oMAACUraU+pXH57CaVYVQ6h1G1BodTar5dQKo2SQikP9wAFaZrmKP5gOIp/SttvZ50mBYUArKDQKqmS2uJdxNCvpO+PswLbOQIA8Hza97GqHBbs3vZw4fCfhFL8iEopgAzFCqjdGDztxx/iNnf9nw91XdtLqrtKCx+uS2oj2e571TRNG0z9ksFwlnXS7pMniAYAClfSJHXy37fTarTb84WYPNG0Gr0czscpizFKem5RKdURJVVKebAH2IK439PnN/qXC+0bjhb+mh/dP6ZioqNiNWBpK8pKqpJ6NCkslAqxWkrLTgCA/lAlxVPt6xC2tLXPQQml0iip3YxQCuDb2n1MHlyf7Pxqb5lOK60C7q6u68sMxrGStuKoaZp3IYRXBQ37NFZLqfQHANi8HOYMhVI8VfveSfmc1lYavu7rq/e3DMYAALAu2vZ1WNM0+wVWSZX8fiytwmtHlSQAUKrZzWy3sKHnEEqVds3IR0mdzJJb9/eTUIofsdIcgFLchxCOvVqdVlrAc1/X9UUG43iSuA/WXWHD1r4PACiVqp/VuWY8lVBqNWv9rAmltmx2MyvqDT84GGh/AkApTtuWY16tbopVUieFnVyJe0l9rrQgcK9pGtVSAAD9oFKKp0r93ul1IYhQavuksACwfr+XuG8PKymuSqoLoVSs9LrPYCirUC0FALBhg4PBVQbXWCjFU71IeeX6Xgjy9wzGAGzJ7Gb20g27c973/UYGIYTruq5NQndY0zS7BbZmvKzruivfz5PCNuF90TTNUWw/CABAdyUNFoCnEUrxPaXtIcCPTQrcIJ7v+0cIwaQbfXZnH6leaEPHncJOtLTKru+5KCyUCvE94/4IAACQGe37+B77cgCQs7al2HGHqlH4ilglVVol3Nsu7W8Wz+VtBkNZxau4DxkAAMAXptXopauytLVeK6EUAFCqtj1XrzcH7YnTAqukit9L6itKPKcuVasBAADrZYuT5a31WgmlAIAS/SyQ6o3SqqSuu/jejOd0ncFQVnEcK+0AAAByU9rz1doIpQCA0rSB1IVXrfuapmmrpPYKO9EuV+eU9rnbKTDUBAAA6DShFABQEoFUv5QW8NzVdX2VwTg2In727gobtlAKAAAgI0IpAKAUAqkeaZrmWJVUloqrlooVdwAAAGRAKAUAlEAg1T+lnXHulAAAIABJREFUVbjc9eQ9Ogkh3GcwjlX0ISwEAAAoglAKAMhZO/n9T4FUvzRNcxRCOCzspHvxHq3r+mMI4TKDoaxiL76nAAAAHn1MfCVeJj5+MkIpACBXbSB1VNd1aRPgPF9pVVL3sYKoL0qsPFItBQAA/Gk4H79PfDV2Eh8/GaEUAJCjD+2qobquU/9IZMuaptkPIbwq7LpPYgVRL9R1fRtCuC7sXA+bpuntSkQAAIBnWOvzrlCK79l1dQBI4G2skLp18XupxIqWPraXLPF1Kq0CDwCA7yttoRSUaq0Lhv/ubcB3vHBxANiyf9V13ac2aCyIVVInhV2Tt30MUOu6vmqa5q7drymD4SzrpGmac4E3S7jradicA59PgELMbmZHg4PBldeLQgk0ExJKAQA5aCcAj7Xr670SK1n6vFdRe+5vMhjHKk7tL8USbuu69j4BYNsE86trr9lhaYOGvtO+DwBI7Xf7R9E0zW4MDEpy3fOqm8sQwn0G41jFWXyvAQBkZXAwEEqtzjXjqZLOP7SVhn1+5YRSW1ZaWevsZuahHfLWm4316aS2OuofdV2f1XXtvUxbJbVT2FXodSVF/NyW1m5zp8DwEwAgR/sZjEkoxVOZg0jo/2/vfnKjSrL9ged7aqmH5q3AZG4AauShXVLMca8AWAFGbwGYBVhlVlBmBW3mITUe9qjNBtJ4BT889Oj9dKsjq7MoA/6TkRkn7ucjoZq06OvrJG/m+cY5RyjFjzx1h6Bds+lMZwlRvS3dUWaQs+iSija675PX728i7t2JOCYSAKA1Qiki813ublZafxRKAQDrNCwTnQ67OnRHsWQ/YJdUtA6hKsr4wvfBLns756xbCgBoUbTRyBu1c30kWOC+Nh1ohhrfN5vOVlq/EUptRqQHTAunHgCIbzGqb2/kO3i4WbQxeJcppYgdQrVEvBdCKQCgRZGmobQyXemygWsgmJ3rI3WJDRJKbUakB4xQCoCHGL4gvEwpPTbqjJuUjpXtYDdHl9SS8m/7UzMXdDu7OedRLxcGAHigVvbQW2vAXZ01cMci1dxX3mAjlOJHWnnAABDLp6UwSkcJ3xOtS+oqaGdQbRGDOt1SAEBrIo04b6Wo7vAjd9VCkBkplFr5/RJKbUakB0wrrbgAxPChjOl7KoziR0qnSrguKfvQ/qz8e482OuV5ztlUAACgJZG6flr5HK9TirtqIcgc9fcQodRmRHqz1CkF7Yo2Kol+DYXot5PJZJpS2jemjzuI1iU1MbrvuyIG0RFfgwAATZhfzDd+mH3n+sj3T+6qhddMpMOZK9+/9ZdV/4V054lfKTTLSX02aRhhdjr8SSmd+k1wV6VLajfYjXuvS+q7hsDuTcPXd5P9nPMjv1cAoBHRun5aOcx+FvC7BZvxaef6aKOf/VsIc+9o5aGUTqnNCPWAmV/MjTUBYFKCqPeTyeRvKaWhiPtCIMUDRNzno6vmO0qw877ZC7zZ1mQyOWjxwgCAUYp2UGavgWuYlAOTcBtG993dyt+XdEptRrQHzOMaiSgAIZyVD21DR5RZ3axE2ePzPNjd/JBS8nnoxw4D/m5fCBwBgEZE+7zZSnHdCD9uq4UAM1qn1MprQTqlNiNaUa+VUw/AHwkIqGXYD/VzSum/Ukp7KaVDgRQrZpdUp0pwdxbsp9vOOUfs3AMAOjObzoRS97BzfXRedh3D91w1soMsWii18gYbodQGzKazaJ1S0f6hwFjYf0Etw2g+J82oImiX1Jl/E3cSMcDTKQUAtCJSuNLSHicj/PiRVl4jocb3zaYznVId+RToR7FTCmBcXuWc9/3OqSRiR8pJA9cQRtk1F+2k6tAtZToAANCCUN1S84t5K4fZfWbnR1oJpZ40cA23VeV7nVBqcyJ1OET6hwJjYrcJNZ3knB+5w6xSeU0dBLuplyklX3DvLmLnkW4pAKAF0UanNxFKGeHHDwyj+zYeSs0v5tEOwlWpPQqlNifUCJiA/2BgDIRS1LRl/AEVHJTXViSCivsZ3j+ugl3zbhkvCQCwSdZ+3J/DZHxLK/WNaDX2KiG5UGpzohWThVIAfzacwnr7nT+RRrXeZCjQKsizStG6pK50Sd1PSulL0KKA9zwAYNOi7TJtqWboszvf0sre25ZC3NuokmH8pcZfyq1EC6Wi/YOBMYjW0t+jzymlbxYwc86n5QtFtM6QZW+GnyOl5PXGg+ScXwT8t9DKF5eohvv3Kti1P885H5RQDQBgE6LVDJtZ+7FzffT5n3/93w+TyeRZA5dDOz6V8Y4tGH2n1ESn1ObMpjOnHoAHmU1nCmaNK0FOD6fuT+2XYgWi/Vu4Eko9TEppKKh8CHjp0Tr6AICOzKazcKP6G1v74TM8X2viNTG/mD8NeFBTKNWhSMv3tso/HKAN0fZ0jFZKafjwcxb85982BoGHKF1S28Fu4qlumZWIWBQ4EMQDABsW7TtkM6HUzvXRx2A1V+q63Lk+aqWeEa3p47LWgXih1GZFG4WkWwraYZRaLPsdBInPSrAA9xGx88RuoRVIKX0MuF9vq7xvAwBsSrTv/K19dvJZnoWWDthGq61X69oUSm2WBwzACJRuix4CneOcs65Z7iTnvNfSnPlbel9Gz7EaEbulFDIAgE0Kt1dqfjFvptO8dMbolqK1kezRQqlq64eEUpsVba/UbksPGBi5aO8fo5dSOg26W2XZljF+3EPE4r7X+QqllE4Cdotu55wdyAIANiXidJTWCu4OGXG8c33UxEj2snfNPqniL7X+Ym4l6gPmtIHrAIjoRXnvj7ZbZ9mTnPNxSiniODbWrHTW7Qa87//IOTdwGWzYgc+9AMAmzKazj/OLebR7v9/SZ6ehW+qff/3fw+Dfv7m/1rqkIh540ynVo7IoLForqROj0AadUgF1NMbvlQ4Cbkl4SWS7ZfwkAMAmRNvL2eJ3RN1S49VMl1QRrYZyWbKLKnRKbd5QWH4e6HoVIQObTWcKKzeYX8yHDylvmruw72vpwcodDEv/c87vhmAn+H07yTk/LkEb/Mnw+gj2GQdu8sJBEABgQz4G2826Nb+Y78+ms9a6pV4End7A/V3uXB81E0jOL+ZPA3bsVf0OpFNq86J9yf3tAdPAdcCozaaziOM/Kcrou2in3r62ZawVP+BUIj14XgJWAIB1i/i9X7cULWhtYkfEiTlV33+EUpvnAQObF62DLNrYT27Wwxi/YbSVD/j8Sc75kS4pOmIMJQCwCRG7tZurGe5cHw338X0Dl8J6nO1cH7V2gNY+qa8IpTasdDtcBbtsoRS9eRTs5/ncwDXwQCml4f3/dQf38U3O+WkD10FbFPHpyYsStAIArM1sOvsc8FBqqxOWDgLWX7m7q9YOAAcd3XdVe0KTUKoNEUf49XDCHxYizWie2G3Rj5TS8XCKp4Mf6FTBloXyWhBK0ZMtr2kAYEN0S63AzvXRl06mlfB9hzvXR60d5I74PaJ6p5lQqg0Rd3LolqIL5cRCNDql+vKigxNbw6mf4waugzYclCI+9EQRAwDYhIih1PP5xby5Q4tlpNuHBi6FOoaxfS3WJYzuu4FQqg0RHzDP5hdzS5/pQcTXsVCqIymlz50UO5/nnBVtmSje06lt73EAwAZEnZTSaiG+h0Oh/FlzY/sm/z4I/yLogU2h1BgEnRE7UXSiE+E6pWbTmfF9nUkp9XJi6zjn7MDCiJWifbR52XBbRvgBAGsVuGbY5OemMsbP9Kf+HDQ4tm8StHb+qbzvVCWUakfEEX6+mNODvWA/Q8QPo9xODye2toI+z1idQ/eSjj3JOUf73AAAxBfxO9aT+cW8yc9NO9dHw0Hfdw1cCqvxfuf66KS1e1nWhew2cCl3tZaD8EKpdkTsfNgqbYgQWbQHxHkD10AFKaVeTmwNRVv7pUZIlxQj4VAWALBuUaelNFsz3Lk+Gj7TnTVwKTzMp4Y/n0f93rCWgE8o1YjZdHYa9IS8E9GEVU4tRCOU6lhKqZcTW690E4ySgyqMwTNjSgGAdSo1w4ieN76Pft80mtCGOvp+GcnYlPnF/NHw+g94c69m09la6o5CqbZEfMhst9qOC7cQ8bVrn1T/Dstpn+hOc86Pxv7LHIsSQkYcTQD34VAWALBuUXcQN9stsrRfKvoY/bHaa3SP1CRwl9TasgmhVFuiFpt9MSeqiKPSdEp1rozx66HjxH6pcfFZgDF5LnQHANYs6nerF6VrpEk710fnJj6E9LL87ppTXu9CqR8QSrUl6gNmV7cU0ZSHRLRT/Zez6ay5tmRWL6U0fLh628Gt3c0527/SuZxz1AWu8BDe2wCAdYpaM9xq/XPTzvXRcG9fNnAp3M4QSK1l79E9HZTXfTRX6xwVKpRqSCk2R23HdUKaaIzuo2kppcNOFq/+UkIL+qU4zxh53QMAaxO8ZnjQcrfU5N/B1IlgKoT3LQdSuqRuTyjVHt1SsB5G9xHBi07mW9sv1amc8+OgC1zhobZyzka9AADrpFuqIsFU84ZAqvXP31G7pAZrDfuEUo2ZTWcngQuQuqWIJGIopVNqZFJKnzs5jb89mUyOG7gOVs+znzHz+gcA1inyzt7mu6UmgqmWNR9IBe+SGtaFrLXmKJRqU+RuKSdGaV55nUY7uTDMdtUpNUIppZPAYxqWPddV0JfS/RYx4IdV2c45+zcAAKxF8BF+W1EO9AimmhOhQ2pSXt9Ru6TWnkUIpdrU8rK2HzmMcPKB0dMlRTS9jPE7LuPe6EPk0QSwKnZLAQDrFLlb6tX8Yh7i+6BgqhkvIwRS5XX9qoFLua+1T7YRSjWotMtdBr38bV/OaVl5UDwL+EsSSo1YSulLJx0pW8G/RFGULinPe5hMdnPOT90HAGAdgq/9mEQ6iF+CqZ87OSAa0cvyO4gg8rqCs9l09nnd/6dCqXZFfjEfRDn5wChFHR8mlBq5lNLwGnjXwV14knO2Xyq+iGNQoRYBLQCwTpEP+g2rP/YauI5b2bk+Gr6H7wVuHohoCAF/ihJIlddzxMPvCxu5z0KpdkV+wGwFH0FI3yKGUpf2SVEcdvJh+FXOOcwXEW6kCA//8dxoUgBgjaIf8juJtPpj5/poqMcMnfFnDVxO7z5NJpPH5Z5HEbkGflW6L9dOKNWo0jb3PvCPMJx8sPiZpswv5i/KiMlodEnxm47G+A1Oywg4gsk5R30vhZqidmIDAMGUQ6ufAv/ewq3+2Lk++rJzfTQcrHzbwOX06t3O9dHT4V5H+fnmF/PD4N+NNxaoCaXaFr3bKNTJB0Yh6sl+oRS/Symdd/JB2H6puA7HfgPgBgeCdgBgjaJ3S72ZX8zD7eXcuT46tGdq5YZ7+bed66NQNbuyuuZNA5fyEBt7HxFKNWw2nX0MPqbJGD+aUWa8Pgn6G1G45w9SSofBT8Yt7OacjYELJOe8r0sKbrSlWwoAWJcycit6MBKyZlj2TA2BxIcGLie6YSTi0B0Vse4Vveb9vkxq2wihVPuin0Z+ZowfjYj6b+lsNp2FaV1mrfY7OZ31S8453Am5ERMiwrf59wEArFP0bqknZfxZOGWc3/Cd/G+6pu5luGevh5GIO9dHGwtG7mt+MR8+9+9Gu+6vbDRUE0o1rpeTD6WlETaidElFfVjokuJGKaXPHY1Rs18qgJxz5PdSWIftsnMNAGAdephOFHKM30Lp8Blqnu/auKIQhg6zxzvXRyFD1fJ6jV6LOSsT2jZGKBVD9JMPxvixaZFff0IpvimldNzJyIDtDp51Y2CXFPyYUAoAWIsyeut9B3f7NPJO+tI1NXTO/FTG0XGzYQXBz0OH2XDPAt+jk1Lrjmzj9RehVAzHHXRL7UZtySW2+cX8ReD9Jx82Od+VMF50Mi7gedlXRINyzo91ScGt7JauQgCAdejhcF8XhxR3ro/Oh3F0ZaTfZQOX1IrhXrzcuT56WvZxhTW/mB8H3le/cDmbzjZ+AF4oFUDZJ9NLS64v6axNOWkT+YONLil+KKX0paOT+Scl/KA9DpbA7dktBQCsxWw6O++kO+d5OVQc3jDSb+f6aPhe+3Lk4dQijBpG9YWva5ea9qsGLuWhmvhuL5SKo5exRqf2S7FGh4Fbaq+EUtxWSum0kxnWW1737SlB4fOx3we4g2cCdgBgjXo5QHYceb/U14YgZimc+tTW1VXVVRg1+c+h9x5qFUOXVBO/E6FUEB3Nid2KPiuWGMoHmcgnGE5LlyTc1mEnp7Ce5Jx15bRF1wfcnfcxAGAtZtPZx066pbqsGZZwaqhR/dxJbfdbPpSdUd2EUUs+drBHatLSdxShVCy9fLl9YqE9axD9AdjbA5zKOhvj98ZOljbknB919LqCddov/34AANahl5rhdq/TM4Z9SjvXR8N3q/+ZTCavO+meGg7Gvp1MJtOd66P96DujbjK/mJ90sEdq0lKX1EQoFUvplnrbyY8zzIp1gpQqymsr8gPjspx0gjtJKX3s6DlxqqDbhINOToTBum3pMgQA1qWjbqnBbgkCurRzffRl5/rouHRP/VRG8UcKqC7LNf9UuqIOd66PPjdwXStX9pz1Msq+qcOmQql4jsuumR686WWJIe0oY/veBP+VCGy5t5TSYScnrrZ0DG5WCQUV1eH+fM4FANapp1rC8zHUDHeuj853ro8OSkA1LR1UHxqr/V6Va3pdOqIel2s+b+Daqin1xV87+XHOWjv8LpQKpuyY6Wn03a/zi7kRTaxEJ4sHr3ptVWetXnRygOFZzlkosjn7uqTgQbZzzoIpAGAtOuuWmpSa4Wg+Sw3dRqWDahiD96h0Ub0ue6jWefD0U/n/fF26oR6VazrutSPqayWQ6mmCUXOB9V8auAbu7rizcTrDEsO92XTWdcLOWhyX+cORnZTwGe4tpXSecx4+dPzSwV38Jef8cfiZGriWsdG1CQ93qOsTAFijIcS56OiGH88v5udjrBmWTqQ//Nz//Ov/DmHJEFgtDvgv/vvoDmsshvF7i3Bp+Pu/lP9+7r376TbKgfeTjuru71tcESKUCmgoWM8v5gcdtRAO/8g/CqZ4iI7mvPbUCckGpZSOc85Dp8tuB7+Hk5zzXkpJYLsmpbsjesgPLdgu7192RQIA1Q376OcX8/cd7cFRM1yyFBr5bFlBCaQ+Bt9Tv+yq1cOmQqmgZtPZSQmmevlH4iHDvXU053U4vTCKVmjWZr+cgIp+wudJCWyNwVqfiF1SV4L9UYi4N/Jw6RQrAEBtB52N4lYzZF1OOqq1D45brTMKpWIbHjL/6Ojn8ZDhzpZOMfTAqCxWaugsKh0vf+/gzj7POZ+mlOxcq2zo6gjaJXWSUvI+2rny+ozWAbqbc36cUnLwBACorkxYOg56mOdb1Aypan4xHwKpZx3d5cvZdNbs9+P/buAauKcyD/JDZ/dv8ZB52sC10LilQKqH0z+6pKiihDjvO7m7wxi/xw1cR++iBju6pMYh6u9ZYAoArE0pRl92dsfVDKmiBFK9jLxcaHrSjFAqvoMyrqYnHjLc1nFHbbWKVdR00MkXkuH5oFOqoqBdKIP3ulDGoQTtEd/PngvVAYA163H8uZohK9VpIPWhNLM0SygVXOms6LGY7SHDd3X20NAlRVXDGL+OvpA8yTkLces5CHrduqTGJep7gL14AMDadDphaaJmyKp0GkhdRfheL5TqwGw6Gwoxnzr80TxkuNH8Yn7Y2UNDgZ3qUkrDF5J3ndzpN6WjhxUqXRwRZ2ifpZTMlR+X06CTAg5yzo8auA4AYDxedDhhaaJmyEN1GkgNDiMcfBdK9aPXk5fDQ+Zf84u5k6X8prwWelrWqUuKtUkpHXR0iOFUcXflogbkgv2RKd2fJwF/6uFz7X4D1wEAjMRsOvvS8eflRTDlwCJ30nEgdVaaV5onlOrEbDo77+gE/E1+nV/Mo44UYkVKIPVrR/fzSjGVDegl5N8KWpRuUumSivih/FPpAmR8oo5s9NwHANaqFKnPOr3rw/fCfzjMzm3ML+aP5hfz804DqatI9R6hVF8OO1lk/y2/lCSbEeowkBoc65Ji3cqYs9ed3PhnOWcHFlYj6pc4u6RGKqX0OeiOhO2cs6IJALBuvY7xW3CYne8aAqmhs27YU93pnQoxtm9BKNWR0pLb+5fc5/OL+cfyRsJIdBpIXSqmsikppZ5Oyv2SczZH/AHKGMSIX+AuU0oOq4xb1OeoUAoAWKtSrO69Y9thdm5Udo997jiQCjO2b0Eo1ZnZdDYkvm87/zF3J5PJuWWG41A+UPQWSA0OSpAMm9LTSbkT+6Ue5KCMvYhGsD9yZXRjxCkBuzlnuw8AgLUqReuIneZ3MRxmP3eYnYX5xXy/dEhF/M57G1cR99YKpTo0m84OO1pk/y3bZZmhk6Yd63zx4GkD18GIldFXvbyHPhFQPEjELqkrO8Uoop749RkWANiE3sf4Tcr3Q4fZmZSRjn/vOJAavIh46F0o1a8xPGS2ysxYhcjOlMWDHzsNpCYKUbQipXTa0Um55znncKeDNq3stgnZJZVS0m3K4DToZ97hPetxA9cBAIzISFZ/TBxmH7dSVxy+J/zS+Y14F/XQu1CqU7Pp7HwEs2IXXpXWXF/sO1B+jx/LmMYevY20eJBReBF0/NVNThR57yzqZwUHUvhNCSejds1Zxg0ArF0pYr8bwZ1fHGY/Mc5vPEqH3FBXfNb5D/1pNp2F/T4hlOrYSGbFLixac52SD2x+MR/2K5x3vHjwUxmvCc0oBd1eTo9tla4JbqF0SW0HvFfvdUnxlagh5Qv78ACATSjF7N5Xfyw8L11Txvl1rnTGfey4rrgQco/UMqFU/3o6Af8jQzHy78M4Pycg4ilzXv/R+5zXBq4B/iSl9LGjk3JPcs7C39uJeqrK75c/KDvy3ge8K1u6pQCADdofweqPhSclmPLZq0NL4/p+7byuuPAi+hQmoVTnyqzYsXUPvSpdU3sNXAs/MKI5r2/LWE1oUkqpp5Nyb3LOngHfUe5PxNNjH0oAAV+LOsLPgRUAYCNKUXtMNcMhrPhl2GHuMHs/Sv338wjG9S28jbpHaplQagRKIfzlyH7sYRzRP+YX80MPmnaV1unzkcx5dbKfCHoqjp4Yi/VddknRldLxGTFY3y6jNAEA1m42nQ2fod6O7M4PO8w/WwESWznkfjyCqUvLPvRSXxRKjcRsOjsJOtbkod7ommrTEBhOJpN/Bd1ncleKTYSQUjrv6AvJduDOiapKl9RuwEs/K8EDfEvU0NIYGQBgY0qRe2w1w8UKkKFr6nED18MdlEDxvEzLGotPPdUXhVLjMqYlhssWXVMnuqY2b3jYDw/9EhiOwWtj+4gkpTR8ITnr5Jf2LOes2PtnUT/I6pLiu1JKJ0H3IjwxchQA2LCx1gx3y2F2020CKDXFYXTd30dyyH3hquyR+tLG5TycUGpEygt3b0RLDL/2vLTn6lrZkLJQ8jzoCf37OJtNZ4qoRPSio2fFYc75aQPX0YSc8+PyPIzmMqUUfm42axH1uasQAgBszMhrhkPX1Jv5xfyzSUttKqP6DkeyAuQme70deBdKjczSQ2ashgfNr/OLuZF+azTsjhru+bBQckRzXq9GtjCUjqSUPnc0TmrLfqk/iFr4VrDntqKO7dwtoTEAwEY4zP77pCUj/RpSmgvOy8SlsdQUl73scQKTUGqEygv55chvw5PyoDn1oKlnaengv8o9H5P9ntpqGZ8yButDJz/4E6HGb11Sj4J2SV2V1yP8UAnVo+5EGP37FACwWaVmOPYJQ8N0n4uyBkTNcEOGZoKhe21oLhjZqL5lb2fTWZffhYVSI1Ve0L0ss3+IZx40dZRRfZ9HtnRwYdgjZRk/PehpjN+rnPPYuxejdr8Zg8pdRf3i9lxXJwCwabPp7NRh9t88X+ybsqN+fUoYNdTU/jHiMGrwfjaddXtoTSg1YuWFHfUk6ao9F06txtBWW04yjGlU37IP9kjRi5TSl87GUJ6MdTxWKXRHDKWuhFLcVUrpY+BF3b2MTgUAAnOY/XdbZWzcsG/qWM2wnlJPPC9h1Fh20X/LEEh13bEolBq58gI/G/t9WCKcuqelMGrMbbWftLnTm1LcfdfJj7UVuIPioQ6CHhQ4KeEo3FXUMFMoBQA0wWH2P9gqk4AWNcOnDV1bWGXtx8FSPXFsqz9u8mkM3wmEUkzKKfiop0lrWYRTw3LDsY97+i5h1O+u7JGiY4cdPSd2c85j3NsSNTDXJcW9lD1klwHv3lbO2QEXAKAJ5TC7YOqPhprhv0rN0Oe2exhCvSHcK2s/fhl5PXHZUHfZG0NtUSjFpLzQ9wRTNxraRf8+hC4luTdD9j8nGQ6FUX8wBFKfG7oeWJnSqdLTh+03Oee9Bq5jLUqBO+L79PuUkvdVHiJqZ+QYg3MAoFGCqW8aaoa/lpqh0X4/sNQVNYzo+1cJ98a49uNbRhNITYRSLJQX/H5HC+1Xbbsk9/9vfjE/HWv3VFk2OBR4/l+ZqSuM+reXs+nsYwsXArWklM47myl+UvYsjUHUArfCPA8VtdNuO+esUx8AaIZg6ru2l0b7nTvU/h8liBomLJ2WWuIvRvTdaFSB1EQoxbLS5bEnmPqhZ6V76kuZI9t10aC01B6Xrqh/lJMM/Me7sgAUupdS6mmM3/YY9ksF7pI60yXFQ5Uuz6jFE7ulAICmCKZu5cnSofaPJaAaVQfV8POWn3sRRP1aaqncbHSB1OAvDVwDDZlNZ0OiPwRTH7VQ/tBWCWiezy/mQ5B3Wu7bafQ3krKw8UXpntMN9W3vZ9OZohFjM7wvnHfyjHiWcz5IKfW8tyjq2EVdUqzKcdADNcP+u6elSxUAoAlDMDW/mE8cWL6V3fLnl/nF/NNSzbCrSTulK2yv/FFHvJtRBlIToRQ3EUzdy+8BVZknu3jY/Pan9TeXcmpj+QHi9/5jZ+WUEIzK0L2Scz4sp796cJhz/thj4bfszdpt4FLu6lNKyUhUVmL4t51zPgv6b+Ggs31+AEAHBFOtyFteAAAWJUlEQVT38qT8eVXu3VmpGZ5HqBsuKwfZF3/2jOO7t9EGUhOhFN8imHqw3x82k3+/YX8qD5rf/2zqTaecYFg8OBYPEacY7uZTCe9glIbOohJ49NCCv1X2S+2VUV89idpt1HPnGptxEjSUej4cAjDKEgBojWDqwXaXP5/OL+aXX9UNPw+12U1eYDnA/rjUDRf/jfiZukWjDqQmQim+RzC1UouQ6veHdRn5t3jYfFn675eHPniWHhyLAOrRUgDld/kwo39wQDGc3v/cyXvKkxLgdDOOcxj7FfQLw2VKyZ4+Vmp4TZUOz4iHcA7slwIAWiSYWqnt8uf3g5/l3l6W792LP4v64W/uMwpw6bD6wl7573INUfdTPaOvK06EUvyIYKqqra9PRiyUB8/C2S0vwmmF+jw4oBi6inLOQzD1907uyasyxu+0gWtZhahFbLukqGUIO98EvLsvSreUzx4AQHNKMDXUDH/126liEVbdWPP7qn5I+9QVi/9u4ipoWunaGYKpK7+pjdi95R/q8uCAr5QA511H92XopnjcwHU8SPkZIp5WHD5n9BIK0p7joJ9lt+yVAgBaNpvOhsM/L/2S4Lvez6azp+qK/yaU4laWgqlP7hgjJJCCbzssIwV6sFW6KaILu0tKNwi1lNdW1NDT+D4AoGklmPrZgXa40RBIOWi2RCjFrQmmGCmBFHxHKfTud3SPdsvumZByzo8C/z6OG7gG+hb13/Z2GZcKANCsst9or6NDi7AKrwVSfyaU4k5KYV4wxVgIpOAWUkrDoYW3Hd2rNznnvVv871p0EHQH5HtdUtSWUvp8h12drdEtBQA0rxxof6puCL95OZvOHL68gVCKOxsK9MMMzKGA5O7RMYEU3EFK6bCzLx4npesojHK9UQvXYbvTCCfql8IngcNyAGBE1A3htzGWP5WxltxAKMW9ldbDnhbcw4JACu7nRUczxLcD7pd6EbhL6nMD18EIpJROA4+U0S0FAIRR6oav/cYYmaGm+LR0DfINQikeZDadDV+OX7qLdOS9QArup4zx66nj5VmwPS5RC9ZOj7FuUbulhvekxw1cBwDArZTRZT93dHgRvudDqSk6dPkDQikerLQi/uQBQwfeDyd5BFJwfyml48A7W25ynHN+2t5l/VEJz7ZbuqZbOkspfQxxpfTkJPDnVqMuAYBQZtPZR3umGIG3s+lsX03xdoRSrIRFhnTgdWktBx5uv6ODCltBOnmiFqotfWXtUkrDF8XToHd+P9q+OwCAoXOk7JmyBoTeDLWPv82mM4fH7kAoxcqU1sQ9iwwJZnh4vCwt5cAKlIJvTyHvk5xzs+8ROef9oF1Sl2W/D2xC1C+NW3ZLAQBRlTUgfzNtiU4s9kf5XntHQilWamhRtMiQQK7KrFf7TGDFStjQ0yGFVyX8aVHUArWTZGxMSulz4FGjQikAIKxSwDdtiejeDd1/9kfdj1CKKkrXiT1TtGz48PO4jJ4E6hgKp5cd3duT1sZm5ZyHDuXdBi7lroYuKQcC2LSw3VJljxwAQEjG+RHYYlyfg2IPIJSimlLsf9zZwnv6sDjNYPkgVNThGL+tBvfQRC2qC6TYuJTSx8DBuU5DACC8Utj/ubPDjPTrzLi+1RBKUVUZ57dnnB+NWOyPcpoB1qQUfd92dL93c85NFINzzo+DdkkN78X2+NGKqOHOdumUBAAIbTadfSzj/D74TdKw10ON27i+1RBKsRZL4/zMi2VTPtkfBZuRUjrs7P3/Tc75aQPXEbZLqnTRQQtOA4+b1i0FAHShHGofdvj+zSoQGjPUMn4qtW1WRCjF2pRxfnvmxbIB70ogZX8UbE5v+09ON7lfqnRJPd/U//8D+TBPM0pAGvXAym4jATkAwEqUsWiPdU3RiLdl/Yd64ooJpVircvLBvFjW5fflg/ZHwWallM47G+W6veFCdtQOifcpJeMOaE3koNRIYgCgK0tdU2qHbMpZ6Y4ymaASoRQbsTQvVtcUtQynah5bPgjtSCkdlw93vXiWc157B1jp0NoPeg99qKc5JSiNehr3eemcBADoitohG3C1tDtKd1RFQik25quuKbumWJVFd9S+7iho0ovOZoQfb2B81vDs3Frz/+cqnOmSomGRu6V6G48KAPCbpdrhT50dcKQ978vhduPm10AoxcYNJx+G+ZzDnE7LDHkg3VHQuBJK9FRA3VrnGL/SJRV1XJcuKZqVUvoYeDzMwSZ33AEA1DZ0rQzdK5PJ5KWRfqzY0Cjx82w6e+Fw+/oIpWhGmdP51DJD7uGyPEB0R0EAKaXTzt7rn+Sc13Waaj9wl9THBq4DvidqcLoVeKQnAMCtzaazk1I7dLCdhxpePy+HRokyKpI1EkrRlNl09nlpmaGRftzG8EHEAwTiedHZCbdXOed1FIWjFs3X1k0GD3AauLihExEAGIUy0m9xsP293zp3dFVqiY9LyMkGCKVo0tJIP225fMvQZTEdPojojoJ4UkpfOtyDclJzhFbOebhf27X+/oouU0o+7NO88r4UdYb8dnmPAAAYhXKw/YV9U9zBYm+UWuKGCaVomrZcbnC2NKrPwnwIrIxze9fR73CrdFrUErUTQgcHkUQOUIVSAMDoLO2b+lk4xTe8Lwfb7Y1qhFCK5i215T4WTo3aZZn1umdUH/QjpXTQ2bjW3ZzzykOYnPNe0C6pq8pBHaxUSulz4DEwu+W9AgBgdMrUJeEUy5bDKAfbGyKUIgzh1GgtwiizXqFfvZ3uf5NzfrrivzNqt9FxGYkGkeiWAgAISjg1eldlIoswqmFCKcIRTo2GMApGIqV0PplMXnf2056uar9U6XzYXcXftWZXgffzMGJltGjUDs7nOefHDVwHAMBGLYVT08Cd8NzeZakTD3XEA2FU24RShPVVOPWyvPkQ3ydhFIxPSum4s1Ns2yvstjhY0d+zbqe6pAgscqBqjxsAQDGEE0PHTAmnHG7vz3Id8dDOqBiEUoRXwqmT4c1nMpn8TWtuWB+G1urZdPZUGAWj9aKzLwjPcs4PGqVVOh6ere6S1kphnLBSSieB34/2V9WpCQDQixJODaHFo3K4vafdxmNzVbrfflJHjEkoRVdm09npUmvuO6cfmrc853V/aK0e+w2BMUspfQ7cFfQtxw/cLxU12Hlffp8QWdRuqa0O30sBAFamHG4fvqf9VMIN9cMYPpVA8XHZF3U+9hsSlVCKLpXTDwdLpx8++E035ay01j4y5xVYVroTenrP3rrvGL/SJfV89Ze0Fk6q0YPIr+MHdWkCAIzBEGqUcEP9sF2XSwfan5ZA0Yi+4IRSdK+8We2X7qnX2nM35rLc/+Ehsqe1FviO3sb4Pck536fjImqnw1lKSecr4ZVuv6hLsbcfOj4UAGBMluqH/6N+uHGLIOqnsivKgfbOCKUYjdI9dVzacwVU6/H1Q+TYQwT4kZTScOppv7Mb9SrnvHfb/3HZBxO1oGyXFD2JfIjGv0UAgDsqu+u/rh/qoKrv0w1BlPF8nRJKMUrfCKg8YFbjU7mfHiLAvZVOm3ed3cHTEjbdxkEZ/RfNpS4pelJez2dBf6Ttu4ThAAD80VL9cNFB9dIOqpW5KrXY10uj+dQQR+K//u///m/s9wD+YH4xHx40e+XPE3fnh4aHyOlkMhmKNqfmugIAAADQs/nF/GmZ8DHUD3f9sm/lrNQPP86mM4cZR0woBd8xv5g/WgqohFT/NozkO196iDjBAAAAAMBozS/mi9rh0/LfiJMvVmm5fnguhGKZUAru6KuHzPBnu+N7eLX8ACkPETuhAAAAAOAb5hfzx0u1w0UdsdegahFALYdQJinxTUIpWIESVA0Pl0Vn1eOAYdXQQvu5/BkeIJ8FUAAAAADwcGUi0yKoerz03wg1xMXB9S9LAdQXHVDch1AKKirzZR8tBVaPy5/Jmk9IfCoPjUkJnCYeHgAAAACweaWz6vFXtcO9pQurVUdchE0Lizrh4uD6F6s7WDWhFDRg6cHztb1bXN35UuD0O2ETAAAAAPRnqevqLgRMNEEoBQAAAAAAQHX/7RYDAAAAAABQm1AKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVPcXtxjq+udf//dwjbf4ZOf66LNfKQAAAAAArRFKQX1v1niPP04mE6EUAAAAAADNMb4PAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQnVAKAAAAAACA6oRSAAAAAAAAVCeUAgAAAAAAoDqhFAAAAAAAANUJpQAAAAAAAKhOKAUAAAAAAEB1QikAAAAAAACqE0oBAAAAAABQ3V/cYqjubI23+ItfJwAAAAAAzZlMJv8fRE+pgFGeHiEAAAAASUVORK5CYII='); &:focus { border-color: @darkGrafitoPurple; } &::selection { background: @darkGrafitoPurple !important; } } &.focused { .prompt, input { color: @darkFg; } } } /**************************************************** Multi-line Editor ****************************************************/ #editor { height: 400px; font-family: 'Fira Code' !important; text-shadow: 0 1px rgba(0,0,0,.3); line-height: 1.5; font-size: 1em; * { font-family: 'Fira Code' !important; } } /**************************************************** Sidebar ****************************************************/ ul.sidebar { position: fixed; left: 0px; width: @sidebarWidth; height: calc(100vh - @mainPushDown); top: @mainTop; background: #5a6169; border-right: @sidebarBorder solid #EEE; display: flex; flex-direction: column; justify-content: flex-start; padding-top: 0.5rem; padding-bottom: 0.5rem; box-shadow: -200px -141px 30px -200px rgba(0,0,0,0.39) inset; -webkit-box-shadow: -200px -141px 30px -200px rgba(0,0,0,0.39) inset; -moz-box-shadow: -200px -141px 30px -200px rgba(0,0,0,0.39) inset; li { padding: 0.3rem; font-size: 2.5rem; margin: 0.3rem; margin-bottom: 1rem; border-radius: 1rem; display: flex; align-items: center; justify-content: center; height: 3rem; color: #AAA; text-shadow: 0px 1px 0px rgba(255,255,255,.3), 0px -1px 0px rgba(0,0,0,.7); &:nth-child(4) { margin-top: auto; } &.active { color: #5fbff9; } &:not(.active):hover { color: #CCC; border-color: #EEE; } } } /**************************************************** Main content window ****************************************************/ #content { position: fixed; left: (@sidebarWidth+@sidebarBorder) - 2px; top: @mainTop; right: 0; width: calc(100vw - (@sidebarWidth+@sidebarBorder) + 1px); height: calc(100vh - @mainPushDown); background: white; margin: 0px; padding: 0px; overflow-x: hidden; overflow-y: hidden; &:focus { outline: none; } } /**************************************************** Slide-in edit options ****************************************************/ .editOptions { position: absolute; top: 15px; right: 15px; z-index: 10; .editOption { background: white; border: 3px solid lightgray; border-radius: 50%; font-size: 2rem; margin-bottom: 1rem; width: 3rem; height: 3rem; color: lightgray; display: flex; justify-content: center; align-items: center; cursor: pointer; &:hover { border-color: gray; color: gray; } &.modifying { &:hover { border-color: @modifyingColor; color: @modifyingColor; } } &.destructive { &:hover { border-color: @destructiveColor; color: @destructiveColor; } } } .editOption-separator { height: 1.4rem; padding-top: 0.4rem; padding-bottom: 0.4rem; width: 50%; border-top: 3px dotted #EEEEEE; text-align: center; left: 0.7rem; position: relative; } } .dark .editOptions { .editOption { background: @darkBgDarker; border-color: #999; color: #999; &:not(.modifying):not(.destructive):hover { border-color: @darkFgDarker; color: @darkFg; } } .editOption-separator { border-color: @darkFgDarker; } } /**************************************************** Graph view ****************************************************/ #graph { .stretched(); .vis-network, .vis-network:focus, canvas, canvas:focus { outline: none !important; } .vis-network { .vis-navigation { .vis-button { filter: opacity(0.3) grayscale(1); &:hover { filter: opacity(1) grayscale(1); //hue-rotate(-213deg) saturate(5); box-shadow: none !important; } } } } } .dark #graph { background: @darkBg; .vis-network { .vis-navigation { .vis-button { filter: opacity(0.3) invert(1) grayscale(1); &:hover { filter: opacity(1) invert(1) grayscale(1); } } } } } /**************************************************** Table view ****************************************************/ #table { .stretched(); .noselect(); padding: 2rem; overflow-y: auto; .dataTables_wrapper { table.dataTable { &>thead .sorting:before, &>thead .sorting_asc:before, &>thead .sorting_desc:before, &>thead .sorting_asc_disabled:before, &>thead .sorting_desc_disabled:before { right: 1.1em; top: 0.7rem; } &>thead .sorting:after, &>thead .sorting_asc:after, &>thead .sorting_desc:after, &>thead .sorting_asc_disabled:after, &>thead .sorting_desc_disabled:after { right: 0.5em; top: 0.7rem; } thead { .sorting_asc, .sorting_desc, .sorting { background-image: none !important; } } tbody { th, td { padding: .5em 1em !important; } } &.stripe tbody tr.odd, &.display tbody tr.odd { background-color: inherit; } } .dtsb-searchBuilder { .dtsb-titleRow { display: none !important; } div.dtsb-group div.dtsb-criteria { select.dtsb-value, input.dtsb-value { border: 1px solid black; height: 2.4rem; border-radius: .375em; background-color: #fff; padding-right: 2.5em; } select.dtsb-data, select.dtsb-condition { border-color: inherit !important; } } &.hidden { display: none; } } .dataTables_filter { padding-bottom: 1rem; text-align: center !important; float: left; input { margin-left: 10px; font-size: 1rem; width: 15rem; vertical-align: inherit !important; } #filterLabel { margin-left: 1rem; } } .dataTables_length { padding-bottom: 1rem; float: right; select { margin-left: 5px; margin-right: 5px; font-size: 1rem; width: 5rem; vertical-align: inherit !important; } } .dataTables_info { padding-top: 1.6rem; } .dataTables_paginate { padding-top: 1rem; .paginate_button { border-radius: 50% !important; } } input, select { &:focus-visible { outline: none; border-color: #5fbff9; } } select { -webkit-appearance: none; appearance: none; -webkit-appearance: none; -moz-appearance: none; background: transparent; background-image: url("data:image/svg+xml;utf8,"); background-repeat: no-repeat; background-position-x: 100%; border: 1px solid #dfdfdf; } } } .dark #table { background: @darkBg; .dataTables_wrapper { table.dataTable { color: @darkFg; background: @darkBgDarker; thead td, thead th { color: @darkFg; } td, th { border-color: black !important; } *:not(.sorting_1):not(.sorting_2):not(.sorting_3) { td, th { border-color: @darkBg !important; } } .sorting_1, .sorting_2, .sorting_3 { background: black !important; } tbody tr:not(.is-selected):nth-child(even) { background: @darkBg !important; } } .dtsb-searchBuilder { button { background-color: black; border-color: black; color: @darkFg; &.is-hovered, &:hover { background-color: @darkBgDarker; color: white; } } } .dataTables_length, .dataTables_filter, .dataTables_info, .dataTables_processing, .dataTables_paginate { color: @darkFgDarker; } .dataTables_paginate { .paginate_button { background: black; color: @darkFgDarker; &:hover { color: @darkFg; } &.current { color: @darkFg !important; } } } input, select { color: @darkFg; &.dtsb-value { background: @darkBg !important; color: @darkFg !important; border-color: @darkFg !important; } } .switch[type=checkbox].is-small+label::before, .switch[type=checkbox].is-small+label:before { background: @darkBgDarker !important; } .switch[type=checkbox].is-info:checked+label::before, .switch[type=checkbox].is-info:checked+label:before { background: #209cee !important; } select { color: @darkFg; background-image: url("data:image/svg+xml;utf8,"); } } } /**************************************************** Query history page ****************************************************/ #query-history { .stretched(); .noselect(); padding: 2rem; overflow-y: auto; table { table-layout: fixed; .query-cell { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: 'Fira Code' !important; } .query-ok { color: green; } .query-wrong { color: red; } th, td { &:last-child { text-align: right; } } } .no-queries { display: flex; justify-content: center; align-items: center; height: 15rem; flex-direction: column; color: #888; .error-icon { font-size: 3rem; } .error-message { margin-top: 1rem; font-size: 1.2rem; } } } .dark #query-history { background: @darkBg; table { color: @darkFg; background: @darkBgDarker; thead td, thead th { color: @darkFg; } td, th { border-color: black !important; } *:not(.sorting_1):not(.sorting_2):not(.sorting_3) { td, th { border-color: @darkBg !important; } } tbody tr:not(.is-selected):nth-child(even) { background: @darkBg !important; } a.button { background: black; color: @darkFgDarker; border-color: #666; &:hover { color: @darkGrafitoPurple; border-color: @darkGrafitoPurple; } } } } /**************************************************** Analytics page ****************************************************/ #database { .stretched(); .noselect(); padding: 2rem; overflow-y: auto; background: #F6F6F6; .hero { .title { color: @grafitoPurple; font-weight: 700; font-size: 3rem; .vernum { font-size: 1.3rem !important; padding-left: 0.35em; padding-right: 0.35em; color: #AAA; background-color: #EEE; height: inherit !important; margin-left: 0.5rem; } } .subtitle { color: #999; font-size: 0.8rem; display: flex; align-items: center; font-weight: bold; i { color: mediumseagreen; font-size: 1.2rem; } } .hero-body { padding: 1.5rem; padding-left: 1rem; padding-right: 1rem; .columns { padding-left: 1rem; padding-right: 1rem; } .right-column { display: flex; align-items: center; justify-content: flex-end; text-align: right; color: #999; b { font-weight: 600; } } } } .card { margin-top: 1.8rem; box-shadow: 0 0.2em 0.4em -0.1em rgb(10 10 10 / 10%), 0 0 0 1px rgb(10 10 10 / 2%); .card-header { box-shadow: none; border-bottom: 1px solid #EEE; .sideinfo { align-items: center; display: flex; padding: .75rem 1rem; color: #999; } } .card-content { padding: 1rem; } } .counters { .counter-column { display: flex; flex-direction: column; //border: 1px solid #EEE; &:not(:first-child) { border-left: 1px solid #EEE; } .counter { font-size: 3rem; font-weight: 600; } .counter-label { display: inline-flex; justify-content: center; align-items: center; font-size: 1.3rem; text-transform: uppercase; color: #AAA; font-weight: 700; text-shadow: rgb(255 255 255 / 50%) 0px 3px 3px; i { margin-right: 0.5rem; } } .counter-units { font-size: 1.5rem; } &:hover { .counter { color: darkgreen; } .counter-label { color: #666; } } } } } .dark #database { background: @darkBg; .hero { .title { color: @darkGrafitoPurple; .vernum { color: #888; background-color: @darkBgDarker; } } } .card { background: @darkBgDarker; color: @darkFg; .card-header { background: black; border-bottom: 1px solid #444; .card-header-title { color: white; } .sideinfo { color: @darkFgDarker; } } .card-content { //padding: 1rem; } } .counters { .counter-column { &:not(:first-child) { border-left: 1px solid #444; } .counter-label { color: @darkFgDarker; text-shadow: rgb(0 0 0 / 50%) 0px 3px 3px; } &:hover { .counter { color: greenyellow; } .counter-label { color: @darkFg; } } } } } /**************************************************** Global settings page ****************************************************/ #settings { .stretched(); .noselect(); padding: 2rem; overflow-y: auto; .panel { box-shadow: 0 0.2em 1em -0.125em rgb(10 10 10 / 3%), 0 0 0 1px rgb(10 10 10 / 3%); .panel-block { padding: 0.5rem 1rem; } } } .dark #settings { background: @darkBg; .panel { box-shadow: 0 0.2em 1em -0.125em rgb(250 250 250 / 3%), 0 0 0 1px rgb(250 250 250 / 3%); .panel-heading { background-color: @darkBgDarker; color: @darkFgDarker; } .panel-block { &:not(:last-child) { border-bottom: 1px solid @darkBgDarker; } } } } /**************************************************** Modals ****************************************************/ .modal { .modal-background { bottom: @infobarHeight !important; background-color: rgba(10,10,10,.5) !important; } .modal-card { .modal-card-title { display: inline-flex; font-size: 1.3rem; i { margin-right: 0.5rem; } } .modal-card-body { .palette-container { display: flex; margin-top: 1rem; margin-bottom: 1rem; } select { border-radius: 5px; padding: 0.3rem; } &.query-mode { padding: 0 !important; } .field-label { align-self: center; label { //font-variant: small-caps; //font-size: 1.2rem; } } button { &.is-hovered, &:hover { border-color: #dbdbdb !important; background: #F6F6F6; } &:not(.simple-dropdown).is-hovered, &:not(.simple-dropdown):hover { color: @destructiveColor; } } .control.has-icons-left .input, .control.has-icons-right .input { &~.icon { color: #AAA; .switchable { border-color: #AAA !important; } } &:focus~.icon { color: #333; .switchable { border-color: #333 !important; } } } } .modal-card-foot { justify-content: flex-end !important; padding-top: 8px; padding-bottom: 8px; .leftmost { margin-right: auto; .field { display: inline-flex !important; } } button { &.is-modifying { border-color: @modifyingColor; color: @modifyingColor; &:hover, &:focus { background-color: @modifyingColor; border-color: @modifyingColor; color: #fff; } } &.is-destructive { border-color: @destructiveColor; color: @destructiveColor; &:hover, &:focus { background-color: @destructiveColor; border-color: @destructiveColor; color: #fff; } } } } } // TODO(UI style) Check if dropdowns in modal dialogs work properly // there is an issue with Bulma & overflows for modal dialogs // labels: ui,bug &.with-dropdown { overflow: visible !important; .modal-card { overflow: visible !important; .modal-card-body { overflow: visible !important; } } } } .dark .modal { .modal-background { background-color: rgba(10,10,10,.7) !important; } .modal-card { .modal-card-head { border-color: black !important; background: @darkBgDarker; .modal-card-title { color: @darkFg !important; } .delete { filter: invert(1); &:hover { filter: none; } } } .modal-card-body { background: lighten(@darkBg, 5%); color: @darkFgDarker !important; .field-label, .field-label label { color: @darkFg !important; } select { background: @darkBgDarker; color: @darkFgDarker; } input { background-color: @darkBgDarker; color: @darkFgDarker; border-color: black; } .control.has-icons-left .input, .control.has-icons-right .input { &~.icon { color: #666; .switchable { border-color: #666 !important; } } &:focus~.icon { color: @darkGrafitoPurple; .switchable { border-color: @darkFg !important; } } } button { background-color: black; border-color: black; color: @darkFg; &.is-hovered, &:hover { background-color: lighten(black, 7%); border-color: black !important; } &:not(.simple-dropdown).is-hovered, &:not(.simple-dropdown):hover { color: @destructiveColor; } } } .modal-card-foot { border-color: black !important; background: @darkBg; color: @darkFg !important; .leftmost { input { background: @darkBgDarker; border-color: black; } button { border-color: black; } select { background: @darkBg; border-color: black; color: @darkFgDarker; } } button { background: transparent; color: @darkFgDarker; &:not(.is-destructive):not(.is-modifying):hover { color: @darkFg; } } } } } /**************************************************** Footer ****************************************************/ .infobar { .noselect(); position: fixed; left: 0px; right: 0px; top: calc(100vh - @infobarHeight); bottom: 0px; background: #F3F3F3; padding: 7px; padding-left: 68px; color: #666; font-size: 0.9em; border-top: 1px solid #DDD; z-index: 3000; .graph-info { .tag { font-weight: 600; font-size: 0.75rem; //text-transform: uppercase; } .breadcrumb { font-size: inherit; display: inline-block; margin-left: 0.6em; a { padding: 0 .5em; color: #666; } b { font-weight: 600; margin-right: 0.3rem; font-size: small; //font-variant: small-caps; } i { //font-variant: all-small-caps; font-style: normal; } li+li::before { content: '\205E'; color: @darkFgDarker; } li.edged+li.edged::before { content: '\2192' !important; color: @darkBgDarker; } } } .table-info { .dt-buttons { display: flex; justify-content: center; .dt-button { border: 0; font-size: 1.4rem; cursor: pointer; background: transparent; &:hover { color: @grafitoPurple; } } } } } .dark .infobar { color: @darkFgDarker; background: @darkBgDarker; border-color: black; .graph-info { .breadcrumb { a { color: @darkFgDarker; } li+li::before { color: #666; } li.edged+li.edged::before { color: @darkFg; } } } .table-info { .dt-buttons { .dt-button { color: @darkFg; &:hover { color: @darkGrafitoPurple; } } } } }