Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
name: Test Docker Build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
service: [backend, frontend]
steps:
Expand Down
39 changes: 38 additions & 1 deletion backend/api/quality-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -588,10 +588,47 @@ function convertToDQV(quality, baseUri = 'http://example.org/quality-assessment/
return dqv;
}

/**
* Update compliance metric based on SHACL validation result and recalculate totals.
* Binary scoring: full weight if conforms with no violations, 0 otherwise.
*/
function updateComplianceMetricFromSHACL(quality, shaclReport) {
const complianceMetric = quality.metrics.find(m => m.id.includes('compliance'));
if (!complianceMetric) {
return quality;
}

const isCompliant = shaclReport.conforms && shaclReport.totalViolations === 0;

complianceMetric.score = isCompliant ? complianceMetric.maxScore : 0;
complianceMetric.totalEntities = 1;
complianceMetric.compliantEntities = isCompliant ? 1 : 0;
complianceMetric.compliancePercentage = isCompliant ? 100.0 : 0.0;
complianceMetric.entityType = 'Catalog';
complianceMetric.found = true;

const totalScore = quality.metrics.reduce((sum, m) => sum + m.score, 0);
const maxScore = quality.metrics.reduce((sum, m) => sum + m.maxScore, 0);
quality.totalScore = Math.round(totalScore * 1000) / 1000;
quality.percentage = maxScore > 0 ? Math.round((totalScore / maxScore) * 1000) / 10 : 0;

for (const categoryData of Object.values(quality.byCategory)) {
const categoryMetrics = categoryData.metrics;
const categoryScore = categoryMetrics.reduce((sum, m) => sum + m.score, 0);
const categoryMaxScore = categoryMetrics.reduce((sum, m) => sum + m.maxScore, 0);

categoryData.score = Math.round(categoryScore * 1000) / 1000;
categoryData.percentage = categoryMaxScore > 0 ? (categoryScore / categoryMaxScore) * 100 : 0;
}

return quality;
}

module.exports = {
calculateQuality,
convertToDQV,
loadVocabulary,
loadMQAConfig,
getProfileInfo
getProfileInfo,
updateComplianceMetricFromSHACL
};
10 changes: 3 additions & 7 deletions backend/api/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const {
validateQualityRequest,
validateSHACLRequest
} = require('./types');
const { calculateQuality, convertToDQV, loadMQAConfig } = require('./quality-service');
const { calculateQuality, convertToDQV, loadMQAConfig, updateComplianceMetricFromSHACL } = require('./quality-service');
const { validateWithSHACL, exportReportAsTurtle, exportReportAsCSV, clearCache } = require('./shacl-service');
const { detectFormat, validateRDFSyntax } = require('./rdf-utils');
const axios = require('axios');
Expand Down Expand Up @@ -339,13 +339,9 @@ router.post('/validate', async (req, res) => {
calculateQuality(content, profile, detectedFormat, version),
validateWithSHACL(content, profile, detectedFormat, version, language, shapesGraphBranch)
]);

// Update compliance metric based on SHACL result
const complianceMetric = quality.metrics.find(m => m.id.includes('compliance'));
if (complianceMetric && !shaclReport.conforms) {
complianceMetric.score = 0;
complianceMetric.compliancePercentage = 0;
}
updateComplianceMetricFromSHACL(quality, shaclReport);

res.json({
success: true,
Expand Down
Loading
Loading