|
|
{% extends 'base.html' %} |
|
|
|
|
|
{% block title %}Prediction Results{% endblock %} |
|
|
|
|
|
{% block content %} |
|
|
<div class="container mt-4"> |
|
|
|
|
|
<div class="row"> |
|
|
<div class="col-12 mb-4"> |
|
|
<div class="card border-primary"> |
|
|
<div class="card-header bg-secondary text-white"> |
|
|
<h4 class="mb-0">Topic</h4> |
|
|
</div> |
|
|
<div class="card-body"> |
|
|
<p class="card-text" style="color: black;">{{ topic }}</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="row"> |
|
|
<div class="col-12 mb-4"> |
|
|
<div class="card border-primary"> |
|
|
<div class="card-header bg-secondary text-white"> |
|
|
<h4 class="mb-0">Essay Comparison</h4> |
|
|
</div> |
|
|
<div class="card-body p-0"> |
|
|
<div class="row g-0"> |
|
|
|
|
|
<div class="col-md-6 border-end"> |
|
|
<div class="p-3"> |
|
|
<h5 class="text-center text-primary">Original Essay</h5> |
|
|
<div class="original-essay" id="originalEssay" style="color: black; height: 400px; overflow-y: auto;"> |
|
|
{{ essay }} |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="col-md-6"> |
|
|
<div class="p-3"> |
|
|
<h5 class="text-center text-success">Corrected Essay</h5> |
|
|
<div class="corrected-essay" id="correctedEssay" style="color: black; height: 400px; overflow-y: auto;"> |
|
|
{{ corrected_essay }} |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="row"> |
|
|
{% set rubrics = [ |
|
|
('Task Response', result[0], tr , 'task_response'), |
|
|
('Coherence and Cohesion', result[1], cc, 'coherence_cohesion'), |
|
|
('Lexical Resource', result[2], lr, 'lexical_resource'), |
|
|
('Grammatical Range and Accuracy', result[3], gra, 'grammatical_accuracy') |
|
|
] %} |
|
|
|
|
|
{% for rubric, score, explanation, link in rubrics %} |
|
|
<div class="col-md-3 mb-4"> |
|
|
<div class="card h-100 bg-light border-info"> |
|
|
<div class="card-body"> |
|
|
<h5 class="card-title" style="color: black;">{{ rubric }}</h5> |
|
|
<div class="score-display mb-3 text-center"> |
|
|
<span class="score">{{ score|int }}</span>/9 |
|
|
</div> |
|
|
<p class="card-text text-truncate-multiline text-dark"> |
|
|
{{ explanation }} |
|
|
</p> |
|
|
<div class="d-flex justify-content-between mt-3"> |
|
|
<button type="button" class="btn btn-sm btn-outline-info" data-bs-toggle="modal" data-bs-target="#feedbackModal{{ loop.index }}"> |
|
|
View Feedback |
|
|
</button> |
|
|
<a href="{{ url_for('infer.rubric_explanation', rubric=link) }}" class="btn btn-sm btn-outline-info"> |
|
|
Details |
|
|
</a> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="modal fade" id="feedbackModal{{ loop.index }}" tabindex="-1" aria-labelledby="feedbackModalLabel{{ loop.index }}" aria-hidden="true"> |
|
|
<div class="modal-dialog modal-dialog-centered"> |
|
|
<div class="modal-content"> |
|
|
<div class="modal-header bg-info text-white"> |
|
|
<h5 class="modal-title" id="feedbackModalLabel{{ loop.index }}">{{ rubric }} Feedback</h5> |
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> |
|
|
</div> |
|
|
<div class="modal-body" style="max-height: 60vh; overflow-y: auto;"> |
|
|
{{ explanation }} |
|
|
</div> |
|
|
<div class="modal-footer"> |
|
|
<button type="button" class="btn btn-info" data-bs-dismiss="modal">Close</button> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
{% endfor %} |
|
|
</div> |
|
|
|
|
|
<div class="text-center mt-4"> |
|
|
<a href="{{ url_for('infer.index') }}" class="btn btn-primary">Submit Another Essay</a> |
|
|
</div> |
|
|
</div> |
|
|
{% endblock %} |
|
|
|
|
|
{% block extra_scripts %} |
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsdiff/5.0.1/diff.min.js"></script> |
|
|
<script> |
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
try { |
|
|
const origEl = document.getElementById('originalEssay'); |
|
|
const corrEl = document.getElementById('correctedEssay'); |
|
|
if (!origEl || !corrEl) return; |
|
|
|
|
|
const originalText = origEl.textContent; |
|
|
const correctedText = corrEl.textContent; |
|
|
|
|
|
|
|
|
const diff = JsDiff.diffWordsWithSpace(originalText, correctedText); |
|
|
|
|
|
|
|
|
if (diff.length <= 1) return; |
|
|
|
|
|
|
|
|
corrEl.innerHTML = ''; |
|
|
|
|
|
|
|
|
diff.forEach(part => { |
|
|
const span = document.createElement('span'); |
|
|
span.textContent = part.value; |
|
|
if (part.added) span.classList.add('diff-ins'); |
|
|
if (part.removed) span.classList.add('diff-del'); |
|
|
corrEl.appendChild(span); |
|
|
}); |
|
|
} |
|
|
catch (e) { |
|
|
console.error('Diff rendering error:', e); |
|
|
} |
|
|
}); |
|
|
</script> |
|
|
<style> |
|
|
.diff-ins {border-bottom:2px solid #28a745; } |
|
|
.diff-del {text-decoration: line-through; color: #dc3545; } |
|
|
|
|
|
|
|
|
.score-display { |
|
|
font-size: 1.2rem; |
|
|
font-weight: bold; |
|
|
} |
|
|
|
|
|
.score { |
|
|
color: #0d6efd; |
|
|
font-size: 1.5rem; |
|
|
} |
|
|
|
|
|
.text-truncate-multiline { |
|
|
display: -webkit-box; |
|
|
-webkit-line-clamp: 3; |
|
|
-webkit-box-orient: vertical; |
|
|
overflow: hidden; |
|
|
text-overflow: ellipsis; |
|
|
min-height: 4.5em; |
|
|
} |
|
|
|
|
|
.card { |
|
|
transition: transform 0.2s; |
|
|
} |
|
|
|
|
|
.card:hover { |
|
|
transform: translateY(-5px); |
|
|
box-shadow: 0 4px 15px rgba(13, 110, 253, 0.25); |
|
|
} |
|
|
</style> |
|
|
{% endblock %} |