Skip to content

Commit 103b06d

Browse files
committed
try to fix xerafin import bug
1 parent 190f892 commit 103b06d

File tree

2 files changed

+60
-13
lines changed

2 files changed

+60
-13
lines changed

internal/wordvault/leitner_converter.go

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/json"
77
"errors"
88
"fmt"
9+
"strconv"
910
"time"
1011

1112
"github.com/jackc/pgx/v5/pgtype"
@@ -74,9 +75,9 @@ func LeitnerImport(ctx context.Context, searchServer *searchserver.Server, lexic
7475
correct int
7576
incorrect int
7677
streak int
77-
lastCorrect sql.NullInt32
78+
lastCorrect interface{}
7879
cardbox sql.NullInt32
79-
nextScheduled sql.NullInt32
80+
nextScheduled interface{}
8081
)
8182

8283
if err := rows.Scan(&question, &correct, &incorrect, &streak, &lastCorrect, &cardbox, &nextScheduled); err != nil {
@@ -152,16 +153,54 @@ func LeitnerImport(ctx context.Context, searchServer *searchserver.Server, lexic
152153
return totalInserted, unimportedAlphagrams, nil
153154

154155
}
155-
func convertLeitnerToFsrs(correct, incorrect, streak int, lastCorrect, nextScheduled, cardbox sql.NullInt32,
156+
func convertLeitnerToFsrs(correct, incorrect, streak int, lastCorrect, nextScheduled interface{}, cardbox sql.NullInt32,
156157
now time.Time) (stores.Card, []stores.ReviewLog, pgtype.Timestamptz) {
157158

158-
lc := lastCorrect.Int32
159-
if !lastCorrect.Valid {
160-
lc = 0
159+
// Convert lastCorrect from interface{} to int64
160+
var lc int64
161+
if lastCorrect != nil {
162+
switch v := lastCorrect.(type) {
163+
case int64:
164+
lc = v
165+
case int32:
166+
lc = int64(v)
167+
case float64:
168+
lc = int64(v)
169+
case string:
170+
// Try to parse as float first (handles scientific notation)
171+
if f, err := strconv.ParseFloat(v, 64); err == nil {
172+
lc = int64(f)
173+
} else if i, err := strconv.ParseInt(v, 10, 64); err == nil {
174+
lc = i
175+
}
176+
}
161177
}
162178

163-
nextScheduledTime := time.Unix(int64(nextScheduled.Int32), 0).UTC()
164-
if !nextScheduled.Valid || nextScheduled.Int32 == 0 {
179+
// Convert nextScheduled from interface{} to time
180+
var nextScheduledTime time.Time
181+
if nextScheduled != nil {
182+
var ts int64
183+
switch v := nextScheduled.(type) {
184+
case int64:
185+
ts = v
186+
case int32:
187+
ts = int64(v)
188+
case float64:
189+
ts = int64(v)
190+
case string:
191+
// Try to parse as float first (handles scientific notation)
192+
if f, err := strconv.ParseFloat(v, 64); err == nil {
193+
ts = int64(f)
194+
} else if i, err := strconv.ParseInt(v, 10, 64); err == nil {
195+
ts = i
196+
}
197+
}
198+
if ts > 0 {
199+
nextScheduledTime = time.Unix(ts, 0).UTC()
200+
} else {
201+
nextScheduledTime = now
202+
}
203+
} else {
165204
nextScheduledTime = now
166205
}
167206

@@ -170,7 +209,7 @@ func convertLeitnerToFsrs(correct, incorrect, streak int, lastCorrect, nextSched
170209
cb = -1
171210
}
172211

173-
lastCorrectTime := time.Unix(int64(lc), 0).UTC()
212+
lastCorrectTime := time.Unix(lc, 0).UTC()
174213
reviewLog := []stores.ReviewLog{{
175214
ImportLog: &stores.ImportLog{
176215
ImportedDate: now,

internal/wordvault/leitner_converter_test.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ func TestConvertToFSRS(t *testing.T) {
1515
is := is.New(t)
1616
// Convert a card we've never missed.
1717
now := time.Date(2024, 11, 14, 3, 4, 5, 0, time.UTC)
18-
card, revLog, _ := convertLeitnerToFsrs(21, 0, 21, sql.NullInt32{Int32: 1712380948, Valid: true},
19-
sql.NullInt32{Int32: 1721117219, Valid: true},
18+
card, revLog, _ := convertLeitnerToFsrs(21, 0, 21, int64(1712380948),
19+
int64(1721117219),
2020
sql.NullInt32{Int32: 7, Valid: true},
2121
now)
2222

@@ -38,8 +38,8 @@ func TestConvertToFSRS(t *testing.T) {
3838
// Convert a card that was last correct after it was due. This can happen
3939
// if you quiz on it outside of cardbox.
4040
card, revLog, _ = convertLeitnerToFsrs(2, 2, 1,
41-
sql.NullInt32{Int32: 1730935552, Valid: true},
42-
sql.NullInt32{Int32: 1730330752, Valid: true},
41+
int64(1730935552),
42+
int64(1730330752),
4343
sql.NullInt32{Int32: 1, Valid: true},
4444
now)
4545
// stability should be handwaved to a small number
@@ -49,4 +49,12 @@ func TestConvertToFSRS(t *testing.T) {
4949
newCard = schedulingCards[rating].Card
5050
is.True(!math.IsNaN(newCard.Stability))
5151
fmt.Println("newCard", newCard.Stability, newCard.Due, newCard.Difficulty)
52+
53+
// Test handling of scientific notation string (the bug we're fixing)
54+
card, _, _ = convertLeitnerToFsrs(5, 1, 4,
55+
"1712380948.0",
56+
"1.756833312857143e+09", // This is the problematic value from the issue
57+
sql.NullInt32{Int32: 3, Valid: true},
58+
now)
59+
is.True(card.Stability > 0) // Should parse correctly and not crash
5260
}

0 commit comments

Comments
 (0)