refactor: 簡化選項詞彙庫資料模型設計
移除不必要的欄位以降低維護成本和實作複雜度: - 移除 FrequencyRating(頻率評級) - 移除 ChineseTranslation(中文翻譯) - 移除 Synonyms(同義詞列表) - 移除 Source(詞彙來源) - 移除 QualityScore(品質評分) 保留核心三參數匹配功能:CEFR等級、詞性、字數 專注於解決測驗選項生成的核心需求 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
396c5be1f0
commit
c277e1b47f
|
|
@ -36,10 +36,10 @@
|
||||||
| REQ-002 | 根據字數(字元長度)匹配類似長度的詞彙 | 高 |
|
| REQ-002 | 根據字數(字元長度)匹配類似長度的詞彙 | 高 |
|
||||||
| REQ-003 | 根據詞性匹配相同詞性的詞彙 | 高 |
|
| REQ-003 | 根據詞性匹配相同詞性的詞彙 | 高 |
|
||||||
| REQ-004 | 每次生成 3 個不同的干擾項 | 高 |
|
| REQ-004 | 每次生成 3 個不同的干擾項 | 高 |
|
||||||
| REQ-005 | 避免選擇同義詞作為干擾項 | 中 |
|
| REQ-005 | 支援多種測驗類型(詞彙選擇、聽力等) | 中 |
|
||||||
| REQ-006 | 避免選擇拼寫過於相似的詞彙 | 中 |
|
| REQ-006 | 提供詞彙庫管理介面 | 低 |
|
||||||
| REQ-007 | 支援多種測驗類型(詞彙選擇、聽力等) | 中 |
|
|
||||||
| REQ-008 | 提供詞彙庫管理介面 | 低 |
|
> **設計簡化說明**:為降低維護成本和實作複雜度,移除了同義詞排除、品質評分、頻率評級等進階功能。專注於三參數匹配的核心功能,確保系統簡潔實用。
|
||||||
|
|
||||||
### 非功能需求
|
### 非功能需求
|
||||||
| 需求ID | 描述 | 指標 |
|
| 需求ID | 描述 | 指標 |
|
||||||
|
|
@ -112,46 +112,16 @@ public class OptionsVocabulary
|
||||||
public string PartOfSpeech { get; set; } = string.Empty;
|
public string PartOfSpeech { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 字數(字元長度)
|
/// 字數(字元長度)- 自動從 Word 計算
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Index("IX_OptionsVocabulary_WordLength")]
|
[Index("IX_OptionsVocabulary_WordLength")]
|
||||||
public int WordLength { get; set; }
|
public int WordLength { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 詞彙使用頻率(1-5,5最高)
|
|
||||||
/// </summary>
|
|
||||||
[Range(1, 5)]
|
|
||||||
public int FrequencyRating { get; set; } = 3;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 中文翻譯(用於避免同義詞)
|
|
||||||
/// </summary>
|
|
||||||
[MaxLength(200)]
|
|
||||||
public string? ChineseTranslation { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 同義詞列表(JSON 格式,用於排除)
|
|
||||||
/// </summary>
|
|
||||||
[MaxLength(500)]
|
|
||||||
public string? Synonyms { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 詞彙來源(dictionary, corpus, manual)
|
|
||||||
/// </summary>
|
|
||||||
[MaxLength(50)]
|
|
||||||
public string? Source { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否啟用
|
/// 是否啟用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsActive { get; set; } = true;
|
public bool IsActive { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 品質評分(用於優先排序)
|
|
||||||
/// </summary>
|
|
||||||
[Range(0, 100)]
|
|
||||||
public int QualityScore { get; set; } = 50;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 創建時間
|
/// 創建時間
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -176,8 +146,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
|
||||||
// 啟用狀態索引
|
// 啟用狀態索引
|
||||||
modelBuilder.Entity<OptionsVocabulary>()
|
modelBuilder.Entity<OptionsVocabulary>()
|
||||||
.HasIndex(e => new { e.IsActive, e.QualityScore })
|
.HasIndex(e => e.IsActive)
|
||||||
.HasDatabaseName("IX_OptionsVocabulary_Active_Quality");
|
.HasDatabaseName("IX_OptionsVocabulary_Active");
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -253,13 +223,9 @@ public class DistractorGenerationService
|
||||||
var maxLength = targetLength + 2;
|
var maxLength = targetLength + 2;
|
||||||
baseQuery = baseQuery.Where(v => v.WordLength >= minLength && v.WordLength <= maxLength);
|
baseQuery = baseQuery.Where(v => v.WordLength >= minLength && v.WordLength <= maxLength);
|
||||||
|
|
||||||
// 5. 排除同義詞(如果有定義)
|
// 5. 隨機排序選取候選詞
|
||||||
// TODO: 實現同義詞排除邏輯
|
|
||||||
|
|
||||||
// 6. 按品質評分和隨機性排序
|
|
||||||
var candidates = await baseQuery
|
var candidates = await baseQuery
|
||||||
.OrderByDescending(v => v.QualityScore)
|
.OrderBy(v => Guid.NewGuid())
|
||||||
.ThenBy(v => Guid.NewGuid())
|
|
||||||
.Take(10) // 取更多候選詞再篩選
|
.Take(10) // 取更多候選詞再篩選
|
||||||
.Select(v => v.Word)
|
.Select(v => v.Word)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
@ -357,10 +323,7 @@ public class OptionsVocabularyController : ControllerBase
|
||||||
Word = request.Word,
|
Word = request.Word,
|
||||||
CEFRLevel = request.CEFRLevel,
|
CEFRLevel = request.CEFRLevel,
|
||||||
PartOfSpeech = request.PartOfSpeech,
|
PartOfSpeech = request.PartOfSpeech,
|
||||||
WordLength = request.Word.Length,
|
WordLength = request.Word.Length
|
||||||
FrequencyRating = request.FrequencyRating,
|
|
||||||
ChineseTranslation = request.ChineseTranslation,
|
|
||||||
Source = "manual"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var success = await _vocabularyService.AddVocabularyAsync(vocabulary);
|
var success = await _vocabularyService.AddVocabularyAsync(vocabulary);
|
||||||
|
|
@ -378,10 +341,7 @@ public class OptionsVocabularyController : ControllerBase
|
||||||
Word = r.Word,
|
Word = r.Word,
|
||||||
CEFRLevel = r.CEFRLevel,
|
CEFRLevel = r.CEFRLevel,
|
||||||
PartOfSpeech = r.PartOfSpeech,
|
PartOfSpeech = r.PartOfSpeech,
|
||||||
WordLength = r.Word.Length,
|
WordLength = r.Word.Length
|
||||||
FrequencyRating = r.FrequencyRating,
|
|
||||||
ChineseTranslation = r.ChineseTranslation,
|
|
||||||
Source = "bulk-import"
|
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var importedCount = await _vocabularyService.BulkImportAsync(vocabularies);
|
var importedCount = await _vocabularyService.BulkImportAsync(vocabularies);
|
||||||
|
|
@ -442,14 +402,6 @@ public class AddVocabularyRequest
|
||||||
[MaxLength(20)]
|
[MaxLength(20)]
|
||||||
public string PartOfSpeech { get; set; } = string.Empty;
|
public string PartOfSpeech { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Range(1, 5)]
|
|
||||||
public int FrequencyRating { get; set; } = 3;
|
|
||||||
|
|
||||||
[MaxLength(200)]
|
|
||||||
public string? ChineseTranslation { get; set; }
|
|
||||||
|
|
||||||
[MaxLength(500)]
|
|
||||||
public string? Synonyms { get; set; }
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -472,12 +424,7 @@ public partial class AddOptionsVocabularyTable : Migration
|
||||||
CEFRLevel = table.Column<string>(maxLength: 2, nullable: false),
|
CEFRLevel = table.Column<string>(maxLength: 2, nullable: false),
|
||||||
PartOfSpeech = table.Column<string>(maxLength: 20, nullable: false),
|
PartOfSpeech = table.Column<string>(maxLength: 20, nullable: false),
|
||||||
WordLength = table.Column<int>(nullable: false),
|
WordLength = table.Column<int>(nullable: false),
|
||||||
FrequencyRating = table.Column<int>(nullable: false, defaultValue: 3),
|
|
||||||
ChineseTranslation = table.Column<string>(maxLength: 200, nullable: true),
|
|
||||||
Synonyms = table.Column<string>(maxLength: 500, nullable: true),
|
|
||||||
Source = table.Column<string>(maxLength: 50, nullable: true),
|
|
||||||
IsActive = table.Column<bool>(nullable: false, defaultValue: true),
|
IsActive = table.Column<bool>(nullable: false, defaultValue: true),
|
||||||
QualityScore = table.Column<int>(nullable: false, defaultValue: 50),
|
|
||||||
CreatedAt = table.Column<DateTime>(nullable: false),
|
CreatedAt = table.Column<DateTime>(nullable: false),
|
||||||
UpdatedAt = table.Column<DateTime>(nullable: false)
|
UpdatedAt = table.Column<DateTime>(nullable: false)
|
||||||
},
|
},
|
||||||
|
|
@ -499,9 +446,9 @@ public partial class AddOptionsVocabularyTable : Migration
|
||||||
columns: new[] { "CEFRLevel", "PartOfSpeech", "WordLength" });
|
columns: new[] { "CEFRLevel", "PartOfSpeech", "WordLength" });
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_OptionsVocabulary_Active_Quality",
|
name: "IX_OptionsVocabulary_Active",
|
||||||
table: "OptionsVocabularies",
|
table: "OptionsVocabularies",
|
||||||
columns: new[] { "IsActive", "QualityScore" });
|
column: "IsActive");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
|
@ -619,19 +566,19 @@ public class VocabularySeeder
|
||||||
var vocabularies = new List<OptionsVocabulary>
|
var vocabularies = new List<OptionsVocabulary>
|
||||||
{
|
{
|
||||||
// A1 Level - 名詞
|
// A1 Level - 名詞
|
||||||
new() { Word = "cat", CEFRLevel = "A1", PartOfSpeech = "noun", WordLength = 3, FrequencyRating = 5, ChineseTranslation = "貓" },
|
new() { Word = "cat", CEFRLevel = "A1", PartOfSpeech = "noun", WordLength = 3 },
|
||||||
new() { Word = "dog", CEFRLevel = "A1", PartOfSpeech = "noun", WordLength = 3, FrequencyRating = 5, ChineseTranslation = "狗" },
|
new() { Word = "dog", CEFRLevel = "A1", PartOfSpeech = "noun", WordLength = 3 },
|
||||||
new() { Word = "book", CEFRLevel = "A1", PartOfSpeech = "noun", WordLength = 4, FrequencyRating = 5, ChineseTranslation = "書" },
|
new() { Word = "book", CEFRLevel = "A1", PartOfSpeech = "noun", WordLength = 4 },
|
||||||
|
|
||||||
// A1 Level - 動詞
|
// A1 Level - 動詞
|
||||||
new() { Word = "eat", CEFRLevel = "A1", PartOfSpeech = "verb", WordLength = 3, FrequencyRating = 5, ChineseTranslation = "吃" },
|
new() { Word = "eat", CEFRLevel = "A1", PartOfSpeech = "verb", WordLength = 3 },
|
||||||
new() { Word = "run", CEFRLevel = "A1", PartOfSpeech = "verb", WordLength = 3, FrequencyRating = 4, ChineseTranslation = "跑" },
|
new() { Word = "run", CEFRLevel = "A1", PartOfSpeech = "verb", WordLength = 3 },
|
||||||
new() { Word = "walk", CEFRLevel = "A1", PartOfSpeech = "verb", WordLength = 4, FrequencyRating = 5, ChineseTranslation = "走" },
|
new() { Word = "walk", CEFRLevel = "A1", PartOfSpeech = "verb", WordLength = 4 },
|
||||||
|
|
||||||
// B1 Level - 形容詞
|
// B1 Level - 形容詞
|
||||||
new() { Word = "beautiful", CEFRLevel = "B1", PartOfSpeech = "adjective", WordLength = 9, FrequencyRating = 4, ChineseTranslation = "美麗的" },
|
new() { Word = "beautiful", CEFRLevel = "B1", PartOfSpeech = "adjective", WordLength = 9 },
|
||||||
new() { Word = "wonderful", CEFRLevel = "B1", PartOfSpeech = "adjective", WordLength = 9, FrequencyRating = 4, ChineseTranslation = "精彩的" },
|
new() { Word = "wonderful", CEFRLevel = "B1", PartOfSpeech = "adjective", WordLength = 9 },
|
||||||
new() { Word = "excellent", CEFRLevel = "B2", PartOfSpeech = "adjective", WordLength = 9, FrequencyRating = 4, ChineseTranslation = "優秀的" },
|
new() { Word = "excellent", CEFRLevel = "B2", PartOfSpeech = "adjective", WordLength = 9 },
|
||||||
|
|
||||||
// ... 更多詞彙
|
// ... 更多詞彙
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue