PreQuestionCandidate.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. namespace App\Models;
  3. use Illuminate\Database\Eloquent\Factories\HasFactory;
  4. use Illuminate\Database\Eloquent\Model;
  5. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  6. use App\Models\SourceFile;
  7. use App\Models\SourcePaper;
  8. use App\Models\PaperPart;
  9. class PreQuestionCandidate extends Model
  10. {
  11. use HasFactory;
  12. protected $fillable = [
  13. 'import_id',
  14. 'source_file_id',
  15. 'source_paper_id',
  16. 'part_id',
  17. 'sequence',
  18. 'index',
  19. 'order_index',
  20. 'question_number',
  21. 'order',
  22. 'raw_markdown',
  23. 'raw_text',
  24. 'clean_markdown',
  25. 'structured_json',
  26. 'stem',
  27. 'options',
  28. 'images',
  29. 'tables',
  30. 'is_question_candidate',
  31. 'ai_confidence',
  32. 'confidence',
  33. 'formula_detected',
  34. 'is_valid_question',
  35. 'status',
  36. 'meta',
  37. ];
  38. protected $casts = [
  39. 'is_question_candidate' => 'boolean',
  40. 'ai_confidence' => 'float',
  41. 'confidence' => 'decimal:2',
  42. 'sequence' => 'integer',
  43. 'order' => 'integer',
  44. 'options' => 'array',
  45. 'images' => 'array',
  46. 'tables' => 'array',
  47. 'formula_detected' => 'boolean',
  48. 'is_valid_question' => 'boolean',
  49. 'meta' => 'array',
  50. 'created_at' => 'datetime',
  51. 'updated_at' => 'datetime',
  52. ];
  53. public const STATUS_PENDING = 'pending';
  54. public const STATUS_REVIEWED = 'reviewed';
  55. public const STATUS_ACCEPTED = 'accepted';
  56. public const STATUS_REJECTED = 'rejected';
  57. public const STATUS_SUPERSEDED = 'superseded';
  58. public function import(): BelongsTo
  59. {
  60. return $this->belongsTo(MarkdownImport::class, 'import_id');
  61. }
  62. public function sourceFile(): BelongsTo
  63. {
  64. return $this->belongsTo(SourceFile::class, 'source_file_id');
  65. }
  66. public function sourcePaper(): BelongsTo
  67. {
  68. return $this->belongsTo(SourcePaper::class, 'source_paper_id');
  69. }
  70. public function part(): BelongsTo
  71. {
  72. return $this->belongsTo(PaperPart::class, 'part_id');
  73. }
  74. public function getConfidenceBadgeAttribute(): string
  75. {
  76. if ($this->ai_confidence === null) {
  77. return 'gray';
  78. }
  79. if ($this->ai_confidence >= 0.8) {
  80. return 'success';
  81. } elseif ($this->ai_confidence >= 0.5) {
  82. return 'warning';
  83. }
  84. return 'danger';
  85. }
  86. public function getStatusBadgeAttribute(): string
  87. {
  88. $badges = [
  89. self::STATUS_PENDING => 'gray',
  90. self::STATUS_REVIEWED => 'info',
  91. self::STATUS_ACCEPTED => 'success',
  92. self::STATUS_REJECTED => 'danger',
  93. self::STATUS_SUPERSEDED => 'gray',
  94. ];
  95. return $badges[$this->status] ?? 'gray';
  96. }
  97. public function getFirstImageAttribute(): ?string
  98. {
  99. if (empty($this->images)) {
  100. return null;
  101. }
  102. $images = is_string($this->images) ? json_decode($this->images, true) : $this->images;
  103. return $images[0] ?? null;
  104. }
  105. public function getStemPreviewAttribute(): string
  106. {
  107. if (!$this->stem) {
  108. return 'No stem extracted';
  109. }
  110. return \Str::limit($this->stem, 100);
  111. }
  112. }