From 6a452bcf432d3b9476e14ec354475d3d81bed4c1 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Thu, 12 Oct 2023 14:53:40 +0200 Subject: [PATCH] Search: Add Filters for ISO, FNumber and Focal Length Range #3818 Signed-off-by: Michael Mayer --- internal/form/search_photos.go | 15 ++- internal/form/search_photos_geo.go | 3 + internal/search/photos.go | 15 +++ internal/search/photos_geo.go | 15 +++ pkg/txt/float.go | 96 ++++++++++++++ pkg/txt/float_test.go | 200 +++++++++++++++++++++++++++++ pkg/txt/int.go | 70 ++++++++++ pkg/txt/int_test.go | 160 ++++++++++++++++++++--- pkg/txt/numeric.go | 55 -------- pkg/txt/numeric_test.go | 149 --------------------- 10 files changed, 552 insertions(+), 226 deletions(-) create mode 100644 pkg/txt/float.go create mode 100644 pkg/txt/float_test.go diff --git a/internal/form/search_photos.go b/internal/form/search_photos.go index 128677deb..586db7189 100644 --- a/internal/form/search_photos.go +++ b/internal/form/search_photos.go @@ -78,12 +78,15 @@ type SearchPhotos struct { Review bool `form:"review" notes:"Finds pictures in review"` // Find photos in review Camera string `form:"camera" example:"camera:canon" notes:"Camera Make/Model Name"` // Camera UID or name Lens string `form:"lens" example:"lens:ef24" notes:"Lens Make/Model Name"` // Lens UID or name - Before time.Time `form:"before" time_format:"2006-01-02" notes:"Finds pictures taken before this date"` // Finds images taken before date - After time.Time `form:"after" time_format:"2006-01-02" notes:"Finds pictures taken after this date"` // Finds images taken after date - Count int `form:"count" binding:"required" serialize:"-"` // Result FILE limit - Offset int `form:"offset" serialize:"-"` // Result FILE offset - Order string `form:"order" serialize:"-"` // Sort order - Merged bool `form:"merged" serialize:"-"` // Merge FILES in response + Iso string `form:"iso" example:"iso:200-400" notes:"ISO Range"` + F string `form:"f" example:"f:2.8-4.5" notes:"F-Number Range"` + Mm string `form:"mm" example:"mm:28-35" notes:"Focal Length Range"` + Before time.Time `form:"before" time_format:"2006-01-02" notes:"Finds pictures taken before this date"` // Finds images taken before date + After time.Time `form:"after" time_format:"2006-01-02" notes:"Finds pictures taken after this date"` // Finds images taken after date + Count int `form:"count" binding:"required" serialize:"-"` // Result FILE limit + Offset int `form:"offset" serialize:"-"` // Result FILE offset + Order string `form:"order" serialize:"-"` // Sort order + Merged bool `form:"merged" serialize:"-"` // Merge FILES in response } func (f *SearchPhotos) GetQuery() string { diff --git a/internal/form/search_photos_geo.go b/internal/form/search_photos_geo.go index 21808609f..3df512154 100644 --- a/internal/form/search_photos_geo.go +++ b/internal/form/search_photos_geo.go @@ -67,6 +67,9 @@ type SearchPhotosGeo struct { Color string `form:"color"` Camera int `form:"camera"` Lens int `form:"lens"` + Iso string `form:"iso" example:"iso:200-400" notes:"ISO Range"` + F string `form:"f" example:"f:2.8-4.5" notes:"F-Number Range"` + Mm string `form:"mm" example:"mm:28-35" notes:"Focal Length Range"` Count int `form:"count" serialize:"-"` Offset int `form:"offset" serialize:"-"` } diff --git a/internal/search/photos.go b/internal/search/photos.go index c8f674493..7b9774c36 100644 --- a/internal/search/photos.go +++ b/internal/search/photos.go @@ -494,6 +494,21 @@ func searchPhotos(f form.SearchPhotos, sess *entity.Session, resultCols string) s = s.Where("lenses.lens_name LIKE ? OR lenses.lens_model LIKE ? OR lenses.lens_slug LIKE ?", v, v, v) } + // Filter by ISO Range. + if rangeStart, rangeEnd, rangeErr := txt.IntRange(f.Iso, 0, 10000000); rangeErr == nil { + s = s.Where("photos.photo_iso >= ? AND photos.photo_iso <= ?", rangeStart, rangeEnd) + } + + // Filter by F-Number Range. + if rangeStart, rangeEnd, rangeErr := txt.FloatRange(f.F, 0, 10000000); rangeErr == nil { + s = s.Where("photos.photo_f_number >= ? AND photos.photo_f_number <= ?", rangeStart-0.01, rangeEnd+0.01) + } + + // Filter by Focal Length Range. + if rangeStart, rangeEnd, rangeErr := txt.IntRange(f.Mm, 0, 10000000); rangeErr == nil { + s = s.Where("photos.photo_focal_length >= ? AND photos.photo_focal_length <= ?", rangeStart, rangeEnd) + } + // Filter by year. if f.Year != "" { s = s.Where(AnyInt("photos.photo_year", f.Year, txt.Or, entity.UnknownYear, txt.YearMax)) diff --git a/internal/search/photos_geo.go b/internal/search/photos_geo.go index 3657ac360..477749b1e 100644 --- a/internal/search/photos_geo.go +++ b/internal/search/photos_geo.go @@ -407,6 +407,21 @@ func UserPhotosGeo(f form.SearchPhotosGeo, sess *entity.Session) (results GeoRes s = s.Where("photos.lens_id = ?", f.Lens) } + // Filter by ISO Range. + if rangeStart, rangeEnd, rangeErr := txt.IntRange(f.Iso, 0, 10000000); rangeErr == nil { + s = s.Where("photos.photo_iso >= ? AND photos.photo_iso <= ?", rangeStart, rangeEnd) + } + + // Filter by F-Number Range. + if rangeStart, rangeEnd, rangeErr := txt.FloatRange(f.F, 0, 10000000); rangeErr == nil { + s = s.Where("photos.photo_f_number >= ? AND photos.photo_f_number <= ?", rangeStart-0.01, rangeEnd+0.01) + } + + // Filter by Focal Length Range. + if rangeStart, rangeEnd, rangeErr := txt.IntRange(f.Mm, 0, 10000000); rangeErr == nil { + s = s.Where("photos.photo_focal_length >= ? AND photos.photo_focal_length <= ?", rangeStart, rangeEnd) + } + // Filter by year. if f.Year != "" { s = s.Where(AnyInt("photos.photo_year", f.Year, txt.Or, entity.UnknownYear, txt.YearMax)) diff --git a/pkg/txt/float.go b/pkg/txt/float.go new file mode 100644 index 000000000..5d340df6f --- /dev/null +++ b/pkg/txt/float.go @@ -0,0 +1,96 @@ +package txt + +import ( + "errors" + "strconv" + "strings" +) + +// IsFloat checks if the string represents a floating point number. +func IsFloat(s string) bool { + if s == "" { + return false + } + + s = strings.TrimSpace(s) + + for _, r := range s { + if r != '.' && r != ',' && (r < '0' || r > '9') { + return false + } + } + + return true +} + +// Float converts a string to a 64-bit floating point number or 0 if invalid. +func Float(s string) float64 { + if s == "" { + return 0 + } + + f, err := strconv.ParseFloat(Numeric(s), 64) + + if err != nil { + return 0 + } + + return f +} + +// Float32 converts a string to a 32-bit floating point number or 0 if invalid. +func Float32(s string) float32 { + return float32(Float(s)) +} + +// FloatRange parses a string as floating point number range and returns an error if it's not a valid range. +func FloatRange(s string, min, max float64) (start float64, end float64, err error) { + if s == "" || len(s) > 40 { + return start, end, errors.New("invalid range") + } + + valid := false + + p := 0 + v := [][]byte{make([]byte, 0, 20), make([]byte, 0, 20)} + + for i, r := range s { + if r == 45 { + if i == 0 || p == 1 { + v[p] = append(v[p], byte(r)) + } else if p == 0 { + p = 1 + } + } + if r == 46 || r >= 48 && r <= 57 { + valid = true + v[p] = append(v[p], byte(r)) + } + } + + if !valid { + return start, end, errors.New("invalid range") + } + + if p == 0 { + start = Float(string(v[0])) + end = start + } else { + start = Float(string(v[0])) + end = Float(string(v[1])) + } + + if start > max { + start = max + } else if start < min { + start = min + } + + if end > max { + end = max + } else if end < min { + end = min + } + + return start, end, nil +} diff --git a/pkg/txt/float_test.go b/pkg/txt/float_test.go new file mode 100644 index 000000000..7e5eb7614 --- /dev/null +++ b/pkg/txt/float_test.go @@ -0,0 +1,200 @@ +package txt + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIsFloat(t *testing.T) { + t.Run("Empty", func(t *testing.T) { + assert.False(t, IsFloat("")) + }) + + t.Run("Zero", func(t *testing.T) { + assert.True(t, IsFloat("0")) + }) + + t.Run("0.5", func(t *testing.T) { + assert.True(t, IsFloat("0.5")) + }) + + t.Run("0,5", func(t *testing.T) { + assert.True(t, IsFloat("0,5")) + }) + + t.Run("123000.45245", func(t *testing.T) { + assert.True(t, IsFloat("123000.45245 ")) + }) + + t.Run("123000.", func(t *testing.T) { + assert.True(t, IsFloat("123000. ")) + }) + + t.Run("01:00", func(t *testing.T) { + assert.False(t, IsFloat("01:00")) + }) + + t.Run("LeadingZeros", func(t *testing.T) { + assert.True(t, IsFloat(" 000123")) + }) + + t.Run("Comma", func(t *testing.T) { + assert.True(t, IsFloat(" 123,556\t ")) + }) +} + +func TestFloat(t *testing.T) { + t.Run("Empty", func(t *testing.T) { + result := Float("") + assert.Equal(t, 0.0, result) + }) + + t.Run("NonNumeric", func(t *testing.T) { + result := Float(" Screenshot ") + assert.Equal(t, 0.0, result) + }) + + t.Run("Zero", func(t *testing.T) { + result := Float("0") + assert.Equal(t, 0.0, result) + }) + + t.Run("0.5", func(t *testing.T) { + result := Float("0.5") + assert.Equal(t, 0.5, result) + }) + + t.Run("01:00", func(t *testing.T) { + result := Float("01:00") + assert.Equal(t, 100.0, result) + }) + + t.Run("LeadingZeros", func(t *testing.T) { + result := Float(" 000123") + assert.Equal(t, 123.0, result) + }) + + t.Run("WhitespacePadding", func(t *testing.T) { + result := Float(" 123,556\t ") + assert.Equal(t, 123.556, result) + }) + + t.Run("PositiveFloat", func(t *testing.T) { + result := Float("123,000.45245 ") + assert.Equal(t, 123000.45245, result) + }) + + t.Run("NegativeFloat", func(t *testing.T) { + result := Float(" - 123,000.45245 ") + assert.Equal(t, -123000.45245, result) + }) + + t.Run("MultipleDots", func(t *testing.T) { + result := Float("123.000.45245.44 m") + assert.Equal(t, 1230004524544.0, result) + }) +} + +func TestFloat32(t *testing.T) { + t.Run("Empty", func(t *testing.T) { + result := Float32("") + assert.Equal(t, float32(0), result) + }) + + t.Run("LeadingZeros", func(t *testing.T) { + result := Float32(" 000123") + assert.Equal(t, float32(123), result) + }) + + t.Run("LongFloat", func(t *testing.T) { + result := Float32("123.87945632786543786547") + assert.Equal(t, float32(123.87945632786543786547), result) + }) +} + +func TestFloatRange(t *testing.T) { + t.Run("Empty", func(t *testing.T) { + start, end, err := FloatRange("", 1, 31) + assert.Equal(t, 0.0, start) + assert.Equal(t, 0.0, end) + assert.Error(t, err) + }) + + t.Run("NonNumeric", func(t *testing.T) { + start, end, err := FloatRange("Screenshot", 1, 31) + assert.Equal(t, 0.0, start) + assert.Equal(t, 0.0, end) + assert.Error(t, err) + }) + + t.Run("Day", func(t *testing.T) { + start, end, err := FloatRange("5.11-24.64", 1, 31) + assert.Equal(t, 5.11, start) + assert.Equal(t, 24.64, end) + assert.NoError(t, err) + }) + + t.Run("Zero", func(t *testing.T) { + start, end, err := FloatRange("0", 5, 10) + assert.Equal(t, 5.0, start) + assert.Equal(t, 5.0, end) + assert.NoError(t, err) + }) + + t.Run("LeadingZeros", func(t *testing.T) { + start, end, err := FloatRange("000123", 1, 1000) + assert.Equal(t, 123.0, start) + assert.Equal(t, 123.0, end) + assert.NoError(t, err) + }) + + t.Run("WhitespacePadding", func(t *testing.T) { + start, end, err := FloatRange(" 123\t ", 1, 1000) + assert.Equal(t, 123.0, start) + assert.Equal(t, 123.0, end) + assert.NoError(t, err) + }) + + t.Run("PositiveInt", func(t *testing.T) { + start, end, err := FloatRange("123", 1, 1000) + assert.Equal(t, 123.0, start) + assert.Equal(t, 123.0, end) + assert.NoError(t, err) + }) + + t.Run("NegativeInt", func(t *testing.T) { + start, end, err := FloatRange("-123", -1000, 1000) + assert.Equal(t, -123.0, start) + assert.Equal(t, -123.0, end) + assert.NoError(t, err) + }) + + t.Run("ZeroOne", func(t *testing.T) { + start, end, err := FloatRange("0-1", -10, 10) + assert.Equal(t, 0.0, start) + assert.Equal(t, 1.0, end) + assert.NoError(t, err) + }) + + t.Run("NegativeRange", func(t *testing.T) { + start, end, err := FloatRange("-99.9--50.005", -100, 1000) + assert.Equal(t, -99.9, start) + assert.Equal(t, -50.005, end) + assert.NoError(t, err) + }) + + t.Run("PositiveRange", func(t *testing.T) { + start, end, err := FloatRange("100 - 201", 1, 1000) + assert.Equal(t, 100.0, start) + assert.Equal(t, 201.0, end) + assert.NoError(t, err) + }) + + t.Run("NegativeToPositive", func(t *testing.T) { + start, end, err := FloatRange("-99999-123456563", -1000000, 1000000) + assert.Equal(t, -99999.0, start) + assert.Equal(t, 1000000.0, end) + assert.NoError(t, err) + }) +} diff --git a/pkg/txt/int.go b/pkg/txt/int.go index 296909513..f5642daf0 100644 --- a/pkg/txt/int.go +++ b/pkg/txt/int.go @@ -1,6 +1,7 @@ package txt import ( + "errors" "strconv" "strings" ) @@ -45,6 +46,58 @@ func IntVal(s string, min, max, def int) (i int) { return i } +// IntRange parses a string as integer range and returns an error if it's not a valid range. +func IntRange(s string, min, max int) (start int, end int, err error) { + if s == "" || len(s) > 40 { + return start, end, errors.New("invalid range") + } + + valid := false + + p := 0 + v := [][]byte{make([]byte, 0, 20), make([]byte, 0, 20)} + + for i, r := range s { + if r == 45 { + if i == 0 || p == 1 { + v[p] = append(v[p], byte(r)) + } else if p == 0 { + p = 1 + } + } + if r == 46 || r >= 48 && r <= 57 { + valid = true + v[p] = append(v[p], byte(r)) + } + } + + if !valid { + return start, end, errors.New("invalid range") + } + + if p == 0 { + start = Int(string(v[0])) + end = start + } else { + start = Int(string(v[0])) + end = Int(string(v[1])) + } + + if start > max { + start = max + } else if start < min { + start = min + } + + if end > max { + end = max + } else if end < min { + end = min + } + + return start, end, nil +} + // UInt converts a string to an unsigned integer or 0 if invalid. func UInt(s string) uint { if s == "" { @@ -62,6 +115,23 @@ func UInt(s string) uint { return uint(result) } +// Int64 converts a string to a signed 64-bit integer or 0 if invalid. +func Int64(s string) int64 { + if s == "" { + return 0 + } + + i := strings.SplitN(Numeric(s), ".", 2) + + result, err := strconv.ParseInt(i[0], 10, 64) + + if err != nil { + return 0 + } + + return result +} + // IsUInt tests if a string represents an unsigned integer. func IsUInt(s string) bool { if s == "" { diff --git a/pkg/txt/int_test.go b/pkg/txt/int_test.go index b26f4d3f3..a5bc54d9f 100644 --- a/pkg/txt/int_test.go +++ b/pkg/txt/int_test.go @@ -80,23 +80,90 @@ func TestIntVal(t *testing.T) { }) } -func TestIsUInt(t *testing.T) { - assert.False(t, IsUInt("")) - assert.False(t, IsUInt("12 3")) - assert.True(t, IsUInt("123")) -} +func TestIntRange(t *testing.T) { + t.Run("Empty", func(t *testing.T) { + start, end, err := IntRange("", 1, 31) + assert.Equal(t, 0, start) + assert.Equal(t, 0, end) + assert.Error(t, err) + }) -func TestIsPosInt(t *testing.T) { - assert.False(t, IsPosInt("")) - assert.False(t, IsPosInt("12 3")) - assert.True(t, IsPosInt("123")) - assert.False(t, IsPosInt(" ")) - assert.False(t, IsPosInt("-1")) - assert.False(t, IsPosInt("0")) - assert.False(t, IsPosInt("0.1")) - assert.False(t, IsPosInt("0,1")) - assert.True(t, IsPosInt("1")) - assert.True(t, IsPosInt("99943546356")) + t.Run("NonNumeric", func(t *testing.T) { + start, end, err := IntRange("Screenshot", 1, 31) + assert.Equal(t, 0, start) + assert.Equal(t, 0, end) + assert.Error(t, err) + }) + + t.Run("Day", func(t *testing.T) { + start, end, err := IntRange("5-24", 1, 31) + assert.Equal(t, 5, start) + assert.Equal(t, 24, end) + assert.NoError(t, err) + }) + + t.Run("Zero", func(t *testing.T) { + start, end, err := IntRange("0", 5, 10) + assert.Equal(t, 5, start) + assert.Equal(t, 5, end) + assert.NoError(t, err) + }) + + t.Run("LeadingZeros", func(t *testing.T) { + start, end, err := IntRange("000123", 1, 1000) + assert.Equal(t, 123, start) + assert.Equal(t, 123, end) + assert.NoError(t, err) + }) + + t.Run("WhitespacePadding", func(t *testing.T) { + start, end, err := IntRange(" 123\t ", 1, 1000) + assert.Equal(t, 123, start) + assert.Equal(t, 123, end) + assert.NoError(t, err) + }) + + t.Run("PositiveInt", func(t *testing.T) { + start, end, err := IntRange("123", 1, 1000) + assert.Equal(t, 123, start) + assert.Equal(t, 123, end) + assert.NoError(t, err) + }) + + t.Run("NegativeInt", func(t *testing.T) { + start, end, err := IntRange("-123", -1000, 1000) + assert.Equal(t, -123, start) + assert.Equal(t, -123, end) + assert.NoError(t, err) + }) + + t.Run("ZeroOne", func(t *testing.T) { + start, end, err := IntRange("0-1", -10, 10) + assert.Equal(t, 0, start) + assert.Equal(t, 1, end) + assert.NoError(t, err) + }) + + t.Run("NegativeRange", func(t *testing.T) { + start, end, err := IntRange("-100--50", -100, 1000) + assert.Equal(t, -100, start) + assert.Equal(t, -50, end) + assert.NoError(t, err) + }) + + t.Run("PositiveRange", func(t *testing.T) { + start, end, err := IntRange("100 - 201", 1, 1000) + assert.Equal(t, 100, start) + assert.Equal(t, 201, end) + assert.NoError(t, err) + }) + + t.Run("NegativeToPositive", func(t *testing.T) { + start, end, err := IntRange("-99999-123456563", -1000000, 1000000) + assert.Equal(t, -99999, start) + assert.Equal(t, 1000000, end) + assert.NoError(t, err) + }) } func TestUInt(t *testing.T) { @@ -130,3 +197,64 @@ func TestUInt(t *testing.T) { assert.Equal(t, uint(0), result) }) } + +func TestInt64(t *testing.T) { + t.Run("Empty", func(t *testing.T) { + result := Int64("") + assert.Equal(t, int64(0), result) + }) + + t.Run("NonNumeric", func(t *testing.T) { + result := Int64(" Screenshot ") + assert.Equal(t, int64(0), result) + }) + + t.Run("Zero", func(t *testing.T) { + result := Int64("0") + assert.Equal(t, int64(0), result) + }) + + t.Run("LeadingZeros", func(t *testing.T) { + result := Int64(" 000123") + assert.Equal(t, int64(123), result) + }) + + t.Run("WhitespacePadding", func(t *testing.T) { + result := Int64(" 123,556\t ") + assert.Equal(t, int64(123), result) + }) + + t.Run("PositiveFloat", func(t *testing.T) { + result := Int64("123,000.45245 ") + assert.Equal(t, int64(123000), result) + }) + + t.Run("NegativeFloat", func(t *testing.T) { + result := Int64(" - 123,000.45245 ") + assert.Equal(t, int64(-123000), result) + }) + + t.Run("MultipleDots", func(t *testing.T) { + result := Int64("123.000.45245.44 m") + assert.Equal(t, int64(1230004524544), result) + }) +} + +func TestIsUInt(t *testing.T) { + assert.False(t, IsUInt("")) + assert.False(t, IsUInt("12 3")) + assert.True(t, IsUInt("123")) +} + +func TestIsPosInt(t *testing.T) { + assert.False(t, IsPosInt("")) + assert.False(t, IsPosInt("12 3")) + assert.True(t, IsPosInt("123")) + assert.False(t, IsPosInt(" ")) + assert.False(t, IsPosInt("-1")) + assert.False(t, IsPosInt("0")) + assert.False(t, IsPosInt("0.1")) + assert.False(t, IsPosInt("0,1")) + assert.True(t, IsPosInt("1")) + assert.True(t, IsPosInt("99943546356")) +} diff --git a/pkg/txt/numeric.go b/pkg/txt/numeric.go index c0e832092..348449c3d 100644 --- a/pkg/txt/numeric.go +++ b/pkg/txt/numeric.go @@ -1,7 +1,6 @@ package txt import ( - "strconv" "strings" ) @@ -32,57 +31,3 @@ func Numeric(s string) string { return s } - -// IsFloat checks if the string represents a floating point number. -func IsFloat(s string) bool { - if s == "" { - return false - } - - s = strings.TrimSpace(s) - - for _, r := range s { - if r != '.' && r != ',' && (r < '0' || r > '9') { - return false - } - } - - return true -} - -// Float converts a string to a 64-bit floating point number or 0 if invalid. -func Float(s string) float64 { - if s == "" { - return 0 - } - - f, err := strconv.ParseFloat(Numeric(s), 64) - - if err != nil { - return 0 - } - - return f -} - -// Float32 converts a string to a 32-bit floating point number or 0 if invalid. -func Float32(s string) float32 { - return float32(Float(s)) -} - -// Int64 converts a string to a signed 64-bit integer or 0 if invalid. -func Int64(s string) int64 { - if s == "" { - return 0 - } - - i := strings.SplitN(Numeric(s), ".", 2) - - result, err := strconv.ParseInt(i[0], 10, 64) - - if err != nil { - return 0 - } - - return result -} diff --git a/pkg/txt/numeric_test.go b/pkg/txt/numeric_test.go index fff9746af..f0b66f1e5 100644 --- a/pkg/txt/numeric_test.go +++ b/pkg/txt/numeric_test.go @@ -57,152 +57,3 @@ func TestNumeric(t *testing.T) { assert.Equal(t, "1230004524544", result) }) } - -func TestIsFloat(t *testing.T) { - t.Run("Empty", func(t *testing.T) { - assert.False(t, IsFloat("")) - }) - - t.Run("Zero", func(t *testing.T) { - assert.True(t, IsFloat("0")) - }) - - t.Run("0.5", func(t *testing.T) { - assert.True(t, IsFloat("0.5")) - }) - - t.Run("0,5", func(t *testing.T) { - assert.True(t, IsFloat("0,5")) - }) - - t.Run("123000.45245", func(t *testing.T) { - assert.True(t, IsFloat("123000.45245 ")) - }) - - t.Run("123000.", func(t *testing.T) { - assert.True(t, IsFloat("123000. ")) - }) - - t.Run("01:00", func(t *testing.T) { - assert.False(t, IsFloat("01:00")) - }) - - t.Run("LeadingZeros", func(t *testing.T) { - assert.True(t, IsFloat(" 000123")) - }) - - t.Run("Comma", func(t *testing.T) { - assert.True(t, IsFloat(" 123,556\t ")) - }) -} - -func TestFloat(t *testing.T) { - t.Run("Empty", func(t *testing.T) { - result := Float("") - assert.Equal(t, 0.0, result) - }) - - t.Run("NonNumeric", func(t *testing.T) { - result := Float(" Screenshot ") - assert.Equal(t, 0.0, result) - }) - - t.Run("Zero", func(t *testing.T) { - result := Float("0") - assert.Equal(t, 0.0, result) - }) - - t.Run("0.5", func(t *testing.T) { - result := Float("0.5") - assert.Equal(t, 0.5, result) - }) - - t.Run("01:00", func(t *testing.T) { - result := Float("01:00") - assert.Equal(t, 100.0, result) - }) - - t.Run("LeadingZeros", func(t *testing.T) { - result := Float(" 000123") - assert.Equal(t, 123.0, result) - }) - - t.Run("WhitespacePadding", func(t *testing.T) { - result := Float(" 123,556\t ") - assert.Equal(t, 123.556, result) - }) - - t.Run("PositiveFloat", func(t *testing.T) { - result := Float("123,000.45245 ") - assert.Equal(t, 123000.45245, result) - }) - - t.Run("NegativeFloat", func(t *testing.T) { - result := Float(" - 123,000.45245 ") - assert.Equal(t, -123000.45245, result) - }) - - t.Run("MultipleDots", func(t *testing.T) { - result := Float("123.000.45245.44 m") - assert.Equal(t, 1230004524544.0, result) - }) -} - -func TestFloat32(t *testing.T) { - t.Run("Empty", func(t *testing.T) { - result := Float32("") - assert.Equal(t, float32(0), result) - }) - - t.Run("LeadingZeros", func(t *testing.T) { - result := Float32(" 000123") - assert.Equal(t, float32(123), result) - }) - - t.Run("LongFloat", func(t *testing.T) { - result := Float32("123.87945632786543786547") - assert.Equal(t, float32(123.87945632786543786547), result) - }) -} - -func TestInt64(t *testing.T) { - t.Run("Empty", func(t *testing.T) { - result := Int64("") - assert.Equal(t, int64(0), result) - }) - - t.Run("NonNumeric", func(t *testing.T) { - result := Int64(" Screenshot ") - assert.Equal(t, int64(0), result) - }) - - t.Run("Zero", func(t *testing.T) { - result := Int64("0") - assert.Equal(t, int64(0), result) - }) - - t.Run("LeadingZeros", func(t *testing.T) { - result := Int64(" 000123") - assert.Equal(t, int64(123), result) - }) - - t.Run("WhitespacePadding", func(t *testing.T) { - result := Int64(" 123,556\t ") - assert.Equal(t, int64(123), result) - }) - - t.Run("PositiveFloat", func(t *testing.T) { - result := Int64("123,000.45245 ") - assert.Equal(t, int64(123000), result) - }) - - t.Run("NegativeFloat", func(t *testing.T) { - result := Int64(" - 123,000.45245 ") - assert.Equal(t, int64(-123000), result) - }) - - t.Run("MultipleDots", func(t *testing.T) { - result := Int64("123.000.45245.44 m") - assert.Equal(t, int64(1230004524544), result) - }) -}