Unverified Commit 1ee2a5bb authored by Kevin Lyda's avatar Kevin Lyda
Browse files

Add convert rules.

parent e0bca4bf
Loading
Loading
Loading
Loading
+46 −3
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ package rules

import (
	"errors"
	"fmt"

	"github.com/ichiban/prolog"
)
@@ -14,6 +15,9 @@ type Engine struct {

var (
	prologKinds = `
		unit_kind(f, temperature).
		unit_kind(k, temperature).
		unit_kind(c, temperature).
		unit_kind(m2, area).
		unit_kind(cm2, area).
		unit_kind(cm, distance).
@@ -28,9 +32,22 @@ var (
		unit_kind(butter, density).
		unit_kind(water, density).
`
	prologKindsConvert = `
		convert_kind(mass, volume, density).
		convert_kind(volume, area, distance).
	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).
`
)

@@ -48,6 +65,10 @@ func New() (*Engine, error) {
		return nil, err
	}

	if err := ngn.p.Exec(prologConvert); err != nil {
		return nil, err
	}

	return ngn, nil
}

@@ -74,3 +95,25 @@ func (ngn *Engine) Kind(unit string) (string, error) {
	}
	return result, nil
}

// Convert converts units.
func (ngn *Engine) Convert(qty float64, givenUnit, targetUnit string) (float64, error) {
	sols, err := ngn.p.Query("convert(?, ?, Qty, ?).", qty, givenUnit, targetUnit)
	if err != nil {
		fmt.Println("Huh?")
		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
		}
		return quantity.Qty, err
	}
	return 0, err
}
+29 −0
Original line number Diff line number Diff line
@@ -30,3 +30,32 @@ func TestKinds(t *testing.T) {
		})
	}
}

func TestConverts(t *testing.T) {
	cases := []struct {
		name   string
		qty    float64
		given  string
		target string
		result float64
	}{
		{
			"c to f",
			22.0,
			"c",
			"f",
			71.6,
		},
	}

	ngn, err := New()
	assert.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)

			assert.InDelta(t, tc.result, result, 0.1)
		})
	}
}