### 1) VOCAB_TTL ###
@prefix ex: <https://example.org/edu#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

ex:Student                 a rdfs:Class ; rdfs:label "Student" ; rdfs:subClassOf foaf:Person .
ex:GrantApplication        a rdfs:Class ; rdfs:label "Need-based Grant Application" .
ex:GrantPayment            a rdfs:Class ; rdfs:label "Grant Payment" .

ex:NeedBasedGrant a skos:Concept ; skos:prefLabel "Need-based Student Grant" .

ex:hasApplicant     a rdf:Property ; rdfs:domain ex:GrantApplication ; rdfs:range ex:Student ; rdfs:label "has applicant" .
ex:appliesFor       a rdf:Property ; rdfs:domain ex:GrantApplication ; rdfs:range skos:Concept ; rdfs:label "applies for" .
ex:status           a rdf:Property ; rdfs:domain ex:GrantApplication ; rdfs:label "status" .
ex:eligible         a rdf:Property ; rdfs:domain ex:GrantApplication ; rdfs:label "eligible" .
ex:issuedPayment    a rdf:Property ; rdfs:domain ex:GrantApplication ; rdfs:range ex:GrantPayment ; rdfs:label "issued payment" .

ex:householdIncome  a rdf:Property ; rdfs:domain ex:Student ; rdfs:label "household income (annual)" .
ex:householdSize    a rdf:Property ; rdfs:domain ex:Student ; rdfs:label "household size" .
ex:enrolledECTS     a rdf:Property ; rdfs:domain ex:Student ; rdfs:label "enrolled ECTS credits" .
ex:tuitionAmount    a rdf:Property ; rdfs:domain ex:Student ; rdfs:label "tuition amount" .

ex:hasEvidence a rdf:Property ; rdfs:domain ex:GrantApplication ; rdfs:label "has evidence" .
ex:IncomeEvidence a rdfs:Class ; rdfs:label "Income Evidence" .
ex:EnrollmentEvidence a rdfs:Class ; rdfs:label "Enrollment Evidence" .
ex:HouseholdEvidence a rdfs:Class ; rdfs:label "Household Evidence" .

# Minimal statuses as SKOS concepts
ex:Submitted a skos:Concept ; skos:prefLabel "Submitted" .
ex:Approved  a skos:Concept ; skos:prefLabel "Approved" .
ex:Rejected  a skos:Concept ; skos:prefLabel "Rejected" .

### 2) PROFILE_SHACL_TTL ###
@prefix sh:  <http://www.w3.org/ns/shacl#> .
@prefix ex:  <https://example.org/edu#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ex:GrantApplicationShape a sh:NodeShape ;
  sh:targetClass ex:GrantApplication ;
  sh:property [
    sh:path ex:hasApplicant ;
    sh:minCount 1 ;
    sh:nodeKind sh:IRI ;
  ] ;
  sh:property [
    sh:path ex:appliesFor ;
    sh:hasValue ex:NeedBasedGrant ;
    sh:minCount 1 ;
  ] ;
  sh:property [
    sh:path ex:status ;
    sh:minCount 1 ;
  ] ;
  sh:property [
    sh:path ex:hasEvidence ;
    sh:minCount 3 ;                         # require at least 3 evidences (income, household, enrollment)
  ] .

ex:StudentShape a sh:NodeShape ;
  sh:targetClass ex:Student ;
  sh:property [
    sh:path ex:householdIncome ;
    sh:minCount 1 ;
    sh:datatype xsd:integer ;
  ] ;
  sh:property [
    sh:path ex:householdSize ;
    sh:minCount 1 ;
    sh:datatype xsd:integer ;
  ] ;
  sh:property [
    sh:path ex:enrolledECTS ;
    sh:minCount 1 ;
    sh:datatype xsd:integer ;
  ] ;
  sh:property [
    sh:path ex:tuitionAmount ;
    sh:minCount 1 ;
    sh:datatype xsd:integer ;
  ] .

### 3) RULES_N3 ###
# Interaction pattern: Need-based Student Grant
# States: Submitted -> (Eligible?) -> Approved/Rejected
# Preconditions: Application conforms to GrantApplicationShape; Student conforms to StudentShape
# Abstract messages: submitApplication, validate, decide, notify

@prefix ex:   <https://example.org/edu#> .
@prefix xsd:  <http://www.w3.org/2001/XMLSchema#> .
@prefix math: <http://www.w3.org/2000/10/swap/math#> .

# R1: Eligibility — ECTS ≥ 30, perCapitaIncome ≤ 18000, tuition > 0
# perCapitaIncome = householdIncome / householdSize
{
  ?app  ex:appliesFor     ex:NeedBasedGrant .
  ?app  ex:hasApplicant   ?s .
  ?s    ex:enrolledECTS   ?ects .
  ?s    ex:householdIncome ?inc .
  ?s    ex:householdSize   ?hh .
  ?s    ex:tuitionAmount   ?fee .
  "30"^^xsd:integer     math:notGreaterThan ?ects .
  (?inc ?hh)            math:quotient       ?pc .
  ?pc                   math:notGreaterThan "18000"^^xsd:integer .
  ?fee                  math:greaterThan    "0"^^xsd:integer .
}
=>
{
  ?app ex:eligible true .
} .

# R2: Approve — eligible true AND status Submitted → status Approved + payment issuance
{
  ?app ex:eligible true .
  ?app ex:status   ex:Submitted .
}
=>
{
  ?app ex:status ex:Approved .
  _:pay a ex:GrantPayment .
  ?app ex:issuedPayment _:pay .
} .

# R3: Reject — eligible false AND status Submitted → status Rejected
{
  ?app ex:eligible false .
  ?app ex:status   ex:Submitted .
}
=>
{
  ?app ex:status ex:Rejected .
} .

### DATA (Turtle from FACTS) ###
@prefix ex: <https://example.org/edu#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .

ex:APP-GR-01 
  ex:appliesFor ex:NeedBasedGrant ;
  ex:hasApplicant ex:Alice ;
  ex:hasEvidence "EnrollmentEvidence" ;
  ex:hasEvidence "HouseholdEvidence" ;
  ex:hasEvidence "IncomeEvidence" ;
  ex:status ex:Submitted .

ex:Alice 
  ex:enrolledECTS 60 ;
  ex:householdIncome 36000 ;
  ex:householdSize 3 ;
  ex:tuitionAmount 1200 .

