master
Giò Diani 2025-01-10 15:22:28 +01:00
commit c1c06cebc9
117 changed files with 180201 additions and 0 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.ttl filter=lfs diff=lfs merge=lfs -text

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
# ---> Laravel
/vendor/
node_modules/
npm-debug.log
yarn-error.log
# Laravel 4 specific
bootstrap/compiled.php
app/storage/
# Laravel 5 & Lumen specific
public/storage
public/hot
# Laravel 5 & Lumen specific with changed public path
public_html/storage
public_html/hot
storage/*.key
.env
Homestead.yaml
Homestead.json
/.vagrant
.phpunit.result.cache
# pixi environments
.pixi
*.egg-info
# Sublime Text
*.sublime-project
*.sublime-workspace

9
README.md Normal file
View File

@ -0,0 +1,9 @@
# Deskriptorenportal
Dieses Projekt wurde im Rahmen des Moduls «Knowledge Engineering and Extraction» an der FH Graubünden entwickelt. Dabei wurden Deskriptoren aus dem Thesaurus «Personen» der Burgerbibliothek Bern in einen RDF-Datensatz anhand der [RiC-O](https://ica-egad.github.io/RiC-O/) aufbereitet. Der RDF-Datensatz ist über eine Webapplikation explorierbar.
## Projektstruktur
- data-factory: Programmcode zur Aggregation und Aufbereitung des RDF-Datensatzes.
- qlever: Konfigurationsdateien für den RDF-Triple-Store / das SPARQL-Engine «[Qlever](https://github.com/ad-freiburg/qlever)».
- webapp: Programmcode der Webapplikation zur Exploration RDF-Datensatzes.
- docs: Dokumentationen zum Projekt (Präsentation, Bericht, Diagramme)

5
data-factory/README.md Normal file
View File

@ -0,0 +1,5 @@
# data-factory
Das Verzeichnis enthält den Programmcode zur Aggregation und Aufbereitung des RDF-Datensatzes.
# Installation
Zur Verwaltung der Abhängigkeiten wird [pixi](https://pixi.sh/) verwendet.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

BIN
data-factory/data/output/agents.ttl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
data-factory/data/output/agents_expanded.ttl (Stored with Git LFS) Normal file

Binary file not shown.

664
data-factory/pixi.lock Normal file
View File

@ -0,0 +1,664 @@
version: 5
environments:
default:
channels:
- url: https://conda.anaconda.org/conda-forge/
indexes:
- https://pypi.org/simple
packages:
linux-64:
- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.8.30-hbcca054_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.43-h712a8e2_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.4-h5888daf_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.2.0-h77fa898_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.2.0-h69a702a_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.2.0-h77fa898_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-h4bc722e_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.47.0-hadc24fc_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.2-hb9d3cd8_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.0-h9ebbce0_100_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.13-5_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2
- pypi: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/2b/c9/1c8fe3ce05d30c87eff498592c89015b19fade13df42850aafae09e94f35/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/a4/29/db12aa4dda81580be1999824a689bd52aa40061fc12c9ccdc3feab5ea718/dateparser-1.2.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/cf/66/d0be7c9518b1b92185018bacd851f977a101c9818686f667bbf884abcfbc/duckdb-1.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/6a/8b/6f0534ff7285e8d97e36a3838f88ffc8deb7cd0bc7b34f9f97d8bfdaae90/owlready2-0.47.tar.gz
- pypi: https://files.pythonhosted.org/packages/7f/1d/5d3ab93a88643c6f87c370d10e500bd8d710900492f3142ff78867c9ba49/owlrl-7.1.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/31/9e/21e05959323883abcee799837d8cac08adf10a48c233432993757e41791a/polars-1.16.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/54/9d/f253554b1457d4fdb3831b7bd5f8f00f1795585a606eabf6fec0a58a9c38/pyarrow-18.1.0-cp313-cp313-manylinux_2_28_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d2/7d/9add7b22a4e695c4f3011ed084ecf725e1f03954b9fa071f1766890b4989/rdflib-7.1.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/f8/bd/9cf93e42daa7b14bc0699d0bd10665345eb1d387f04d0abf47f436662c2d/reasonable-0.2.6-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/db/60/1eeca2074f5b87df394fccaa432ae3fc06c9c9bfa97c5051aed70e6e00c2/regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/97/3f/c4c51c55ff8487f2e6d0e618dba917e3c3ee2caae6cf0fbb59c9b1876f2e/tzlocal-5.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl
- pypi: .
packages:
- kind: conda
name: _libgcc_mutex
version: '0.1'
build: conda_forge
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726
md5: d7c89558ba9fa0495403155b64376d81
license: None
purls: []
size: 2562
timestamp: 1578324546067
- kind: conda
name: _openmp_mutex
version: '4.5'
build: 2_gnu
build_number: 16
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22
md5: 73aaf86a425cc6e73fcf236a5a46396d
depends:
- _libgcc_mutex 0.1 conda_forge
- libgomp >=7.5.0
constrains:
- openmp_impl 9999
license: BSD-3-Clause
license_family: BSD
purls: []
size: 23621
timestamp: 1650670423406
- kind: pypi
name: beautifulsoup4
version: 4.12.3
url: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl
sha256: b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed
requires_dist:
- soupsieve>1.2
- cchardet ; extra == 'cchardet'
- chardet ; extra == 'chardet'
- charset-normalizer ; extra == 'charset-normalizer'
- html5lib ; extra == 'html5lib'
- lxml ; extra == 'lxml'
requires_python: '>=3.6.0'
- kind: conda
name: bzip2
version: 1.0.8
build: h4bc722e_7
build_number: 7
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda
sha256: 5ced96500d945fb286c9c838e54fa759aa04a7129c59800f0846b4335cee770d
md5: 62ee74e96c5ebb0af99386de58cf9553
depends:
- __glibc >=2.17,<3.0.a0
- libgcc-ng >=12
license: bzip2-1.0.6
license_family: BSD
purls: []
size: 252783
timestamp: 1720974456583
- kind: conda
name: ca-certificates
version: 2024.8.30
build: hbcca054_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.8.30-hbcca054_0.conda
sha256: afee721baa6d988e27fef1832f68d6f32ac8cc99cdf6015732224c2841a09cea
md5: c27d1c142233b5bc9ca570c6e2e0c244
license: ISC
purls: []
size: 159003
timestamp: 1725018903918
- kind: pypi
name: certifi
version: 2024.8.30
url: https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl
sha256: 922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8
requires_python: '>=3.6'
- kind: pypi
name: charset-normalizer
version: 3.4.0
url: https://files.pythonhosted.org/packages/2b/c9/1c8fe3ce05d30c87eff498592c89015b19fade13df42850aafae09e94f35/charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
sha256: 4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc
requires_python: '>=3.7.0'
- kind: pypi
name: dateparser
version: 1.2.0
url: https://files.pythonhosted.org/packages/a4/29/db12aa4dda81580be1999824a689bd52aa40061fc12c9ccdc3feab5ea718/dateparser-1.2.0-py2.py3-none-any.whl
sha256: 0b21ad96534e562920a0083e97fd45fa959882d4162acc358705144520a35830
requires_dist:
- python-dateutil
- pytz
- regex!=2019.2.19,!=2021.8.27
- tzlocal
- hijri-converter ; extra == 'calendars'
- convertdate ; extra == 'calendars'
- fasttext ; extra == 'fasttext'
- langdetect ; extra == 'langdetect'
requires_python: '>=3.7'
- kind: pypi
name: duckdb
version: 1.1.3
url: https://files.pythonhosted.org/packages/cf/66/d0be7c9518b1b92185018bacd851f977a101c9818686f667bbf884abcfbc/duckdb-1.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
sha256: d5724fd8a49e24d730be34846b814b98ba7c304ca904fbdc98b47fa95c0b0cee
requires_python: '>=3.7.0'
- kind: pypi
name: idna
version: '3.10'
url: https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl
sha256: 946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
requires_dist:
- ruff>=0.6.2 ; extra == 'all'
- mypy>=1.11.2 ; extra == 'all'
- pytest>=8.3.2 ; extra == 'all'
- flake8>=7.1.1 ; extra == 'all'
requires_python: '>=3.6'
- kind: pypi
name: knex
version: 0.1.0
path: .
sha256: cffbf0bef24f3987a81885b0346d6d20b76d95050b3675cfb0083ad3dba54200
requires_dist:
- rdflib>=7.1.1,<8
- dateparser>=1.2.0,<2
- beautifulsoup4>=4.12.3,<5
- requests>=2.32.3,<3
- owlrl>=7.1.2,<8
- duckdb>=1.1.3,<2
- polars[pyarrow]>=1.16.0,<2
- reasonable>=0.2.6,<0.3
- owlready2>=0.47,<0.48
requires_python: '>=3.11'
editable: true
- kind: conda
name: ld_impl_linux-64
version: '2.43'
build: h712a8e2_2
build_number: 2
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.43-h712a8e2_2.conda
sha256: 7c91cea91b13f4314d125d1bedb9d03a29ebbd5080ccdea70260363424646dbe
md5: 048b02e3962f066da18efe3a21b77672
depends:
- __glibc >=2.17,<3.0.a0
constrains:
- binutils_impl_linux-64 2.43
license: GPL-3.0-only
license_family: GPL
purls: []
size: 669211
timestamp: 1729655358674
- kind: conda
name: libexpat
version: 2.6.4
build: h5888daf_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.4-h5888daf_0.conda
sha256: 56541b98447b58e52d824bd59d6382d609e11de1f8adf20b23143e353d2b8d26
md5: db833e03127376d461e1e13e76f09b6c
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=13
constrains:
- expat 2.6.4.*
license: MIT
license_family: MIT
purls: []
size: 73304
timestamp: 1730967041968
- kind: conda
name: libffi
version: 3.4.2
build: h7f98852_5
build_number: 5
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2
sha256: ab6e9856c21709b7b517e940ae7028ae0737546122f83c2aa5d692860c3b149e
md5: d645c6d2ac96843a2bfaccd2d62b3ac3
depends:
- libgcc-ng >=9.4.0
license: MIT
license_family: MIT
purls: []
size: 58292
timestamp: 1636488182923
- kind: conda
name: libgcc
version: 14.2.0
build: h77fa898_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.2.0-h77fa898_1.conda
sha256: 53eb8a79365e58849e7b1a068d31f4f9e718dc938d6f2c03e960345739a03569
md5: 3cb76c3f10d3bc7f1105b2fc9db984df
depends:
- _libgcc_mutex 0.1 conda_forge
- _openmp_mutex >=4.5
constrains:
- libgomp 14.2.0 h77fa898_1
- libgcc-ng ==14.2.0=*_1
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
purls: []
size: 848745
timestamp: 1729027721139
- kind: conda
name: libgcc-ng
version: 14.2.0
build: h69a702a_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.2.0-h69a702a_1.conda
sha256: 3a76969c80e9af8b6e7a55090088bc41da4cffcde9e2c71b17f44d37b7cb87f7
md5: e39480b9ca41323497b05492a63bc35b
depends:
- libgcc 14.2.0 h77fa898_1
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
purls: []
size: 54142
timestamp: 1729027726517
- kind: conda
name: libgomp
version: 14.2.0
build: h77fa898_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.2.0-h77fa898_1.conda
sha256: 1911c29975ec99b6b906904040c855772ccb265a1c79d5d75c8ceec4ed89cd63
md5: cc3573974587f12dda90d96e3e55a702
depends:
- _libgcc_mutex 0.1 conda_forge
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
purls: []
size: 460992
timestamp: 1729027639220
- kind: conda
name: libmpdec
version: 4.0.0
build: h4bc722e_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-h4bc722e_0.conda
sha256: d02d1d3304ecaf5c728e515eb7416517a0b118200cd5eacbe829c432d1664070
md5: aeb98fdeb2e8f25d43ef71fbacbeec80
depends:
- __glibc >=2.17,<3.0.a0
- libgcc-ng >=12
license: BSD-2-Clause
license_family: BSD
purls: []
size: 89991
timestamp: 1723817448345
- kind: conda
name: libsqlite
version: 3.47.0
build: hadc24fc_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.47.0-hadc24fc_1.conda
sha256: 8a9aadf996a2399f65b679c6e7f29139d5059f699c63e6d7b50e20db10c00508
md5: b6f02b52a174e612e89548f4663ce56a
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=13
- libzlib >=1.3.1,<2.0a0
license: Unlicense
purls: []
size: 875349
timestamp: 1730208050020
- kind: conda
name: libuuid
version: 2.38.1
build: h0b41bf4_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda
sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18
md5: 40b61aab5c7ba9ff276c41cfffe6b80b
depends:
- libgcc-ng >=12
license: BSD-3-Clause
license_family: BSD
purls: []
size: 33601
timestamp: 1680112270483
- kind: conda
name: libzlib
version: 1.3.1
build: hb9d3cd8_2
build_number: 2
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4
md5: edb0dca6bc32e4f4789199455a1dbeb8
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=13
constrains:
- zlib 1.3.1 *_2
license: Zlib
license_family: Other
purls: []
size: 60963
timestamp: 1727963148474
- kind: conda
name: ncurses
version: '6.5'
build: he02047a_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda
sha256: 6a1d5d8634c1a07913f1c525db6455918cbc589d745fac46d9d6e30340c8731a
md5: 70caf8bb6cf39a0b6b7efc885f51c0fe
depends:
- __glibc >=2.17,<3.0.a0
- libgcc-ng >=12
license: X11 AND BSD-3-Clause
purls: []
size: 889086
timestamp: 1724658547447
- kind: conda
name: openssl
version: 3.3.2
build: hb9d3cd8_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.2-hb9d3cd8_0.conda
sha256: cee91036686419f6dd6086902acf7142b4916e1c4ba042e9ca23e151da012b6d
md5: 4d638782050ab6faa27275bed57e9b4e
depends:
- __glibc >=2.17,<3.0.a0
- ca-certificates
- libgcc >=13
license: Apache-2.0
license_family: Apache
purls: []
size: 2891789
timestamp: 1725410790053
- kind: pypi
name: owlready2
version: '0.47'
url: https://files.pythonhosted.org/packages/6a/8b/6f0534ff7285e8d97e36a3838f88ffc8deb7cd0bc7b34f9f97d8bfdaae90/owlready2-0.47.tar.gz
sha256: af7e1d2205c0b5886d2e34397ab8c10ca29ff68c3dc3702d43393966ac7f6eb0
requires_dist:
- rdflib ; extra == 'test'
- flask ; extra == 'test'
- gevent ; extra == 'test'
requires_python: '>=3.6'
- kind: pypi
name: owlrl
version: 7.1.2
url: https://files.pythonhosted.org/packages/7f/1d/5d3ab93a88643c6f87c370d10e500bd8d710900492f3142ff78867c9ba49/owlrl-7.1.2-py3-none-any.whl
sha256: b4234191d1981ee7c551fa203cc0d21470c38e624e6795f3ecac55651dab26b1
requires_dist:
- rdflib>=7.1.1
requires_python: '>=3.8,<4.0'
- kind: pypi
name: polars
version: 1.16.0
url: https://files.pythonhosted.org/packages/31/9e/21e05959323883abcee799837d8cac08adf10a48c233432993757e41791a/polars-1.16.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
sha256: e626d21dcd2566e1442dac414fe177bc70ebfc2f16620d59d778b1b774361018
requires_dist:
- numpy>=1.16.0 ; extra == 'numpy'
- pandas ; extra == 'pandas'
- polars[pyarrow] ; extra == 'pandas'
- pyarrow>=7.0.0 ; extra == 'pyarrow'
- pydantic ; extra == 'pydantic'
- fastexcel>=0.9 ; extra == 'calamine'
- openpyxl>=3.0.0 ; extra == 'openpyxl'
- xlsx2csv>=0.8.0 ; extra == 'xlsx2csv'
- xlsxwriter ; extra == 'xlsxwriter'
- polars[calamine,openpyxl,xlsx2csv,xlsxwriter] ; extra == 'excel'
- adbc-driver-manager[dbapi] ; extra == 'adbc'
- adbc-driver-sqlite[dbapi] ; extra == 'adbc'
- connectorx>=0.3.2 ; extra == 'connectorx'
- sqlalchemy ; extra == 'sqlalchemy'
- polars[pandas] ; extra == 'sqlalchemy'
- polars[adbc,connectorx,sqlalchemy] ; extra == 'database'
- nest-asyncio ; extra == 'database'
- fsspec ; extra == 'fsspec'
- deltalake>=0.15.0 ; extra == 'deltalake'
- pyiceberg>=0.5.0 ; extra == 'iceberg'
- gevent ; extra == 'async'
- cloudpickle ; extra == 'cloudpickle'
- matplotlib ; extra == 'graph'
- altair>=5.4.0 ; extra == 'plot'
- great-tables>=0.8.0 ; extra == 'style'
- backports-zoneinfo ; python_full_version < '3.9' and extra == 'timezone'
- tzdata ; platform_system == 'Windows' and extra == 'timezone'
- cudf-polars-cu12 ; extra == 'gpu'
- polars[async,cloudpickle,database,deltalake,excel,fsspec,graph,iceberg,numpy,pandas,plot,pyarrow,pydantic,style,timezone] ; extra == 'all'
requires_python: '>=3.9'
- kind: pypi
name: pyarrow
version: 18.1.0
url: https://files.pythonhosted.org/packages/54/9d/f253554b1457d4fdb3831b7bd5f8f00f1795585a606eabf6fec0a58a9c38/pyarrow-18.1.0-cp313-cp313-manylinux_2_28_x86_64.whl
sha256: 36ac22d7782554754a3b50201b607d553a8d71b78cdf03b33c1125be4b52397c
requires_dist:
- pytest ; extra == 'test'
- hypothesis ; extra == 'test'
- cffi ; extra == 'test'
- pytz ; extra == 'test'
- pandas ; extra == 'test'
requires_python: '>=3.9'
- kind: pypi
name: pyparsing
version: 3.2.0
url: https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl
sha256: 93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84
requires_dist:
- railroad-diagrams ; extra == 'diagrams'
- jinja2 ; extra == 'diagrams'
requires_python: '>=3.9'
- kind: conda
name: python
version: 3.13.0
build: h9ebbce0_100_cp313
build_number: 100
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.0-h9ebbce0_100_cp313.conda
sha256: 6ab5179679f0909db828d8316f3b8b379014a82404807310fe7df5a6cf303646
md5: 08e9aef080f33daeb192b2ddc7e4721f
depends:
- __glibc >=2.17,<3.0.a0
- bzip2 >=1.0.8,<2.0a0
- ld_impl_linux-64 >=2.36.1
- libexpat >=2.6.3,<3.0a0
- libffi >=3.4,<4.0a0
- libgcc >=13
- libmpdec >=4.0.0,<5.0a0
- libsqlite >=3.46.1,<4.0a0
- libuuid >=2.38.1,<3.0a0
- libzlib >=1.3.1,<2.0a0
- ncurses >=6.5,<7.0a0
- openssl >=3.3.2,<4.0a0
- python_abi 3.13.* *_cp313
- readline >=8.2,<9.0a0
- tk >=8.6.13,<8.7.0a0
- tzdata
- xz >=5.2.6,<6.0a0
license: Python-2.0
purls: []
size: 33112481
timestamp: 1728419573472
- kind: pypi
name: python-dateutil
version: 2.9.0.post0
url: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl
sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
requires_dist:
- six>=1.5
requires_python: '!=3.0.*,!=3.1.*,!=3.2.*,>=2.7'
- kind: conda
name: python_abi
version: '3.13'
build: 5_cp313
build_number: 5
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.13-5_cp313.conda
sha256: 438225b241c5f9bddae6f0178a97f5870a89ecf927dfca54753e689907331442
md5: 381bbd2a92c863f640a55b6ff3c35161
constrains:
- python 3.13.* *_cp313
license: BSD-3-Clause
license_family: BSD
purls: []
size: 6217
timestamp: 1723823393322
- kind: pypi
name: pytz
version: '2024.2'
url: https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl
sha256: 31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725
- kind: pypi
name: rdflib
version: 7.1.1
url: https://files.pythonhosted.org/packages/d2/7d/9add7b22a4e695c4f3011ed084ecf725e1f03954b9fa071f1766890b4989/rdflib-7.1.1-py3-none-any.whl
sha256: e590fa9a2c34ba33a667818b5a84be3fb8a4d85868f8038f17912ec84f912a25
requires_dist:
- berkeleydb>=18.1.0,<19.0.0 ; extra == 'berkeleydb'
- html5rdf>=1.2,<2 ; extra == 'html'
- isodate>=0.7.2,<1.0.0 ; python_full_version < '3.11'
- lxml>=4.3,<6.0 ; extra == 'lxml'
- networkx>=2,<4 ; extra == 'networkx'
- orjson>=3.9.14,<4 ; extra == 'orjson'
- pyparsing>=2.1.0,<4
requires_python: '>=3.8.1,<4.0.0'
- kind: conda
name: readline
version: '8.2'
build: h8228510_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda
sha256: 5435cf39d039387fbdc977b0a762357ea909a7694d9528ab40f005e9208744d7
md5: 47d31b792659ce70f470b5c82fdfb7a4
depends:
- libgcc-ng >=12
- ncurses >=6.3,<7.0a0
license: GPL-3.0-only
license_family: GPL
purls: []
size: 281456
timestamp: 1679532220005
- kind: pypi
name: reasonable
version: 0.2.6
url: https://files.pythonhosted.org/packages/f8/bd/9cf93e42daa7b14bc0699d0bd10665345eb1d387f04d0abf47f436662c2d/reasonable-0.2.6-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
sha256: 5e6b5aea2bbf4cadcf26a8e256d76670f37848707849a9590f94d2aa1a9c2392
- kind: pypi
name: regex
version: 2024.11.6
url: https://files.pythonhosted.org/packages/db/60/1eeca2074f5b87df394fccaa432ae3fc06c9c9bfa97c5051aed70e6e00c2/regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
sha256: 3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c
requires_python: '>=3.8'
- kind: pypi
name: requests
version: 2.32.3
url: https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl
sha256: 70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
requires_dist:
- charset-normalizer<4,>=2
- idna<4,>=2.5
- urllib3<3,>=1.21.1
- certifi>=2017.4.17
- pysocks!=1.5.7,>=1.5.6 ; extra == 'socks'
- chardet<6,>=3.0.2 ; extra == 'use-chardet-on-py3'
requires_python: '>=3.8'
- kind: pypi
name: six
version: 1.16.0
url: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
sha256: 8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*'
- kind: pypi
name: soupsieve
version: '2.6'
url: https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl
sha256: e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9
requires_python: '>=3.8'
- kind: conda
name: tk
version: 8.6.13
build: noxft_h4845f30_101
build_number: 101
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda
sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e
md5: d453b98d9c83e71da0741bb0ff4d76bc
depends:
- libgcc-ng >=12
- libzlib >=1.2.13,<2.0.0a0
license: TCL
license_family: BSD
purls: []
size: 3318875
timestamp: 1699202167581
- kind: conda
name: tzdata
version: 2024b
build: hc8b5060_0
subdir: noarch
noarch: generic
url: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda
sha256: 4fde5c3008bf5d2db82f2b50204464314cc3c91c1d953652f7bd01d9e52aefdf
md5: 8ac3367aafb1cc0a068483c580af8015
license: LicenseRef-Public-Domain
purls: []
size: 122354
timestamp: 1728047496079
- kind: pypi
name: tzlocal
version: '5.2'
url: https://files.pythonhosted.org/packages/97/3f/c4c51c55ff8487f2e6d0e618dba917e3c3ee2caae6cf0fbb59c9b1876f2e/tzlocal-5.2-py3-none-any.whl
sha256: 49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8
requires_dist:
- tzdata ; platform_system == 'Windows'
- backports-zoneinfo ; python_full_version < '3.9'
- pytest>=4.3 ; extra == 'devenv'
- pytest-mock>=3.3 ; extra == 'devenv'
- pytest-cov ; extra == 'devenv'
- check-manifest ; extra == 'devenv'
- zest-releaser ; extra == 'devenv'
requires_python: '>=3.8'
- kind: pypi
name: urllib3
version: 2.2.3
url: https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl
sha256: ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac
requires_dist:
- brotli>=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli'
- brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli'
- h2<5,>=4 ; extra == 'h2'
- pysocks!=1.5.7,<2.0,>=1.5.6 ; extra == 'socks'
- zstandard>=0.18.0 ; extra == 'zstd'
requires_python: '>=3.8'
- kind: conda
name: xz
version: 5.2.6
build: h166bdaf_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2
sha256: 03a6d28ded42af8a347345f82f3eebdd6807a08526d47899a42d62d319609162
md5: 2161070d867d1b1204ea749c8eec4ef0
depends:
- libgcc-ng >=12
license: LGPL-2.1 and GPL-2.0
purls: []
size: 418368
timestamp: 1660346797927

View File

@ -0,0 +1,25 @@
[project]
authors = [{name = "Giò Diani", email = "mail@gionathandiani.name"}]
dependencies = [ "rdflib>=7.1.1,<8", "dateparser>=1.2.0,<2", "beautifulsoup4>=4.12.3,<5", "requests>=2.32.3,<3", "owlrl>=7.1.2,<8", "duckdb>=1.1.3,<2", "polars[pyarrow]>=1.16.0,<2", "reasonable>=0.2.6,<0.3", "owlready2>=0.47,<0.48"]
description = "Transforms tabular data to a graph."
name = "knex"
requires-python = ">= 3.11"
version = "0.1.0"
repository = "https://gitea.fhgr.ch/dianigionath/knex"
[build-system]
build-backend = "hatchling.build"
requires = ["hatchling"]
[tool.pixi.project]
channels = ["conda-forge"]
platforms = ["linux-64"]
[tool.pixi.pypi-dependencies]
knex = { path = ".", editable = true }
[host-dependencies]
sling = "~=1.3.1"
[tool.pixi.tasks]
sling_install = "wget -O sling_linux_amd64.tar.gz https://github.com/slingdata-io/sling-cli/releases/download/v1.3.1/sling_linux_amd64.tar.gz && tar -xzvf sling_linux_amd64.tar.gz -C $PIXI_PROJECT_ROOT/.pixi/envs/default/bin && rm sling_linux_amd64.tar.gz"

View File

@ -0,0 +1,258 @@
import re
from pathlib import Path
import duckdb
from rdflib import RDF, BNode, Graph, Literal, URIRef
from rdflib.namespace import RDFS, XSD, Namespace
BIO = Namespace("http://purl.org/vocab/bio/0.1/")
RICO = Namespace("https://www.ica.org/standards/RiC/ontology#")
WD = Namespace("http://www.wikidata.org/wiki/")
DATA_PATH = Path("../data")
DB = duckdb.connect(DATA_PATH / "input" / "deskriptoren.db")
# database queries
# get agents
df = DB.sql("""
SELECT
id_nr,
id_name,
ark,
beschreibung
FROM
input.personendeskriptoren
WHERE
ark NOT NULL
""").pl()
# Get sex of agents
df_sex = DB.sql("""
SELECT
ark,
geschlecht
FROM
input.personendeskriptoren
WHERE geschlecht NOT NULL
""").pl()
# Get birthdates of agents
df_birth_dates = DB.sql("""
SELECT
ark,
geburtsdatum
FROM
input.personendeskriptoren
WHERE geburtsdatum NOT NULL
""").pl()
# Get baptism dates of agents
df_baptism_dates = DB.sql("""
SELECT
ark,
taufdatum
FROM
input.personendeskriptoren
WHERE taufdatum NOT NULL
""").pl()
# Get death dates of agents
df_death_dates = DB.sql("""
SELECT
ark,
todesdatum
FROM
input.personendeskriptoren
WHERE todesdatum NOT NULL
""").pl()
# Get burial dates of agents
df_burial_dates = DB.sql("""
SELECT
ark,
begrabnisdatum
FROM
input.personendeskriptoren
WHERE begrabnisdatum NOT NULL
""").pl()
# Get all children relations
df_children = DB.sql("""
SELECT DISTINCT
p1.ark AS sub_ark,
p2.ark AS obj_ark
FROM
input.personendeskriptoren_zusatz pz
JOIN
input.personendeskriptoren p1 ON p1.id_nr = pz.col_001
JOIN
input.personendeskriptoren p2 ON p2.id_nr = pz.col_004
WHERE
pz.col_002 = 'Kind:'
""").pl()
# Get all spouses
df_life_partners = DB.sql("""
SELECT DISTINCT
p1.ark AS sub_ark,
p2.ark AS obj_ark
FROM
input.personendeskriptoren_zusatz pz
JOIN
input.personendeskriptoren p1 ON p1.id_nr = pz.col_001
JOIN
input.personendeskriptoren p2 ON p2.id_nr = pz.col_004
WHERE
pz.col_002 = 'Lebenspartner / Lebenspartnerin:'
""").pl()
# Get all life partners
df_spouses = DB.sql("""
SELECT DISTINCT
p1.ark AS sub_ark,
p2.ark AS obj_ark
FROM
input.personendeskriptoren_zusatz pz
JOIN
input.personendeskriptoren p1 ON p1.id_nr = pz.col_001
JOIN
input.personendeskriptoren p2 ON p2.id_nr = pz.col_004
WHERE
pz.col_002 = 'Ehepartner / Ehepartnerin:'
""").pl()
# convert dates from dataset to literals
def date_lit(date):
# If format is YYYY => gYear
if re.match(r"\d{4}$", date):
return Literal(date, datatype=XSD.gYear)
# If format is YYYY-mm or mm.YYYY => gYearMonth
elif re.match(r"\d{2}\.\d{4}", date):
date = date.split(".")
date = "-".join(date[::-1])
return Literal(date, datatype=XSD.gYearMonth)
# If format is YYYY-mm-dd or dd.mm.YYYY => date
elif re.match(r"\d{4}\-\d{2}-\d{2}$|\d{2}\.\d{2}.\d{4}$", date):
date = date.split(".")
date = "-".join(date[::-1])
return Literal(date, datatype=XSD.date)
# If format is YYYY v. Chr. => -YYYY => gYear
elif re.match(r"\d+(?=\sv\.\sChr\.)", date):
jh = int(re.match(r"\d+(?=\sv\.\sChr\.)", date).group())
jh = str(f"-{jh:04d}")
return Literal(jh, datatype=XSD.gYear)
# Return as string if no ISO date found / possible
else:
return Literal(date, datatype=XSD.string)
# init graph
g = Graph()
# create prefixes for namespaces
g.bind("bio", BIO)
g.bind("rico", RICO)
g.bind("wd", WD)
def bbb_uri_ref(name):
return URIRef("https://burgerbib.ch/" + str(name))
def agent(ark):
return bbb_uri_ref("indexterms/" + str(ark))
# Define Demographic Groups
demographicgroup_sex_m = bbb_uri_ref("DemographicGroups/SexMale")
g.add((demographicgroup_sex_m, RDFS.subClassOf, RICO.DemographicGroup))
g.add((demographicgroup_sex_m, RDFS.label, Literal("Male (biological sex)")))
demographicgroup_sex_f = bbb_uri_ref("DemographicGroups/SexFemale")
g.add((demographicgroup_sex_f, RDFS.subClassOf, RICO.DemographicGroup))
g.add((demographicgroup_sex_f, RDFS.label, Literal("Female (biological sex)")))
# Define association
hasOrHadLifePartner = bbb_uri_ref("relations/hasOrHadLifePartner")
g.add((hasOrHadLifePartner, RDFS.subPropertyOf, RICO.hasFamilyAssociationWith))
g.add((hasOrHadLifePartner, RDFS.label, Literal("Connects two Persons who are or were in a romantic relationship, as if they are spouses but without being legally married.")))
# Define Identifiertypes
idtype_ark = bbb_uri_ref("IdentifierTypes/ARK")
g.add((idtype_ark, RDFS.subClassOf, RICO.IdentifierType))
g.add((idtype_ark, RICO.closeTo, WD.Q2860403))
idtype_scope = bbb_uri_ref("IdentifierTypes/Scope-ID")
g.add((idtype_scope, RDFS.subClassOf, RICO.IdentifierType))
g.add((idtype_scope, RDFS.label, Literal("ID from the ScopeArchiv AIS.")))
# Define new EventTypes
eventtype_baptism = bbb_uri_ref("EventTypes/Baptism")
g.add((eventtype_baptism, RDFS.subClassOf, RICO.EventType))
g.add((eventtype_baptism, RICO.closeTo, BIO.Baptism))
eventtype_burial = bbb_uri_ref("EventTypes/Burial")
g.add((eventtype_burial, RDFS.subClassOf, RICO.EventType))
g.add((eventtype_burial, RICO.closeTo, BIO.Burial))
# Iterate dataset and generate triples
for row in df.rows(named=True):
ark_id = bbb_uri_ref("identifiers/"+row["ark"])
g.add((ark_id, RICO.isOrWasIdentifierOf, (agent(row["ark"]))))
g.add((ark_id, RICO.hasIdentifierType, idtype_ark))
g.add((ark_id, RICO.normalizedValue, Literal(row["ark"], datatype=XSD.string)))
scope_id = bbb_uri_ref("identifiers/scope:"+str(row["id_nr"]))
g.add((scope_id, RICO.isOrWasIdentifierOf, (agent(row["ark"]))))
g.add((scope_id, RICO.hasIdentifierType, idtype_scope))
g.add((scope_id, RICO.normalizedValue, Literal(row["id_nr"], datatype=XSD.nonNegativeInteger)))
label = re.findall(r".+(?=\(Personen\\Natürliche Personen\\.+\))", row["id_name"])[0].strip()
name = label.split("(")[0].strip()
g.add((agent(row["ark"]), RDF.type, RICO.Person))
g.add((agent(row["ark"]), RICO.hasOrHadName, Literal(name, datatype=XSD.string)))
g.add((agent(row["ark"]), RDFS.label, Literal(label, datatype=XSD.string)))
g.add((agent(row["ark"]), RICO.generalDescription, Literal(row["beschreibung"], datatype=XSD.string)))
for row in df_sex.rows():
if row[1] == "männlich":
g.add((agent(row[0]), RICO.hasOrHadDemographicGroup, demographicgroup_sex_m))
else:
g.add((agent(row[0]), RICO.hasOrHadDemographicGroup, demographicgroup_sex_f))
# Add birth dates.
for row in df_birth_dates.rows():
g.add((agent(row[0]), RICO.hasBirthDate, date_lit(row[1])))
# Add baptism dates.
for row in df_baptism_dates.rows():
baptism = BNode()
g.add((baptism, RICO.hasEventType, eventtype_baptism))
g.add((baptism, RICO.occurredAtDate, date_lit(row[1])))
g.add((agent(row[0]), RICO.isAssociatedWithEvent, baptism))
# Add dates of death.
for row in df_death_dates.rows():
g.add((agent(row[0]), RICO.hasDeathDate, date_lit(row[1])))
# Add dates of burial.
for row in df_burial_dates.rows():
burial = BNode()
g.add((burial, RICO.hasEventType, eventtype_burial))
g.add((burial, RICO.occurredAtDate, date_lit(row[1])))
g.add((agent(row[0]), RICO.isAssociatedWithEvent, burial))
for row in df_children.rows():
g.add((agent(row[0]), RICO.hasChild, agent(row[1])))
for row in df_spouses.rows():
g.add((agent(row[0]), RICO.hasOrHadSpouse, agent(row[1])))
for row in df_life_partners.rows():
g.add((agent(row[0]), RICO.hasOrHadLifePartner, agent(row[1])))
# Save graph to ttl file.
g.serialize(destination=DATA_PATH / "output" / "agents.ttl")

View File

View File

@ -0,0 +1,36 @@
from pathlib import Path
from owlrl import DeductiveClosure, OWLRL_Extension
from rdflib import Graph as _Graph
from rdflib import Literal
DATA_PATH = Path("../data")
# patch hack to catch triples w/ Literal as subject: https://github.com/RDFLib/OWL-RL/issues/50#issuecomment-1476897684
class Graph(_Graph):
def __init__(self, *p, **k):
self._offensive = set()
super().__init__(*p, **k)
def add(self, t):
if isinstance(t[0], Literal):
self._offensive.add(t)
# so that it keeps working as usual
return super().add(t)
# Load dataset and ontologies.
g = Graph()
g.parse(DATA_PATH / "output" / "agents.ttl")
g.parse(DATA_PATH / "input" / "onto_RiC-O_1-0-2.rdf", format="application/rdf+xml")
g.parse(DATA_PATH / "input" / "onto_bio_0.1.rdf", format="application/rdf+xml")
# Apply reasoning using
DeductiveClosure(OWLRL_Extension, rdfs_closure = True, axiomatic_triples = True, datatype_axioms = True).expand(g)
# Remove offensive triples
for offensive_triple in g._offensive:
g.remove(offensive_triple)
# Save the expanded RDF graph
g.serialize(destination= DATA_PATH / "output" / "agents_expanded.ttl")

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
import os.path as path
import subprocess
DATA_PATH = str(path.abspath(path.join(__file__ ,"../../data/input")))
BIN_PATH = str(path.abspath(path.join(__file__ ,"../../.pixi/envs/default/bin")))
SLING_CONFIG = str(path.abspath(path.join(__file__ ,"../../.sling")))
subprocess.run(f"export DUCKDB='duckdb:///{DATA_PATH}/deskriptoren.db'; {BIN_PATH}/sling run --src-stream file:///{DATA_PATH}/personendeskriptoren.csv --src-options '{{\"delimiter\": \";\"}}' --tgt-conn duckdb:///{DATA_PATH}/deskriptoren.db --tgt-object {{stream_file_folder}}.{{stream_file_name}} --mode full-refresh; {BIN_PATH}/sling run --src-stream file:///{DATA_PATH}/personendeskriptoren_zusatz.csv --src-options '{{\"header\": false}}' --tgt-conn duckdb:///{DATA_PATH}/deskriptoren.db --tgt-object {{stream_file_folder}}.{{stream_file_name}} --mode full-refresh", shell=True)

276
docs/diagrams/C4.drawio Normal file
View File

@ -0,0 +1,276 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0" version="26.0.4" pages="2">
<diagram name="Seite-1" id="Fh3o327mbMo_3nkY4QW4">
<mxGraphModel dx="796" dy="1107" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="light-dark(#13171f, #121212)" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="TKOOJ7FrXuCLbUddgnAH-12" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#FFFFFF;" parent="1" source="TKOOJ7FrXuCLbUddgnAH-1" target="TKOOJ7FrXuCLbUddgnAH-6" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="szCxDTQn5Ym88xMkrpwM-3" value="besucht Webseite&lt;br&gt;[HTTPS]" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;fontColor=#FFFFFF;labelBackgroundColor=#13171F;" parent="TKOOJ7FrXuCLbUddgnAH-12" vertex="1" connectable="0">
<mxGeometry x="-0.1101" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Benutzer:in" c4Type="Person" c4Description="Person welche recherchiert." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-1">
<mxCell style="html=1;fontSize=11;dashed=0;whiteSpace=wrap;fillColor=#083F75;strokeColor=#06315C;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="80" y="290" width="200" height="180" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="SPARQL Engine" c4Type="Container" c4Technology="Qlever" c4Description="RDF Triple Store und Endpoint&lt;br&gt; für SPARQL-Anfragen." label="&lt;font style=&quot;font-size: 14px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%:&amp;nbsp;%c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#FFF&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-3">
<mxCell style="shape=cylinder3;size=15;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="840" y="310" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="Deskriptorenportal" c4Type="Container" c4Technology="Apache Echarts, Pico CSS" c4Description="Bietet Möglichkeit zur Exploration und Visualisierung des RDF-Datensatzes." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%:&amp;nbsp;%c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-5">
<mxCell style="shape=mxgraph.c4.webBrowserContainer2;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;strokeColor=#118ACD;fillColor=#23A2D9;strokeColor=#118ACD;strokeColor2=#0E7DAD;fontSize=12;fontColor=#ffffff;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="460" y="490" width="240" height="160" as="geometry" />
</mxCell>
</object>
<mxCell id="TKOOJ7FrXuCLbUddgnAH-7" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#FFFFFF;" parent="1" source="TKOOJ7FrXuCLbUddgnAH-6" target="TKOOJ7FrXuCLbUddgnAH-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="TKOOJ7FrXuCLbUddgnAH-9" value="Liefert an den Browser &lt;br&gt;der Benutzer:innen" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;fontColor=#FFFFFF;labelBackgroundColor=light-dark(#13171f, #ededed);" parent="TKOOJ7FrXuCLbUddgnAH-7" vertex="1" connectable="0">
<mxGeometry x="-0.0118" y="-2" relative="1" as="geometry">
<mxPoint x="3" y="-5" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="TKOOJ7FrXuCLbUddgnAH-10" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#FFFFFF;" parent="1" source="TKOOJ7FrXuCLbUddgnAH-6" target="TKOOJ7FrXuCLbUddgnAH-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="TKOOJ7FrXuCLbUddgnAH-14" value="SPARQL-Abfragen &lt;br&gt;&lt;div&gt;[TCP]&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;fontColor=#FFFFFF;labelBackgroundColor=light-dark(#13171f, #ededed);" parent="TKOOJ7FrXuCLbUddgnAH-10" vertex="1" connectable="0">
<mxGeometry x="-0.2714" y="-2" relative="1" as="geometry">
<mxPoint x="21" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Webapplikation" c4Type="Container" c4Technology="PHP (Laravel)" c4Description="Verarbeitung der Benutzer:innenanfragen." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-6">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="460" y="310" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="Webapplikation" c4Type="SystemScopeBoundary" c4Application="Software System" label="&lt;font color=&quot;#fff&quot; style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;&lt;div style=&quot;text-align: left&quot;&gt;%c4Name%&lt;/div&gt;&lt;/b&gt;&lt;/font&gt;&lt;div style=&quot;text-align: left&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;[%c4Application%]&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-11">
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#FFFFFF;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="440" y="290" width="660" height="420" as="geometry" />
</mxCell>
</object>
<mxCell id="TKOOJ7FrXuCLbUddgnAH-13" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=12 12;exitX=1;exitY=0.75;exitDx=0;exitDy=0;exitPerimeter=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#FFFFFF;" parent="1" source="TKOOJ7FrXuCLbUddgnAH-1" target="TKOOJ7FrXuCLbUddgnAH-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="szCxDTQn5Ym88xMkrpwM-4" value="Führt Recherchen durch" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;labelBackgroundColor=#13171F;fontColor=#FFFFFF;" parent="TKOOJ7FrXuCLbUddgnAH-13" vertex="1" connectable="0">
<mxGeometry x="-0.1256" y="-3" relative="1" as="geometry">
<mxPoint x="3" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Data-Factory" c4Type="SystemScopeBoundary" c4Application="Software System" label="&lt;font style=&quot;font-size: 16px&quot; color=&quot;#fff&quot;&gt;&lt;b&gt;&lt;div style=&quot;text-align: left&quot;&gt;%c4Name%&lt;/div&gt;&lt;/b&gt;&lt;/font&gt;&lt;div style=&quot;text-align: left&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;[%c4Application%]&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-15">
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#FFFFFF;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="28" y="828" width="942" height="300" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="RDBMS" c4Type="Container" c4Technology="DuckDB" c4Description="Speicher für aggregierte Daten." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%:&amp;nbsp;%c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#FFF&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-17">
<mxCell style="shape=cylinder3;size=15;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="48" y="918" width="240" height="120" as="geometry" />
</mxCell>
</object>
<mxCell id="TKOOJ7FrXuCLbUddgnAH-24" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#FFFFFF;strokeWidth=1;endSize=12;" parent="1" source="TKOOJ7FrXuCLbUddgnAH-18" target="TKOOJ7FrXuCLbUddgnAH-17" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="szCxDTQn5Ym88xMkrpwM-13" value="Schreibt in Datenbank" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=#13171F;fontColor=#FFFFFF;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="TKOOJ7FrXuCLbUddgnAH-24" vertex="1" connectable="0">
<mxGeometry x="-0.0412" relative="1" as="geometry">
<mxPoint x="-4" as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="sling.py" c4Type="Container" c4Technology="Sling" c4Description="Datenformatmigration (CSV zu DuckDB)." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-18">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="453" y="848" width="240" height="120" as="geometry" />
</mxCell>
</object>
<mxCell id="TKOOJ7FrXuCLbUddgnAH-23" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=light-dark(#ffffff, #ededed);" parent="1" source="TKOOJ7FrXuCLbUddgnAH-19" target="TKOOJ7FrXuCLbUddgnAH-22" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="szCxDTQn5Ym88xMkrpwM-11" value="&lt;div&gt;Versendet Suchanfragen&lt;/div&gt;&lt;div&gt;[TCP]&lt;br&gt;&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#FFFFFF;labelBackgroundColor=#13171F;" parent="TKOOJ7FrXuCLbUddgnAH-23" vertex="1" connectable="0">
<mxGeometry x="-0.175" y="1" relative="1" as="geometry">
<mxPoint x="-1" y="8" as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="scraper.py" c4Type="Container" c4Technology="Python (Polars, BeautifoulSoup)" c4Description="Web Scraping Deskriptorrelationen." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-19">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="710" y="988" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="converter.py" c4Type="Container" c4Technology="Python (Polars, RDFLib)" c4Description="Konvertiert aggregierte Daten&lt;br&gt; in RDF-Datensatz." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-20">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="452" y="988" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="reasoner.py" c4Type="Container" c4Technology="Python (OWL-RL)" c4Description="Inferenzbildung" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-21">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="710" y="848" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="Archivkatalog BBB" c4Type="Webseite" c4Description="Deskriptorensuche im Online-Archivkatalog&lt;br&gt; der Burgerbibliothek Bern." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="TKOOJ7FrXuCLbUddgnAH-22">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#8C8496;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#736782;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="710" y="1189" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="Metagrid API" c4Type="REST-API" c4Description="Metagrid Widget." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="nDUugynr7aaaKtocWSmK-3">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#8C8496;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#736782;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="1" vertex="1">
<mxGeometry x="40" y="510" width="240" height="120" as="geometry" />
</mxCell>
</object>
<mxCell id="rk8Oe00xCAcymTSaSZzT-1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#FFFFFF;endSize=12;" parent="1" source="TKOOJ7FrXuCLbUddgnAH-17" target="TKOOJ7FrXuCLbUddgnAH-20" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="szCxDTQn5Ym88xMkrpwM-14" value="Liest Datenbank" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#FFFFFF;labelBackgroundColor=#13171F;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" parent="rk8Oe00xCAcymTSaSZzT-1" vertex="1" connectable="0">
<mxGeometry x="-0.0345" y="1" relative="1" as="geometry">
<mxPoint x="2" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="rk8Oe00xCAcymTSaSZzT-4" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#FCFCFC;" parent="1" source="TKOOJ7FrXuCLbUddgnAH-5" target="nDUugynr7aaaKtocWSmK-3" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="rk8Oe00xCAcymTSaSZzT-5" value="&lt;div&gt;Abfrage Metagrid API&lt;/div&gt;&lt;div&gt;[TCP]&lt;br&gt;&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;fontColor=light-dark(#ffffff, #ededed);labelBackgroundColor=#13171F;" parent="rk8Oe00xCAcymTSaSZzT-4" vertex="1" connectable="0">
<mxGeometry x="-0.037" relative="1" as="geometry">
<mxPoint x="-8" as="offset" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="kzD1AV3YNQLLHYj1P6X-" name="Seite-2">
<mxGraphModel dx="1549" dy="948" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="BeuyoDY-F5J9U9UKxqlo-1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.75;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#000000;" edge="1" parent="1" source="BeuyoDY-F5J9U9UKxqlo-3" target="BeuyoDY-F5J9U9UKxqlo-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-2" value="besucht Webseite&lt;br&gt;[HTTPS]" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;fontColor=#000000;labelBackgroundColor=default;" vertex="1" connectable="0" parent="BeuyoDY-F5J9U9UKxqlo-1">
<mxGeometry x="-0.1101" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Benutzer:in" c4Type="Person" c4Description="Person welche recherchiert." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-3">
<mxCell style="html=1;fontSize=11;dashed=0;whiteSpace=wrap;fillColor=#083F75;strokeColor=#06315C;fontColor=#ffffff;shape=mxgraph.c4.person2;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0]];resizable=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="80" y="290" width="200" height="180" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="SPARQL Engine" c4Type="Container" c4Technology="Qlever" c4Description="RDF Triple Store und Endpoint&lt;br&gt; für SPARQL-Anfragen." label="&lt;font style=&quot;font-size: 14px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%:&amp;nbsp;%c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#FFF&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-4">
<mxCell style="shape=cylinder3;size=15;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="840" y="310" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="Deskriptorenportal" c4Type="Container" c4Technology="Apache Echarts, Pico CSS" c4Description="Bietet Möglichkeit zur Exploration und Visualisierung des RDF-Datensatzes." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%:&amp;nbsp;%c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-5">
<mxCell style="shape=mxgraph.c4.webBrowserContainer2;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;strokeColor=#118ACD;fillColor=#23A2D9;strokeColor=#118ACD;strokeColor2=#0E7DAD;fontSize=12;fontColor=#ffffff;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="460" y="490" width="240" height="160" as="geometry" />
</mxCell>
</object>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-6" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#000000;" edge="1" parent="1" source="BeuyoDY-F5J9U9UKxqlo-10" target="BeuyoDY-F5J9U9UKxqlo-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-7" value="Liefert an den Browser &lt;br&gt;der Benutzer:innen" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;fontColor=#000000;labelBackgroundColor=default;" vertex="1" connectable="0" parent="BeuyoDY-F5J9U9UKxqlo-6">
<mxGeometry x="-0.0118" y="-2" relative="1" as="geometry">
<mxPoint x="3" y="-5" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-8" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#000000;" edge="1" parent="1" source="BeuyoDY-F5J9U9UKxqlo-10" target="BeuyoDY-F5J9U9UKxqlo-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-9" value="SPARQL-Abfragen &lt;br&gt;&lt;div&gt;[TCP]&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;fontColor=#000000;labelBackgroundColor=default;" vertex="1" connectable="0" parent="BeuyoDY-F5J9U9UKxqlo-8">
<mxGeometry x="-0.2714" y="-2" relative="1" as="geometry">
<mxPoint x="21" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Webapplikation" c4Type="Container" c4Technology="PHP (Laravel)" c4Description="Verarbeitung der Benutzer:innenanfragen." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-10">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="460" y="310" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="Webapplikation" c4Type="SystemScopeBoundary" c4Application="Software System" label="&lt;font color=&quot;#000&quot; style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;&lt;div style=&quot;text-align: left&quot;&gt;%c4Name%&lt;/div&gt;&lt;/b&gt;&lt;/font&gt;&lt;div style=&quot;text-align: left&quot;&gt;&lt;font color=&quot;#000&quot;&gt;[%c4Application%]&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-11">
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#000000;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="440" y="290" width="660" height="420" as="geometry" />
</mxCell>
</object>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-12" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=12 12;exitX=1;exitY=0.75;exitDx=0;exitDy=0;exitPerimeter=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#000000;" edge="1" parent="1" source="BeuyoDY-F5J9U9UKxqlo-3" target="BeuyoDY-F5J9U9UKxqlo-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-13" value="Führt Recherchen durch" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;labelBackgroundColor=default;fontColor=light-dark(#000000,#121212);" vertex="1" connectable="0" parent="BeuyoDY-F5J9U9UKxqlo-12">
<mxGeometry x="-0.1256" y="-3" relative="1" as="geometry">
<mxPoint x="3" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="Data-Factory" c4Type="SystemScopeBoundary" c4Application="Software System" label="&lt;font style=&quot;font-size: 16px&quot; color=&quot;#000&quot;&gt;&lt;b&gt;&lt;div style=&quot;text-align: left&quot;&gt;%c4Name%&lt;/div&gt;&lt;/b&gt;&lt;/font&gt;&lt;div style=&quot;text-align: left&quot;&gt;&lt;font color=&quot;#000&quot;&gt;[%c4Application%]&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-14">
<mxCell style="rounded=1;fontSize=11;whiteSpace=wrap;html=1;dashed=1;arcSize=20;fillColor=none;strokeColor=#000000;fontColor=#333333;labelBackgroundColor=none;align=left;verticalAlign=bottom;labelBorderColor=none;spacingTop=0;spacing=10;dashPattern=8 4;metaEdit=1;rotatable=0;perimeter=rectanglePerimeter;noLabel=0;labelPadding=0;allowArrows=0;connectable=0;expand=0;recursiveResize=0;editable=1;pointerEvents=0;absoluteArcSize=1;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="28" y="828" width="942" height="300" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="RDBMS" c4Type="Container" c4Technology="DuckDB" c4Description="Speicher für aggregierte Daten." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%:&amp;nbsp;%c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#FFF&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-15">
<mxCell style="shape=cylinder3;size=15;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#23A2D9;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="48" y="918" width="240" height="120" as="geometry" />
</mxCell>
</object>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-16" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#000000;strokeWidth=1;endSize=12;" edge="1" parent="1" source="BeuyoDY-F5J9U9UKxqlo-18" target="BeuyoDY-F5J9U9UKxqlo-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-17" value="Schreibt in Datenbank" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];labelBackgroundColor=default;fontColor=#000000;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" connectable="0" parent="BeuyoDY-F5J9U9UKxqlo-16">
<mxGeometry x="-0.0412" relative="1" as="geometry">
<mxPoint x="-4" as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="sling.py" c4Type="Container" c4Technology="Sling" c4Description="Datenformatmigration (CSV zu DuckDB)." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-18">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="453" y="848" width="240" height="120" as="geometry" />
</mxCell>
</object>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-19" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=light-dark(#000000,#EDEDED);" edge="1" parent="1" source="BeuyoDY-F5J9U9UKxqlo-21" target="BeuyoDY-F5J9U9UKxqlo-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-20" value="&lt;div&gt;Versendet Suchanfragen&lt;/div&gt;&lt;div&gt;[TCP]&lt;br&gt;&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#000000;labelBackgroundColor=default;" vertex="1" connectable="0" parent="BeuyoDY-F5J9U9UKxqlo-19">
<mxGeometry x="-0.175" y="1" relative="1" as="geometry">
<mxPoint x="-1" y="8" as="offset" />
</mxGeometry>
</mxCell>
<object placeholders="1" c4Name="scraper.py" c4Type="Container" c4Technology="Python (Polars, BeautifoulSoup)" c4Description="Web Scraping Deskriptorrelationen." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-21">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="710" y="988" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="converter.py" c4Type="Container" c4Technology="Python (Polars, RDFLib)" c4Description="Konvertiert aggregierte Daten&lt;br&gt; in RDF-Datensatz." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-22">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="452" y="988" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="reasoner.py" c4Type="Container" c4Technology="Python (OWL-RL)" c4Description="Inferenzbildung" label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%: %c4Technology%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-23">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;fontSize=11;labelBackgroundColor=none;fillColor=#23A2D9;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#0E7DAD;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="710" y="848" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="Archivkatalog BBB" c4Type="Webseite" c4Description="Deskriptorensuche im Online-Archivkatalog&lt;br&gt; der Burgerbibliothek Bern." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-24">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#8C8496;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#736782;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="710" y="1189" width="240" height="120" as="geometry" />
</mxCell>
</object>
<object placeholders="1" c4Name="Metagrid API" c4Type="REST-API" c4Description="Metagrid Widget." label="&lt;font style=&quot;font-size: 16px&quot;&gt;&lt;b&gt;%c4Name%&lt;/b&gt;&lt;/font&gt;&lt;div&gt;[%c4Type%]&lt;/div&gt;&lt;br&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px&quot;&gt;&lt;font color=&quot;#fff&quot;&gt;%c4Description%&lt;/font&gt;&lt;/div&gt;" id="BeuyoDY-F5J9U9UKxqlo-25">
<mxCell style="rounded=1;whiteSpace=wrap;html=1;labelBackgroundColor=none;fillColor=#8C8496;fontColor=#ffffff;align=center;arcSize=10;strokeColor=#736782;metaEdit=1;resizable=0;points=[[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.75,1,0],[0.5,1,0],[0.25,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" parent="1">
<mxGeometry x="40" y="510" width="240" height="120" as="geometry" />
</mxCell>
</object>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-26" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#000000;endSize=12;" edge="1" parent="1" source="BeuyoDY-F5J9U9UKxqlo-15" target="BeuyoDY-F5J9U9UKxqlo-22">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-27" value="Liest Datenbank" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#000000;labelBackgroundColor=default;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;" vertex="1" connectable="0" parent="BeuyoDY-F5J9U9UKxqlo-26">
<mxGeometry x="-0.0345" y="1" relative="1" as="geometry">
<mxPoint x="2" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-28" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;dashed=1;dashPattern=12 12;fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;strokeColor=#000000;" edge="1" parent="1" source="BeuyoDY-F5J9U9UKxqlo-5" target="BeuyoDY-F5J9U9UKxqlo-25">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="BeuyoDY-F5J9U9UKxqlo-29" value="&lt;div&gt;Abfrage Metagrid API&lt;/div&gt;&lt;div&gt;[TCP]&lt;br&gt;&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Archivo;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DArchivo;fontColor=light-dark(#000000,#EDEDED);labelBackgroundColor=default;" vertex="1" connectable="0" parent="BeuyoDY-F5J9U9UKxqlo-28">
<mxGeometry x="-0.037" relative="1" as="geometry">
<mxPoint x="-8" as="offset" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -0,0 +1,317 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Linux x86_64; rv:133.0) Gecko/20100101 Firefox/133.0" version="26.0.2">
<diagram name="Seite-1" id="PRhg9wa9ExF9cAME3UJU">
<mxGraphModel dx="3978" dy="215" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="a77S1M_pYEWMkv2cS37W-37" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-860" y="2320" width="1650" height="1210" as="geometry" />
</mxCell>
<mxCell id="36" value="&lt;div align=&quot;left&quot;&gt;&lt;b&gt;Namespaces:&lt;/b&gt;&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;rdfs: &amp;lt;http://www.w3.org/2000/01/rdf-schema#&amp;gt;&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;rico: &amp;lt;https://www.ica.org/standards/RiC/ontology#&amp;gt;&lt;/div&gt;&lt;div align=&quot;left&quot;&gt;xsd: &amp;lt;http://www.w3.org/2001/XMLSchema#&amp;gt;&lt;br&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Arial;labelBackgroundColor=#FFFFFF;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="-840" y="3428" width="520" height="80" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-150" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;fontFamily=Arial;fontSize=18;entryX=0;entryY=0;entryDx=0;entryDy=0;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-149" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-151" value="rico:generalDescription" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-150" vertex="1" connectable="0">
<mxGeometry x="-0.1582" y="2" relative="1" as="geometry">
<mxPoint x="73" y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-163" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-158" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-182" value="rico:hasBirthDate" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=18;fontFamily=Arial;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-163" vertex="1" connectable="0">
<mxGeometry x="0.0223" y="2" relative="1" as="geometry">
<mxPoint x="2" y="-8" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-164" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-155" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-190" value="rdfs:label" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-164" vertex="1" connectable="0">
<mxGeometry x="0.0112" y="-1" relative="1" as="geometry">
<mxPoint x="-26" y="8" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-171" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-172" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="-60" y="3060" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-180" value="rico:isAssociatedWithEvent" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-171" vertex="1" connectable="0">
<mxGeometry x="0.2073" y="-1" relative="1" as="geometry">
<mxPoint x="30" y="-13" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-176" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-175" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-179" value="rico:isAssociatedWithEvent" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-176" vertex="1" connectable="0">
<mxGeometry x="-0.1002" relative="1" as="geometry">
<mxPoint x="109" y="38" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-186" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;fontSize=18;fontFamily=Arial;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-185" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="-2" y="2825" as="sourcePoint" />
<mxPoint x="738.0000000000005" y="2893.000000000001" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-189" value="rico:hasDeathDate" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-186" vertex="1" connectable="0">
<mxGeometry x="0.0116" y="2" relative="1" as="geometry">
<mxPoint x="10" y="-4" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-192" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-191" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-193" value="rico:hasOrHadDemographicGroup" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-192" vertex="1" connectable="0">
<mxGeometry x="0.1105" y="1" relative="1" as="geometry">
<mxPoint x="69" y="130" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-226" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-195" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-227" value="&lt;font&gt;rico:hasOrHadName&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-226" vertex="1" connectable="0">
<mxGeometry x="0.0267" y="3" relative="1" as="geometry">
<mxPoint x="15" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-120" value="rico:Person" style="ellipse;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="-520" y="2590" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-205" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-172" target="uDEteLiTxk0n7zJ6qiSI-202" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-237" value="&lt;font&gt;rico:occurredAtDate&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-205" vertex="1" connectable="0">
<mxGeometry x="-0.0889" y="1" relative="1" as="geometry">
<mxPoint x="23" y="10" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-125" value="&amp;lt;https://burgerbib.ch/EventTypes/Baptism&amp;gt;" style="ellipse;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="390" y="3080" width="370" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-200" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-175" target="uDEteLiTxk0n7zJ6qiSI-199" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-236" value="&lt;font&gt;rico:occurredAtDate&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-200" vertex="1" connectable="0">
<mxGeometry x="-0.2812" y="-1" relative="1" as="geometry">
<mxPoint x="47" y="20" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-126" value="&amp;lt;https://burgerbib.ch/EventTypes/Burial&amp;gt;" style="ellipse;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="390" y="2820" width="350" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-143" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;fontFamily=Arial;fontSize=18;entryX=0.5;entryY=1;entryDx=0;entryDy=0;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-132" target="uDEteLiTxk0n7zJ6qiSI-120" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="-480" y="2300" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-145" value="rico:isOrWasIdentifierOf" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-143" vertex="1" connectable="0">
<mxGeometry x="-0.4249" y="-2" relative="1" as="geometry">
<mxPoint x="26" y="-76" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-216" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;fontFamily=Arial;fontSize=18;entryX=0.5;entryY=0;entryDx=0;entryDy=0;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-132" target="uDEteLiTxk0n7zJ6qiSI-214" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-235" value="&lt;font&gt;rico:normalizedValue&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-216" vertex="1" connectable="0">
<mxGeometry x="-0.0445" relative="1" as="geometry">
<mxPoint x="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-132" value="https://burgerbib.ch/identifiers/&quot;ARK&quot;" style="ellipse;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="-800" y="3190" width="370" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-144" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-135" target="uDEteLiTxk0n7zJ6qiSI-120" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-146" value="rico:isOrWasIdentifierOf" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-144" vertex="1" connectable="0">
<mxGeometry x="-0.6529" y="1" relative="1" as="geometry">
<mxPoint x="-53" y="-138" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-217" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-135" target="uDEteLiTxk0n7zJ6qiSI-211" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-234" value="&lt;font&gt;rico:normalizedValue&lt;/font&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-217" vertex="1" connectable="0">
<mxGeometry x="0.4488" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-135" value="https://burgerbib.ch/identifiers/scope:&quot;ID-Nr.&quot;" style="ellipse;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="-410" y="3190" width="390" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-147" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="120" y="2460" width="250" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-148" value="&quot;Beschreibung&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-147" vertex="1">
<mxGeometry width="250" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-149" value="Datatype: xsd:String" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-147" vertex="1">
<mxGeometry y="30" width="250" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-153" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="120" y="2370" width="350" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-154" value="&quot;ID-Name (Geburtsdatum-Todesdatum)&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-153" vertex="1">
<mxGeometry width="350" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-155" value="Datatype: xsd:String" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-153" vertex="1">
<mxGeometry y="30" width="350" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-156" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="120" y="2640" width="250" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-157" value="&quot;Geburtsdatum&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-156" vertex="1">
<mxGeometry width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-158" value="Datatype: xsd:date" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-156" vertex="1">
<mxGeometry y="30" width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-173" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;fontFamily=Arial;fontSize=18;entryX=0;entryY=0.5;entryDx=0;entryDy=0;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-172" target="uDEteLiTxk0n7zJ6qiSI-125" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-174" value="rico:hasEventType" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-173" vertex="1" connectable="0">
<mxGeometry x="-0.0812" y="-1" relative="1" as="geometry">
<mxPoint x="17" y="-3" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-172" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="120" y="3090" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-177" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;fontFamily=Arial;fontSize=18;entryX=0;entryY=0.5;entryDx=0;entryDy=0;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-175" target="uDEteLiTxk0n7zJ6qiSI-126" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="270" y="2940" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-178" value="rico:hasEventType" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-177" vertex="1" connectable="0">
<mxGeometry x="0.4247" y="2" relative="1" as="geometry">
<mxPoint x="-42" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-175" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="120" y="2830" width="40" height="40" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-183" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="120" y="2730" width="250" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-184" value="&quot;Todesdatum&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-183" vertex="1">
<mxGeometry width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-185" value="Datatype: xsd:date" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-183" vertex="1">
<mxGeometry y="30" width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-209" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-191" target="uDEteLiTxk0n7zJ6qiSI-207" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-233" value="rdfs:label" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=18;fontFamily=Arial;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-209" vertex="1" connectable="0">
<mxGeometry x="-0.1462" relative="1" as="geometry">
<mxPoint x="2" y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-191" value="&amp;lt;https://burgerbib.ch/demographicgroups/&quot;SexFemale OR SexMale&quot;&amp;gt;" style="ellipse;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1">
<mxGeometry x="120" y="3300" width="600" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-194" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="120" y="2550" width="250" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-195" value="&quot;ID-Name&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-194" vertex="1">
<mxGeometry width="250" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-196" value="Datatype: xsd:String" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-194" vertex="1">
<mxGeometry y="30" width="250" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-197" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="390" y="2970" width="250" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-198" value="&quot;Begräbnisdatum&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-197" vertex="1">
<mxGeometry width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-199" value="Datatype: xsd:date" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-197" vertex="1">
<mxGeometry y="30" width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-201" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="390" y="3210" width="250" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-202" value="&quot;Taufdatum&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-201" vertex="1">
<mxGeometry width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-203" value="Datatype: xsd:date" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-201" vertex="1">
<mxGeometry y="30" width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-206" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="295" y="3447" width="250" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-207" value="&quot;Geschlecht&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-206" vertex="1">
<mxGeometry width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-208" value="Datatype: xsd:String" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-206" vertex="1">
<mxGeometry y="30" width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-210" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="-385" y="3320" width="340" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-211" value="&quot;ID-Nr.&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-210" vertex="1">
<mxGeometry width="340.00000000000006" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-212" value="Datatype: xsd:nonNegativeInteger" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-210" vertex="1">
<mxGeometry y="30" width="340.00000000000006" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-213" value="" style="group;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="1" vertex="1" connectable="0">
<mxGeometry x="-740" y="3320" width="250" height="60" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-214" value="&quot;ARK&quot;" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-213" vertex="1">
<mxGeometry width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-215" value="Datatype: xsd:String" style="rounded=0;whiteSpace=wrap;html=1;labelBackgroundColor=#FFFFFF;fontFamily=Arial;fontSize=18;" parent="uDEteLiTxk0n7zJ6qiSI-213" vertex="1">
<mxGeometry y="30" width="250.00000000000003" height="30" as="geometry" />
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-219" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-120" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-650" y="2620" />
<mxPoint x="-650" y="2500" />
<mxPoint x="-460" y="2500" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-220" value="&lt;div&gt;rico:hasChild&lt;br&gt;[Kind]&lt;br&gt;&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-219" vertex="1" connectable="0">
<mxGeometry x="0.2326" y="-4" relative="1" as="geometry">
<mxPoint x="-5" y="6" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-221" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-120" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-720" y="2620" />
<mxPoint x="-720" y="2420" />
<mxPoint x="-460" y="2420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-222" value="&lt;div&gt;rico:hasOrHadSpouse&lt;br&gt;[Ehepartner / Ehepartnerin]&lt;br&gt;&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-221" vertex="1" connectable="0">
<mxGeometry x="-0.0169" y="-2" relative="1" as="geometry">
<mxPoint x="82" y="14" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-223" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;curved=1;fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="1" source="uDEteLiTxk0n7zJ6qiSI-120" target="uDEteLiTxk0n7zJ6qiSI-120" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-780" y="2620" />
<mxPoint x="-780" y="2350" />
<mxPoint x="-460" y="2350" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="uDEteLiTxk0n7zJ6qiSI-224" value="&amp;lt;https://burgerbib.ch/relations/hasOrHadLifePartner&amp;gt;&lt;br&gt;[Lebenspartner / Lebenspartnerin]" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontFamily=Arial;fontSize=18;labelBackgroundColor=#FFFFFF;" parent="uDEteLiTxk0n7zJ6qiSI-223" vertex="1" connectable="0">
<mxGeometry x="0.347" y="1" relative="1" as="geometry">
<mxPoint x="-39" y="21" as="offset" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

Binary file not shown.

19
docs/presentation/LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (C) 2011-2024 Hakim El Hattab, http://hakim.se, and reveal.js contributors
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.

Binary file not shown.

93
docs/presentation/dist/font/OFL.txt vendored Normal file
View File

@ -0,0 +1,93 @@
Copyright 2020 The Archivo Project Authors (https://github.com/Omnibus-Type/Archivo)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

30
docs/presentation/dist/reset.css vendored Normal file
View File

@ -0,0 +1,30 @@
/* http://meyerweb.com/eric/tools/css/reset/
v4.0 | 20180602
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
main, menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, main, menu, nav, section {
display: block;
}

9
docs/presentation/dist/reveal.css vendored Normal file

File diff suppressed because one or more lines are too long

9
docs/presentation/dist/reveal.esm.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

9
docs/presentation/dist/reveal.js vendored Normal file

File diff suppressed because one or more lines are too long

1
docs/presentation/dist/reveal.js.map vendored Normal file

File diff suppressed because one or more lines are too long

385
docs/presentation/dist/theme/dracula.css vendored Normal file
View File

@ -0,0 +1,385 @@
/**
* Dracula Dark theme for reveal.js.
* Based on https://draculatheme.com
*/
/**
* Dracula colors by Zeno Rocha
* https://draculatheme.com/contribute
*/
html * {
color-profile: sRGB;
rendering-intent: auto;
}
section.has-light-background, section.has-light-background h1, section.has-light-background h2, section.has-light-background h3, section.has-light-background h4, section.has-light-background h5, section.has-light-background h6 {
color: #282A36;
}
/*********************************************
* GLOBAL STYLES
*********************************************/
:root {
--r-background-color: #13171f;
--r-main-font: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
--r-main-font-size: 40px;
--r-main-color: #f0f1f3;
--r-block-margin: 20px;
--r-heading-margin: 0 0 20px 0;
--r-heading-font: League Gothic, Impact, sans-serif;
--r-heading-color: #f0f1f3;
--r-heading-line-height: 1.2;
--r-heading-letter-spacing: normal;
--r-heading-text-transform: none;
--r-heading-text-shadow: none;
--r-heading-font-weight: normal;
--r-heading1-text-shadow: none;
--r-heading1-size: 3.77em;
--r-heading2-size: 2.11em;
--r-heading3-size: 1.55em;
--r-heading4-size: 1em;
--r-code-font: Fira Code, Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
--r-link-color: #00a9fe;
--r-link-color-dark: #00a9fe;
--r-link-color-hover: #8BE9FD;
--r-selection-background-color: #44475A;
--r-selection-color: #fff;
--r-overlay-element-bg-color: 240, 240, 240;
--r-overlay-element-fg-color: 0, 0, 0;
}
.reveal-viewport {
background: #282A36;
background-color: var(--r-background-color);
}
.reveal {
font-family: var(--r-main-font);
font-size: var(--r-main-font-size);
font-weight: normal;
color: var(--r-main-color);
}
.reveal ::selection {
color: var(--r-selection-color);
background: var(--r-selection-background-color);
text-shadow: none;
}
.reveal ::-moz-selection {
color: var(--r-selection-color);
background: var(--r-selection-background-color);
text-shadow: none;
}
.reveal .slides section,
.reveal .slides section > section {
line-height: 1.3;
font-weight: inherit;
}
/*********************************************
* HEADERS
*********************************************/
.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4,
.reveal h5,
.reveal h6 {
margin: var(--r-heading-margin);
color: var(--r-heading-color);
font-family: var(--r-heading-font);
font-weight: var(--r-heading-font-weight);
line-height: var(--r-heading-line-height);
letter-spacing: var(--r-heading-letter-spacing);
text-transform: var(--r-heading-text-transform);
text-shadow: var(--r-heading-text-shadow);
word-wrap: break-word;
}
.reveal h1 {
font-size: var(--r-heading1-size);
}
.reveal h2 {
font-size: var(--r-heading2-size);
}
.reveal h3 {
font-size: var(--r-heading3-size);
}
.reveal h4 {
font-size: var(--r-heading4-size);
}
.reveal h1 {
text-shadow: var(--r-heading1-text-shadow);
}
/*********************************************
* OTHER
*********************************************/
.reveal p {
margin: var(--r-block-margin) 0;
line-height: 1.3;
}
/* Remove trailing margins after titles */
.reveal h1:last-child,
.reveal h2:last-child,
.reveal h3:last-child,
.reveal h4:last-child,
.reveal h5:last-child,
.reveal h6:last-child {
margin-bottom: 0;
}
/* Ensure certain elements are never larger than the slide itself */
.reveal img,
.reveal video,
.reveal iframe {
max-width: 95%;
max-height: 95%;
}
.reveal strong,
.reveal b {
font-weight: bold;
}
.reveal em {
font-style: italic;
}
.reveal ol,
.reveal dl,
.reveal ul {
display: inline-block;
text-align: left;
margin: 0 0 0 1em;
}
.reveal ol {
list-style-type: decimal;
}
.reveal ul {
list-style-type: disc;
}
.reveal ul ul {
list-style-type: square;
}
.reveal ul ul ul {
list-style-type: circle;
}
.reveal ul ul,
.reveal ul ol,
.reveal ol ol,
.reveal ol ul {
display: block;
margin-left: 40px;
}
.reveal dt {
font-weight: bold;
}
.reveal dd {
margin-left: 40px;
}
.reveal blockquote {
display: block;
position: relative;
width: 70%;
margin: var(--r-block-margin) auto;
padding: 5px;
font-style: italic;
background: rgba(255, 255, 255, 0.05);
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2);
}
.reveal blockquote p:first-child,
.reveal blockquote p:last-child {
display: inline-block;
}
.reveal q {
font-style: italic;
}
.reveal pre {
display: block;
position: relative;
width: 90%;
margin: var(--r-block-margin) auto;
text-align: left;
font-size: 0.55em;
font-family: var(--r-code-font);
line-height: 1.2em;
word-wrap: break-word;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15);
}
.reveal code {
font-family: var(--r-code-font);
text-transform: none;
tab-size: 2;
}
.reveal pre code {
display: block;
padding: 5px;
overflow: auto;
max-height: 400px;
word-wrap: normal;
}
.reveal .code-wrapper {
white-space: normal;
}
.reveal .code-wrapper code {
white-space: pre;
}
.reveal table {
margin: auto;
border-collapse: collapse;
border-spacing: 0;
}
.reveal table th {
font-weight: bold;
}
.reveal table th,
.reveal table td {
text-align: left;
padding: 0.2em 0.5em 0.2em 0.5em;
border-bottom: 1px solid;
}
.reveal table th[align=center],
.reveal table td[align=center] {
text-align: center;
}
.reveal table th[align=right],
.reveal table td[align=right] {
text-align: right;
}
.reveal table tbody tr:last-child th,
.reveal table tbody tr:last-child td {
border-bottom: none;
}
.reveal sup {
vertical-align: super;
font-size: smaller;
}
.reveal sub {
vertical-align: sub;
font-size: smaller;
}
.reveal small {
display: inline-block;
font-size: 0.6em;
line-height: 1.2em;
vertical-align: top;
}
.reveal small * {
vertical-align: top;
}
.reveal img {
margin: var(--r-block-margin) 0;
}
/*********************************************
* LINKS
*********************************************/
.reveal a {
color: var(--r-link-color);
text-decoration: none;
transition: color 0.15s ease;
}
.reveal a:hover {
color: var(--r-link-color-hover);
text-shadow: none;
border: none;
}
.reveal .roll span:after {
color: #fff;
background: var(--r-link-color-dark);
}
/*********************************************
* Frame helper
*********************************************/
.reveal .r-frame {
border: 4px solid var(--r-main-color);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
}
.reveal a .r-frame {
transition: all 0.15s linear;
}
.reveal a:hover .r-frame {
border-color: var(--r-link-color);
box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
}
/*********************************************
* NAVIGATION CONTROLS
*********************************************/
.reveal .controls {
color: var(--r-link-color);
}
/*********************************************
* PROGRESS BAR
*********************************************/
.reveal .progress {
background: rgba(0, 0, 0, 0.2);
color: var(--r-link-color);
}
/*********************************************
* PRINT BACKGROUND
*********************************************/
@media print {
.backgrounds {
background-color: var(--r-background-color);
}
}
:root {
--r-bold-color: #FFB86C;
--r-italic-color: #F1FA8C;
--r-inline-code-color: #50FA7B;
--r-list-bullet-color: #8BE9FD;
}
.reveal strong, .reveal b {
color: var(--r-bold-color);
}
.reveal em, .reveal i, .reveal blockquote {
color: var(--r-italic-color);
}
.reveal code {
color: var(--r-inline-code-color);
}
.reveal ul li::marker, .reveal ol li::marker {
color: var(--r-list-bullet-color);
}

View File

@ -0,0 +1,206 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Präsentation Deskriptorenportal</title>
<link rel="stylesheet" href="dist/reset.css">
<link rel="stylesheet" href="dist/reveal.css">
<link rel="stylesheet" href="dist/theme/dracula.css">
<style>
@font-face {
font-family: "Archivo";
font-style: normal;
font-display: swap;
src: local("Archivo"), url("dist/font/Archivo-VariableFont_wdth,wght.ttf") format("truetype");
font-weight: 400 700;
font-stretch: 62% 125%;
}
:root{
--r-main-font: 'Archivo', -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, verdana, arial, sans-serif;
--r-heading-font: 'Archivo', -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, verdana, arial, sans-serif;
--r-heading-font-weight: 700;
--r-list-bullet-color: #fff;
}
video{
border: 1px solid #181e28;
}
.reveal h2 {
font-size: 1.3em
}
.reveal video{
max-width: 85%;
}
a.cite {
display: block;
font-size: .7em
}
ul.lit li {
font-size: .5em;
}
p.image-note{
font-size: .4em;
margin-top: 0;
text-align: left;
}
.flex{
display: flex;
justify-content: space-between;
}
.flex>*{
max-width: 45%;
}
.flex>*>img{
max-width: 100%;
margin: 0;
}
.reveal .slide-number{
bottom: 1.5em;
right: 2.05em;
font-size: .5em;
width: 1.5em;
padding: 0;
text-align: center;
background: none;
}
</style>
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h2>Deskriptorenportal</h2>
<p>Abbildung von Personendeskriptoren mit der <br />Records in Contexts Ontology (RiC-O)</p>
</section>
<section>
<h2>Ausgangslage & Ziel</h2>
<div class="flex">
<ul style="font-size: .75em; max-width: 40%;">
<li>Die Burgerbibliothek Bern verwendet zur Verzeichnung ihrer Archivalien Deskriptoren.</li>
<li>Die Deskriptoren sollen in einen RDF-Datensatz unter Verwendung der Records in Contexts Ontology (RiC-O)
gewandelt werden.</li>
</ul>
<div style="max-width: 55%;">
<img src="media/screenshot-desk-search.png"
alt="Screenshot der Deskriptorensuche im Archivkatalog der Burgerbibliothek Bern.">
<p class="image-note">Screenshot der Deskriptorensuche im Archivkatalog der Burgerbibliothek Bern.</p>
<div>
</div>
</section>
<section>
<h2>Records in Contexts (RiC)</h2>
<ul>
<li>RiC ist ein archivischer Verzeichnungsstandard welcher die amtierenden Standards ISAD(G), ISAAR(CPF), ISDF und ISDIAH ablöst. <a class="cite" href="#/literaturverzeichnis">(EGAD, 2024)</a></li>
<li>Bestandteil des Standards ist die Records in Contexts Ontology (RiC-O), welche als Blaupause zur Erstellung von RDF-Datensätzen im archivischen Kontext zu verstehen ist.<a class="cite" href="#/literaturverzeichnis">(ICA EGAD,
2024, Abs. «RiC-O design principles»)</a></li>
</ul>
</section>
<section>
<h2>Datenaggregation und -modellierung (1/3)</h2>
<ul>
<li>CSV-Export via Archivinformationssystem (AIS)<br>(49&thinsp;242&nbsp;Einträge)</li>
<li>Relationen zwischen Deskriptoren via Web Scraping<br>(82&thinsp;027&nbsp;Einträge)</li>
<li>Serialisierung in Turtle mit RDFLib (61&thinsp;069 Tripel) <a class="cite" href="#/literaturverzeichnis">(RDFLib Team, 2024)</a></li>
<li>Inferenzbildung mit OWL-RL (5&thinsp;338&thinsp;997 Tripel) <a class="cite" href="#/literaturverzeichnis">(Herman, 2014)</a></li>
<li>RDF-Triple-Store / SPARQL-Engine Qlever <a class="cite" href="#/literaturverzeichnis">(Bast et al., 2022)</a></li>
</ul>
</section>
<section>
<h2>Datenaggregation und -modellierung (2/3)</h2>
<img src="media/c4-data.svg" alt="C4 Diagramm des Systemkontexts für die Datenaggregation">
</section>
<section>
<h2>Datenaggregation und -modellierung (3/3)</h2>
<img src="media/data-model.svg" alt="Diagramm des RDF-Datenmodells">
</section>
<section>
<h2>Webapplikation</h2>
<img src="media/C4-webapp.svg" alt="C4 Diagramm des Systemkontexts für die Webapplikation.">
</section>
<section>
<h2>Suche</h2>
<video data-autoplay loop controls src="media/search.webm"></video>
</section>
<section>
<h2>Zeitstrahl</h2>
<video data-autoplay loop controls src="media/timeline.webm"></video>
</section>
<section>
<h2>Deskriptorendetailansicht</h2>
<video data-autoplay loop controls src="media/detail.webm"></video>
</section>
<section>
<h2>Diskussion</h2>
<ul>
<li>Konsistenz in der Datenmodellierung: Geburts- und Todesdatum ebenfalls als «rico:EventType»
modellieren? Oder z. B. BIO Vocabulary verwenden?<a class="cite" href="#/literaturverzeichnis">(Davis et al., 2011)</a></li>
<li>OWL-RL: Infernzbildung führt zu Tripel mit Literalen in der Subjektposition. Patch ist eine
Kombination der Lösungsvorschläge von <a href="#/literaturverzeichnis">al-Dosari (2023)</a> und <a href="#/literaturverzeichnis">Car (2023)</a></li>
</ul>
</section>
<section id="literaturverzeichnis">
<h2>Literaturverzeichnis</h2>
<ul class="lit">
<li>
al-Dosari, M. (2023, März). OWL RL creates triples with a Literal as Subject when evaluating
PROV-O ontology #50. Zugriff am 28. Dezember 2024 unter <a
href="https://github.com/RDFLib/OWL-RL/issues/50#issuecomment-1476897684">https://github.com/RDFLib/OWL-RL/issues/50#issuecomment-1476897684</a>
</li>
<li>Bast, H., Kalmbach, J., Klumpp, T., Kramer, F., & Schnelle, N. (2022). Efficient and Effective
SPARQL Autocompletion on Very Large Knowledge Graphs. Proceedings of the 31st ACM International
Conference on Information & Knowledge Management, 28932902. <a
href="https://doi.org/10.1145/3511808.3557093">https://doi.org/10.1145/3511808.3557093</a>
</li>
<li>
Car, N. (2023, August). Unexpected behaviour of OWL-RL reasoner (Literals in the position of
Subjects) #63. Zugriff am 28. Dezember 2024 unter <a
href="https://github.com/RDFLib/OWL-RL/issues/63#issuecomment-2283074918">https://github.com/RDFLib/OWL-RL/issues/63#issuecomment-2283074918</a>
</li>
<li>
Davis, I., & Galbraith, D. (2011, Juni). BIO: A vocabulary for biographical information. Zugriff am 17. Dezember 2024 unter <a href="http://purl.org/vocab/bio/0.1/">http://purl.org/vocab/bio/0.1/</a>
</li>
<li>EGAD. (2024, Juni). Records in Contexts (RiC). Zugriff am 17. Dezember 2024 unter <a
href="https://www.ica.org/ica-network/expert-groups/egad/records-in-contexts-ric/">https://www.ica.org/ica-network/expert-groups/egad/records-in-contexts-ric/</a>
</li>
<li>Herman, I. (2014, Oktober). OWL-RL: OWL-RL: A simple OWL2 RL reasoner on top of RDFLib. <a
href="https://doi.org/10.5281/zenodo.14543">https://doi.org/10.5281/zenodo.14543</a></li>
<li>ICA EGAD. (2024, September). International Council on Archives Records in Contexts Ontology (ICA
RiC-O). Zugriff am 2. November 2024 unter <a
href="https://www.ica.org/standards/RiC/RiC-O_1-0-2.html">https://www.ica.org/standards/RiC/RiC-O_1-0-2.html</a>
</li>
<li>RDFLib Team. (2024). RDFLib. Zugriff am 17. November 2024 unter <a
href="https://github.com/RDFLib/rdflib">https://github.com/RDFLib/rdflib</a>/li>
</ul>
</section>
</div>
</div>
<script src="dist/reveal.js"></script>
<script>
Reveal.initialize({
width: 1080,
height: 720,
history: true,
controls: false,
hash: true,
slideNumber: true,
mouseWheel: true,
});
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 479 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 483 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

Binary file not shown.

13
qlever/.gitignore vendored Executable file
View File

@ -0,0 +1,13 @@
# pixi environments
.pixi
*.egg-info
# qlever files
*.ttl
*.stxxl
*.index*
*.vocabulary*
*.meta-data.json
*.server-log.txt
*.settings.json

23
qlever/Qleverfile Executable file
View File

@ -0,0 +1,23 @@
[data]
NAME = Deskriptoren
DESCRIPTION = Deskriptoren der Burgerbibliothek Bern
TEXT_DESCRIPTION = Enthält Personendeskriptoren der Burgerbibliothek Bern, welche anhand der RiC-O modelliert sind.
[index]
INPUT_FILES = agents_expanded.ttl
CAT_INPUT_FILES = cat ${INPUT_FILES}
SETTINGS_JSON = { "ascii-prefixes-only": false, "num-triples-per-batch": 100000 }
[server]
PORT = 7019
ACCESS_TOKEN = ${data:NAME}_7643543846_yBT78gwAdHMR
MEMORY_FOR_QUERIES = 5G
CACHE_MAX_SIZE = 2G
TIMEOUT = 30s
[runtime]
SYSTEM = docker
IMAGE = docker.io/adfreiburg/qlever:latest
[ui]
UI_CONFIG = BBB

12
qlever/README.md Normal file
View File

@ -0,0 +1,12 @@
# Qlever
Umgebung für [qlever-control](https://github.com/ad-freiburg/qlever-control)
Um den Index aufzubauen muss der RDF-Datensatz in das Verzeichnis kopiert werden.
```bash
cp ../data-factory/data/output/agents_expanded.ttl ./
```
Initialisierung Index und Server starten
```bash
qlever index && qlever start
```

466
qlever/pixi.lock Executable file
View File

@ -0,0 +1,466 @@
version: 5
environments:
default:
channels:
- url: https://conda.anaconda.org/conda-forge/
indexes:
- https://pypi.org/simple
packages:
linux-64:
- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.8.30-hbcca054_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.43-h712a8e2_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.4-h5888daf_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.2.0-h77fa898_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.2.0-h69a702a_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.2.0-h77fa898_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-h4bc722e_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.47.0-hadc24fc_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.4.0-hb9d3cd8_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.0-h9ebbce0_101_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.13-5_cp313.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda
- conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2
- pypi: https://files.pythonhosted.org/packages/f7/be/a606a6701d491cfae75583c80a6583f8abe9c36c0b9666e867e7cdd62fe8/argcomplete-3.5.1-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/58/4d/8245e6f76a93c98aab285a43ea71ff1b171bcd90c9d238bf81f7021fb233/psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/cf/d9/b1003ae23cc6e48c81c9a2cc23edf8d34b3b978eb4fe91b941992e88e351/qlever-0.5.12-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/7f/be/df630c387a0a054815d60be6a97eb4e8f17385d5d6fe660e1c02750062b4/termcolor-2.5.0-py3-none-any.whl
packages:
- kind: conda
name: _libgcc_mutex
version: '0.1'
build: conda_forge
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726
md5: d7c89558ba9fa0495403155b64376d81
license: None
purls: []
size: 2562
timestamp: 1578324546067
- kind: conda
name: _openmp_mutex
version: '4.5'
build: 2_gnu
build_number: 16
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22
md5: 73aaf86a425cc6e73fcf236a5a46396d
depends:
- _libgcc_mutex 0.1 conda_forge
- libgomp >=7.5.0
constrains:
- openmp_impl 9999
license: BSD-3-Clause
license_family: BSD
purls: []
size: 23621
timestamp: 1650670423406
- kind: pypi
name: argcomplete
version: 3.5.1
url: https://files.pythonhosted.org/packages/f7/be/a606a6701d491cfae75583c80a6583f8abe9c36c0b9666e867e7cdd62fe8/argcomplete-3.5.1-py3-none-any.whl
sha256: 1a1d148bdaa3e3b93454900163403df41448a248af01b6e849edc5ac08e6c363
requires_dist:
- coverage ; extra == 'test'
- pexpect ; extra == 'test'
- wheel ; extra == 'test'
- ruff ; extra == 'test'
- mypy ; extra == 'test'
requires_python: '>=3.8'
- kind: conda
name: bzip2
version: 1.0.8
build: h4bc722e_7
build_number: 7
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda
sha256: 5ced96500d945fb286c9c838e54fa759aa04a7129c59800f0846b4335cee770d
md5: 62ee74e96c5ebb0af99386de58cf9553
depends:
- __glibc >=2.17,<3.0.a0
- libgcc-ng >=12
license: bzip2-1.0.6
license_family: BSD
purls: []
size: 252783
timestamp: 1720974456583
- kind: conda
name: ca-certificates
version: 2024.8.30
build: hbcca054_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.8.30-hbcca054_0.conda
sha256: afee721baa6d988e27fef1832f68d6f32ac8cc99cdf6015732224c2841a09cea
md5: c27d1c142233b5bc9ca570c6e2e0c244
license: ISC
purls: []
size: 159003
timestamp: 1725018903918
- kind: conda
name: ld_impl_linux-64
version: '2.43'
build: h712a8e2_2
build_number: 2
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.43-h712a8e2_2.conda
sha256: 7c91cea91b13f4314d125d1bedb9d03a29ebbd5080ccdea70260363424646dbe
md5: 048b02e3962f066da18efe3a21b77672
depends:
- __glibc >=2.17,<3.0.a0
constrains:
- binutils_impl_linux-64 2.43
license: GPL-3.0-only
license_family: GPL
purls: []
size: 669211
timestamp: 1729655358674
- kind: conda
name: libexpat
version: 2.6.4
build: h5888daf_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.4-h5888daf_0.conda
sha256: 56541b98447b58e52d824bd59d6382d609e11de1f8adf20b23143e353d2b8d26
md5: db833e03127376d461e1e13e76f09b6c
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=13
constrains:
- expat 2.6.4.*
license: MIT
license_family: MIT
purls: []
size: 73304
timestamp: 1730967041968
- kind: conda
name: libffi
version: 3.4.2
build: h7f98852_5
build_number: 5
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2
sha256: ab6e9856c21709b7b517e940ae7028ae0737546122f83c2aa5d692860c3b149e
md5: d645c6d2ac96843a2bfaccd2d62b3ac3
depends:
- libgcc-ng >=9.4.0
license: MIT
license_family: MIT
purls: []
size: 58292
timestamp: 1636488182923
- kind: conda
name: libgcc
version: 14.2.0
build: h77fa898_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.2.0-h77fa898_1.conda
sha256: 53eb8a79365e58849e7b1a068d31f4f9e718dc938d6f2c03e960345739a03569
md5: 3cb76c3f10d3bc7f1105b2fc9db984df
depends:
- _libgcc_mutex 0.1 conda_forge
- _openmp_mutex >=4.5
constrains:
- libgomp 14.2.0 h77fa898_1
- libgcc-ng ==14.2.0=*_1
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
purls: []
size: 848745
timestamp: 1729027721139
- kind: conda
name: libgcc-ng
version: 14.2.0
build: h69a702a_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.2.0-h69a702a_1.conda
sha256: 3a76969c80e9af8b6e7a55090088bc41da4cffcde9e2c71b17f44d37b7cb87f7
md5: e39480b9ca41323497b05492a63bc35b
depends:
- libgcc 14.2.0 h77fa898_1
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
purls: []
size: 54142
timestamp: 1729027726517
- kind: conda
name: libgomp
version: 14.2.0
build: h77fa898_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.2.0-h77fa898_1.conda
sha256: 1911c29975ec99b6b906904040c855772ccb265a1c79d5d75c8ceec4ed89cd63
md5: cc3573974587f12dda90d96e3e55a702
depends:
- _libgcc_mutex 0.1 conda_forge
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
purls: []
size: 460992
timestamp: 1729027639220
- kind: conda
name: libmpdec
version: 4.0.0
build: h4bc722e_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libmpdec-4.0.0-h4bc722e_0.conda
sha256: d02d1d3304ecaf5c728e515eb7416517a0b118200cd5eacbe829c432d1664070
md5: aeb98fdeb2e8f25d43ef71fbacbeec80
depends:
- __glibc >=2.17,<3.0.a0
- libgcc-ng >=12
license: BSD-2-Clause
license_family: BSD
purls: []
size: 89991
timestamp: 1723817448345
- kind: conda
name: libsqlite
version: 3.47.0
build: hadc24fc_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.47.0-hadc24fc_1.conda
sha256: 8a9aadf996a2399f65b679c6e7f29139d5059f699c63e6d7b50e20db10c00508
md5: b6f02b52a174e612e89548f4663ce56a
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=13
- libzlib >=1.3.1,<2.0a0
license: Unlicense
purls: []
size: 875349
timestamp: 1730208050020
- kind: conda
name: libuuid
version: 2.38.1
build: h0b41bf4_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda
sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18
md5: 40b61aab5c7ba9ff276c41cfffe6b80b
depends:
- libgcc-ng >=12
license: BSD-3-Clause
license_family: BSD
purls: []
size: 33601
timestamp: 1680112270483
- kind: conda
name: libzlib
version: 1.3.1
build: hb9d3cd8_2
build_number: 2
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda
sha256: d4bfe88d7cb447768e31650f06257995601f89076080e76df55e3112d4e47dc4
md5: edb0dca6bc32e4f4789199455a1dbeb8
depends:
- __glibc >=2.17,<3.0.a0
- libgcc >=13
constrains:
- zlib 1.3.1 *_2
license: Zlib
license_family: Other
purls: []
size: 60963
timestamp: 1727963148474
- kind: conda
name: ncurses
version: '6.5'
build: he02047a_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda
sha256: 6a1d5d8634c1a07913f1c525db6455918cbc589d745fac46d9d6e30340c8731a
md5: 70caf8bb6cf39a0b6b7efc885f51c0fe
depends:
- __glibc >=2.17,<3.0.a0
- libgcc-ng >=12
license: X11 AND BSD-3-Clause
purls: []
size: 889086
timestamp: 1724658547447
- kind: conda
name: openssl
version: 3.4.0
build: hb9d3cd8_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.4.0-hb9d3cd8_0.conda
sha256: 814b9dff1847b132c676ee6cc1a8cb2d427320779b93e1b6d76552275c128705
md5: 23cc74f77eb99315c0360ec3533147a9
depends:
- __glibc >=2.17,<3.0.a0
- ca-certificates
- libgcc >=13
license: Apache-2.0
license_family: Apache
purls: []
size: 2947466
timestamp: 1731377666602
- kind: pypi
name: psutil
version: 6.1.0
url: https://files.pythonhosted.org/packages/58/4d/8245e6f76a93c98aab285a43ea71ff1b171bcd90c9d238bf81f7021fb233/psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
sha256: 498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b
requires_dist:
- black ; extra == 'dev'
- check-manifest ; extra == 'dev'
- coverage ; extra == 'dev'
- packaging ; extra == 'dev'
- pylint ; extra == 'dev'
- pyperf ; extra == 'dev'
- pypinfo ; extra == 'dev'
- pytest-cov ; extra == 'dev'
- requests ; extra == 'dev'
- rstcheck ; extra == 'dev'
- ruff ; extra == 'dev'
- sphinx ; extra == 'dev'
- sphinx-rtd-theme ; extra == 'dev'
- toml-sort ; extra == 'dev'
- twine ; extra == 'dev'
- virtualenv ; extra == 'dev'
- wheel ; extra == 'dev'
- pytest ; extra == 'test'
- pytest-xdist ; extra == 'test'
- setuptools ; extra == 'test'
requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*'
- kind: conda
name: python
version: 3.13.0
build: h9ebbce0_101_cp313
build_number: 101
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.0-h9ebbce0_101_cp313.conda
sha256: 66a7997b24b2dca636df11402abec7bd2199ddf6971eb47a3ee6b1d27d4faee9
md5: f4fea9d5bb3f2e61a39950a7ab70ee4e
depends:
- __glibc >=2.17,<3.0.a0
- bzip2 >=1.0.8,<2.0a0
- ld_impl_linux-64 >=2.36.1
- libexpat >=2.6.4,<3.0a0
- libffi >=3.4,<4.0a0
- libgcc >=13
- libmpdec >=4.0.0,<5.0a0
- libsqlite >=3.47.0,<4.0a0
- libuuid >=2.38.1,<3.0a0
- libzlib >=1.3.1,<2.0a0
- ncurses >=6.5,<7.0a0
- openssl >=3.4.0,<4.0a0
- python_abi 3.13.* *_cp313
- readline >=8.2,<9.0a0
- tk >=8.6.13,<8.7.0a0
- tzdata
- xz >=5.2.6,<6.0a0
license: Python-2.0
purls: []
size: 33054218
timestamp: 1732736838043
- kind: conda
name: python_abi
version: '3.13'
build: 5_cp313
build_number: 5
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.13-5_cp313.conda
sha256: 438225b241c5f9bddae6f0178a97f5870a89ecf927dfca54753e689907331442
md5: 381bbd2a92c863f640a55b6ff3c35161
constrains:
- python 3.13.* *_cp313
license: BSD-3-Clause
license_family: BSD
purls: []
size: 6217
timestamp: 1723823393322
- kind: pypi
name: qlever
version: 0.5.12
url: https://files.pythonhosted.org/packages/cf/d9/b1003ae23cc6e48c81c9a2cc23edf8d34b3b978eb4fe91b941992e88e351/qlever-0.5.12-py3-none-any.whl
sha256: bb86eb17c7768b2915150205c0058bb3716d689d1d94eb14a28008bdbdd6c9e0
requires_dist:
- psutil
- termcolor
- argcomplete
requires_python: '>=3.8'
- kind: conda
name: readline
version: '8.2'
build: h8228510_1
build_number: 1
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda
sha256: 5435cf39d039387fbdc977b0a762357ea909a7694d9528ab40f005e9208744d7
md5: 47d31b792659ce70f470b5c82fdfb7a4
depends:
- libgcc-ng >=12
- ncurses >=6.3,<7.0a0
license: GPL-3.0-only
license_family: GPL
purls: []
size: 281456
timestamp: 1679532220005
- kind: pypi
name: termcolor
version: 2.5.0
url: https://files.pythonhosted.org/packages/7f/be/df630c387a0a054815d60be6a97eb4e8f17385d5d6fe660e1c02750062b4/termcolor-2.5.0-py3-none-any.whl
sha256: 37b17b5fc1e604945c2642c872a3764b5d547a48009871aea3edd3afa180afb8
requires_dist:
- pytest ; extra == 'tests'
- pytest-cov ; extra == 'tests'
requires_python: '>=3.9'
- kind: conda
name: tk
version: 8.6.13
build: noxft_h4845f30_101
build_number: 101
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda
sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e
md5: d453b98d9c83e71da0741bb0ff4d76bc
depends:
- libgcc-ng >=12
- libzlib >=1.2.13,<2.0.0a0
license: TCL
license_family: BSD
purls: []
size: 3318875
timestamp: 1699202167581
- kind: conda
name: tzdata
version: 2024b
build: hc8b5060_0
subdir: noarch
noarch: generic
url: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda
sha256: 4fde5c3008bf5d2db82f2b50204464314cc3c91c1d953652f7bd01d9e52aefdf
md5: 8ac3367aafb1cc0a068483c580af8015
license: LicenseRef-Public-Domain
purls: []
size: 122354
timestamp: 1728047496079
- kind: conda
name: xz
version: 5.2.6
build: h166bdaf_0
subdir: linux-64
url: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2
sha256: 03a6d28ded42af8a347345f82f3eebdd6807a08526d47899a42d62d319609162
md5: 2161070d867d1b1204ea749c8eec4ef0
depends:
- libgcc-ng >=12
license: LGPL-2.1 and GPL-2.0
purls: []
size: 418368
timestamp: 1660346797927

17
qlever/pyproject.toml Executable file
View File

@ -0,0 +1,17 @@
[project]
authors = [{name = "Giò Diani", email = "mail@gionathandiani.name"}]
dependencies = ["qlever>=0.5.8,<0.6"]
description = "Enviroment for the SPARQL-Engine «QLever»"
name = "qlever"
requires-python = ">= 3.11"
version = "0.1.0"
[build-system]
build-backend = "hatchling.build"
requires = ["hatchling"]
[tool.pixi.project]
channels = ["conda-forge"]
platforms = ["linux-64"]
[tool.pixi.tasks]

1737
qlever/src/qlever-ui-backend.yaml Executable file

File diff suppressed because it is too large Load Diff

1580
qlever/src/qlever-ui-example.yaml Executable file

File diff suppressed because it is too large Load Diff

0
qlever/src/qlever/__init__.py Executable file
View File

18
webapp/.editorconfig Normal file
View File

@ -0,0 +1,18 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4

67
webapp/.env.example Normal file
View File

@ -0,0 +1,67 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_TIMEZONE=UTC
APP_URL=http://localhost
APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database
PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12
LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=
SESSION_DRIVER=file
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database
CACHE_STORE=file
CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=log
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
VITE_APP_NAME="${APP_NAME}"
QLEVER_URL="http://localhost:7019/?query="

11
webapp/.gitattributes vendored Normal file
View File

@ -0,0 +1,11 @@
* text=auto eol=lf
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore

22
webapp/.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
/.phpunit.cache
/node_modules
/public/build
/public/hot
/public/storage
/storage/*.key
/storage/pail
/vendor
.env
.env.backup
.env.production
.phpactor.json
.phpunit.result.cache
Homestead.json
Homestead.yaml
auth.json
npm-debug.log
yarn-error.log
/.fleet
/.idea
/.vscode
/.zed

9
webapp/LICENSE.md Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) Gionathan Diani. All rights reserved.
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.

26
webapp/README.md Normal file
View File

@ -0,0 +1,26 @@
# webapp
In diesem Verzeichnis befindet sich der Programmcode für die Webapplikation zur Exploration des RDF-Datensatzes.
## Inbetriebnahme
Folgend Voraussetzungen müssen erfüllt sein um die Applikation auszuführen:
- Ein Qlever Server ist vorhanden
- PHP, Composer, Node und NPM müssen installiert sein: https://laravel.com/docs/11.x/installation#installing-php
### Installation
Installiere Abhängigkeiten des Projekts:
```bash
composer install && npm i
```
Erstelle eine Kopie der Enviroment-Konfigurationsdatei und generiere den application key:
```bash
cp .env.example .env && ./artisan key:generate
```
### Lokalen Entwicklungsserver starten
```bash
composer dev run
```
## Lizenzen
- Die Webapplikation ist mit dem Laravel Framework umgsetzt welches der [MIT Lizenz](https://github.com/laravel/laravel) untersteht.
- Der Programmcode der Webapplikation ist unter der [MIT Lizenz](LICENSE.md) verfügbar.

51
webapp/app/Helpers.php Normal file
View File

@ -0,0 +1,51 @@
<?php
namespace App;
use DateTime;
class Helpers
{
/**
* Credit: https://www.php.net/manual/en/function.checkdate.php#113205
** @return bool
*/
static function dateValid($date, $format = 'Y-m-d')
{
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
/**
* @return array
*/
static function buildTree(array $elements, string $parentId): array
{
$branch = [];
foreach ($elements as $key => $el) {
if($el['ark_parent']['value'] === $parentId){
$el['name'] = $el['name_child']['value'];
$el['ark'] = $el['ark_child']['value'];
$children = self::buildTree($elements, $el['ark_child']['value']);
if($children){
$el['children'] = $children;
}else{
$el['value'] = 1;
}
unset($el['ark_child'], $el['ark_parent'], $el['name_child']);
$branch[] = $el;
}
}
return $branch;
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace App\Http\Controllers;
abstract class Controller
{
//
}

25
webapp/app/Metagrid.php Normal file
View File

@ -0,0 +1,25 @@
<?php
namespace App;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Response;
class Metagrid{
/**
* Get data from metagrid
* @param int $id Scope-ID
*/
public static function widget(int $id)
{
$request = Http::get("https://api.metagrid.ch/widget/burgerbibliothek/person/{$id}");
if($request->successful()){
return $request->json();
}
return false;
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
/** @use HasFactory<\Database\Factories\UserFactory> */
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
}
}

294
webapp/app/Sparql.php Normal file
View File

@ -0,0 +1,294 @@
<?php
namespace App;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Response;
use Symfony\Component\Console\Helper\Helper;
class Sparql
{
public static function get(string $query): ?array
{
$endpoint = env('QLEVER_URL', 'http://localhost:7019/?query=');
$request = $endpoint.urlencode($query);
$get = Http::get($request);
if($get->successful()){
$json = $get->json();
return count($json['results']['bindings']) > 0 ? $json['results']['bindings'] : null;
}
return null;
}
public static function person(string $id): ?array
{
$query = '
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
SELECT DISTINCT ?name ?sex ?desc ?birth_date ?baptism_date ?death_date ?burial_date ?id_type ?scope_id {
?person a rico:Person ;
rico:hasOrHadIdentifier ?id_ark ;
rico:hasOrHadIdentifier ?id_scope ;
rico:hasOrHadName ?name ;
rico:hasOrHadDemographicGroup ?demographic_groups .
?id_ark rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue "'.$id.'" .
?id_scope rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/Scope-ID> ;
rico:normalizedValue ?scope_id .
?demographic_groups rdfs:label ?sex .
OPTIONAL {
?person rico:hasBirthDate ?birth_date
} .
OPTIONAL {
?person rico:hasDeathDate ?death_date
} .
OPTIONAL {
?person rico:generalDescription ?desc
} .
OPTIONAL {
?person rico:isAssociatedWithEvent ?event .
?event rico:hasEventType <https://burgerbib.ch/EventTypes/Baptism> ;
rico:occurredAtDate ?baptism_date .
} .
OPTIONAL {
?person rico:isAssociatedWithEvent ?event .
?event rico:hasEventType <https://burgerbib.ch/EventTypes/Burial> ;
rico:occurredAtDate ?burial_date .
} .
}
LIMIT 1
';
return self::get($query);
}
public static function spouses(string $id): ?array
{
$query = '
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
SELECT ?ark ?name {
<https://burgerbib.ch/indexterms/ark:36599/'.$id.'> rico:hasOrHadSpouse ?spouse .
?spouse rico:hasOrHadName ?name ;
rico:hasOrHadIdentifier ?id_spouse .
?id_spouse rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue ?ark .
}
';
return self::get($query);
}
public static function lifePartner(string $id): ?array
{
$query = '
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
SELECT ?ark ?name {
<https://burgerbib.ch/indexterms/ark:36599/'.$id.'> rico:hasOrHadLifePartner ?partner .
?partner rico:hasOrHadName ?name ;
rico:hasOrHadIdentifier ?id_partner .
?id_partner rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue ?ark .
}
';
return self::get($query);
}
public static function children(string $id): ?array
{
$query = '
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
SELECT ?ark ?name {
<https://burgerbib.ch/indexterms/ark:36599/'.$id.'> rico:hasChild ?child .
?child rico:hasOrHadName ?name ;
rico:hasOrHadIdentifier ?id_child .
?id_child rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue ?ark .
}
';
return self::get($query);
}
public static function children_extended(string $id): ?array
{
$query = '
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
SELECT DISTINCT ?ark_parent ?ark_child ?name_child {
<https://burgerbib.ch/indexterms/ark:36599/'.$id.'> rico:hasChild+ ?child .
?child rico:hasOrHadName ?name_child ;
rico:hasOrHadIdentifier ?id_child ;
rico:isChildOf ?parent .
?parent rico:hasOrHadIdentifier ?id_parent .
?id_child rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue ?ark_child .
?id_parent rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue ?ark_parent .
}
';
return self::get($query);
}
public static function parents(string $id): ?array
{
$query = '
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
SELECT ?ark ?name {
<https://burgerbib.ch/indexterms/ark:36599/'.$id.'> rico:isChildOf ?parent .
?parent rico:hasOrHadName ?name ;
rico:hasOrHadIdentifier ?id_parent .
?id_parent rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue ?ark .
}
';
return self::get($query);
}
public static function siblings(string $id): ?array
{
$query = "
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
SELECT DISTINCT ?ark ?name {
<https://burgerbib.ch/indexterms/ark:36599/{$id}> rico:isChildOf ?parent .
?parent rico:hasChild ?child .
?child rico:hasOrHadIdentifier ?id ;
rico:hasOrHadName ?name .
?id rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue ?ark .
FILTER (?ark != 'ark:36599/{$id}')
}
";
return self::get($query);
}
public static function list(int $offset = 0): ?array
{
$query = "
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT DISTINCT ?name ?birth_date ?death_date ?ark {
?person a rico:Person ;
rico:hasOrHadIdentifier ?id ;
rico:hasOrHadName ?name ;
rico:hasBirthDate ?birth_date ;
rico:hasDeathDate ?death_date .
?id rico:hasIdentifierType ?idtype ;
rico:normalizedValue ?ark .
FILTER (?idtype = <https://burgerbib.ch/IdentifierTypes/ARK>)
}
ORDER BY ASC(?name)
LIMIT 100 OFFSET ".($offset * 100);
return self::get($query);
}
public static function search(string $term, array $options, int $offset = 0): ?array
{
$hasDescendant = $options['hasDescendant'] ? 'rico:hasDescendant ?descendant ;' : '';
$birthYear = $options['birthYear'] ? "BIND(YEAR(?birth_date) AS ?birth_year) FILTER (?birth_year = '{$options['birthYear']}'^^xsd:int)" : '';
$birthMonth = $options['birthMonth'] ? "BIND(MONTH(?birth_date) AS ?birth_month) FILTER (?birth_month = '{$options['birthMonth']}'^^xsd:int)" : '';
$birthDay = $options['birthDay'] ? "BIND(DAY(?birth_date) AS ?birth_day) FILTER (?birth_day = '{$options['birthDay']}'^^xsd:int)" : '';
$deathYear = $options['deathYear'] ? "BIND(YEAR(?death_date) AS ?death_year) FILTER (?death_year = '{$options['deathYear']}'^^xsd:int)" : '';
$deathMonth = $options['deathMonth'] ? "BIND(MONTH(?death_date) AS ?death_month) FILTER (?death_month = '{$options['deathMonth']}'^^xsd:int)" : '';
$deathDay = $options['deathDay'] ? "BIND(DAY(?death_date) AS ?death_day) FILTER (?death_day = '{$options['deathDay']}'^^xsd:int)" : '';
if($term){
$term_split = explode(' ', $term);
$term_query = '';
foreach ($term_split as $t) {
$term_query .= "CONTAINS(LCASE(?name),LCASE('{$t}')) && ";
}
$term = 'FILTER ('.rtrim($term_query, '&& ').')';
}else{
$term = '';
}
$query = "
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT DISTINCT ?name ?birth_date ?death_date ?ark {
?person a rico:Person ;
rico:hasOrHadIdentifier ?id ;
rico:hasOrHadName ?name ;
rico:hasBirthDate ?birth_date ;
{$hasDescendant}
rico:hasDeathDate ?death_date .
?id rico:hasIdentifierType ?idtype ;
rico:normalizedValue ?ark .
FILTER (?idtype = <https://burgerbib.ch/IdentifierTypes/ARK>)
{$term}
{$birthYear}
{$birthMonth}
{$birthDay}
{$deathYear}
{$deathMonth}
{$deathDay}
}
ORDER BY ASC(?name)
LIMIT 100 OFFSET ".($offset * 100);
return self::get($query);
}
public static function filterByBirthdate(string $from, string $to, int $offset = 0): ?array
{
$query = "
PREFIX rico: <https://www.ica.org/standards/RiC/ontology#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?name ?sex ?birth_date ?baptism_date ?death_date ?burial_date ?id_type ?ark {
?person a rico:Person ;
rico:hasOrHadIdentifier ?id_primary ;
rico:hasOrHadIdentifier ?id_secondary ;
rico:hasOrHadName ?name ;
rico:hasBirthDate ?birth_date ;
rico:hasDeathDate ?death_date .
OPTIONAL {
?person rico:isAssociatedWithEvent ?event .
?event rico:hasEventType <https://burgerbib.ch/EventTypes/Baptism> ;
rico:occurredAtDate ?baptism_date .
} .
OPTIONAL {
?person rico:isAssociatedWithEvent ?event .
?event rico:hasEventType <https://burgerbib.ch/EventTypes/Burial> ;
rico:occurredAtDate ?burial_date .
} .
?id_primary rico:hasIdentifierType <https://burgerbib.ch/IdentifierTypes/ARK> ;
rico:normalizedValue ?ark .
FILTER (?birth_date > '{$from}'^^xsd:date && ?birth_date < '{$to}'^^xsd:date && DATATYPE(?death_date) = xsd:date)
}
ORDER BY DESC (?birth_date)
LIMIT 50 OFFSET ".($offset * 100);
return self::get($query);
}
}

15
webapp/artisan Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env php
<?php
use Symfony\Component\Console\Input\ArgvInput;
define('LARAVEL_START', microtime(true));
// Register the Composer autoloader...
require __DIR__.'/vendor/autoload.php';
// Bootstrap Laravel and handle the command...
$status = (require_once __DIR__.'/bootstrap/app.php')
->handleCommand(new ArgvInput);
exit($status);

18
webapp/bootstrap/app.php Normal file
View File

@ -0,0 +1,18 @@
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
//
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();

2
webapp/bootstrap/cache/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -0,0 +1,5 @@
<?php
return [
App\Providers\AppServiceProvider::class,
];

71
webapp/composer.json Normal file
View File

@ -0,0 +1,71 @@
{
"name": "laravel/laravel",
"type": "project",
"description": "The skeleton application for the Laravel framework.",
"keywords": ["laravel", "framework"],
"license": "MIT",
"require": {
"php": "^8.2",
"laravel/framework": "^11.9",
"laravel/tinker": "^2.9",
"picocss/pico": "^2.0"
},
"require-dev": {
"fakerphp/faker": "^1.23",
"laravel/pail": "^1.1",
"laravel/pint": "^1.13",
"laravel/sail": "^1.26",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.1",
"phpunit/phpunit": "^11.0.1"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi",
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
"@php artisan migrate --graceful --ansi"
],
"dev": [
"Composer\\Config::disableProcessTimeout",
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
]
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
"minimum-stability": "stable",
"prefer-stable": true
}

7894
webapp/composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

126
webapp/config/app.php Normal file
View File

@ -0,0 +1,126 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application, which will be used when the
| framework needs to place the application's name in a notification or
| other UI elements where an application name needs to be displayed.
|
*/
'name' => env('APP_NAME', 'Laravel'),
/*
|--------------------------------------------------------------------------
| Application Environment
|--------------------------------------------------------------------------
|
| This value determines the "environment" your application is currently
| running in. This may determine how you prefer to configure various
| services the application utilizes. Set this in your ".env" file.
|
*/
'env' => env('APP_ENV', 'production'),
/*
|--------------------------------------------------------------------------
| Application Debug Mode
|--------------------------------------------------------------------------
|
| When your application is in debug mode, detailed error messages with
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
*/
'debug' => (bool) env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
| Application URL
|--------------------------------------------------------------------------
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| the application so that it's available within Artisan commands.
|
*/
'url' => env('APP_URL', 'http://localhost'),
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. The timezone
| is set to "UTC" by default as it is suitable for most use cases.
|
*/
'timezone' => env('APP_TIMEZONE', 'UTC'),
/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by Laravel's translation / localization methods. This option can be
| set to any locale for which you plan to have translation strings.
|
*/
'locale' => env('APP_LOCALE', 'en'),
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| This key is utilized by Laravel's encryption services and should be set
| to a random, 32 character string to ensure that all encrypted values
| are secure. You should do this prior to deploying the application.
|
*/
'cipher' => 'AES-256-CBC',
'key' => env('APP_KEY'),
'previous_keys' => [
...array_filter(
explode(',', env('APP_PREVIOUS_KEYS', ''))
),
],
/*
|--------------------------------------------------------------------------
| Maintenance Mode Driver
|--------------------------------------------------------------------------
|
| These configuration options determine the driver used to determine and
| manage Laravel's "maintenance mode" status. The "cache" driver will
| allow maintenance mode to be controlled across multiple machines.
|
| Supported drivers: "file", "cache"
|
*/
'maintenance' => [
'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
'store' => env('APP_MAINTENANCE_STORE', 'database'),
],
];

115
webapp/config/auth.php Normal file
View File

@ -0,0 +1,115 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option defines the default authentication "guard" and password
| reset "broker" for your application. You may change these values
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => env('AUTH_GUARD', 'web'),
'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| which utilizes session storage plus the Eloquent user provider.
|
| All authentication guards have a user provider, which defines how the
| users are actually retrieved out of your database or other storage
| system used by the application. Typically, Eloquent is utilized.
|
| Supported: "session"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication guards have a user provider, which defines how the
| users are actually retrieved out of your database or other storage
| system used by the application. Typically, Eloquent is utilized.
|
| If you have multiple user tables or models you may configure multiple
| providers to represent the model / table. These providers may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', App\Models\User::class),
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| These configuration options specify the behavior of Laravel's password
| reset functionality, including the table utilized for token storage
| and the user provider that is invoked to actually retrieve users.
|
| The expiry time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
| The throttle setting is the number of seconds a user must wait before
| generating more password reset tokens. This prevents the user from
| quickly generating a very large amount of password reset tokens.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| window expires and users are asked to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
];

108
webapp/config/cache.php Normal file
View File

@ -0,0 +1,108 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Cache Store
|--------------------------------------------------------------------------
|
| This option controls the default cache store that will be used by the
| framework. This connection is utilized if another isn't explicitly
| specified when running a cache operation inside the application.
|
*/
'default' => env('CACHE_STORE', 'database'),
/*
|--------------------------------------------------------------------------
| Cache Stores
|--------------------------------------------------------------------------
|
| Here you may define all of the cache "stores" for your application as
| well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches.
|
| Supported drivers: "array", "database", "file", "memcached",
| "redis", "dynamodb", "octane", "null"
|
*/
'stores' => [
'array' => [
'driver' => 'array',
'serialize' => false,
],
'database' => [
'driver' => 'database',
'connection' => env('DB_CACHE_CONNECTION'),
'table' => env('DB_CACHE_TABLE', 'cache'),
'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
'lock_table' => env('DB_CACHE_LOCK_TABLE'),
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
'lock_path' => storage_path('framework/cache/data'),
],
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'sasl' => [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
'redis' => [
'driver' => 'redis',
'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
],
'dynamodb' => [
'driver' => 'dynamodb',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
'octane' => [
'driver' => 'octane',
],
],
/*
|--------------------------------------------------------------------------
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| When utilizing the APC, database, memcached, Redis, and DynamoDB cache
| stores, there might be other applications using the same cache. For
| that reason, you may prefix every cache key to avoid collisions.
|
*/
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'),
];

173
webapp/config/database.php Normal file
View File

@ -0,0 +1,173 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for database operations. This is
| the connection which will be utilized unless another connection
| is explicitly specified when you execute a query / statement.
|
*/
'default' => env('DB_CONNECTION', 'sqlite'),
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Below are all of the database connections defined for your application.
| An example configuration is provided for each database system which
| is supported by Laravel. You're free to add / remove connections.
|
*/
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'url' => env('DB_URL'),
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
'busy_timeout' => null,
'journal_mode' => null,
'synchronous' => null,
],
'mysql' => [
'driver' => 'mysql',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'mariadb' => [
'driver' => 'mariadb',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'pgsql' => [
'driver' => 'pgsql',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'public',
'sslmode' => 'prefer',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'url' => env('DB_URL'),
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '1433'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => '',
'prefix_indexes' => true,
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run on the database.
|
*/
'migrations' => [
'table' => 'migrations',
'update_date_on_publish' => true,
],
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer body of commands than a typical key-value system
| such as Memcached. You may define your connection settings here.
|
*/
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
],
];

View File

@ -0,0 +1,77 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. The "local" disk, as well as a variety of cloud
| based disks are available to your application for file storage.
|
*/
'default' => env('FILESYSTEM_DISK', 'local'),
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Below you may configure as many filesystem disks as necessary, and you
| may even configure multiple disks for the same driver. Examples for
| most supported storage drivers are configured here for reference.
|
| Supported drivers: "local", "ftp", "sftp", "s3"
|
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/private'),
'serve' => true,
'throw' => false,
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
'throw' => false,
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
],
],
/*
|--------------------------------------------------------------------------
| Symbolic Links
|--------------------------------------------------------------------------
|
| Here you may configure the symbolic links that will be created when the
| `storage:link` Artisan command is executed. The array keys should be
| the locations of the links and the values should be their targets.
|
*/
'links' => [
public_path('storage') => storage_path('app/public'),
],
];

132
webapp/config/logging.php Normal file
View File

@ -0,0 +1,132 @@
<?php
use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
use Monolog\Processor\PsrLogMessageProcessor;
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
|--------------------------------------------------------------------------
|
| This option defines the default log channel that is utilized to write
| messages to your logs. The value provided here should match one of
| the channels present in the list of "channels" configured below.
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
/*
|--------------------------------------------------------------------------
| Deprecations Log Channel
|--------------------------------------------------------------------------
|
| This option controls the log channel that should be used to log warnings
| regarding deprecated PHP and library features. This allows you to get
| your application ready for upcoming major versions of dependencies.
|
*/
'deprecations' => [
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
],
/*
|--------------------------------------------------------------------------
| Log Channels
|--------------------------------------------------------------------------
|
| Here you may configure the log channels for your application. Laravel
| utilizes the Monolog PHP logging library, which includes a variety
| of powerful log handlers and formatters that you're free to use.
|
| Available drivers: "single", "daily", "slack", "syslog",
| "errorlog", "monolog", "custom", "stack"
|
*/
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => explode(',', env('LOG_STACK', 'single')),
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => env('LOG_DAILY_DAYS', 14),
'replace_placeholders' => true,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
'level' => env('LOG_LEVEL', 'critical'),
'replace_placeholders' => true,
],
'papertrail' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
],
'processors' => [PsrLogMessageProcessor::class],
],
'stderr' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDERR_FORMATTER'),
'with' => [
'stream' => 'php://stderr',
],
'processors' => [PsrLogMessageProcessor::class],
],
'syslog' => [
'driver' => 'syslog',
'level' => env('LOG_LEVEL', 'debug'),
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
'replace_placeholders' => true,
],
'errorlog' => [
'driver' => 'errorlog',
'level' => env('LOG_LEVEL', 'debug'),
'replace_placeholders' => true,
],
'null' => [
'driver' => 'monolog',
'handler' => NullHandler::class,
],
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
],
];

116
webapp/config/mail.php Normal file
View File

@ -0,0 +1,116 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Mailer
|--------------------------------------------------------------------------
|
| This option controls the default mailer that is used to send all email
| messages unless another mailer is explicitly specified when sending
| the message. All additional mailers can be configured within the
| "mailers" array. Examples of each type of mailer are provided.
|
*/
'default' => env('MAIL_MAILER', 'log'),
/*
|--------------------------------------------------------------------------
| Mailer Configurations
|--------------------------------------------------------------------------
|
| Here you may configure all of the mailers used by your application plus
| their respective settings. Several examples have been configured for
| you and you are free to add your own as your application requires.
|
| Laravel supports a variety of mail "transport" drivers that can be used
| when delivering an email. You may specify which one you're using for
| your mailers below. You may also add additional mailers if needed.
|
| Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
| "postmark", "resend", "log", "array",
| "failover", "roundrobin"
|
*/
'mailers' => [
'smtp' => [
'transport' => 'smtp',
'url' => env('MAIL_URL'),
'host' => env('MAIL_HOST', '127.0.0.1'),
'port' => env('MAIL_PORT', 2525),
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
],
'ses' => [
'transport' => 'ses',
],
'postmark' => [
'transport' => 'postmark',
// 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
// 'client' => [
// 'timeout' => 5,
// ],
],
'resend' => [
'transport' => 'resend',
],
'sendmail' => [
'transport' => 'sendmail',
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
],
'log' => [
'transport' => 'log',
'channel' => env('MAIL_LOG_CHANNEL'),
],
'array' => [
'transport' => 'array',
],
'failover' => [
'transport' => 'failover',
'mailers' => [
'smtp',
'log',
],
],
'roundrobin' => [
'transport' => 'roundrobin',
'mailers' => [
'ses',
'postmark',
],
],
],
/*
|--------------------------------------------------------------------------
| Global "From" Address
|--------------------------------------------------------------------------
|
| You may wish for all emails sent by your application to be sent from
| the same address. Here you may specify a name and address that is
| used globally for all emails that are sent by your application.
|
*/
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
];

112
webapp/config/queue.php Normal file
View File

@ -0,0 +1,112 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Queue Connection Name
|--------------------------------------------------------------------------
|
| Laravel's queue supports a variety of backends via a single, unified
| API, giving you convenient access to each backend using identical
| syntax for each. The default queue connection is defined below.
|
*/
'default' => env('QUEUE_CONNECTION', 'database'),
/*
|--------------------------------------------------------------------------
| Queue Connections
|--------------------------------------------------------------------------
|
| Here you may configure the connection options for every queue backend
| used by your application. An example configuration is provided for
| each backend supported by Laravel. You're also free to add more.
|
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
*/
'connections' => [
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'connection' => env('DB_QUEUE_CONNECTION'),
'table' => env('DB_QUEUE_TABLE', 'jobs'),
'queue' => env('DB_QUEUE', 'default'),
'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
'after_commit' => false,
],
'beanstalkd' => [
'driver' => 'beanstalkd',
'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
'queue' => env('BEANSTALKD_QUEUE', 'default'),
'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
'block_for' => 0,
'after_commit' => false,
],
'sqs' => [
'driver' => 'sqs',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
'queue' => env('SQS_QUEUE', 'default'),
'suffix' => env('SQS_SUFFIX'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'after_commit' => false,
],
'redis' => [
'driver' => 'redis',
'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
'block_for' => null,
'after_commit' => false,
],
],
/*
|--------------------------------------------------------------------------
| Job Batching
|--------------------------------------------------------------------------
|
| The following options configure the database and table that store job
| batching information. These options can be updated to any database
| connection and table which has been defined by your application.
|
*/
'batching' => [
'database' => env('DB_CONNECTION', 'sqlite'),
'table' => 'job_batches',
],
/*
|--------------------------------------------------------------------------
| Failed Queue Jobs
|--------------------------------------------------------------------------
|
| These options configure the behavior of failed queue job logging so you
| can control how and where failed jobs are stored. Laravel ships with
| support for storing failed jobs in a simple file or in a database.
|
| Supported drivers: "database-uuids", "dynamodb", "file", "null"
|
*/
'failed' => [
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
'database' => env('DB_CONNECTION', 'sqlite'),
'table' => 'failed_jobs',
],
];

View File

@ -0,0 +1,38 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Third Party Services
|--------------------------------------------------------------------------
|
| This file is for storing the credentials for third party services such
| as Mailgun, Postmark, AWS and more. This file provides the de facto
| location for this type of information, allowing packages to have
| a conventional file to locate the various service credentials.
|
*/
'postmark' => [
'token' => env('POSTMARK_TOKEN'),
],
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'resend' => [
'key' => env('RESEND_KEY'),
],
'slack' => [
'notifications' => [
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
],
],
];

217
webapp/config/session.php Normal file
View File

@ -0,0 +1,217 @@
<?php
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Session Driver
|--------------------------------------------------------------------------
|
| This option determines the default session driver that is utilized for
| incoming requests. Laravel supports a variety of storage options to
| persist session data. Database storage is a great default choice.
|
| Supported: "file", "cookie", "database", "apc",
| "memcached", "redis", "dynamodb", "array"
|
*/
'driver' => env('SESSION_DRIVER', 'database'),
/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to expire immediately when the browser is closed then you may
| indicate that via the expire_on_close configuration option.
|
*/
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
/*
|--------------------------------------------------------------------------
| Session Encryption
|--------------------------------------------------------------------------
|
| This option allows you to easily specify that all of your session data
| should be encrypted before it's stored. All encryption is performed
| automatically by Laravel and you may use the session like normal.
|
*/
'encrypt' => env('SESSION_ENCRYPT', false),
/*
|--------------------------------------------------------------------------
| Session File Location
|--------------------------------------------------------------------------
|
| When utilizing the "file" session driver, the session files are placed
| on disk. The default storage location is defined here; however, you
| are free to provide another location where they should be stored.
|
*/
'files' => storage_path('framework/sessions'),
/*
|--------------------------------------------------------------------------
| Session Database Connection
|--------------------------------------------------------------------------
|
| When using the "database" or "redis" session drivers, you may specify a
| connection that should be used to manage these sessions. This should
| correspond to a connection in your database configuration options.
|
*/
'connection' => env('SESSION_CONNECTION'),
/*
|--------------------------------------------------------------------------
| Session Database Table
|--------------------------------------------------------------------------
|
| When using the "database" session driver, you may specify the table to
| be used to store sessions. Of course, a sensible default is defined
| for you; however, you're welcome to change this to another table.
|
*/
'table' => env('SESSION_TABLE', 'sessions'),
/*
|--------------------------------------------------------------------------
| Session Cache Store
|--------------------------------------------------------------------------
|
| When using one of the framework's cache driven session backends, you may
| define the cache store which should be used to store the session data
| between requests. This must match one of your defined cache stores.
|
| Affects: "apc", "dynamodb", "memcached", "redis"
|
*/
'store' => env('SESSION_STORE'),
/*
|--------------------------------------------------------------------------
| Session Sweeping Lottery
|--------------------------------------------------------------------------
|
| Some session drivers must manually sweep their storage location to get
| rid of old sessions from storage. Here are the chances that it will
| happen on a given request. By default, the odds are 2 out of 100.
|
*/
'lottery' => [2, 100],
/*
|--------------------------------------------------------------------------
| Session Cookie Name
|--------------------------------------------------------------------------
|
| Here you may change the name of the session cookie that is created by
| the framework. Typically, you should not need to change this value
| since doing so does not grant a meaningful security improvement.
|
*/
'cookie' => env(
'SESSION_COOKIE',
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
),
/*
|--------------------------------------------------------------------------
| Session Cookie Path
|--------------------------------------------------------------------------
|
| The session cookie path determines the path for which the cookie will
| be regarded as available. Typically, this will be the root path of
| your application, but you're free to change this when necessary.
|
*/
'path' => env('SESSION_PATH', '/'),
/*
|--------------------------------------------------------------------------
| Session Cookie Domain
|--------------------------------------------------------------------------
|
| This value determines the domain and subdomains the session cookie is
| available to. By default, the cookie will be available to the root
| domain and all subdomains. Typically, this shouldn't be changed.
|
*/
'domain' => env('SESSION_DOMAIN'),
/*
|--------------------------------------------------------------------------
| HTTPS Only Cookies
|--------------------------------------------------------------------------
|
| By setting this option to true, session cookies will only be sent back
| to the server if the browser has a HTTPS connection. This will keep
| the cookie from being sent to you when it can't be done securely.
|
*/
'secure' => env('SESSION_SECURE_COOKIE'),
/*
|--------------------------------------------------------------------------
| HTTP Access Only
|--------------------------------------------------------------------------
|
| Setting this value to true will prevent JavaScript from accessing the
| value of the cookie and the cookie will only be accessible through
| the HTTP protocol. It's unlikely you should disable this option.
|
*/
'http_only' => env('SESSION_HTTP_ONLY', true),
/*
|--------------------------------------------------------------------------
| Same-Site Cookies
|--------------------------------------------------------------------------
|
| This option determines how your cookies behave when cross-site requests
| take place, and can be used to mitigate CSRF attacks. By default, we
| will set this value to "lax" to permit secure cross-site requests.
|
| See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
|
| Supported: "lax", "strict", "none", null
|
*/
'same_site' => env('SESSION_SAME_SITE', 'lax'),
/*
|--------------------------------------------------------------------------
| Partitioned Cookies
|--------------------------------------------------------------------------
|
| Setting this value to true will tie the cookie to the top-level site for
| a cross-site context. Partitioned cookies are accepted by the browser
| when flagged "secure" and the Same-Site attribute is set to "none".
|
*/
'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
];

1
webapp/database/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.sqlite*

View File

@ -0,0 +1,44 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
/**
* The current password being used by the factory.
*/
protected static ?string $password;
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => static::$password ??= Hash::make('password'),
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);
}
}

View File

@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
Schema::create('sessions', function (Blueprint $table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->longText('payload');
$table->integer('last_activity')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('users');
Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions');
}
};

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('cache', function (Blueprint $table) {
$table->string('key')->primary();
$table->mediumText('value');
$table->integer('expiration');
});
Schema::create('cache_locks', function (Blueprint $table) {
$table->string('key')->primary();
$table->string('owner');
$table->integer('expiration');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('cache');
Schema::dropIfExists('cache_locks');
}
};

View File

@ -0,0 +1,57 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('jobs', function (Blueprint $table) {
$table->id();
$table->string('queue')->index();
$table->longText('payload');
$table->unsignedTinyInteger('attempts');
$table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('available_at');
$table->unsignedInteger('created_at');
});
Schema::create('job_batches', function (Blueprint $table) {
$table->string('id')->primary();
$table->string('name');
$table->integer('total_jobs');
$table->integer('pending_jobs');
$table->integer('failed_jobs');
$table->longText('failed_job_ids');
$table->mediumText('options')->nullable();
$table->integer('cancelled_at')->nullable();
$table->integer('created_at');
$table->integer('finished_at')->nullable();
});
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('jobs');
Schema::dropIfExists('job_batches');
Schema::dropIfExists('failed_jobs');
}
};

View File

@ -0,0 +1,23 @@
<?php
namespace Database\Seeders;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
}
}

3045
webapp/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

20
webapp/package.json Normal file
View File

@ -0,0 +1,20 @@
{
"private": true,
"type": "module",
"scripts": {
"build": "vite build",
"dev": "vite"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"axios": "^1.7.4",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^1.0",
"postcss": "^8.4.47",
"tailwindcss": "^3.4.13",
"vite": "^5.0"
},
"dependencies": {
"echarts": "^5.5.1"
}
}

33
webapp/phpunit.xml Normal file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
>
<testsuites>
<testsuite name="Unit">
<directory>tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory>tests/Feature</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>app</directory>
</include>
</source>
<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_STORE" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="MAIL_MAILER" value="array"/>
<env name="PULSE_ENABLED" value="false"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
</phpunit>

6
webapp/postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

21
webapp/public/.htaccess Normal file
View File

@ -0,0 +1,21 @@
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

View File

17
webapp/public/index.php Normal file
View File

@ -0,0 +1,17 @@
<?php
use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
// Determine if the application is in maintenance mode...
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
require $maintenance;
}
// Register the Composer autoloader...
require __DIR__.'/../vendor/autoload.php';
// Bootstrap Laravel and handle the request...
(require_once __DIR__.'/../bootstrap/app.php')
->handleRequest(Request::capture());

2
webapp/public/robots.txt Normal file
View File

@ -0,0 +1,2 @@
User-agent: *
Disallow:

View File

@ -0,0 +1,90 @@
body>header{
background: var(--pico-card-sectioning-background-color);
position: sticky;
top: 0;
z-index: 99;
}
dt{
font-weight: 700;
}
dd{
margin: 0;
}
header>h1,
header>h2{
margin-bottom: 0;
font-size: 1.5em;
}
dd + dt{
margin-top: calc(var(--pico-typography-spacing-vertical) * .5);
}
a{
color: var(--pico-contrast);
}
p.badge{
background: var(--pico-mark-background-color);
color: var(--pico-mark-color);
border-radius: var(--pico-border-radius);
padding: var(--pico-spacing);
}
label{
padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal)
}
fieldset>label:first-child{
padding-left: 0;
}
ul.list{
padding: 0;
}
ul.list li{
list-style-type: none;
}
ul.list li>a>span{
display: block;
}
ul.list li>a>span:first-child{
--pico-font-size: 1rem;
font-weight: bold;
font-size: var(--pico-font-size);
}
ul.list li>a>span:last-child{
--pico-font-size: .75em;
font-weight: bold;
font-size: var(--pico-font-size);
}
ul{
padding: 0;
}
ul li{
list-style: none !important;
}
.grid.start{
grid-template-columns: repeat(2, minmax(0,50%));
grid-template-row: repeat(2, 1fr);
}
article.search{
grid-column: 1 / 4;
}
article>div h2{
--pico-font-size: 1rem;
margin-bottom: 0.3em;
}

View File

@ -0,0 +1,5 @@
import * as echarts from 'echarts';
const timeline = document.getElementById('chart');
const timelienChart = echarts.init(timeline);
window.timelienChart = timelienChart;

View File

@ -0,0 +1,5 @@
import * as echarts from 'echarts';
const tree = document.getElementById('tree-chart');
const treeChart = echarts.init(tree);
window.treeChart = treeChart;

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
@vite(['vendor/picocss/pico/css/pico.min.css', 'resources/css/app.css', 'resources/js/app.js'])
<title>Deskriptorenportal Burgerbibliothek Bern @yield('title')</title>
</head>
<body>
<header class="is-fixed-above-lg is-fixed">
<nav class="container-fluid">
<ul>
<li><a href="/" class="contrast">Start</a></li>
<li><a href="/list" class="contrast">Liste</a></li>
<li><a href="/timeline" class="contrast">Zeitstrahl</a></li>
</ul>
</nav>
</header>
<main class="container-fluid">
@yield('main')
</main>
</body>
</html>

View File

@ -0,0 +1,67 @@
@extends('base')
@section('main')
<div class="grid start">
<article class="search">
<header>
<h2>Suche</h2>
</header>
<form action="/search" method="get">
<div role="search">
<input name="term" type="search" placeholder="Suche" minlength="3" />
<input type="submit" value="Search" />
</div>
<details>
<summary>Eweiterte Suchoptionen</summary>
<label>
<input type="checkbox" name="hasDescendant" />
hat Nachfahren
</label>
<div class="grid">
<label>
Geburtsjahr
<input type="number" step="1" placeholder="YYYY" name="birthYear" />
</label>
<label>
Geburtsmonat
<input type="number" step="1" placeholder="mm" min="1" max="12" name="birthMonth" />
</label>
<label>
Geburtstag
<input type="number" step="1" placeholder="dd" min="1" max="31" name="birthDay" />
</label>
</div>
<div class="grid">
<label>
Todesjahr
<input type="number" step="1" placeholder="YYYY" name="deathYear" />
</label>
<label>
Todesmonat
<input type="number" step="1" placeholder="mm" min="1" max="12" name="deathMonth" />
</label>
<label>
Todestag
<input type="number" step="1" placeholder="dd" min="1" max="31" name="deathDay" />
</label>
</div>
</details>
</form>
</article>
<article>
<header>
<h2>Liste</h2>
</header>
<p>Unter der folgenden Seite findest du alle Deskriptoren, alphabetisch sortiert.</p>
<a href="/list" role="button">Zur Liste</a>
</article>
<article>
<header>
<h2>Zeitstrahl</h2>
</header>
<p>Auf der folgenden Seite, kannst du nach Deskriptoren anhand ihrer Lebensn suchen.</p>
<a href="/timeline" role="button">Zum Zeitstrahl</a>
</article>
<div>
@endsection

View File

@ -0,0 +1,8 @@
<footer>
@if (isset($page) && $page > 0)
<a href="/list/p/{{ $page - 1 }}" role="button" tabindex="0">Vorherige Seite</a>
<a href="/list/p/{{ $page + 1 }}" role="button" tabindex="0">Nächste Seite</a>
@else
<a href="/list/p/1" role="button" tabindex="0">NEXT</a>
@endif
</footer>

View File

@ -0,0 +1,36 @@
@extends('base')
@section('main')
<article>
<header>
@if (isset($term))
<h1>Suchresultat für «{{ $term }}»</h1>
@else
<h1>Deskriptoren</h1>
@endif
</header>
@if ($persons)
<ul class="list">
@foreach ($persons as $person)
<li>
<a href="/person/{{ $person['ark']['value'] }}">
<span>
{!! $person['name']['value'] !!}
</span>
<span>
{{ $person['birth_date']['value'] }} &mdash; {{ $person['death_date']['value'] }}
</span>
</a>
</li>
@endforeach
</ul>
@else
<p>Keine Einträge gefunden</p>
@endif
@if (!isset($term))
@include('list-footer')
@endif
</article>
@endsection

View File

@ -0,0 +1,190 @@
@extends('base')
@section('main')
<article>
<header>
<h1>{{ $basic['name']['value'] }}</h1>
</header>
<div class="grid">
@if (isset($basic['desc']))
<div>
<p style="hyphens: auto;hyphenate-limit-chars: auto 3; hyphenate-limit-lines: 4;">
{{ $basic['desc']['value'] }}
</p>
<div>
<h2>Weblinks</h2>
<div id="metagrid-widget">
<span aria-busy="true">Links werden gesucht</span>
</div>
</div>
</div>
@endif
<div>
<dl>
<dt>Geschlecht (biologisch)</dt>
<dd>{{ $basic['sex']['value'] == 'Female (biological sex)' ? 'Weiblich' : 'Männlich' }}</dd>
@if (isset($basic['birth_date']))
<dt>Geburtsdatum</dt>
<dd>{{ $basic['birth_date']['value'] }}</dd>
@endif
@if (isset($basic['baptism_date']))
<dt>Taufdatum</dt>
<dd>{{ $basic['baptism_date']['value'] }}</dd>
@endif
@if (isset($basic['death_date']))
<dt>Todesdatum</dt>
<dd>{{ $basic['death_date']['value'] }}</dd>
@endif
@if (isset($basic['burial_date']))
<dt>Begräbnisdatum</dt>
<dd>{{ $basic['burial_date']['value'] }}</dd>
@endif
</dl>
</div>
<div>
<dl>
@if ($parents)
<dt>Eltern</dt>
@foreach ($parents as $child)
<dd><a href="/person/{{ $child['ark']['value'] }}">{{ $child['name']['value'] }}</a></dd>
@endforeach
@endif
@if ($siblings)
<dt>Geschwister</dt>
@foreach ($siblings as $sibling)
<dd><a href="/person/{{ $sibling['ark']['value'] }}">{{ $sibling['name']['value'] }}</a></dd>
@endforeach
@endif
@if ($spouses)
<dt>Ehepartner:innen</dt>
@foreach ($spouses as $spouse)
<dd><a href="/person/{{ $spouse['ark']['value'] }}">{{ $spouse['name']['value'] }}</a></dd>
@endforeach
@endif
@if ($partner)
<dt>Lebenspartner:innen</dt>
@foreach ($partner as $p)
<dd><a href="/person/{{ $p['ark']['value'] }}">{{ $p['name']['value'] }}</a></dd>
@endforeach
@endif
@if ($children)
<dt>Kinder</dt>
@foreach ($children as $child)
<dd><a href="/person/{{ $child['ark']['value'] }}">{{ $child['name']['value'] }}</a></dd>
@endforeach
@endif
</dl>
<ul>
<li><a title="Verzeichnungseinheiten zu «{{ $basic['name']['value'] }}» im Archivkatalog der Burgerbibliothek Bern."
href="https://katalog.burgerbib.ch/resultatliste.aspx?deskriptorId={{ $basic['scope_id']['value'] }}">
Verzeichnungseinheiten
</a></li>
@if (isset($basic['birth_date']))
<li><a href="/timeline?from={{ $basic['birth_date']['value'] }}">
Zeitstrahl
</a></li>
@endif
</ul>
</div>
</div>
</article>
@if ($links)
<article>
<header>Nachkommenschaft</header>
<div id="tree-chart" style="height: 1000px"></div>
</article>
@vite('resources/js/treechart.js')
<script type="module">
const option = {
series: {
type: 'tree',
roam: true,
symbol: 'emptyCircle',
expandAndCollapse: false,
layout: 'radial',
data: [{
name: '{{ $basic['name']['value'] }}',
ark: '{{ $ark }}',
symbolSize: 15,
children: {!! json_encode($links) !!}
}],
emphasis: {
focus: 'ancestor',
},
emphasis: {
focus: 'descendant'
},
radius: [0, '90%'],
labelLayout: {
hideOverlap: true,
},
label: {
rotate: 'tangential',
fontSize: 21,
color: '#fff',
backgroundColor: '#181c25'
}
}
};
option && treeChart.setOption(option);
treeChart.on('click', (e) => {
window.open(`/person/${e.data.ark}`, '_self');
});
</script>
@endif
<template id="metagrid-template">
<div>
<ul></ul>
<p>
<small>Links via <a href="https://www.metagrid.ch/">Metagrid</a> die Vernetzungsinitiative der
SAGW</small>
</p>
</div>
</template>
<script>
async function metagridWidget() {
let response;
const metagridWidget = document.getElementById('metagrid-widget');
const metagridTemplate = document.getElementById('metagrid-template');
const clone = metagridTemplate.content.cloneNode(true);
try {
response = await fetch('https://api.metagrid.ch/widget/burgerbibliothek/person/{{ $basic['scope_id']['value'] }}.json');
} catch (error) {
console.log('Fehler:', error);
}
if (await response?.ok) {
let r = await response.json();
const list = clone.querySelector('ul');
for (const [key, value] of Object.entries(r[0])) {
let li = document.createElement('li');
li.innerHTML = `<a href="${value.url}" data-tooltip="${value.short_description}">${key}</a>`
list.appendChild(li)
}
metagridWidget.replaceWith(clone);
} else {
let noLinks = document.createElement('p');
noLinks.innerText = 'Keine Links vorhanden.';
noLinks.classList.add('badge');
metagridWidget.replaceWith(noLinks);
}
}
metagridWidget();
</script>
@endsection

View File

@ -0,0 +1,150 @@
@extends('base')
@section('main')
<h1>Zeitstrahl</h1>
<article>
<header>
<form method="get" action="/timeline">
<fieldset role="group">
<label for="from">Von:</label>
<input type="date" id="from"name="from" aria-label="Datum von" value="{{ $from }}">
<label for="to">Bis:</label>
<input type="date" id="to" name="to" aria-label="Darum bis" value="{{ $to }}">
<input type="submit" value="Aktualisieren" />
</fieldset>
</form>
</header>
@if ($from > $to)
<p class="badge">Das «Datum von» muss vor dem «Datum bis» liegen.</p>
@endif
<div id="chart" style="width: 100%; height: {{ ($len * 120) }}px"></div>
<footer>
@if ($len >= 50 && $page >= 1)
<a href="/timeline/?page={{ $page - 1 }}&from={{ $from }}&to={{ $to }}" role="button" tabindex="1">Vorherige Seite</a>
<a href="/timeline/?page={{ $page + 1 }}&from={{ $from }}&to={{ $to }}" role="button" tabindex="0">Nächste Seite</a>
@elseif ($len >= 50 & $page <= 1)
<a href="/timeline/?page={{ $page + 1 }}&from={{ $from }}&to={{ $to }}" role="button" tabindex="0">Nächste Seite</a>
@endif
</footer>
</article>
@if ($len > 0)
@vite('resources/js/timeline.js')
<script type="module">
const symBirth = 'path://M86.4 5.5L61.8 47.6C58 54.1 56 61.6 56 69.2L56 72c0 22.1 17.9 40 40 40s40-17.9 40-40l0-2.8c0-7.6-2-15-5.8-21.6L105.6 5.5C103.6 2.1 100 0 96 0s-7.6 2.1-9.6 5.5zm128 0L189.8 47.6c-3.8 6.5-5.8 14-5.8 21.6l0 2.8c0 22.1 17.9 40 40 40s40-17.9 40-40l0-2.8c0-7.6-2-15-5.8-21.6L233.6 5.5C231.6 2.1 228 0 224 0s-7.6 2.1-9.6 5.5zM317.8 47.6c-3.8 6.5-5.8 14-5.8 21.6l0 2.8c0 22.1 17.9 40 40 40s40-17.9 40-40l0-2.8c0-7.6-2-15-5.8-21.6L361.6 5.5C359.6 2.1 356 0 352 0s-7.6 2.1-9.6 5.5L317.8 47.6zM128 176c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 48c-35.3 0-64 28.7-64 64l0 71c8.3 5.2 18.1 9 28.8 9c13.5 0 27.2-6.1 38.4-13.4c5.4-3.5 9.9-7.1 13-9.7c1.5-1.3 2.7-2.4 3.5-3.1c.4-.4 .7-.6 .8-.8l.1-.1s0 0 0 0s0 0 0 0s0 0 0 0s0 0 0 0c3.1-3.2 7.4-4.9 11.9-4.8s8.6 2.1 11.6 5.4c0 0 0 0 0 0s0 0 0 0l.1 .1c.1 .1 .4 .4 .7 .7c.7 .7 1.7 1.7 3.1 3c2.8 2.6 6.8 6.1 11.8 9.5c10.2 7.1 23 13.1 36.3 13.1s26.1-6 36.3-13.1c5-3.5 9-6.9 11.8-9.5c1.4-1.3 2.4-2.3 3.1-3c.3-.3 .6-.6 .7-.7l.1-.1c3-3.5 7.4-5.4 12-5.4s9 2 12 5.4l.1 .1c.1 .1 .4 .4 .7 .7c.7 .7 1.7 1.7 3.1 3c2.8 2.6 6.8 6.1 11.8 9.5c10.2 7.1 23 13.1 36.3 13.1s26.1-6 36.3-13.1c5-3.5 9-6.9 11.8-9.5c1.4-1.3 2.4-2.3 3.1-3c.3-.3 .6-.6 .7-.7l.1-.1c2.9-3.4 7.1-5.3 11.6-5.4s8.7 1.6 11.9 4.8c0 0 0 0 0 0s0 0 0 0s0 0 0 0l.1 .1c.2 .2 .4 .4 .8 .8c.8 .7 1.9 1.8 3.5 3.1c3.1 2.6 7.5 6.2 13 9.7c11.2 7.3 24.9 13.4 38.4 13.4c10.7 0 20.5-3.9 28.8-9l0-71c0-35.3-28.7-64-64-64l0-48c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 48-64 0 0-48c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 48-64 0 0-48zM448 394.6c-8.5 3.3-18.2 5.4-28.8 5.4c-22.5 0-42.4-9.9-55.8-18.6c-4.1-2.7-7.8-5.4-10.9-7.8c-2.8 2.4-6.1 5-9.8 7.5C329.8 390 310.6 400 288 400s-41.8-10-54.6-18.9c-3.5-2.4-6.7-4.9-9.4-7.2c-2.7 2.3-5.9 4.7-9.4 7.2C201.8 390 182.6 400 160 400s-41.8-10-54.6-18.9c-3.7-2.6-7-5.2-9.8-7.5c-3.1 2.4-6.8 5.1-10.9 7.8C71.2 390.1 51.3 400 28.8 400c-10.6 0-20.3-2.2-28.8-5.4L0 480c0 17.7 14.3 32 32 32l384 0c17.7 0 32-14.3 32-32l0-85.4z'
const symDeath = 'path://M32.0106 4.0131L16.0106 4L11 16.9916L15.9779 43.9828L31.9779 44L37 17.0129L32.0106 4.0131ZM23.0002 26V17.9975L19.9999 18L19.9982 16L23.0002 15.9975V13H25.0002V15.9959L27.9982 15.9935L27.9999 17.9935L25.0002 17.9959V26L23.0002 26Z'
const option = {
backgroundColor: '#181c25',
grid: {
show: false,
top: 50,
right: 50,
left: 50,
bottom: 50
},
emphasis: {
disabled: true
},
tooltip: {
show: false
},
xAxis: {
type: 'time',
axisLabel: {
fontSize: 24
},
splitLine: {
show: true,
lineStyle: {
color: '#aaa',
type: [5, 20]
}
},
},
yAxis: {
show: false,
type: 'category',
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
//color: '#fff',
fontSize: 16
}
},
series: [
@foreach ($persons as $person)
{
type: 'line',
animation: false,
symbolSize: 32,
symbolKeepAspect: true,
lineStyle: {
color: '#fff',
width: 3
},
itemStyle: {
color: '#fff'
},
label: {
show: true,
position: 'bottom',
fontSize: 21,
distance: 25,
formatter: function(d) {
return d.value[0];
}
},
data: [
{
value: ['{{ $person['birth_date']['value'] }}', '{{ $person['ark']['value'] }}'],
label: 'Geburt',
symbol: symBirth,
symbolOffset: ['50%', '-100%']
},
{
value: ['{{ $person['death_date']['value'] }}', '{{ $person['ark']['value'] }}'],
symbol: symDeath,
symbolOffset: ['-50%', '-100%']
}
],
markLine: {
symbol: 'none',
lineStyle: 'none',
data: [
[{
name: '{{ $person['ark']['value'] }}',
label: {
position: 'middle',
distance: 10,
fontSize: 21,
formatter: '{{ $person['name']['value'] }}'
},
coord: ['{{ $person['birth_date']['value'] }}', '{{ $person['ark']['value'] }}'],
},
{
coord: ['{{ $person['death_date']['value'] }}', '{{ $person['ark']['value'] }}'],
}]
]
}
},
@endforeach
]
};
option && timelienChart.setOption(option);
timelienChart.on('click', (e) => {
window.open(`/person/${e.name}`, '_self');
});
</script>
@endif
@endsection

Some files were not shown because too many files have changed in this diff Show More