diff --git a/rules/rules.go b/rules/rules.go index a66a97f813e0013700c29ee3da86593dad050463..9a9946d32d3c694753b21bfa27ed8b6081739e2d 100644 --- a/rules/rules.go +++ b/rules/rules.go @@ -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). @@ -33,21 +35,44 @@ var ( unit_kind(water, density). ` prologConvert = ` -rule(GivenQuant, f, TargetQuant, c) :- - TargetQuant is (GivenQuant - 32) * 5 / 9. -rule(GivenQuant, c, TargetQuant, f) :- - TargetQuant is (GivenQuant / 5 * 9) + 32. -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). -convert(GivenQuant, GivenUnit, TargetQuant, TargetUnit) :- - unit_kind(GivenUnit, temperature), - unit_kind(TargetUnit, temperature), - rule(GivenQuant, GivenUnit, TargetQuant, TargetUnit). + rule(GivenQuant, f, TargetQuant, c) :- + TargetQuant is (GivenQuant - 32) * 5 / 9. + rule(GivenQuant, c, TargetQuant, f) :- + TargetQuant is (GivenQuant / 5 * 9) + 32. + 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, !. ` ) @@ -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 @@ -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 - } + var quantity struct { + Qty float64 + } + 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 } diff --git a/rules/rules_test.go b/rules/rules_test.go index 2331c51b44ed6cbbaa60620f29a4fa6ed9c8c032..e23f50c20bffa92a94abcbc1915efdb658cd0bbc 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestKinds(t *testing.T) { @@ -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) }) @@ -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) })