From 00aba6afcc6981752bef92d5f9a8caa00dfc0b62 Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 27 Dec 2024 16:19:57 +0100
Subject: [PATCH 01/16] init recommendation app

---
 project/recommendation/__init__.py | 0
 project/recommendation/admin.py    | 3 +++
 project/recommendation/apps.py     | 6 ++++++
 project/recommendation/models.py   | 3 +++
 4 files changed, 12 insertions(+)
 create mode 100644 project/recommendation/__init__.py
 create mode 100644 project/recommendation/admin.py
 create mode 100644 project/recommendation/apps.py
 create mode 100644 project/recommendation/models.py

diff --git a/project/recommendation/__init__.py b/project/recommendation/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/project/recommendation/admin.py b/project/recommendation/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/project/recommendation/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/project/recommendation/apps.py b/project/recommendation/apps.py
new file mode 100644
index 0000000..fc75208
--- /dev/null
+++ b/project/recommendation/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class DaliaConfig(AppConfig):
+    default_auto_field = "django.db.models.BigAutoField"
+    name = "project.recommendation"
diff --git a/project/recommendation/models.py b/project/recommendation/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/project/recommendation/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
-- 
GitLab


From d34586709924a98279c63b200f1afe4f0beb396e Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 27 Dec 2024 16:22:30 +0100
Subject: [PATCH 02/16] added api model for suggestions of related content of a
 material

---
 project/recommendation/api_models/__init__.py   | 0
 project/recommendation/api_models/api_models.py | 7 +++++++
 2 files changed, 7 insertions(+)
 create mode 100644 project/recommendation/api_models/__init__.py
 create mode 100644 project/recommendation/api_models/api_models.py

diff --git a/project/recommendation/api_models/__init__.py b/project/recommendation/api_models/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/project/recommendation/api_models/api_models.py b/project/recommendation/api_models/api_models.py
new file mode 100644
index 0000000..9488658
--- /dev/null
+++ b/project/recommendation/api_models/api_models.py
@@ -0,0 +1,7 @@
+from dataclasses import dataclass
+from typing import List
+
+
+@dataclass
+class SuggestedContents:
+    uris: List[str]
-- 
GitLab


From 6e373597402561aab43e44dd32c56d7669a15969 Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 27 Dec 2024 16:24:20 +0100
Subject: [PATCH 03/16] implemted query for suggested content, using just
 schema:isPartOf attribut

---
 project/recommendation/materials/__init__.py  |  0
 .../materials/suggested_content.py            | 36 +++++++++++++++++++
 2 files changed, 36 insertions(+)
 create mode 100644 project/recommendation/materials/__init__.py
 create mode 100644 project/recommendation/materials/suggested_content.py

diff --git a/project/recommendation/materials/__init__.py b/project/recommendation/materials/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/project/recommendation/materials/suggested_content.py b/project/recommendation/materials/suggested_content.py
new file mode 100644
index 0000000..fc9c0b6
--- /dev/null
+++ b/project/recommendation/materials/suggested_content.py
@@ -0,0 +1,36 @@
+from uuid import UUID
+
+from rdflib import URIRef, Variable
+
+from project.dalia.query.utils import query_dalia_dataset
+from project.dalia.query_builder.query_builder import QueryBuilder
+from project.recommendation.api_models.api_models import (
+    SuggestedContents,
+)
+
+
+def get_suggested_contents(uuid: UUID):
+    query = _query_for_suggested_content(uuid)
+    results = query_dalia_dataset(query)
+    response = SuggestedContents([str(result[0]) for result in results])
+
+    return response
+
+
+def _query_for_suggested_content(uri: str):
+    var_material = Variable("material")
+
+    query = (
+        QueryBuilder()
+        .SELECT(var_material)
+        .WHERE(
+            (
+                URIRef(f"https://id.dalia.education/learning-resource/{uri}"),
+                URIRef("https://schema.org/isPartOf"),
+                var_material,
+            )
+        )
+        .build()
+    )
+
+    return query
-- 
GitLab


From b12258e8ad1d150e1b929f7fcf9d7350d645f143 Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 27 Dec 2024 16:26:14 +0100
Subject: [PATCH 04/16] added serializer for suggested contents

---
 project/recommendation/serializers.py | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 project/recommendation/serializers.py

diff --git a/project/recommendation/serializers.py b/project/recommendation/serializers.py
new file mode 100644
index 0000000..d663a7b
--- /dev/null
+++ b/project/recommendation/serializers.py
@@ -0,0 +1,8 @@
+from rest_framework_dataclasses.serializers import DataclassSerializer
+
+import project.recommendation.api_models.api_models as api_models
+
+
+class SuggestedContentSerializer(DataclassSerializer):
+    class Meta:
+        dataclass = api_models.SuggestedContents
-- 
GitLab


From aaddc2b421d9f578f02a9fb3c7d1f221e0ca435b Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 27 Dec 2024 16:28:50 +0100
Subject: [PATCH 05/16] added view for suggested contents

---
 project/recommendation/views.py | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 project/recommendation/views.py

diff --git a/project/recommendation/views.py b/project/recommendation/views.py
new file mode 100644
index 0000000..e29e695
--- /dev/null
+++ b/project/recommendation/views.py
@@ -0,0 +1,17 @@
+from uuid import UUID
+
+from rest_framework.request import Request
+from rest_framework.response import Response
+from rest_framework.views import APIView
+
+import project.recommendation.serializers as serializers
+from project.recommendation.materials.suggested_content import get_suggested_contents
+
+
+# endpoint /<uuid:material_id>/suggestions
+class MaterialSuggestionsView(APIView):
+    def get(self, request: Request, material_id: UUID):
+        result_serializer = serializers.SuggestedContentSerializer(
+            get_suggested_contents(material_id)
+        )
+        return Response(result_serializer.data)
-- 
GitLab


From dea0df1a7d3f21267f045f5ce7c817a8fb2aa5d6 Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 27 Dec 2024 16:29:58 +0100
Subject: [PATCH 06/16] added endpoint for suggested contents

---
 project/recommendation/urls.py | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 project/recommendation/urls.py

diff --git a/project/recommendation/urls.py b/project/recommendation/urls.py
new file mode 100644
index 0000000..398d0ca
--- /dev/null
+++ b/project/recommendation/urls.py
@@ -0,0 +1,15 @@
+"""
+URL configuration for app 'recommendation'.
+"""
+
+from django.urls import path
+
+from project.recommendation import views
+
+urlpatterns = [
+    path(
+        "v1/<uuid:material_id>/suggestions",
+        views.MaterialSuggestionsView.as_view(),
+        name="material_suggestions",
+    ),
+]
-- 
GitLab


From b5bccac420ab782742402ab43d7f072edb5f28cc Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 27 Dec 2024 16:30:43 +0100
Subject: [PATCH 07/16] added recommendation app in main config

---
 project/urls.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/project/urls.py b/project/urls.py
index 41455dc..edc927f 100644
--- a/project/urls.py
+++ b/project/urls.py
@@ -17,7 +17,9 @@ Including another URLconf
 from django.urls import include, path
 
 from project.dalia import urls as dalia_urls
+from project.recommendation import urls as recommendation_urls
 
 urlpatterns = [
     path('api/dalia/', include(dalia_urls)),
+    path('api/dalia/recommendation/', include(recommendation_urls)),
 ]
-- 
GitLab


From 864a7d0cad1ee6fdfea603026f113ccf5e81ab1e Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 27 Dec 2024 16:32:32 +0100
Subject: [PATCH 08/16] added tests for recommendation query building

---
 tests/project/recommendation/__init__.py   |  0
 tests/project/recommendation/test_query.py | 32 ++++++++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 tests/project/recommendation/__init__.py
 create mode 100644 tests/project/recommendation/test_query.py

diff --git a/tests/project/recommendation/__init__.py b/tests/project/recommendation/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/project/recommendation/test_query.py b/tests/project/recommendation/test_query.py
new file mode 100644
index 0000000..7aa3663
--- /dev/null
+++ b/tests/project/recommendation/test_query.py
@@ -0,0 +1,32 @@
+from project.recommendation.api_models.api_models import (
+    RecommendationMaterialSuggestedContentRequest,
+    SuggestedContents,
+)
+from project.recommendation.materials.suggested_content import (
+    _query_for_suggested_content,
+    get_suggested_contents,
+)
+
+
+def test_query_for_suggested_content():
+    request = RecommendationMaterialSuggestedContentRequest(
+        uri="https://id.dalia.education/learning-resource/39ea23c6-a591-442f-afde-c3262e20f1e4"
+    )
+
+    print()
+    print("--- QUERY ---")
+    print(_query_for_suggested_content(request.uri))
+    print("--- QUERY ---")
+
+
+def test_get_suggested_content():
+    request = RecommendationMaterialSuggestedContentRequest(
+        uri="https://id.dalia.education/learning-resource/39ea23c6-a591-442f-afde-c3262e20f1e4"
+    )
+
+    results = get_suggested_contents(request)
+    assert results == [
+        SuggestedContents(
+            uri="https://av.tib.eu/series/1527/datenmanagement+in+der+chemie+videos+zum+acf+praktikum+an+der+rwth+aachen+university"
+        )
+    ]
-- 
GitLab


From 931389b81a252f17966c76a4d1108f74d5d2b01c Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Sat, 28 Dec 2024 13:09:30 +0100
Subject: [PATCH 09/16] changed uri in query, now using constant defined in
 dalia app

---
 project/recommendation/materials/suggested_content.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/project/recommendation/materials/suggested_content.py b/project/recommendation/materials/suggested_content.py
index fc9c0b6..892c6bf 100644
--- a/project/recommendation/materials/suggested_content.py
+++ b/project/recommendation/materials/suggested_content.py
@@ -4,6 +4,7 @@ from rdflib import URIRef, Variable
 
 from project.dalia.query.utils import query_dalia_dataset
 from project.dalia.query_builder.query_builder import QueryBuilder
+from project.dalia.rdf.prefix import LEARNING_RESOURCE_BASE_URI
 from project.recommendation.api_models.api_models import (
     SuggestedContents,
 )
@@ -17,7 +18,7 @@ def get_suggested_contents(uuid: UUID):
     return response
 
 
-def _query_for_suggested_content(uri: str):
+def _query_for_suggested_content(uuid: UUID):
     var_material = Variable("material")
 
     query = (
@@ -25,7 +26,7 @@ def _query_for_suggested_content(uri: str):
         .SELECT(var_material)
         .WHERE(
             (
-                URIRef(f"https://id.dalia.education/learning-resource/{uri}"),
+                URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
                 URIRef("https://schema.org/isPartOf"),
                 var_material,
             )
-- 
GitLab


From 3be0232b8daedd54b2eb28ace641f56a2d78f979 Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Sat, 28 Dec 2024 13:09:54 +0100
Subject: [PATCH 10/16] updated tests

---
 tests/project/recommendation/test_query.py | 25 ++++++++--------------
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/tests/project/recommendation/test_query.py b/tests/project/recommendation/test_query.py
index 7aa3663..826c3cb 100644
--- a/tests/project/recommendation/test_query.py
+++ b/tests/project/recommendation/test_query.py
@@ -1,7 +1,6 @@
-from project.recommendation.api_models.api_models import (
-    RecommendationMaterialSuggestedContentRequest,
-    SuggestedContents,
-)
+from uuid import UUID
+
+from project.recommendation.api_models.api_models import SuggestedContents
 from project.recommendation.materials.suggested_content import (
     _query_for_suggested_content,
     get_suggested_contents,
@@ -9,24 +8,18 @@ from project.recommendation.materials.suggested_content import (
 
 
 def test_query_for_suggested_content():
-    request = RecommendationMaterialSuggestedContentRequest(
-        uri="https://id.dalia.education/learning-resource/39ea23c6-a591-442f-afde-c3262e20f1e4"
-    )
+    uuid  = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
 
     print()
     print("--- QUERY ---")
-    print(_query_for_suggested_content(request.uri))
+    print(_query_for_suggested_content(uuid))
     print("--- QUERY ---")
 
 
 def test_get_suggested_content():
-    request = RecommendationMaterialSuggestedContentRequest(
-        uri="https://id.dalia.education/learning-resource/39ea23c6-a591-442f-afde-c3262e20f1e4"
-    )
+    uuid  = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
 
-    results = get_suggested_contents(request)
-    assert results == [
-        SuggestedContents(
-            uri="https://av.tib.eu/series/1527/datenmanagement+in+der+chemie+videos+zum+acf+praktikum+an+der+rwth+aachen+university"
+    results = get_suggested_contents(uuid)
+    assert results == SuggestedContents(
+            uris=["https://av.tib.eu/series/1527/datenmanagement+in+der+chemie+videos+zum+acf+praktikum+an+der+rwth+aachen+university"]
         )
-    ]
-- 
GitLab


From cd7717deb450545dc63115b1ee07e4f8b5eed622 Mon Sep 17 00:00:00 2001
From: agneskleinhans <kleinhansagnes@gmail.com>
Date: Fri, 17 Jan 2025 16:40:39 +0100
Subject: [PATCH 11/16] add query keywords

---
 .../materials/suggested_content.py            | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/project/recommendation/materials/suggested_content.py b/project/recommendation/materials/suggested_content.py
index 892c6bf..db5cc71 100644
--- a/project/recommendation/materials/suggested_content.py
+++ b/project/recommendation/materials/suggested_content.py
@@ -12,7 +12,10 @@ from project.recommendation.api_models.api_models import (
 
 def get_suggested_contents(uuid: UUID):
     query = _query_for_suggested_content(uuid)
-    results = query_dalia_dataset(query)
+    results = []
+    for q in query:
+        results += query_dalia_dataset(q)
+    #results = query_dalia_dataset(query[0])
     response = SuggestedContents([str(result[0]) for result in results])
 
     return response
@@ -34,4 +37,16 @@ def _query_for_suggested_content(uuid: UUID):
         .build()
     )
 
-    return query
+
+    query2 = f"""
+        PREFIX schema: <https://schema.org/>
+        SELECT ?sub (COUNT(?sharedKeyword) AS ?keywordCount) WHERE {{
+            <{LEARNING_RESOURCE_BASE_URI}{uuid}> schema:keywords ?sharedKeyword .
+            ?sub schema:keywords ?sharedKeyword .
+            FILTER(?sub != <{LEARNING_RESOURCE_BASE_URI}{uuid}>)
+        }}
+        GROUP BY ?sub
+        HAVING(?keywordCount >= 2)
+        """
+
+    return [query, query2]
-- 
GitLab


From e6f974eafb8cdabce2d81cd14065712201514275 Mon Sep 17 00:00:00 2001
From: flange <38500-flange@users.noreply.git.rwth-aachen.de>
Date: Fri, 24 Jan 2025 15:48:45 +0100
Subject: [PATCH 12/16] change order of social_media list of communities

---
 .../dalia/query/communities/one_to_one_metadata.py | 14 ++++++++------
 .../dalia/query/communities/test_communities.py    |  4 ++--
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/project/dalia/query/communities/one_to_one_metadata.py b/project/dalia/query/communities/one_to_one_metadata.py
index 65d11f9..0cf04f1 100644
--- a/project/dalia/query/communities/one_to_one_metadata.py
+++ b/project/dalia/query/communities/one_to_one_metadata.py
@@ -53,14 +53,19 @@ def process_result_for_one_to_one_metadata_for_community(result) -> Community:
 
 def process_social_media_in_result(result):
     social_media = []
-    if result.bluesky_handle:
+
+    if result.zenodo_community_id:
         social_media.append(
-            SocialMedia(name="Bluesky", url="https://bsky.app/profile/" + str(result.bluesky_handle))
+            SocialMedia(name="Zenodo", url="https://zenodo.org/communities/" + str(result.zenodo_community_id))
         )
     if result.youtube_channel_id:
         social_media.append(
             SocialMedia(name="YouTube", url="https://www.youtube.com/channel/" + str(result.youtube_channel_id))
         )
+    if result.bluesky_handle:
+        social_media.append(
+            SocialMedia(name="Bluesky", url="https://bsky.app/profile/" + str(result.bluesky_handle))
+        )
     if result.mastodon_address:
         server = str(result.mastodon_address).split("@")[-1]
         handle = str(result.mastodon_address).split("@")[0]
@@ -71,10 +76,7 @@ def process_social_media_in_result(result):
         social_media.append(
             SocialMedia(name="LinkedIn", url="https://www.linkedin.com/company/" + str(result.linkedin_id))
         )
-    if result.zenodo_community_id:
-        social_media.append(
-            SocialMedia(name="Zenodo", url="https://zenodo.org/communities/" + str(result.zenodo_community_id))
-        )
+
     return social_media
 
 
diff --git a/tests/project/dalia/query/communities/test_communities.py b/tests/project/dalia/query/communities/test_communities.py
index 71b2abb..812e89d 100644
--- a/tests/project/dalia/query/communities/test_communities.py
+++ b/tests/project/dalia/query/communities/test_communities.py
@@ -21,11 +21,11 @@ def test_get_on_CommunityView_returns_200_and_community_data_for_existing_commun
         image=None,
         url='https://www.nfdi4chem.de/',
         social_media=[
-            SocialMedia(name='Bluesky', url='https://bsky.app/profile/nfdi4chem.de'),
+            SocialMedia(name='Zenodo', url='https://zenodo.org/communities/nfdi4chem'),
             SocialMedia(name='YouTube', url='https://www.youtube.com/channel/UCQlKQDjyYFzlUFrDfR9vVJg'),
+            SocialMedia(name='Bluesky', url='https://bsky.app/profile/nfdi4chem.de'),
             SocialMedia(name='Mastodon', url='https://nfdi.social/@NFDI4Chem'),
             SocialMedia(name='LinkedIn', url='https://www.linkedin.com/company/nfdi4chem'),
-            SocialMedia(name='Zenodo', url='https://zenodo.org/communities/nfdi4chem')
         ],
         about='NFDI4Chem is building an open and FAIR infrastructure for research data management in chemistry. The '
               'consortium consists of dedicated data producers and users from university and non-university research, '
-- 
GitLab


From a21bfd99e65a89ac9aa9ba89292df12cee3b2d8b Mon Sep 17 00:00:00 2001
From: flange <38500-flange@users.noreply.git.rwth-aachen.de>
Date: Thu, 30 Jan 2025 19:27:07 +0100
Subject: [PATCH 13/16] update facet items

---
 project/dalia/query/items/facets/facet_objects.py | 3 +++
 project/dalia/rdf/namespace/hcrt.py               | 1 +
 2 files changed, 4 insertions(+)

diff --git a/project/dalia/query/items/facets/facet_objects.py b/project/dalia/query/items/facets/facet_objects.py
index 971a3ee..657c3b3 100644
--- a/project/dalia/query/items/facets/facet_objects.py
+++ b/project/dalia/query/items/facets/facet_objects.py
@@ -87,6 +87,7 @@ LEARNING_RESOURCE_TYPE_FACET = FacetObject(
         hcrt.experiment: "Experiment",
         MoDalia.Lecture: "Lecture",
         hcrt.lesson_plan: "Lesson Plan",
+        hcrt.other: "Other resource type",
         SCHEMA.PodcastSeries: "PodcastSeries",
         MoDalia.Poster: "Poster",
         hcrt.index: "Reference Work",
@@ -108,7 +109,9 @@ LANGUAGE_FACET = FacetObject(
     predicate=DCTERMS.language,
     items={
         Literal("en"): "English",
+        Literal("fr"): "French",
         Literal("de"): "German",
+        Literal("es"): "Spanish",
     },
     selected_facet_initializer=Literal,
 )
diff --git a/project/dalia/rdf/namespace/hcrt.py b/project/dalia/rdf/namespace/hcrt.py
index 0f96e60..5223948 100644
--- a/project/dalia/rdf/namespace/hcrt.py
+++ b/project/dalia/rdf/namespace/hcrt.py
@@ -16,6 +16,7 @@ educational_game = URIRef(NS + "educational_game")
 experiment = URIRef(NS + "experiment")
 lesson_plan = URIRef(NS + "lesson_plan")
 index = URIRef(NS + "index")
+other = URIRef(NS + "other")
 slide = URIRef(NS + "slide")
 text = URIRef(NS + "text")
 textbook = URIRef(NS + "textbook")
-- 
GitLab


From ecfa388b249f37454d9c5b6cc3d1543b4dfb7c0d Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Fri, 7 Mar 2025 00:33:01 +0100
Subject: [PATCH 14/16] Get suggested content considering different ranking
 metrics

---
 .vscode/settings.json                         |  18 +++
 .../materials/suggested_content.py            | 136 +++++++++++++++---
 tests/project/recommendation/test_query.py    |  85 +++++++++--
 3 files changed, 207 insertions(+), 32 deletions(-)
 create mode 100644 .vscode/settings.json

diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..b9398da
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,18 @@
+{   
+    "[python]": {
+        "editor.defaultFormatter": "charliermarsh.ruff",
+        "editor.formatOnSave": true,
+        "editor.rulers": [
+            88
+        ],
+        "editor.renderWhitespace": "trailing",
+        "editor.codeActionsOnSave": {
+            "source.organizeImports.ruff": "explicit"
+        }
+    },
+    "python.testing.pytestArgs": [
+        "tests"
+    ],
+    "python.testing.unittestEnabled": false,
+    "python.testing.pytestEnabled": true
+}
\ No newline at end of file
diff --git a/project/recommendation/materials/suggested_content.py b/project/recommendation/materials/suggested_content.py
index db5cc71..89015a8 100644
--- a/project/recommendation/materials/suggested_content.py
+++ b/project/recommendation/materials/suggested_content.py
@@ -4,49 +4,147 @@ from rdflib import URIRef, Variable
 
 from project.dalia.query.utils import query_dalia_dataset
 from project.dalia.query_builder.query_builder import QueryBuilder
+from project.dalia.rdf.namespace import SCHEMA, MoDalia, fabio
 from project.dalia.rdf.prefix import LEARNING_RESOURCE_BASE_URI
 from project.recommendation.api_models.api_models import (
     SuggestedContents,
 )
 
 
-def get_suggested_contents(uuid: UUID):
-    query = _query_for_suggested_content(uuid)
-    results = []
-    for q in query:
-        results += query_dalia_dataset(q)
-    #results = query_dalia_dataset(query[0])
-    response = SuggestedContents([str(result[0]) for result in results])
+def _get_shared_keywords(uuid: UUID):
+    query = f"""
+        PREFIX schema: <https://schema.org/>
+        SELECT ?sub (COUNT(?sharedKeyword) AS ?keywordCount) WHERE {{
+            <{LEARNING_RESOURCE_BASE_URI}{uuid}> schema:keywords ?sharedKeyword .
+            ?sub schema:keywords ?sharedKeyword .
+            FILTER(?sub != <{LEARNING_RESOURCE_BASE_URI}{uuid}>)
+        }}
+        GROUP BY ?sub
+        HAVING(?keywordCount >= 2)
+        """
 
-    return response
+    results = query_dalia_dataset(query)
+    return [result[0] for result in results]
 
 
-def _query_for_suggested_content(uuid: UUID):
+def _get_is_part_of(uuid: UUID):
     var_material = Variable("material")
+    query = (
+        QueryBuilder()
+        .SELECT(var_material)
+        .WHERE(
+            (
+                URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
+                URIRef(URIRef(SCHEMA.NS + "isPartOf")),
+                var_material,
+            )
+        )
+        .build()
+    )
+    results = query_dalia_dataset(query)
+    return [result[0] for result in results]
 
+
+def _get_is_related_to(uuid: UUID):
+    var_material = Variable("material")
     query = (
         QueryBuilder()
         .SELECT(var_material)
         .WHERE(
             (
                 URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
-                URIRef("https://schema.org/isPartOf"),
+                URIRef(URIRef(MoDalia.NS + "isRelatedTo")),
                 var_material,
             )
         )
         .build()
     )
+    results = query_dalia_dataset(query)
+    return [result[0] for result in results]
 
 
-    query2 = f"""
+def _get_is_based_on(uuid: UUID):
+    var_material = Variable("material")
+    query = (
+        QueryBuilder()
+        .SELECT(var_material)
+        .WHERE(
+            (
+                URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
+                URIRef(URIRef(MoDalia.NS + "isBasedOn")),
+                var_material,
+            )
+        )
+        .build()
+    )
+    results = query_dalia_dataset(query)
+    return [result[0] for result in results]
+
+
+def _get_authors(uuid: UUID):
+    query = f"""
+        PREFIX arq: <http://jena.apache.org/ARQ/list#>
         PREFIX schema: <https://schema.org/>
-        SELECT ?sub (COUNT(?sharedKeyword) AS ?keywordCount) WHERE {{
-            <{LEARNING_RESOURCE_BASE_URI}{uuid}> schema:keywords ?sharedKeyword .
-            ?sub schema:keywords ?sharedKeyword .
-            FILTER(?sub != <{LEARNING_RESOURCE_BASE_URI}{uuid}>)
+        PREFIX m4i: <http://w3id.org/nfdi4ing/metadata4ing#>
+
+        SELECT DISTINCT ?lr WHERE {{
+            <{LEARNING_RESOURCE_BASE_URI}{uuid}> schema:author ?list.
+            ?list arq:member ?member.
+            ?member a ?type.
+	        ?member m4i:orcidId ?id.
+            ?lr schema:author ?newlist.
+            ?newlist arq:member ?newmember.
+            ?newmember m4i:orcidId ?id.
+            FILTER(?lr != <{LEARNING_RESOURCE_BASE_URI}{uuid}>)
+            FILTER(?type = schema:Person)
         }}
-        GROUP BY ?sub
-        HAVING(?keywordCount >= 2)
-        """
+    LIMIT 10"""
+    results = query_dalia_dataset(query)
+    return [result[0] for result in results]
+
+
+def _get_same_discipline(uuid: UUID):
+    var_material = Variable("material")
+    var_discipline = Variable("discipline")
+    query = (
+        QueryBuilder()
+        .SELECT(var_material)
+        .WHERE(
+            (
+                URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
+                URIRef(URIRef(fabio.NS + "hasDiscipline")),
+                var_discipline,
+            ),
+            (
+                var_material,
+                URIRef(URIRef(fabio.NS + "hasDiscipline")),
+                var_discipline,
+            ),
+        )
+        .build()
+    )
+    results = query_dalia_dataset(query)
+    return [result[0] for result in results]
+
+
+RANKING = (
+    _get_is_part_of,
+    _get_is_based_on,
+    _get_is_related_to,
+    _get_authors,
+    _get_shared_keywords,
+    _get_same_discipline,
+)
+
+
+def get_suggested_contents(uuid: UUID):
+    number_of_materials = 5
+    results = set()
+    for i in range(len(RANKING)):
+        for result in RANKING[i](uuid):
+            if LEARNING_RESOURCE_BASE_URI == result[: len(LEARNING_RESOURCE_BASE_URI)]:
+                results.add(result)
+            if len(results) == number_of_materials:
+                return SuggestedContents(results)
 
-    return [query, query2]
+    return SuggestedContents(results)
diff --git a/tests/project/recommendation/test_query.py b/tests/project/recommendation/test_query.py
index 826c3cb..66dcc92 100644
--- a/tests/project/recommendation/test_query.py
+++ b/tests/project/recommendation/test_query.py
@@ -1,25 +1,84 @@
 from uuid import UUID
 
-from project.recommendation.api_models.api_models import SuggestedContents
 from project.recommendation.materials.suggested_content import (
-    _query_for_suggested_content,
+    _get_authors,
+    _get_is_based_on,
+    _get_is_part_of,
+    _get_is_related_to,
+    _get_same_discipline,
+    _get_shared_keywords,
     get_suggested_contents,
 )
 
+# def test_query_for_suggested_content():
+#     uuid  = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
 
-def test_query_for_suggested_content():
-    uuid  = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+#     print()
+#     print("--- QUERY ---")
+#     print(_query_for_suggested_content(uuid))
+#     print("--- QUERY ---")
 
-    print()
-    print("--- QUERY ---")
-    print(_query_for_suggested_content(uuid))
-    print("--- QUERY ---")
 
+# def test_get_suggested_content():
+#     uuid  = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
 
-def test_get_suggested_content():
-    uuid  = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+#     results = get_suggested_contents(uuid)
+#     assert results == SuggestedContents(
+#             uris=["https://av.tib.eu/series/1527/datenmanagement+in+der+chemie+videos+zum+acf+praktikum+an+der+rwth+aachen+university"]
+#         )
 
+
+def test_get_is_part_of():
+    uuid = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+
+    print("get is part of")
+    results = _get_is_part_of(uuid)
+    print("\n".join(results))
+
+
+def test_get_is_related_to():
+    uuid = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+
+    print("get is based on")
+    results = _get_is_related_to(uuid)
+    print("\n".join(results))
+
+
+def test_get_is_based_on():
+    uuid = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+
+    print("get is related to")
+    results = _get_is_based_on(uuid)
+    print("\n".join(results))
+
+
+def test_get_shared_keywords():
+    uuid = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+
+    print("get shared keywords")
+    results = _get_shared_keywords(uuid)
+    print("\n".join(results))
+
+
+def test_get_authors():
+    uuid = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+
+    print("get authors")
+    results = _get_authors(uuid)
+    print("\n".join(results))
+
+
+def test_get_same_discipline():
+    uuid = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+
+    print("get same discipline")
+    results = _get_same_discipline(uuid)
+    print("\n".join(results))
+
+
+def test_get_suggested_contents():
+    uuid = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+
+    print("get suggested contents")
     results = get_suggested_contents(uuid)
-    assert results == SuggestedContents(
-            uris=["https://av.tib.eu/series/1527/datenmanagement+in+der+chemie+videos+zum+acf+praktikum+an+der+rwth+aachen+university"]
-        )
+    print("\n".join(results.uris))
-- 
GitLab


From 00a6fcd7b332ab70d75ea83cc24a4581e9c250c5 Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Mon, 14 Apr 2025 22:52:21 +0200
Subject: [PATCH 15/16] finished /items/{}/recommendations api end point
 according to the doc

---
 .vscode/settings.json                         |  3 +-
 .../recommendation/api_models/api_models.py   |  6 ++--
 .../materials/suggested_content.py            | 36 ++++++++++++-------
 project/recommendation/urls.py                |  4 +--
 project/recommendation/views.py               | 14 +++++---
 5 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/.vscode/settings.json b/.vscode/settings.json
index b9398da..81b3e0a 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -11,7 +11,8 @@
         }
     },
     "python.testing.pytestArgs": [
-        "tests"
+        "tests",
+        "-s"
     ],
     "python.testing.unittestEnabled": false,
     "python.testing.pytestEnabled": true
diff --git a/project/recommendation/api_models/api_models.py b/project/recommendation/api_models/api_models.py
index 9488658..9d34c50 100644
--- a/project/recommendation/api_models/api_models.py
+++ b/project/recommendation/api_models/api_models.py
@@ -1,7 +1,9 @@
 from dataclasses import dataclass
-from typing import List
+from typing import List, Optional
+
+from project.dalia.api_models.api_models import Item
 
 
 @dataclass
 class SuggestedContents:
-    uris: List[str]
+    results: Optional[List[Item]]
diff --git a/project/recommendation/materials/suggested_content.py b/project/recommendation/materials/suggested_content.py
index 89015a8..6c5754e 100644
--- a/project/recommendation/materials/suggested_content.py
+++ b/project/recommendation/materials/suggested_content.py
@@ -1,11 +1,13 @@
+from typing import Set
 from uuid import UUID
 
 from rdflib import URIRef, Variable
 
+from project.dalia.query.items.metadata.items import get_metadata_for_learning_resources
 from project.dalia.query.utils import query_dalia_dataset
 from project.dalia.query_builder.query_builder import QueryBuilder
+from project.dalia.rdf.dalia_kb import _LEARNING_RESOURCE_BASE_URI
 from project.dalia.rdf.namespace import SCHEMA, MoDalia, fabio
-from project.dalia.rdf.prefix import LEARNING_RESOURCE_BASE_URI
 from project.recommendation.api_models.api_models import (
     SuggestedContents,
 )
@@ -15,9 +17,9 @@ def _get_shared_keywords(uuid: UUID):
     query = f"""
         PREFIX schema: <https://schema.org/>
         SELECT ?sub (COUNT(?sharedKeyword) AS ?keywordCount) WHERE {{
-            <{LEARNING_RESOURCE_BASE_URI}{uuid}> schema:keywords ?sharedKeyword .
+            <{_LEARNING_RESOURCE_BASE_URI}{uuid}> schema:keywords ?sharedKeyword .
             ?sub schema:keywords ?sharedKeyword .
-            FILTER(?sub != <{LEARNING_RESOURCE_BASE_URI}{uuid}>)
+            FILTER(?sub != <{_LEARNING_RESOURCE_BASE_URI}{uuid}>)
         }}
         GROUP BY ?sub
         HAVING(?keywordCount >= 2)
@@ -34,7 +36,7 @@ def _get_is_part_of(uuid: UUID):
         .SELECT(var_material)
         .WHERE(
             (
-                URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
+                URIRef(f"{_LEARNING_RESOURCE_BASE_URI}{uuid}"),
                 URIRef(URIRef(SCHEMA.NS + "isPartOf")),
                 var_material,
             )
@@ -52,7 +54,7 @@ def _get_is_related_to(uuid: UUID):
         .SELECT(var_material)
         .WHERE(
             (
-                URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
+                URIRef(f"{_LEARNING_RESOURCE_BASE_URI}{uuid}"),
                 URIRef(URIRef(MoDalia.NS + "isRelatedTo")),
                 var_material,
             )
@@ -70,7 +72,7 @@ def _get_is_based_on(uuid: UUID):
         .SELECT(var_material)
         .WHERE(
             (
-                URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
+                URIRef(f"{_LEARNING_RESOURCE_BASE_URI}{uuid}"),
                 URIRef(URIRef(MoDalia.NS + "isBasedOn")),
                 var_material,
             )
@@ -88,14 +90,14 @@ def _get_authors(uuid: UUID):
         PREFIX m4i: <http://w3id.org/nfdi4ing/metadata4ing#>
 
         SELECT DISTINCT ?lr WHERE {{
-            <{LEARNING_RESOURCE_BASE_URI}{uuid}> schema:author ?list.
+            <{_LEARNING_RESOURCE_BASE_URI}{uuid}> schema:author ?list.
             ?list arq:member ?member.
             ?member a ?type.
 	        ?member m4i:orcidId ?id.
             ?lr schema:author ?newlist.
             ?newlist arq:member ?newmember.
             ?newmember m4i:orcidId ?id.
-            FILTER(?lr != <{LEARNING_RESOURCE_BASE_URI}{uuid}>)
+            FILTER(?lr != <{_LEARNING_RESOURCE_BASE_URI}{uuid}>)
             FILTER(?type = schema:Person)
         }}
     LIMIT 10"""
@@ -111,7 +113,7 @@ def _get_same_discipline(uuid: UUID):
         .SELECT(var_material)
         .WHERE(
             (
-                URIRef(f"{LEARNING_RESOURCE_BASE_URI}{uuid}"),
+                URIRef(f"{_LEARNING_RESOURCE_BASE_URI}{uuid}"),
                 URIRef(URIRef(fabio.NS + "hasDiscipline")),
                 var_discipline,
             ),
@@ -137,14 +139,22 @@ RANKING = (
 )
 
 
-def get_suggested_contents(uuid: UUID):
+def get_suggested_contents_id(uuid: UUID) -> Set:
     number_of_materials = 5
     results = set()
     for i in range(len(RANKING)):
         for result in RANKING[i](uuid):
-            if LEARNING_RESOURCE_BASE_URI == result[: len(LEARNING_RESOURCE_BASE_URI)]:
+            if (
+                _LEARNING_RESOURCE_BASE_URI
+                == result[: len(_LEARNING_RESOURCE_BASE_URI)]
+            ):
                 results.add(result)
             if len(results) == number_of_materials:
-                return SuggestedContents(results)
+                return results
 
-    return SuggestedContents(results)
+    return results
+
+
+def get_suggested_contents(uuid: UUID) -> SuggestedContents:
+    ids = get_suggested_contents_id(uuid)
+    return SuggestedContents(get_metadata_for_learning_resources(list(ids)))
diff --git a/project/recommendation/urls.py b/project/recommendation/urls.py
index 398d0ca..2b33939 100644
--- a/project/recommendation/urls.py
+++ b/project/recommendation/urls.py
@@ -8,8 +8,8 @@ from project.recommendation import views
 
 urlpatterns = [
     path(
-        "v1/<uuid:material_id>/suggestions",
+        "v1/item/<uuid:material_id>/recommendations",
         views.MaterialSuggestionsView.as_view(),
-        name="material_suggestions",
+        name="material_recommendations",
     ),
 ]
diff --git a/project/recommendation/views.py b/project/recommendation/views.py
index e29e695..52c245f 100644
--- a/project/recommendation/views.py
+++ b/project/recommendation/views.py
@@ -1,5 +1,6 @@
 from uuid import UUID
 
+from rest_framework import status
 from rest_framework.request import Request
 from rest_framework.response import Response
 from rest_framework.views import APIView
@@ -8,10 +9,13 @@ import project.recommendation.serializers as serializers
 from project.recommendation.materials.suggested_content import get_suggested_contents
 
 
-# endpoint /<uuid:material_id>/suggestions
+# endpoint /items/<uuid:material_id>/recommendations
 class MaterialSuggestionsView(APIView):
     def get(self, request: Request, material_id: UUID):
-        result_serializer = serializers.SuggestedContentSerializer(
-            get_suggested_contents(material_id)
-        )
-        return Response(result_serializer.data)
+        suggested_contents = get_suggested_contents(material_id)
+        if len(suggested_contents.results) == 0:
+            return Response(
+                {"messages": "No suggestions found"}, status=status.HTTP_404_NOT_FOUND
+            )
+        result = serializers.SuggestedContentSerializer(suggested_contents)
+        return Response(result.data)
-- 
GitLab


From 20e5a880125e121c135e5a7ad07ef7eb79d915b2 Mon Sep 17 00:00:00 2001
From: "Xia, Ning" <ning.xia@tu-darmstadt.de>
Date: Mon, 14 Apr 2025 22:53:14 +0200
Subject: [PATCH 16/16] added test for call the functions of endpotin
 /items/{}/recommendations

---
 tests/project/recommendation/test_query.py      |  3 ++-
 tests/project/recommendation/test_serialiser.py | 13 +++++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 tests/project/recommendation/test_serialiser.py

diff --git a/tests/project/recommendation/test_query.py b/tests/project/recommendation/test_query.py
index 66dcc92..0d9f5b6 100644
--- a/tests/project/recommendation/test_query.py
+++ b/tests/project/recommendation/test_query.py
@@ -81,4 +81,5 @@ def test_get_suggested_contents():
 
     print("get suggested contents")
     results = get_suggested_contents(uuid)
-    print("\n".join(results.uris))
+    for result in results:
+        print(result)
diff --git a/tests/project/recommendation/test_serialiser.py b/tests/project/recommendation/test_serialiser.py
new file mode 100644
index 0000000..966bb87
--- /dev/null
+++ b/tests/project/recommendation/test_serialiser.py
@@ -0,0 +1,13 @@
+from uuid import UUID
+
+from project.recommendation.materials.suggested_content import get_suggested_contents
+from project.recommendation.serializers import SuggestedContentSerializer
+
+
+def test_suggested_content_serializer():
+    uuid = UUID("39ea23c6-a591-442f-afde-c3262e20f1e4")
+
+    print("get suggested contents")
+    results = get_suggested_contents(uuid)
+    serializer = SuggestedContentSerializer(results)
+    print(serializer.data)
-- 
GitLab