GopalKrushnaMahapatra commited on
Commit
c5a1ab8
·
verified ·
1 Parent(s): fd3f4a7

Update plagiarism.html

Browse files
Files changed (1) hide show
  1. plagiarism.html +271 -83
plagiarism.html CHANGED
@@ -5,7 +5,7 @@
5
  <title>Plagiarism Check – TrueWrite Scan</title>
6
  <meta name="viewport" content="width=device-width,initial-scale=1" />
7
  <script src="https://cdn.tailwindcss.com"></script>
8
- <!-- jsPDF (kept for backward compatibility but server PDF will be used) -->
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
10
  </head>
11
  <body class="bg-gradient-to-br from-slate-950 via-slate-900 to-violet-950 text-white min-h-screen flex flex-col">
@@ -177,8 +177,159 @@
177
  </div>
178
 
179
  <!-- Extra sections (unchanged UI text) -->
180
- <!-- ... (unchanged content omitted here for brevity but included in full file) ... -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  </main>
183
 
184
  <!-- Footer -->
@@ -198,7 +349,7 @@
198
  window.location.href = "login.html";
199
  }
200
 
201
- // jsPDF helper (kept but not used for server reports)
202
  function getJsPDF() {
203
  if (window.jspdf && window.jspdf.jsPDF) return window.jspdf.jsPDF;
204
  if (window.jsPDF) return window.jsPDF;
@@ -443,104 +594,141 @@
443
  }
444
  });
445
 
446
- // Helper to download blob
447
- function downloadBlob(blob, filename) {
448
- const url = URL.createObjectURL(blob);
449
- const a = document.createElement("a");
450
- a.href = url;
451
- a.download = filename || "report.pdf";
452
- document.body.appendChild(a);
453
- a.click();
454
- a.remove();
455
- setTimeout(() => URL.revokeObjectURL(url), 30000);
456
- }
457
-
458
- // Generic fetch PDF routine
459
- async function fetchReportPdf({ endpointGet, endpointFile, text, file, defaultFilename }) {
460
- if (file) {
461
- const form = new FormData();
462
- form.append("file", file, file.name);
463
- const res = await fetch(`${BACKEND_URL}${endpointFile}`, {
464
- method: "POST",
465
- headers: { "Authorization": `Bearer ${token}` },
466
- body: form
467
- });
468
- if (!res.ok) {
469
- const txt = await res.text();
470
- throw new Error(txt || `Server responded ${res.status}`);
471
- }
472
- const blob = await res.blob();
473
- const cd = res.headers.get("content-disposition") || "";
474
- const m = cd.match(/filename\*?=(?:UTF-8'')?["']?([^;"']+)/i);
475
- const fname = m ? decodeURIComponent(m[1]) : defaultFilename;
476
- downloadBlob(blob, fname);
477
- return;
478
- } else {
479
- const q = encodeURIComponent(text || "");
480
- const url = `${BACKEND_URL}${endpointGet}?text=${q}`;
481
- const res = await fetch(url, {
482
- method: "GET",
483
- headers: { "Authorization": `Bearer ${token}` }
484
- });
485
- if (!res.ok) {
486
- const txt = await res.text();
487
- throw new Error(txt || `Server responded ${res.status}`);
488
- }
489
- const blob = await res.blob();
490
- const cd = res.headers.get("content-disposition") || "";
491
- const m = cd.match(/filename\*?=(?:UTF-8'')?["']?([^;"']+)/i);
492
- const fname = m ? decodeURIComponent(m[1]) : defaultFilename;
493
- downloadBlob(blob, fname);
494
- }
495
- }
496
-
497
- // Download PDF report (server-generated)
498
- downloadBtn.addEventListener("click", async () => {
499
  if (!lastResult) {
500
  alert("Run a check first.");
501
  return;
502
  }
503
 
504
- try {
505
- setLoading(true);
506
- const file = fileInput.files[0] && !(fileInput.files[0].type === "text/plain" || fileInput.files[0].name.toLowerCase().endsWith(".txt")) ? fileInput.files[0] : null;
507
- await fetchReportPdf({
508
- endpointGet: "/report/plagiarism",
509
- endpointFile: "/report/plagiarism-file",
510
- text: textarea.value,
511
- file,
512
- defaultFilename: "TrueWrite_PlagiarismReport.pdf"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
  });
514
- } catch (err) {
515
- console.error(err);
516
- alert("Failed to download report: " + (err.message || err));
517
- } finally {
518
- setLoading(false);
519
  }
 
 
 
 
 
 
 
 
 
 
 
520
  });
521
 
522
- // Reviews slider and gauge init (unchanged)
523
  const reviews = [
524
- { name: "Aarav S.", role: "B.Tech Student", text: "Great for a quick originality check before using heavy tools like Turnitin.", stars: 5 },
525
- { name: "Priya K.", role: "Research Scholar", text: "Helps me understand how similarity scores work in a simple, visible way.", stars: 5 },
526
- { name: "Rahul M.", role: "Content Writer", text: "Nice to get an approximate plagiarism percentage while drafting blog posts.", stars: 4 },
527
- { name: "Sneha R.", role: "M.Sc. Student", text: "Perfect educational example to show classmates how plagiarism detection is implemented.", stars: 5 },
528
- { name: "Vikram J.", role: "Developer", text: "Clean UI and easy to tweak the logic for my own experiments.", stars: 4 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
529
  ];
530
 
531
- function starRow(stars) { let html = ""; for (let i = 0; i < 5; i++) html += `<span class="${i < stars ? "text-yellow-400" : "text-slate-600"} text-sm">★</span>`; return html; }
532
  let currentReview = 0;
533
  const reviewCard = document.getElementById("reviewCard");
534
  const reviewDots = document.getElementById("reviewDots");
 
 
 
 
 
 
 
 
 
535
  function renderReview() {
536
  const r = reviews[currentReview];
537
- reviewCard.innerHTML = `<div class="flex items-center gap-2 mb-2">${starRow(r.stars)}</div><p class="text-sm text-slate-200 mb-3">"${r.text}"</p><p class="text-sm font-semibold">${r.name}</p><p class="text-xs text-slate-400">${r.role}</p>`;
538
- reviewDots.innerHTML = reviews.map((_, i) => `<span class="w-2 h-2 rounded-full ${i === currentReview ? "bg-[#0487D9]" : "bg-slate-600"}"></span>`).join("");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  }
540
- function nextReview() { currentReview = (currentReview + 1) % reviews.length; renderReview(); }
541
- function prevReview() { currentReview = (currentReview - 1 + reviews.length) % reviews.length; renderReview(); }
542
- document.getElementById("nextReview").onclick = () => { clearInterval(reviewTimer); nextReview(); reviewTimer = setInterval(nextReview, 6000); };
543
- document.getElementById("prevReview").onclick = () => { clearInterval(reviewTimer); prevReview(); reviewTimer = setInterval(prevReview, 6000); };
 
 
 
 
 
 
 
 
544
  let reviewTimer = setInterval(nextReview, 6000);
545
  renderReview();
546
 
 
5
  <title>Plagiarism Check – TrueWrite Scan</title>
6
  <meta name="viewport" content="width=device-width,initial-scale=1" />
7
  <script src="https://cdn.tailwindcss.com"></script>
8
+ <!-- jsPDF (no integrity to avoid local SRI issues) -->
9
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
10
  </head>
11
  <body class="bg-gradient-to-br from-slate-950 via-slate-900 to-violet-950 text-white min-h-screen flex flex-col">
 
177
  </div>
178
 
179
  <!-- Extra sections (unchanged UI text) -->
180
+ <section class="mt-10 space-y-4">
181
+ <h2 class="text-xl md:text-2xl font-semibold">Why choose this plagiarism checker?</h2>
182
+ <p class="text-sm text-slate-300">
183
+ TrueWrite Scan’s plagiarism page is built to help you understand how similarity checks work,
184
+ from input text to percentage score and PDF report.
185
+ </p>
186
+
187
+ <div class="grid md:grid-cols-3 gap-5 mt-3">
188
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
189
+ <div class="flex items-center gap-3 mb-2">
190
+ <div class="w-9 h-9 rounded-full bg-emerald-500/20 flex items-center justify-center">
191
+ <span class="text-lg">📊</span>
192
+ </div>
193
+ <p class="font-semibold text-sm">Clear percentage score</p>
194
+ </div>
195
+ <p class="text-xs text-slate-300">
196
+ See an easy-to-understand plagiarism percentage instead of raw technical metrics.
197
+ </p>
198
+ </div>
199
+
200
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
201
+ <div class="flex items-center gap-3 mb-2">
202
+ <div class="w-9 h-9 rounded-full bg-indigo-500/20 flex items-center justify-center">
203
+ <span class="text-lg">🌐</span>
204
+ </div>
205
+ <p class="font-semibold text-sm">Backend similarity engine</p>
206
+ </div>
207
+ <p class="text-xs text-slate-300">
208
+ The backend uses TF-IDF and set-based similarity to compare your text with a demo corpus.
209
+ </p>
210
+ </div>
211
+
212
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
213
+ <div class="flex items-center gap-3 mb-2">
214
+ <div class="w-9 h-9 rounded-full bg-fuchsia-500/20 flex items-center justify-center">
215
+ <span class="text-lg">📄</span>
216
+ </div>
217
+ <p class="font-semibold text-sm">Instant PDF reports</p>
218
+ </div>
219
+ <p class="text-xs text-slate-300">
220
+ Export a mini plagiarism report so you can attach it with your draft or keep it for records.
221
+ </p>
222
+ </div>
223
+ </div>
224
+ </section>
225
+
226
+ <section class="mt-10 space-y-4">
227
+ <h2 class="text-xl md:text-2xl font-semibold">Who can use this tool?</h2>
228
+ <p class="text-sm text-slate-300">
229
+ Anyone who wants a first originality check before using heavy enterprise tools.
230
+ </p>
231
+
232
+ <div class="grid md:grid-cols-3 gap-5 mt-3">
233
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
234
+ <div class="flex items-center gap-3 mb-2">
235
+ <div class="w-9 h-9 rounded-full bg-sky-500/20 flex items-center justify-center">
236
+ <span class="text-lg">🎓</span>
237
+ </div>
238
+ <p class="font-semibold text-sm">Students & project teams</p>
239
+ </div>
240
+ <p class="text-xs text-slate-300">
241
+ Check reports, abstracts, and essays for overlap with sample academic-style text.
242
+ </p>
243
+ </div>
244
+
245
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
246
+ <div class="flex items-center gap-3 mb-2">
247
+ <div class="w-9 h-9 rounded-full bg-amber-500/20 flex items-center justify-center">
248
+ <span class="text-lg">👩‍🏫</span>
249
+ </div>
250
+ <p class="font-semibold text-sm">Educators</p>
251
+ </div>
252
+ <p class="text-xs text-slate-300">
253
+ Demonstrate the concept of similarity checking in class with a clear, visual UI.
254
+ </p>
255
+ </div>
256
 
257
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
258
+ <div class="flex items-center gap-3 mb-2">
259
+ <div class="w-9 h-9 rounded-full bg-rose-500/20 flex items-center justify-center">
260
+ <span class="text-lg">✍️</span>
261
+ </div>
262
+ <p class="font-semibold text-sm">Bloggers & writers</p>
263
+ </div>
264
+ <p class="text-xs text-slate-300">
265
+ Quickly see if short articles look too similar to built-in reference styles.
266
+ </p>
267
+ </div>
268
+ </div>
269
+ </section>
270
+
271
+ <section class="mt-10 space-y-4">
272
+ <h2 class="text-xl md:text-2xl font-semibold">How does this plagiarism checker work?</h2>
273
+ <p class="text-sm text-slate-300">
274
+ The logic is intentionally simple and transparent so you can follow and later extend it with
275
+ more advanced databases or APIs.
276
+ </p>
277
+
278
+ <div class="grid md:grid-cols-3 gap-5 mt-3">
279
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
280
+ <div class="flex items-center gap-3 mb-2">
281
+ <div class="w-9 h-9 rounded-full bg-emerald-500/20 flex items-center justify-center">
282
+ <span class="text-lg">1️⃣</span>
283
+ </div>
284
+ <p class="font-semibold text-sm">Clean and vectorise</p>
285
+ </div>
286
+ <p class="text-xs text-slate-300">
287
+ Your text is cleaned and transformed into TF-IDF vectors on the server.
288
+ </p>
289
+ </div>
290
+
291
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
292
+ <div class="flex items-center gap-3 mb-2">
293
+ <div class="w-9 h-9 rounded-full bg-indigo-500/20 flex items-center justify-center">
294
+ <span class="text-lg">2️⃣</span>
295
+ </div>
296
+ <p class="font-semibold text-sm">Compare with corpus</p>
297
+ </div>
298
+ <p class="text-xs text-slate-300">
299
+ The backend compares your text with stored documents using cosine and set-based similarity.
300
+ </p>
301
+ </div>
302
+
303
+ <div class="bg-slate-900/70 border border-slate-800 rounded-2xl p-4">
304
+ <div class="flex items-center gap-3 mb-2">
305
+ <div class="w-9 h-9 rounded-full bg-fuchsia-500/20 flex items-center justify-center">
306
+ <span class="text-lg">3️⃣</span>
307
+ </div>
308
+ <p class="font-semibold text-sm">Return a percentage</p>
309
+ </div>
310
+ <p class="text-xs text-slate-300">
311
+ The highest overlap is converted into a simple percentage and returned to this page with top matches.
312
+ </p>
313
+ </div>
314
+ </div>
315
+ </section>
316
+
317
+ <section class="mt-12">
318
+ <h2 class="text-xl md:text-2xl font-semibold mb-3">Top reviews for this plagiarism tool</h2>
319
+ <div class="bg-slate-900/80 border border-slate-800 rounded-2xl p-5 md:p-6 relative overflow-hidden">
320
+ <div id="reviewCard" class="transition-all duration-500"></div>
321
+
322
+ <div class="flex items-center justify-between mt-4">
323
+ <div id="reviewDots" class="flex gap-1.5"></div>
324
+ <div class="flex gap-2">
325
+ <button id="prevReview"
326
+ class="w-8 h-8 rounded-full border border-slate-600 flex items-center justify-center text-xs hover:bg-slate-800">‹</button>
327
+ <button id="nextReview"
328
+ class="w-8 h-8 rounded-full border border-slate-600 flex items-center justify-center text-xs hover:bg-slate-800">›</button>
329
+ </div>
330
+ </div>
331
+ </div>
332
+ </section>
333
  </main>
334
 
335
  <!-- Footer -->
 
349
  window.location.href = "login.html";
350
  }
351
 
352
+ // jsPDF helper
353
  function getJsPDF() {
354
  if (window.jspdf && window.jspdf.jsPDF) return window.jspdf.jsPDF;
355
  if (window.jsPDF) return window.jsPDF;
 
594
  }
595
  });
596
 
597
+ // Download PDF report
598
+ downloadBtn.addEventListener("click", () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
599
  if (!lastResult) {
600
  alert("Run a check first.");
601
  return;
602
  }
603
 
604
+ const jsPDF = getJsPDF();
605
+ if (!jsPDF) return;
606
+
607
+ const doc = new jsPDF({ unit: "pt", format: "a4" });
608
+ let y = 40;
609
+
610
+ doc.setFontSize(16);
611
+ doc.text("TrueWrite Scan — Plagiarism Report", 40, y); y += 22;
612
+
613
+ doc.setFontSize(11);
614
+ doc.text("Generated: " + new Date().toLocaleString(), 40, y); y += 18;
615
+ doc.text("User: " + (user || "N/A"), 40, y); y += 18;
616
+
617
+ const pr = lastResult.result.plagiarism_percent ?? "N/A";
618
+ doc.setFontSize(12);
619
+ doc.text(`Plagiarism: ${pr}%`, 40, y); y += 16;
620
+
621
+ if (lastResult.result.summary) {
622
+ doc.setFontSize(10);
623
+ const summaryLines = doc.splitTextToSize("Summary: " + lastResult.result.summary, 520);
624
+ doc.text(summaryLines, 40, y);
625
+ y += summaryLines.length * 12 + 10;
626
+ }
627
+
628
+ if (lastResult.result.matches && lastResult.result.matches.length) {
629
+ doc.setFontSize(11);
630
+ doc.text("Top matches:", 40, y); y += 14;
631
+ lastResult.result.matches.forEach(m => {
632
+ const line = `• ${m.title} — ${m.score}%`;
633
+ doc.text(line, 48, y);
634
+ y += 12;
635
  });
 
 
 
 
 
636
  }
637
+
638
+ y += 10;
639
+ doc.setFontSize(11);
640
+ doc.text("--- Original text (truncated) ---", 40, y); y += 16;
641
+ doc.setFontSize(9);
642
+ const raw = lastResult.input || "";
643
+ const truncated = raw.length > 3000 ? raw.slice(0, 3000) + "\n\n[TRUNCATED]" : raw;
644
+ const textLines = doc.splitTextToSize(truncated, 520);
645
+ doc.text(textLines, 40, y);
646
+
647
+ doc.save("plagiarism-report.pdf");
648
  });
649
 
650
+ // Reviews slider
651
  const reviews = [
652
+ {
653
+ name: "Aarav S.",
654
+ role: "B.Tech Student",
655
+ text: "Great for a quick originality check before using heavy tools like Turnitin.",
656
+ stars: 5
657
+ },
658
+ {
659
+ name: "Priya K.",
660
+ role: "Research Scholar",
661
+ text: "Helps me understand how similarity scores work in a simple, visible way.",
662
+ stars: 5
663
+ },
664
+ {
665
+ name: "Rahul M.",
666
+ role: "Content Writer",
667
+ text: "Nice to get an approximate plagiarism percentage while drafting blog posts.",
668
+ stars: 4
669
+ },
670
+ {
671
+ name: "Sneha R.",
672
+ role: "M.Sc. Student",
673
+ text: "Perfect educational example to show classmates how plagiarism detection is implemented.",
674
+ stars: 5
675
+ },
676
+ {
677
+ name: "Vikram J.",
678
+ role: "Developer",
679
+ text: "Clean UI and easy to tweak the logic for my own experiments.",
680
+ stars: 4
681
+ }
682
  ];
683
 
 
684
  let currentReview = 0;
685
  const reviewCard = document.getElementById("reviewCard");
686
  const reviewDots = document.getElementById("reviewDots");
687
+
688
+ function starRow(stars) {
689
+ let html = "";
690
+ for (let i = 0; i < 5; i++) {
691
+ html += `<span class="${i < stars ? "text-yellow-400" : "text-slate-600"} text-sm">★</span>`;
692
+ }
693
+ return html;
694
+ }
695
+
696
  function renderReview() {
697
  const r = reviews[currentReview];
698
+ reviewCard.innerHTML = `
699
+ <div class="flex items-center gap-2 mb-2">
700
+ ${starRow(r.stars)}
701
+ </div>
702
+ <p class="text-sm text-slate-200 mb-3">"${r.text}"</p>
703
+ <p class="text-sm font-semibold">${r.name}</p>
704
+ <p class="text-xs text-slate-400">${r.role}</p>
705
+ `;
706
+ reviewDots.innerHTML = reviews.map((_, i) =>
707
+ `<span class="w-2 h-2 rounded-full ${i === currentReview ? "bg-[#0487D9]" : "bg-slate-600"}"></span>`
708
+ ).join("");
709
+ }
710
+
711
+ function nextReview() {
712
+ currentReview = (currentReview + 1) % reviews.length;
713
+ renderReview();
714
+ }
715
+
716
+ function prevReview() {
717
+ currentReview = (currentReview - 1 + reviews.length) % reviews.length;
718
+ renderReview();
719
  }
720
+
721
+ document.getElementById("nextReview").onclick = () => {
722
+ clearInterval(reviewTimer);
723
+ nextReview();
724
+ reviewTimer = setInterval(nextReview, 6000);
725
+ };
726
+ document.getElementById("prevReview").onclick = () => {
727
+ clearInterval(reviewTimer);
728
+ prevReview();
729
+ reviewTimer = setInterval(nextReview, 6000);
730
+ };
731
+
732
  let reviewTimer = setInterval(nextReview, 6000);
733
  renderReview();
734