Loading rules/rules.go +63 −26 Original line number Diff line number Diff line Loading @@ -20,10 +20,12 @@ var ( unit_kind(c, temperature). unit_kind(m2, area). unit_kind(cm2, area). unit_kind(mm, distance). unit_kind(cm, distance). unit_kind(m, distance). unit_kind(km, distance). unit_kind(feet, distance). unit_kind(mg, mass). unit_kind(g, mass). unit_kind(kg, mass). unit_kind(lb, mass). Loading @@ -41,13 +43,36 @@ rule(GivenQuant, c, TargetQuant, k) :- TargetQuant is GivenQuant + 273.15. rule(GivenQuant, k, TargetQuant, c) :- TargetQuant is GivenQuant - 273.15. rule(GivenQuant, GivenUnit, TargetQuant, TargetUnit) :- rule(GivenQuant, GivenUnit, X, Y), rule(X, Y, TargetQuant, TargetUnit). ratio(m, km, 0.001). ratio(m, cm, 100). ratio(m, mm, 1000). ratio(feet, m, 0.3048). ratio(feet, inches, 12). ratio(g, mg, 1000). ratio(g, kg, 0.001). ratio(X, Y, Ratio) :- ratio(Y, X, Z), Ratio is 1/Z, !. ratio(X, Y, Ratio) :- ratio(Y, Step, R1), ratio(Step, Z, R2), Step =\= Y, Step =\= Z, Ratio is R1 * R2, !. convert(GivenQuant, GivenUnit, TargetQuant, TargetUnit) :- unit_kind(GivenUnit, temperature), unit_kind(TargetUnit, temperature), rule(GivenQuant, GivenUnit, TargetQuant, TargetUnit). convert(GivenQuant, GivenUnit, TargetQuant, TargetUnit) :- write("foo"), nl, ratio(GivenUnit, TargetUnit, Ratio), TargetQuant is GivenQuant * Ratio, !. ` ) Loading @@ -60,6 +85,9 @@ func New() (*Engine, error) { if err := ngn.p.Exec(`:- set_prolog_flag(double_quotes, atom).`); err != nil { return nil, err } if err := ngn.p.Exec(`:- set_prolog_flag(debug, on).`); err != nil { return nil, err } if err := ngn.p.Exec(prologKinds); err != nil { return nil, err Loading Loading @@ -98,22 +126,31 @@ func (ngn *Engine) Kind(unit string) (string, error) { // Convert converts units. func (ngn *Engine) Convert(qty float64, givenUnit, targetUnit string) (float64, error) { sols, err := ngn.p.Query("convert(?, ?, Qty, ?).", qty, givenUnit, targetUnit) sol := ngn.p.QuerySolution("convert(?, ?, Qty, ?).", qty, givenUnit, targetUnit) if sol == nil { fmt.Println("sol == nil") return 0, errors.New("Query failed") } err := sol.Err() if err != nil { fmt.Println("Huh?") fmt.Println("sol.Err()") return 0, err } defer sols.Close() for sols.Next() { var quantity struct { Qty float64 } if err := sols.Scan(&quantity); err != nil { fmt.Println("Scan?") return 0, err } err = sol.Scan(&quantity) if err == nil { fmt.Println("got qty") return quantity.Qty, err } fmt.Println("qty scan failed") var dbg []byte if err := sol.Scan(&dbg); err != nil { fmt.Println("on dbg scan") return 0, err } fmt.Printf("dbg: '%s'\n", dbg) return 0, err } rules/rules_test.go +15 −13 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestKinds(t *testing.T) { Loading @@ -20,11 +21,11 @@ func TestKinds(t *testing.T) { } ngn, err := New() assert.NoError(t, err) require.NoError(t, err) for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { result, err := ngn.Kind(tc.query) assert.NoError(t, err) require.NoError(t, err) assert.Equal(t, tc.result, result) }) Loading @@ -36,31 +37,32 @@ func TestConverts(t *testing.T) { name string qty float64 given string target string result float64 target string }{ { "c to f", 22.0, "c", "f", 71.6, 22.0, "c", 71.6, "f", }, { "k to f", 22.0, "k", "f", -420.07, 22.0, "k", -420.07, "f", }, { "inches to cm", 2.0, "inches", 5.08, "cm", }, } ngn, err := New() assert.NoError(t, err) require.NoError(t, err) for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { result, err := ngn.Convert(tc.qty, tc.given, tc.target) assert.NoError(t, err) require.NoError(t, err) assert.InDelta(t, tc.result, result, 0.1) }) Loading Loading
rules/rules.go +63 −26 Original line number Diff line number Diff line Loading @@ -20,10 +20,12 @@ var ( unit_kind(c, temperature). unit_kind(m2, area). unit_kind(cm2, area). unit_kind(mm, distance). unit_kind(cm, distance). unit_kind(m, distance). unit_kind(km, distance). unit_kind(feet, distance). unit_kind(mg, mass). unit_kind(g, mass). unit_kind(kg, mass). unit_kind(lb, mass). Loading @@ -41,13 +43,36 @@ rule(GivenQuant, c, TargetQuant, k) :- TargetQuant is GivenQuant + 273.15. rule(GivenQuant, k, TargetQuant, c) :- TargetQuant is GivenQuant - 273.15. rule(GivenQuant, GivenUnit, TargetQuant, TargetUnit) :- rule(GivenQuant, GivenUnit, X, Y), rule(X, Y, TargetQuant, TargetUnit). ratio(m, km, 0.001). ratio(m, cm, 100). ratio(m, mm, 1000). ratio(feet, m, 0.3048). ratio(feet, inches, 12). ratio(g, mg, 1000). ratio(g, kg, 0.001). ratio(X, Y, Ratio) :- ratio(Y, X, Z), Ratio is 1/Z, !. ratio(X, Y, Ratio) :- ratio(Y, Step, R1), ratio(Step, Z, R2), Step =\= Y, Step =\= Z, Ratio is R1 * R2, !. convert(GivenQuant, GivenUnit, TargetQuant, TargetUnit) :- unit_kind(GivenUnit, temperature), unit_kind(TargetUnit, temperature), rule(GivenQuant, GivenUnit, TargetQuant, TargetUnit). convert(GivenQuant, GivenUnit, TargetQuant, TargetUnit) :- write("foo"), nl, ratio(GivenUnit, TargetUnit, Ratio), TargetQuant is GivenQuant * Ratio, !. ` ) Loading @@ -60,6 +85,9 @@ func New() (*Engine, error) { if err := ngn.p.Exec(`:- set_prolog_flag(double_quotes, atom).`); err != nil { return nil, err } if err := ngn.p.Exec(`:- set_prolog_flag(debug, on).`); err != nil { return nil, err } if err := ngn.p.Exec(prologKinds); err != nil { return nil, err Loading Loading @@ -98,22 +126,31 @@ func (ngn *Engine) Kind(unit string) (string, error) { // Convert converts units. func (ngn *Engine) Convert(qty float64, givenUnit, targetUnit string) (float64, error) { sols, err := ngn.p.Query("convert(?, ?, Qty, ?).", qty, givenUnit, targetUnit) sol := ngn.p.QuerySolution("convert(?, ?, Qty, ?).", qty, givenUnit, targetUnit) if sol == nil { fmt.Println("sol == nil") return 0, errors.New("Query failed") } err := sol.Err() if err != nil { fmt.Println("Huh?") fmt.Println("sol.Err()") return 0, err } defer sols.Close() for sols.Next() { var quantity struct { Qty float64 } if err := sols.Scan(&quantity); err != nil { fmt.Println("Scan?") return 0, err } err = sol.Scan(&quantity) if err == nil { fmt.Println("got qty") return quantity.Qty, err } fmt.Println("qty scan failed") var dbg []byte if err := sol.Scan(&dbg); err != nil { fmt.Println("on dbg scan") return 0, err } fmt.Printf("dbg: '%s'\n", dbg) return 0, err }
rules/rules_test.go +15 −13 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestKinds(t *testing.T) { Loading @@ -20,11 +21,11 @@ func TestKinds(t *testing.T) { } ngn, err := New() assert.NoError(t, err) require.NoError(t, err) for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { result, err := ngn.Kind(tc.query) assert.NoError(t, err) require.NoError(t, err) assert.Equal(t, tc.result, result) }) Loading @@ -36,31 +37,32 @@ func TestConverts(t *testing.T) { name string qty float64 given string target string result float64 target string }{ { "c to f", 22.0, "c", "f", 71.6, 22.0, "c", 71.6, "f", }, { "k to f", 22.0, "k", "f", -420.07, 22.0, "k", -420.07, "f", }, { "inches to cm", 2.0, "inches", 5.08, "cm", }, } ngn, err := New() assert.NoError(t, err) require.NoError(t, err) for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { result, err := ngn.Convert(tc.qty, tc.given, tc.target) assert.NoError(t, err) require.NoError(t, err) assert.InDelta(t, tc.result, result, 0.1) }) Loading