Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 50 additions & 1 deletion internal/ui/practice_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ func (m *PracticeSession) handleAnswerSubmission() (tea.Model, tea.Cmd) {
originalItem := m.getCurrentRawItem()
expectedInput := m.getExpectedInput(originalItem)

isCorrect := m.isInputCorrect(userInput, expectedInput)
isCorrect := m.isInputCorrectForItem(userInput, originalItem)
m.recordSpacedRepetition(originalItem, isCorrect)

if isCorrect {
Expand Down Expand Up @@ -972,6 +972,55 @@ func (m PracticeSession) getExpectedInput(item string) string {
return item
}

func (m PracticeSession) isInputCorrectForItem(userInput, item string) bool {
acceptedInputs := m.getAcceptedInputs(item)
for _, expected := range acceptedInputs {
if expected == "" {
continue
}
if m.isInputCorrect(userInput, expected) {
return true
}
}
return false
}

func (m PracticeSession) getAcceptedInputs(item string) []string {
expected := strings.TrimSpace(m.getExpectedInput(item))
trimmedItem := strings.TrimSpace(item)
_, translation := practice.ParseLine(item)
translation = strings.TrimSpace(translation)

acceptedSet := make(map[string]struct{})
if expected != "" {
acceptedSet[expected] = struct{}{}
}
if trimmedItem != "" {
acceptedSet[trimmedItem] = struct{}{}
}

if expected != "" && translation != "" {
withSpace := strings.TrimSpace(expected + " " + translation)
if withSpace != "" {
acceptedSet[withSpace] = struct{}{}
}
withArrow := strings.TrimSpace(expected + " ->> " + translation)
if withArrow != "" {
acceptedSet[withArrow] = struct{}{}
}
}

if len(acceptedSet) == 0 && trimmedItem != "" {
return []string{trimmedItem}
}

result := make([]string, 0, len(acceptedSet))
for candidate := range acceptedSet {
result = append(result, candidate)
}
return result
}

// 检查输入是否正确
func (m PracticeSession) isInputCorrect(userInput, expectedInput string) bool {
// 获取匹配模式
Expand Down
77 changes: 73 additions & 4 deletions internal/ui/practice_session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,75 @@ func TestIsInputCorrect(t *testing.T) {
}
}

func TestIsInputCorrectForItem(t *testing.T) {
setupPracticeSessionTest(t)

session := &PracticeSession{}
item := "People often use the phrase '2' in conversation. ->> In everyday conversations, people frequently mention 'a great number of' when they want to emphasize quantity."

config.AppConfig.CorrectnessMatchMode = "exact_match"
exactMatchCases := []struct {
name string
input string
want bool
}{
{
name: "只输入原文",
input: "People often use the phrase '2' in conversation.",
want: true,
},
{
name: "输入原文和翻译",
input: "People often use the phrase '2' in conversation. In everyday conversations, people frequently mention 'a great number of' when they want to emphasize quantity.",
want: true,
},
{
name: "输入带箭头的完整原始行",
input: "People often use the phrase '2' in conversation. ->> In everyday conversations, people frequently mention 'a great number of' when they want to emphasize quantity.",
want: true,
},
{
name: "仅输入翻译",
input: "In everyday conversations, people frequently mention 'a great number of' when they want to emphasize quantity.",
want: false,
},
}

for _, tt := range exactMatchCases {
t.Run(tt.name, func(t *testing.T) {
if got := session.isInputCorrectForItem(tt.input, item); got != tt.want {
t.Errorf("isInputCorrectForItem() = %v, want %v", got, tt.want)
}
})
}

config.AppConfig.CorrectnessMatchMode = "word_match"
wordMatchCases := []struct {
name string
input string
want bool
}{
{
name: "忽略标点仍判定正确",
input: "People often use the phrase 2 in conversation In everyday conversations people frequently mention a great number of when they want to emphasize quantity",
want: true,
},
{
name: "单词错误仍判定错误",
input: "People often use the phrase two in chat. In common talks, folks often mention a great number when they want to emphasize quantity.",
want: false,
},
}

for _, tt := range wordMatchCases {
t.Run(tt.name, func(t *testing.T) {
if got := session.isInputCorrectForItem(tt.input, item); got != tt.want {
t.Errorf("isInputCorrectForItem() = %v, want %v", got, tt.want)
}
})
}
}

// 测试normalizeForWordMatch方法
func TestNormalizeForWordMatch(t *testing.T) {
// 创建测试会话
Expand Down Expand Up @@ -245,9 +314,9 @@ func TestGetCurrentItem(t *testing.T) {

// 创建测试会话
session := &PracticeSession{
resourceType: practice.Words,
items: []string{"apple ->> 苹果", "banana ->> 香蕉", "orange ->> 橙子"},
practiceOrder: []int{0, 1, 2},
resourceType: practice.Words,
items: []string{"apple ->> 苹果", "banana ->> 香蕉", "orange ->> 橙子"},
practiceOrder: []int{0, 1, 2},
completedCount: 0,
}

Expand Down Expand Up @@ -357,4 +426,4 @@ func TestGetCurrentItem(t *testing.T) {
if result != "" {
t.Errorf("超出范围 getCurrentItem() = %v, want empty string", result)
}
}
}
Binary file modified mllt-cli
Binary file not shown.