File size: 4,749 Bytes
a561338 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime
# ---- Shared ----
class DocumentInfo(BaseModel):
id: int
name: str
author: Optional[str] = None
class OverlapDetail(BaseModel):
# For lexical/internal
fromDoc: str
toDoc: str
text: str
similarity: float # percent (0β100)
sectionA: Optional[str] = None
sectionB: Optional[str] = None
context: Optional[str] = None
class ComparisonDetail(BaseModel):
id: str # "i-j"
docA: str
docB: str
similarity: float # percent (0β100)
flagged: bool
overlaps: List[OverlapDetail] = Field(default_factory=list)
contentA: str = ""
contentB: str = ""
class InternalReportSummary(BaseModel):
totalDocuments: int
totalComparisons: int
flaggedComparisons: int
highestSimilarity: float
averageSimilarity: Optional[float] = None
class InternalReportDetail(BaseModel):
id: str
name: str
analysisType: str = "internal"
uploadDate: datetime
processingTime: str
status: str = "completed"
documents: List[DocumentInfo]
comparisons: List[ComparisonDetail]
summary: InternalReportSummary
class LexicalMatch(BaseModel):
matched_text: str
similarity: float
source_type: str
source_title: str
source_url: str
section: Optional[str] = None
context: Optional[str] = None
class LexicalDocResult(BaseModel):
id: int
name: str
author: Optional[str] = None
similarity: float # overall percent
flagged: bool
wordCount: Optional[int] = None
matches: List[LexicalMatch] = Field(default_factory=list)
content: Optional[str] = None
ai_similarity: float = 0.0
class TeacherLexicalSummary(BaseModel):
totalDocuments: int
flaggedDocuments: int
highestSimilarity: float
averageSimilarity: Optional[float] = None
totalMatches: int
averageAiSimilarity: float = 0.0
class TeacherLexicalBatchReport(BaseModel):
id: str
name: str
analysisType: str = "lexical"
uploadDate: datetime
processingTime: str
status: str = "completed"
documents: List[LexicalDocResult]
summary: TeacherLexicalSummary
# ---- Teacher Semantic (internal/external) ----
class SemanticOverlap(BaseModel):
textA: str
textB: str
cosine: float # 0β1
cosine_pct: float # 0β100
sectionA: Optional[str] = None
sectionB: Optional[str] = None
confidence: str # "high" | "medium" | "low"
class SemanticComparison(BaseModel):
id: str
docA: str
docB: str
similarity: float # aggregated cosine percent
flagged: bool
overlaps: List[SemanticOverlap] = Field(default_factory=list)
class TeacherSemanticReport(BaseModel):
id: str
name: str
analysisType: str = "semantic"
mode: str # "internal" | "external"
uploadDate: datetime
processingTime: str
status: str = "completed"
documents: List[DocumentInfo]
comparisons: List[SemanticComparison]
summary: InternalReportSummary
narrative: Optional[str] = None
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime
class CodeMatch(BaseModel):
matched_code: str
similarity: float
source_type: str # 'peer', 'github', 'stackoverflow', 'web'
source_title: str
source_url: Optional[str] = None
match_type: str # 'exact', 'structural', 'token_sequence'
line_start: Optional[int] = None
line_end: Optional[int] = None
context: Optional[str] = None
class CodeFunction(BaseModel):
name: str
start_line: int
end_line: int
code: str
complexity: int # Cyclomatic complexity
tokens: List[str]
ast_hash: str
class CodeDocResult(BaseModel):
id: int
name: str
author: Optional[str] = None
similarity: float
flagged: bool
lineCount: int
functionCount: int
matches: List[CodeMatch]
functions: List[CodeFunction]
content: str # Full code content
language: str
class CodeAnalysisSummary(BaseModel):
totalDocuments: int
flaggedDocuments: int
highestSimilarity: float
averageSimilarity: float
totalMatches: int
peerMatches: int
externalMatches: int
class TeacherCodeBatchReport(BaseModel):
id: str
name: str
uploadDate: datetime
processingTime: str
documents: List[CodeDocResult]
summary: CodeAnalysisSummary
assignmentTopic: Optional[str] = None
class InternalMatch(BaseModel):
"""Match between two student submissions"""
student1_id: int
student2_id: int
student1_name: str
student2_name: str
similarity: float
match_type: str
matched_functions: List[str]
|