mirror of
https://github.com/fhswf/aki_prj23_transparenzregister.git
synced 2025-04-22 11:42:55 +02:00
Visualize company sentiment (#422)
Updates the tab and widget "Stimmung"
This commit is contained in:
parent
65c41bb20c
commit
4e83c83374
72
poetry.lock
generated
72
poetry.lock
generated
@ -1,4 +1,4 @@
|
|||||||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "accelerate"
|
name = "accelerate"
|
||||||
@ -2207,13 +2207,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipykernel"
|
name = "ipykernel"
|
||||||
version = "6.26.0"
|
version = "6.27.0"
|
||||||
description = "IPython Kernel for Jupyter"
|
description = "IPython Kernel for Jupyter"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "ipykernel-6.26.0-py3-none-any.whl", hash = "sha256:3ba3dc97424b87b31bb46586b5167b3161b32d7820b9201a9e698c71e271602c"},
|
{file = "ipykernel-6.27.0-py3-none-any.whl", hash = "sha256:4388caa3c2cba0a381e20d289545e88a8aef1fe57a884d4c018718ec8c23c121"},
|
||||||
{file = "ipykernel-6.26.0.tar.gz", hash = "sha256:553856658eb8430bbe9653ea041a41bff63e9606fc4628873fc92a6cf3abd404"},
|
{file = "ipykernel-6.27.0.tar.gz", hash = "sha256:7f4986f606581be73bfb32dc7a1ac9fa0e804c9be50ddf1c7a119413e982693f"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -2551,13 +2551,13 @@ jupyter-server = ">=1.1.2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jupyter-server"
|
name = "jupyter-server"
|
||||||
version = "2.10.1"
|
version = "2.11.0"
|
||||||
description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications."
|
description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "jupyter_server-2.10.1-py3-none-any.whl", hash = "sha256:20519e355d951fc5e1b6ac5952854fe7620d0cfb56588fa4efe362a758977ed3"},
|
{file = "jupyter_server-2.11.0-py3-none-any.whl", hash = "sha256:c9bd6e6d71dc5a2a25df167dc323422997f14682b008bfecb5d7920a55020ea7"},
|
||||||
{file = "jupyter_server-2.10.1.tar.gz", hash = "sha256:e6da2657a954a7879eed28cc08e0817b01ffd81d7eab8634660397b55f926472"},
|
{file = "jupyter_server-2.11.0.tar.gz", hash = "sha256:78c97ec8049f9062f0151725bc8a1364dfed716646a66819095e0e8a24793eba"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -3033,16 +3033,6 @@ files = [
|
|||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
|
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
|
{file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
|
||||||
{file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
|
{file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"},
|
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
|
{file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
|
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
|
||||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
|
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
|
||||||
@ -4058,13 +4048,13 @@ testing = ["aboutcode-toolkit (>=6.0.0)", "black", "pytest (>=6,!=7.0.0)", "pyte
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
version = "3.11.0"
|
version = "4.0.0"
|
||||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"},
|
{file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"},
|
||||||
{file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"},
|
{file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -4209,13 +4199,13 @@ tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prometheus-client"
|
name = "prometheus-client"
|
||||||
version = "0.18.0"
|
version = "0.19.0"
|
||||||
description = "Python client for the Prometheus monitoring system."
|
description = "Python client for the Prometheus monitoring system."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "prometheus_client-0.18.0-py3-none-any.whl", hash = "sha256:8de3ae2755f890826f4b6479e5571d4f74ac17a81345fe69a6778fdb92579184"},
|
{file = "prometheus_client-0.19.0-py3-none-any.whl", hash = "sha256:c88b1e6ecf6b41cd8fb5731c7ae919bf66df6ec6fafa555cd6c0e16ca169ae92"},
|
||||||
{file = "prometheus_client-0.18.0.tar.gz", hash = "sha256:35f7a8c22139e2bb7ca5a698e92d38145bc8dc74c1c0bf56f25cca886a764e17"},
|
{file = "prometheus_client-0.19.0.tar.gz", hash = "sha256:4585b0d1223148c27a225b10dbec5ae9bc4c81a99a3fa80774fa6209935324e1"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -4629,13 +4619,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pygments"
|
name = "pygments"
|
||||||
version = "2.17.1"
|
version = "2.17.2"
|
||||||
description = "Pygments is a syntax highlighting package written in Python."
|
description = "Pygments is a syntax highlighting package written in Python."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "pygments-2.17.1-py3-none-any.whl", hash = "sha256:1b37f1b1e1bff2af52ecaf28cc601e2ef7077000b227a0675da25aef85784bc4"},
|
{file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
|
||||||
{file = "pygments-2.17.1.tar.gz", hash = "sha256:e45a0e74bf9c530f564ca81b8952343be986a29f6afe7f5ad95c5f06b7bdf5e8"},
|
{file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -4965,7 +4955,6 @@ files = [
|
|||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
|
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||||
@ -4973,15 +4962,8 @@ files = [
|
|||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
|
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
|
||||||
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
|
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
||||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
||||||
@ -4998,7 +4980,6 @@ files = [
|
|||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
|
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
||||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||||
@ -5006,7 +4987,6 @@ files = [
|
|||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
|
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||||
@ -5837,13 +5817,13 @@ win32 = ["pywin32"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "setuptools"
|
name = "setuptools"
|
||||||
version = "69.0.0"
|
version = "69.0.2"
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "setuptools-69.0.0-py3-none-any.whl", hash = "sha256:eb03b43f23910c5fd0909cb677ad017cd9531f493d27f8b3f5316ff1fb07390e"},
|
{file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"},
|
||||||
{file = "setuptools-69.0.0.tar.gz", hash = "sha256:4c65d4f7891e5b046e9146913b87098144de2ca2128fbc10135b8556a6ddd946"},
|
{file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -7300,19 +7280,19 @@ zstd = ["zstandard (>=0.18.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtualenv"
|
name = "virtualenv"
|
||||||
version = "20.24.6"
|
version = "20.24.7"
|
||||||
description = "Virtual Python Environment builder"
|
description = "Virtual Python Environment builder"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"},
|
{file = "virtualenv-20.24.7-py3-none-any.whl", hash = "sha256:a18b3fd0314ca59a2e9f4b556819ed07183b3e9a3702ecfe213f593d44f7b3fd"},
|
||||||
{file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"},
|
{file = "virtualenv-20.24.7.tar.gz", hash = "sha256:69050ffb42419c91f6c1284a7b24e0475d793447e35929b488bf6a0aade39353"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
distlib = ">=0.3.7,<1"
|
distlib = ">=0.3.7,<1"
|
||||||
filelock = ">=3.12.2,<4"
|
filelock = ">=3.12.2,<4"
|
||||||
platformdirs = ">=3.9.1,<4"
|
platformdirs = ">=3.9.1,<5"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
||||||
@ -7334,13 +7314,13 @@ colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\" and python
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wcwidth"
|
name = "wcwidth"
|
||||||
version = "0.2.10"
|
version = "0.2.12"
|
||||||
description = "Measures the displayed width of unicode strings in a terminal"
|
description = "Measures the displayed width of unicode strings in a terminal"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
{file = "wcwidth-0.2.10-py2.py3-none-any.whl", hash = "sha256:aec5179002dd0f0d40c456026e74a729661c9d468e1ed64405e3a6c2176ca36f"},
|
{file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"},
|
||||||
{file = "wcwidth-0.2.10.tar.gz", hash = "sha256:390c7454101092a6a5e43baad8f83de615463af459201709556b6e4b1c861f97"},
|
{file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -53,3 +53,49 @@
|
|||||||
.dash-filter input {
|
.dash-filter input {
|
||||||
text-align: center !important;
|
text-align: center !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sentiment-wrapper {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
background-color: white;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-wrapper .sentiment-title {
|
||||||
|
color: var(--raisin-black);
|
||||||
|
padding-right: 30px;
|
||||||
|
vertical-align:middle;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-wrapper .sentiment-line {
|
||||||
|
width: 60%;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-wrapper .sentiment-gauge {
|
||||||
|
max-width: 30%;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-left: 5%;
|
||||||
|
margin-right: 5%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-table {
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sentiment-disclaimer {
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
circle {
|
||||||
|
stroke-width: 25px;
|
||||||
|
}
|
||||||
|
.tick {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@ -9,7 +9,11 @@ from babel.numbers import format_currency
|
|||||||
from dash import dash_table, dcc, html
|
from dash import dash_table, dcc, html
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from aki_prj23_transparenzregister.ui import data_elements, finance_elements
|
from aki_prj23_transparenzregister.ui import (
|
||||||
|
data_elements,
|
||||||
|
finance_elements,
|
||||||
|
sentiment_elements,
|
||||||
|
)
|
||||||
from aki_prj23_transparenzregister.utils.networkx.network_2d import create_2d_graph
|
from aki_prj23_transparenzregister.utils.networkx.network_2d import create_2d_graph
|
||||||
from aki_prj23_transparenzregister.utils.networkx.network_base import initialize_network
|
from aki_prj23_transparenzregister.utils.networkx.network_base import initialize_network
|
||||||
from aki_prj23_transparenzregister.utils.networkx.networkx_data import (
|
from aki_prj23_transparenzregister.utils.networkx.networkx_data import (
|
||||||
@ -113,7 +117,7 @@ def create_company_stats(
|
|||||||
pd.DataFrame(
|
pd.DataFrame(
|
||||||
data={
|
data={
|
||||||
"revenue": [""],
|
"revenue": [""],
|
||||||
"date": datetime.today(),
|
"date": datetime.today().strftime("%d.%m.%Y"),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if finance_data.empty
|
if finance_data.empty
|
||||||
@ -124,6 +128,30 @@ def create_company_stats(
|
|||||||
# set data for third widget
|
# set data for third widget
|
||||||
widget3_title = "Stimmung"
|
widget3_title = "Stimmung"
|
||||||
|
|
||||||
|
sentiment_data = data_elements.get_last_article_of_one_company(
|
||||||
|
selected_company_id, session
|
||||||
|
)
|
||||||
|
if sentiment_data.empty:
|
||||||
|
sentiment_data = pd.DataFrame(
|
||||||
|
{
|
||||||
|
"timestamp": datetime.today().strftime("%d.%m.%Y"),
|
||||||
|
"overall_sentiment_label": "n.a.",
|
||||||
|
},
|
||||||
|
index=[0],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sentiment_data["overall_sentiment_label"] = sentiment_data[
|
||||||
|
"overall_sentiment_label"
|
||||||
|
].apply(lambda _: _.value)
|
||||||
|
sentiment_data["overall_sentiment_label"] = sentiment_data[
|
||||||
|
"overall_sentiment_label"
|
||||||
|
].replace({-1: "negativ", 0: "neutral", 1: "positiv"})
|
||||||
|
sentiment_data["timestamp"] = sentiment_data["timestamp"].dt.strftime(
|
||||||
|
"%d.%m.%Y"
|
||||||
|
)
|
||||||
|
widget3_content = sentiment_data["overall_sentiment_label"][0]
|
||||||
|
widget3_info = f"Stand: {sentiment_data['timestamp'][0]}"
|
||||||
|
|
||||||
return html.Div(
|
return html.Div(
|
||||||
className="stats-wrapper",
|
className="stats-wrapper",
|
||||||
children=[
|
children=[
|
||||||
@ -219,7 +247,11 @@ def create_company_stats(
|
|||||||
),
|
),
|
||||||
html.H1(
|
html.H1(
|
||||||
className="widget-content",
|
className="widget-content",
|
||||||
children="1234",
|
children=[widget3_content],
|
||||||
|
),
|
||||||
|
html.Div(
|
||||||
|
className="widget-info",
|
||||||
|
children=[widget3_info],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -269,6 +301,9 @@ def create_tabs(session: Session, selected_company_id: int) -> html:
|
|||||||
value="tab-3",
|
value="tab-3",
|
||||||
className="tab-style",
|
className="tab-style",
|
||||||
selected_className="selected-tab-style",
|
selected_className="selected-tab-style",
|
||||||
|
children=sentiment_elements.sentiment_layout(
|
||||||
|
selected_company_id, session
|
||||||
|
),
|
||||||
),
|
),
|
||||||
dcc.Tab(
|
dcc.Tab(
|
||||||
label="Verflechtungen",
|
label="Verflechtungen",
|
||||||
|
@ -38,6 +38,7 @@ def get_person_data(session: Session) -> pd.DataFrame:
|
|||||||
A dataframe containing all available company data including the corresponding district court.
|
A dataframe containing all available company data including the corresponding district court.
|
||||||
"""
|
"""
|
||||||
query_person = session.query(entities.Person)
|
query_person = session.query(entities.Person)
|
||||||
|
|
||||||
engine = session.bind
|
engine = session.bind
|
||||||
if not isinstance(engine, sa.engine.Engine):
|
if not isinstance(engine, sa.engine.Engine):
|
||||||
raise TypeError
|
raise TypeError
|
||||||
@ -119,9 +120,9 @@ def get_options(session: Session | None) -> dict[int, str]:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
persons = get_person_data(session).rename("p_{}".format)
|
persons = get_person_data(session).rename("p_{}".format)
|
||||||
persons["person_lastname_firstname"] = (
|
persons[
|
||||||
persons["person_lastname"] + ", " + persons["person_firstname"]
|
"person_lastname_firstname"
|
||||||
)
|
] = f"{persons['person_lastname']}, {persons['person_firstname']}"
|
||||||
persons_options = persons["person_lastname_firstname"]
|
persons_options = persons["person_lastname_firstname"]
|
||||||
companies = get_company_data(session).rename("c_{}".format)
|
companies = get_company_data(session).rename("c_{}".format)
|
||||||
companies_options = companies["company_name"]
|
companies_options = companies["company_name"]
|
||||||
@ -164,3 +165,61 @@ def get_person_relations_of_one_company(
|
|||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
return pd.DataFrame(data)
|
return pd.DataFrame(data)
|
||||||
|
|
||||||
|
|
||||||
|
def get_news_of_one_company(selected_company_id: int, session: Session) -> pd.DataFrame:
|
||||||
|
"""Collects all news articles of one company.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
selected_company_id: Id of the company.
|
||||||
|
session: A session connecting to the database.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dataframe containing all news of the selected company.
|
||||||
|
"""
|
||||||
|
certainty_minimum = 0.9
|
||||||
|
data = (
|
||||||
|
session.query(
|
||||||
|
entities.News.title,
|
||||||
|
entities.News.timestamp,
|
||||||
|
entities.News.source_url,
|
||||||
|
entities.News.source_domain,
|
||||||
|
entities.News.overall_sentiment_label,
|
||||||
|
entities.News.overall_sentiment_certainty,
|
||||||
|
entities.Sentiment.times_named,
|
||||||
|
)
|
||||||
|
.join(entities.Sentiment, entities.News.id == entities.Sentiment.article_id)
|
||||||
|
.filter(entities.Sentiment.company_id == selected_company_id)
|
||||||
|
.filter(entities.News.overall_sentiment_certainty >= certainty_minimum)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
return pd.DataFrame(data)
|
||||||
|
|
||||||
|
|
||||||
|
def get_last_article_of_one_company(
|
||||||
|
selected_company_id: int, session: Session
|
||||||
|
) -> pd.DataFrame:
|
||||||
|
"""Collects all news articles of one company.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
selected_company_id: Id of the company.
|
||||||
|
session: A session connecting to the database.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dataframe containing all news of the selected company.
|
||||||
|
"""
|
||||||
|
certainty_minimum = 0.9
|
||||||
|
data = (
|
||||||
|
session.query(
|
||||||
|
entities.News.timestamp,
|
||||||
|
entities.News.overall_sentiment_label,
|
||||||
|
)
|
||||||
|
.join(entities.Sentiment, entities.News.id == entities.Sentiment.article_id)
|
||||||
|
.filter(entities.Sentiment.company_id == selected_company_id)
|
||||||
|
.filter(entities.News.overall_sentiment_certainty >= certainty_minimum)
|
||||||
|
.order_by(entities.News.timestamp.desc())
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
if not data:
|
||||||
|
return pd.DataFrame()
|
||||||
|
return pd.DataFrame(dict(data), index=[0])
|
||||||
|
@ -124,7 +124,7 @@ def update_figure(value: str, data: str) -> html:
|
|||||||
if value is None:
|
if value is None:
|
||||||
return ""
|
return ""
|
||||||
finance_df = pd.read_json(StringIO(data))
|
finance_df = pd.read_json(StringIO(data))
|
||||||
if finance_df[value].count() <= 2: # noqa: PLR2004
|
if not finance_df[value].count(): # noqa: PLR2004
|
||||||
return html.H3(
|
return html.H3(
|
||||||
className="metrics-graph-response",
|
className="metrics-graph-response",
|
||||||
children=[
|
children=[
|
||||||
@ -171,4 +171,6 @@ def financials_figure(selected_finance_df: pd.DataFrame, metric: str) -> go.Figu
|
|||||||
title=f"Entwicklungsverlauf: {METRICS[metric]}",
|
title=f"Entwicklungsverlauf: {METRICS[metric]}",
|
||||||
yaxis_title=f"{METRICS[metric]} in Euro (€)",
|
yaxis_title=f"{METRICS[metric]} in Euro (€)",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fig_line.update_xaxes(tickformat="%b %Y")
|
||||||
return fig_line
|
return fig_line
|
||||||
|
270
src/aki_prj23_transparenzregister/ui/sentiment_elements.py
Normal file
270
src/aki_prj23_transparenzregister/ui/sentiment_elements.py
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
"""Sentiment elements for Dash."""
|
||||||
|
|
||||||
|
from typing import Final
|
||||||
|
|
||||||
|
import dash_daq as daq
|
||||||
|
import pandas as pd
|
||||||
|
import plotly.graph_objs as go
|
||||||
|
from dash import dash_table, dcc, html
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from aki_prj23_transparenzregister.ui import data_elements
|
||||||
|
|
||||||
|
COLORS: Final[dict[str, str]] = {
|
||||||
|
"light": "#edefef",
|
||||||
|
"lavender-blush": "#f3e8ee",
|
||||||
|
"ash-gray": "#bacdb0",
|
||||||
|
"cambridge-blue": "#729b79",
|
||||||
|
"paynes-gray": "#475b63",
|
||||||
|
"raisin-black": "#2e2c2f",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def sentiment_layout(selected_company_id: int, session: Session) -> html:
|
||||||
|
"""Creates the content for the sentiment tab of the company page.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
selected_company_id: Id of the company.
|
||||||
|
session: A session connecting to the database.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The html div.
|
||||||
|
"""
|
||||||
|
articles = data_elements.get_news_of_one_company(selected_company_id, session)
|
||||||
|
|
||||||
|
# number of article sentiments for the rolling mean
|
||||||
|
n = 10
|
||||||
|
|
||||||
|
if articles.empty or (len(articles) < n):
|
||||||
|
return html.Div(
|
||||||
|
className="sentiment-wrapper",
|
||||||
|
children=[
|
||||||
|
html.H3(
|
||||||
|
className="sentiment-title",
|
||||||
|
children=[
|
||||||
|
"Für dieses Unternehmen wurden leider nicht genug Nachrichten bzw. Artikel gefunden."
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# replace enum types with values
|
||||||
|
articles["overall_sentiment_label"] = articles["overall_sentiment_label"].apply(
|
||||||
|
lambda _: _.value
|
||||||
|
)
|
||||||
|
|
||||||
|
articles = articles.sort_values(by=["timestamp"], ascending=True)
|
||||||
|
articles["rolling_mean"] = articles["overall_sentiment_label"].rolling(n).mean()
|
||||||
|
|
||||||
|
sentiment_score = articles["rolling_mean"].iloc[-1] + 1
|
||||||
|
|
||||||
|
articles["timestamp"] = pd.to_datetime(
|
||||||
|
articles["timestamp"].dt.strftime("%d.%m.%Y, %H:%M"), dayfirst=True
|
||||||
|
)
|
||||||
|
|
||||||
|
table = (
|
||||||
|
articles[
|
||||||
|
[
|
||||||
|
"timestamp",
|
||||||
|
"title",
|
||||||
|
"times_named",
|
||||||
|
"source_domain",
|
||||||
|
"overall_sentiment_label",
|
||||||
|
]
|
||||||
|
]
|
||||||
|
.fillna("n.a.")
|
||||||
|
.rename(
|
||||||
|
columns={
|
||||||
|
"timestamp": "Datum",
|
||||||
|
"title": "Titel",
|
||||||
|
"times_named": "Erwähnungen",
|
||||||
|
"source_domain": "Quelle",
|
||||||
|
"overall_sentiment_label": "Stimmung",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.sort_values(by=["Datum"], ascending=False)
|
||||||
|
)
|
||||||
|
|
||||||
|
table["Datum"] = table["Datum"].dt.strftime("%d.%m.%Y")
|
||||||
|
table["Stimmung"] = table["Stimmung"].replace(
|
||||||
|
{-1: "negativ", 0: "neutral", 1: "positiv"}
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
html.Div(
|
||||||
|
className="sentiment-wrapper",
|
||||||
|
children=[
|
||||||
|
html.Div(
|
||||||
|
className="sentiment-line",
|
||||||
|
children=[
|
||||||
|
dcc.Graph(figure=sentiment_trend_figure(articles, n)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
html.Div(
|
||||||
|
className="sentiment-gauge",
|
||||||
|
children=[
|
||||||
|
html.H3("Aktueller Stimmungstrend*"),
|
||||||
|
sentiment_gauge_figure(sentiment_score),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
html.Div(
|
||||||
|
className="sentiment-table",
|
||||||
|
children=[
|
||||||
|
dash_table.DataTable(
|
||||||
|
table.to_dict("records"),
|
||||||
|
[{"name": i, "id": i} for i in table.columns],
|
||||||
|
style_table={
|
||||||
|
"width": "80%",
|
||||||
|
"marginLeft": "auto",
|
||||||
|
"marginRight": "auto",
|
||||||
|
"padding": "20px",
|
||||||
|
"color": COLORS["raisin-black"],
|
||||||
|
},
|
||||||
|
style_cell={
|
||||||
|
"textAlign": "center",
|
||||||
|
"fontFamily": "Times",
|
||||||
|
"fontSize": "14px",
|
||||||
|
},
|
||||||
|
style_cell_conditional=[
|
||||||
|
{"if": {"column_id": "Titel"}, "textAlign": "left"},
|
||||||
|
{"if": {"column_id": "Quelle"}, "textAlign": "left"},
|
||||||
|
],
|
||||||
|
style_header={
|
||||||
|
"backgroundColor": COLORS["raisin-black"],
|
||||||
|
"fontWeight": "bold",
|
||||||
|
"color": "white",
|
||||||
|
"fontSize": "16px",
|
||||||
|
},
|
||||||
|
style_data={
|
||||||
|
"whiteSpace": "normal",
|
||||||
|
"height": "auto",
|
||||||
|
},
|
||||||
|
style_data_conditional=[
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"column_id": "Stimmung",
|
||||||
|
"filter_query": '{Stimmung} = "negativ"',
|
||||||
|
},
|
||||||
|
"color": "red",
|
||||||
|
"fontWeight": "bold",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"column_id": "Stimmung",
|
||||||
|
"filter_query": '{Stimmung} = "positiv"',
|
||||||
|
},
|
||||||
|
"color": "green",
|
||||||
|
"fontWeight": "bold",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {"state": "selected"}, # 'active' | 'selected'
|
||||||
|
"backgroundColor": COLORS["light"],
|
||||||
|
"border": "1px solid " + COLORS["paynes-gray"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
page_size=10,
|
||||||
|
sort_action="native",
|
||||||
|
sort_mode="multi",
|
||||||
|
column_selectable="single",
|
||||||
|
filter_action="native",
|
||||||
|
filter_options={"placeholder_text": "Filter"},
|
||||||
|
style_filter={
|
||||||
|
"text-align": "center",
|
||||||
|
"backgroundColor": COLORS["light"],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
html.Div(
|
||||||
|
className="sentiment-disclaimer",
|
||||||
|
children=[
|
||||||
|
f"*Für den aktuellen Stimmungstrend wurden die letzten {n} Artikel verwendet."
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def sentiment_trend_figure(articles: pd.DataFrame, n: int) -> go.Figure:
|
||||||
|
"""Creates trend plot for the rolling mean sentiment trend.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
articles: Dataframe containing all available news including the sentiments.
|
||||||
|
n: number of minimum articles used for the rolling mean.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Plotly go figure.
|
||||||
|
"""
|
||||||
|
articles = articles.iloc[n:]
|
||||||
|
|
||||||
|
sentiment_fig = go.Figure()
|
||||||
|
# add trace for company 1
|
||||||
|
sentiment_fig.add_trace(
|
||||||
|
go.Scatter(
|
||||||
|
x=articles["timestamp"],
|
||||||
|
y=articles["overall_sentiment_label"],
|
||||||
|
line_color=COLORS["raisin-black"],
|
||||||
|
marker_color=COLORS["raisin-black"],
|
||||||
|
mode="lines+markers",
|
||||||
|
name="Einzelne Artikel",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
sentiment_fig.add_trace(
|
||||||
|
go.Scatter(
|
||||||
|
x=articles["timestamp"],
|
||||||
|
y=articles["rolling_mean"],
|
||||||
|
line_color=COLORS["cambridge-blue"],
|
||||||
|
marker_color=COLORS["cambridge-blue"],
|
||||||
|
mode="lines+markers",
|
||||||
|
name="Gleitender Mittelwert",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# set title and labels
|
||||||
|
sentiment_fig.update_layout(
|
||||||
|
title="Stimmungsverlauf",
|
||||||
|
yaxis_range=[-1.5, 1.5],
|
||||||
|
yaxis={
|
||||||
|
"tickmode": "array",
|
||||||
|
"tickvals": [-1, 0, 1],
|
||||||
|
"ticktext": ["Negativ (-1) ", "Neutral (0) ", "Positiv (1) "],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
sentiment_fig.update_xaxes(tickformat="%d.%b.%Y")
|
||||||
|
return sentiment_fig
|
||||||
|
|
||||||
|
|
||||||
|
def sentiment_gauge_figure(sentiment_score: float) -> daq:
|
||||||
|
"""Creates gauge plot for the current sentiment trend.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sentiment_score: Float between 0 and 2.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Daq gauge plot.
|
||||||
|
"""
|
||||||
|
if not sentiment_score <= 2 and sentiment_score >= 0: # noqa: PLR2004
|
||||||
|
raise ValueError(
|
||||||
|
f"Expected sentiment score is not between 0 and 2, got {sentiment_score} ."
|
||||||
|
)
|
||||||
|
|
||||||
|
return daq.Gauge(
|
||||||
|
color={
|
||||||
|
"gradient": True,
|
||||||
|
"ranges": {"red": [0, 0.6], "yellow": [0.6, 1.4], "green": [1.4, 2]},
|
||||||
|
},
|
||||||
|
scale={
|
||||||
|
"custom": {
|
||||||
|
0.3: {"label": " Negativ", "style": {"font-size": "16px"}},
|
||||||
|
1: {"label": "Neutral", "style": {"font-size": "16px"}},
|
||||||
|
1.7: {"label": "Positiv", "style": {"font-size": "16px"}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value=sentiment_score,
|
||||||
|
max=2,
|
||||||
|
min=0,
|
||||||
|
size=300,
|
||||||
|
)
|
@ -10,6 +10,7 @@ from sqlalchemy.orm import Session, sessionmaker
|
|||||||
from aki_prj23_transparenzregister.config.config_template import SQLiteConnectionString
|
from aki_prj23_transparenzregister.config.config_template import SQLiteConnectionString
|
||||||
from aki_prj23_transparenzregister.models.company import CapitalTypeEnum
|
from aki_prj23_transparenzregister.models.company import CapitalTypeEnum
|
||||||
from aki_prj23_transparenzregister.utils import data_transfer
|
from aki_prj23_transparenzregister.utils import data_transfer
|
||||||
|
from aki_prj23_transparenzregister.utils.enum_types import SentimentLabel
|
||||||
from aki_prj23_transparenzregister.utils.sql import entities
|
from aki_prj23_transparenzregister.utils.sql import entities
|
||||||
from aki_prj23_transparenzregister.utils.sql.connector import (
|
from aki_prj23_transparenzregister.utils.sql.connector import (
|
||||||
get_engine,
|
get_engine,
|
||||||
@ -189,3 +190,277 @@ def full_db(empty_db: Session, finance_statements: list[dict[str, Any]]) -> Sess
|
|||||||
empty_db.commit()
|
empty_db.commit()
|
||||||
# print(pd.read_sql_table("company", empty_db.bind).to_string())
|
# print(pd.read_sql_table("company", empty_db.bind).to_string())
|
||||||
return empty_db
|
return empty_db
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def news_db(full_db: Session) -> Session:
|
||||||
|
news_example = entities.News(
|
||||||
|
title="AI Revolution in Tech",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 1, 15, 30),
|
||||||
|
text="The latest advancements in AI are transforming the tech industry.",
|
||||||
|
source_url="http://example-news.com/ai-revolution",
|
||||||
|
source_domain="example-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.95,
|
||||||
|
number_of_companies=2,
|
||||||
|
sum_of_times_named=5,
|
||||||
|
)
|
||||||
|
full_db.add(news_example)
|
||||||
|
full_db.commit()
|
||||||
|
# Print to see the object representation
|
||||||
|
|
||||||
|
# Example instances of Sentiment for different company IDs
|
||||||
|
sentiment_examples = [
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=news_example.id, # This should be the actual ID after insertion into the database
|
||||||
|
times_named=3,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
|
||||||
|
specific_sentiment_score=0.5,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=2,
|
||||||
|
article_id=news_example.id, # This should be the actual ID after insertion into the database
|
||||||
|
times_named=2,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.2,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=3,
|
||||||
|
article_id=news_example.id, # This should be the actual ID after insertion into the database
|
||||||
|
times_named=1,
|
||||||
|
specific_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.8,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
full_db.add_all(sentiment_examples)
|
||||||
|
add_news_examples = [
|
||||||
|
entities.News(
|
||||||
|
title="Breakthrough in Renewable Energy",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 1, 15, 30),
|
||||||
|
text="Innovative solar panels are expected to revolutionize the energy sector.",
|
||||||
|
source_url="http://example-news.com/renewable-breakthrough",
|
||||||
|
source_domain="eco-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.9,
|
||||||
|
number_of_companies=1,
|
||||||
|
sum_of_times_named=3,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="Global Economic Outlook",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 2, 10, 0),
|
||||||
|
text="Economists predict a challenging year ahead for global markets.",
|
||||||
|
source_url="http://example-news.com/economic-outlook",
|
||||||
|
source_domain="finance-world.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.95,
|
||||||
|
number_of_companies=3,
|
||||||
|
sum_of_times_named=7,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="Tech Giants Merge",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 3, 12, 45),
|
||||||
|
text="Two leading tech companies have announced a merger, sparking industry-wide discussions.",
|
||||||
|
source_url="http://example-news.com/tech-merger",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.91,
|
||||||
|
number_of_companies=2,
|
||||||
|
sum_of_times_named=10,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="Deutsche Bank announces huge job loss plan",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 5, 12, 45),
|
||||||
|
text="Deutsche Bank has announced plans for major job losses and will also scale down massively its operations worldwide, as part of a major shake-up of.",
|
||||||
|
source_url="http://example-news.com/deutsche-bank",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.9,
|
||||||
|
number_of_companies=1,
|
||||||
|
sum_of_times_named=8,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="Germany approves reforms to help its tech industry compete with Silicon Valley",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 6, 9, 45),
|
||||||
|
text="Germany on Friday approved a litany of changes to its rules for stock-based compensation at tech startups, listing of companies and taxation.",
|
||||||
|
source_url="http://example-news.com/german-tech-industry",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.97,
|
||||||
|
number_of_companies=3,
|
||||||
|
sum_of_times_named=5,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="German housebuilding is collapsing ",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 8, 12, 30),
|
||||||
|
text="German housebuilding is on the brink of collapse as construction projects are being canceled and orders are slowing.",
|
||||||
|
source_url="http://example-news.com/german-housing",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.96,
|
||||||
|
number_of_companies=3,
|
||||||
|
sum_of_times_named=2,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="The Berlin start-ups tearing up capitalism and putting workers first",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 10, 12, 45),
|
||||||
|
text="Berlin is one of Europe's hottest start-up hubs. But companies setting up there are doing things differently and it starts with where the power lies.",
|
||||||
|
source_url="http://example-news.com/tech-merger",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.91,
|
||||||
|
number_of_companies=2,
|
||||||
|
sum_of_times_named=10,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="Air traffic across Germany disrupted due to mass walkouts",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 3, 12, 45),
|
||||||
|
text="Security workers are staging a full-day walkout at airports across Germany over pay disputes.",
|
||||||
|
source_url="http://example-news.com/tech-merger",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.95,
|
||||||
|
number_of_companies=3,
|
||||||
|
sum_of_times_named=17,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="Car makers face fraud claims",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 12, 12, 45),
|
||||||
|
text="The German economy grew 0.6 percent in Q1, quarter on quarter, helped by strong exports, booming construction and higher household and state spending.",
|
||||||
|
source_url="http://example-news.com/tech-merger",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.9,
|
||||||
|
number_of_companies=2,
|
||||||
|
sum_of_times_named=10,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="Inflation rises, unemployment falls",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 15, 12, 45),
|
||||||
|
text="German inflation rose in February, reaching its highest level in four-and-a-half years, while unemployment fell more than expected.",
|
||||||
|
source_url="http://example-news.com/inflation",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.POSITIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.98,
|
||||||
|
number_of_companies=2,
|
||||||
|
sum_of_times_named=10,
|
||||||
|
),
|
||||||
|
entities.News(
|
||||||
|
title="Exports struggle on slow factory output",
|
||||||
|
timestamp=datetime.datetime(2023, 11, 16, 12, 45),
|
||||||
|
text="Exports rebounded by less than expected in October, according to latest official figures.",
|
||||||
|
source_url="http://example-news.com/exports",
|
||||||
|
source_domain="tech-news.com",
|
||||||
|
overall_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
overall_sentiment_certainty=0.98,
|
||||||
|
number_of_companies=3,
|
||||||
|
sum_of_times_named=4,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
full_db.add_all(add_news_examples)
|
||||||
|
full_db.commit()
|
||||||
|
# Additional examples for the Sentiment entity
|
||||||
|
sentiment_more_examples = [
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
2
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=1,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEUTRAL, # type: ignore
|
||||||
|
specific_sentiment_score=0.5,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=3,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
1
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
1
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
3
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
4
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
5
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
6
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
7
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
8
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
9
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
entities.Sentiment(
|
||||||
|
company_id=1,
|
||||||
|
article_id=add_news_examples[
|
||||||
|
10
|
||||||
|
].id, # Placeholder ID, replace with actual after insertion
|
||||||
|
times_named=4,
|
||||||
|
specific_sentiment_label=SentimentLabel.NEGATIVE, # type: ignore
|
||||||
|
specific_sentiment_score=0.3,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
full_db.add_all(sentiment_more_examples)
|
||||||
|
full_db.commit()
|
||||||
|
return full_db
|
||||||
|
@ -4,6 +4,7 @@ import pandas as pd
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from aki_prj23_transparenzregister.ui import data_elements
|
from aki_prj23_transparenzregister.ui import data_elements
|
||||||
|
from aki_prj23_transparenzregister.utils.enum_types import SentimentLabel
|
||||||
|
|
||||||
|
|
||||||
def test_import() -> None:
|
def test_import() -> None:
|
||||||
@ -86,3 +87,27 @@ def test_get_finance_data(full_db: Session) -> None:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
pd.testing.assert_frame_equal(finance_df, test_data)
|
pd.testing.assert_frame_equal(finance_df, test_data)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_news_of_one_company0(news_db: Session) -> None:
|
||||||
|
"""Tests what happens if no sentiment can be found."""
|
||||||
|
selected_company_id = 100
|
||||||
|
assert data_elements.get_news_of_one_company(selected_company_id, news_db).empty
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_news_of_one_company1(news_db: Session) -> None:
|
||||||
|
"""Tests if the sentiments can be collected for a company specified."""
|
||||||
|
selected_company_id = 2
|
||||||
|
sentiment_df = data_elements.get_news_of_one_company(selected_company_id, news_db)
|
||||||
|
assert sentiment_df is not None
|
||||||
|
assert sentiment_df.to_dict(orient="records") == [
|
||||||
|
{
|
||||||
|
"overall_sentiment_certainty": 0.95,
|
||||||
|
"overall_sentiment_label": SentimentLabel.POSITIVE,
|
||||||
|
"source_domain": "example-news.com",
|
||||||
|
"source_url": "http://example-news.com/ai-revolution",
|
||||||
|
"times_named": 2,
|
||||||
|
"timestamp": pd.Timestamp("2023-11-01 15:30:00"),
|
||||||
|
"title": "AI Revolution in Tech",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
32
tests/ui/sentiment_elements_test.py
Normal file
32
tests/ui/sentiment_elements_test.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"""Tests for sentiment ui elements."""
|
||||||
|
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from aki_prj23_transparenzregister.ui import data_elements, sentiment_elements
|
||||||
|
|
||||||
|
|
||||||
|
def test_sentiment_layout(news_db: Session) -> None:
|
||||||
|
"""Checks if the sentiment tab layout of the company page can be created."""
|
||||||
|
selected_company_id = 1
|
||||||
|
sentiment_elements.sentiment_layout(selected_company_id, news_db)
|
||||||
|
|
||||||
|
|
||||||
|
def test_sentiment_trend_figure(news_db: Session) -> None:
|
||||||
|
"""Checks if the sentiment trend graph can be created."""
|
||||||
|
n = 10
|
||||||
|
company_id = 1
|
||||||
|
articles = data_elements.get_news_of_one_company(company_id, news_db)
|
||||||
|
|
||||||
|
articles["overall_sentiment_label"] = articles["overall_sentiment_label"].apply(
|
||||||
|
lambda _: _.value
|
||||||
|
)
|
||||||
|
|
||||||
|
articles = articles.sort_values(by=["timestamp"], ascending=True)
|
||||||
|
articles["rolling_mean"] = articles["overall_sentiment_label"].rolling(n).mean()
|
||||||
|
sentiment_elements.sentiment_trend_figure(articles, n)
|
||||||
|
|
||||||
|
|
||||||
|
def test_sentiment_gauge_figure() -> None:
|
||||||
|
"""Checks if the sentiment gauge graph can be created."""
|
||||||
|
sentiment_score = 0.2
|
||||||
|
sentiment_elements.sentiment_gauge_figure(sentiment_score)
|
Loading…
x
Reference in New Issue
Block a user