From 3aaae870ba76d8f0907b10a61d829ad353936306 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 20 Jan 2024 17:56:39 -0500 Subject: flatten source directory structure by removing modules --- compressor.go | 93 ++++++++++++++++++++++++++++++++++ compressor/compressor.go | 100 ------------------------------------ main.go | 64 ++++++++++------------- mass.go | 28 ++++++++++ mass/mass.go | 47 ----------------- pressure.go | 40 +++++++++++++++ pressure/pressure.go | 48 ------------------ temperature.go | 60 ++++++++++++++++++++++ temperature/temperature.go | 71 -------------------------- ui.go | 124 +++++++++++++++++++++------------------------ util.go | 21 ++++++++ util/util.go | 31 ------------ volume.go | 33 ++++++++++++ volume/volume.go | 44 ---------------- 14 files changed, 360 insertions(+), 444 deletions(-) create mode 100644 compressor.go delete mode 100644 compressor/compressor.go create mode 100644 mass.go delete mode 100644 mass/mass.go create mode 100644 pressure.go delete mode 100644 pressure/pressure.go create mode 100644 temperature.go delete mode 100644 temperature/temperature.go create mode 100644 util.go delete mode 100644 util/util.go create mode 100644 volume.go delete mode 100644 volume/volume.go diff --git a/compressor.go b/compressor.go new file mode 100644 index 0000000..a3a16db --- /dev/null +++ b/compressor.go @@ -0,0 +1,93 @@ +package main + +import ( + "github.com/BurntSushi/toml" + "io/fs" + fp "path/filepath" + "strings" +) + +const root = "compressor_maps/" + +type Compressor struct { + Name string + FileName string + // MinX is the distance of the y-axis from left of image in pixels. + MinX int + // MinY is the distance of the x-axis from the top of the image in + //pixels. + MinY int + // MaxX is the distance of the end of the graph from the left of the + // image in pixels. + MaxX int + // MaxY is the distance of the top of the graph from the top of the + // image in pixels. + MaxY int + // MaxFlow is the mass flow rate at MaxX. + MaxFlow MassFlowRate + // MaxPR is the pressure ratio at MaxY. + MaxPR float32 +} + +// [manufacturer][series][model] +var Compressors = make(map[string]map[string]map[string]Compressor) + +func init() { + // Walk root, looking for .toml files describing a compressor. + // Parse these toml files, create a Compressor and add it to Compressors. + err := fp.WalkDir(root, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if fp.Ext(path) != ".toml" { + return nil + } + + path = path[len(root):] + + // manufacturer/series, model + manSer, mod := fp.Split(path) + manSer = fp.Clean(manSer) // Clean trailing slash + mod = mod[:len(mod)-len(".toml")] // Trim .toml extension + // manufacturer, series + man, ser := fp.Split(manSer) + man = fp.Clean(man) // Clean trailing slash + + if _, ok := Compressors[man]; !ok { // Manufacturer does NOT exist + Compressors[man] = make(map[string]map[string]Compressor) + } + if _, ok := Compressors[man][ser]; !ok { // Series does NOT exist + Compressors[man][ser] = make(map[string]Compressor) + } + + tomlFile := fp.Join(root, path) + var c Compressor + if _, err = toml.DecodeFile(tomlFile, &c); err != nil { + return err + } + c.FileName = strings.TrimSuffix(tomlFile, ".toml") + ".jpg" + c.MaxFlow, err = readMaxFlow(tomlFile) + if err != nil { + return err + } + Compressors[man][ser][mod] = c + return nil + }) + Check(err) +} + +func readMaxFlow(tomlFile string) (MassFlowRate, error) { + flow := struct { + FlowVal float32 + FlowUnit string + }{} + if _, err := toml.DecodeFile(tomlFile, &flow); err != nil { + return -1, err + } + unit, err := ParseMassFlowRateUnit(flow.FlowUnit) + if err != nil { + return -1, err + } + return MassFlowRate(flow.FlowVal) * unit, nil +} diff --git a/compressor/compressor.go b/compressor/compressor.go deleted file mode 100644 index 9983ecb..0000000 --- a/compressor/compressor.go +++ /dev/null @@ -1,100 +0,0 @@ -package compressor - -import ( - "github.com/BurntSushi/toml" - "io/fs" - fp "path/filepath" - "strings" - - "volute/mass" - "volute/util" -) - -const root = "compressor_maps/" - -type Compressor struct { - Name string - FileName string - // MinX is the distance of the y-axis from left of image in pixels. - MinX int - // MinY is the distance of the x-axis from the top of the image in - //pixels. - MinY int - // MaxX is the distance of the end of the graph from the left of the - // image in pixels. - MaxX int - // MaxY is the distance of the top of the graph from the top of the - // image in pixels. - MaxY int - // MaxFlow is the mass flow rate at MaxX. - MaxFlow mass.FlowRate - // MaxPR is the pressure ratio at MaxY. - MaxPR float32 -} - -// [manufacturer][series][model] -var compressors = make(map[string]map[string]map[string]Compressor) - -func init() { - // Walk root, looking for .toml files describing a compressor. - // Parse these toml files, create a Compressor and add it to compressors. - err := fp.WalkDir(root, func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - - if fp.Ext(path) != ".toml" { - return nil - } - - path = path[len(root):] - - // manufacturer/series, model - manSer, mod := fp.Split(path) - manSer = fp.Clean(manSer) // Clean trailing slash - mod = mod[:len(mod)-len(".toml")] // Trim .toml extension - // manufacturer, series - man, ser := fp.Split(manSer) - man = fp.Clean(man) // Clean trailing slash - - if _, ok := compressors[man]; !ok { // Manufacturer does NOT exist - compressors[man] = make(map[string]map[string]Compressor) - } - if _, ok := compressors[man][ser]; !ok { // Series does NOT exist - compressors[man][ser] = make(map[string]Compressor) - } - - tomlFile := fp.Join(root, path) - var c Compressor - if _, err = toml.DecodeFile(tomlFile, &c); err != nil { - return err - } - c.FileName = strings.TrimSuffix(tomlFile, ".toml") + ".jpg" - c.MaxFlow, err = readMaxFlow(tomlFile) - if err != nil { - return err - } - compressors[man][ser][mod] = c - return nil - }) - util.Check(err) -} - -func Compressors() map[string]map[string]map[string]Compressor { - return compressors -} - -func readMaxFlow(tomlFile string) (mass.FlowRate, error) { - flow := struct { - FlowVal float32 - FlowUnit string - }{} - if _, err := toml.DecodeFile(tomlFile, &flow); err != nil { - return -1, err - } - unit, err := mass.FlowRateUnitFromString(flow.FlowUnit) - if err != nil { - return -1, err - } - return mass.FlowRate(flow.FlowVal) * unit, nil -} diff --git a/main.go b/main.go index 491aa80..39483b2 100644 --- a/main.go +++ b/main.go @@ -7,13 +7,6 @@ import ( "image/draw" _ "image/jpeg" "os" - - "volute/compressor" - "volute/mass" - "volute/pressure" - "volute/temperature" - "volute/util" - "volute/volume" ) const ( @@ -21,33 +14,31 @@ const ( airMolarMass = 0.0289647 // kg/mol ) -// numPoints is the number of datapoints on the compressor map. +// Number of data points on the compressor map. var numPoints = 1 var ( - displacement = 2000 * volume.CubicCentimetre - // volumeUnitIndex is used to index volume.UnitStrings(). - volumeUnitIndex = volume.DefaultUnitIndex + displacement = 2000 * CubicCentimetre + volumeUnitIndex int32 - engineSpeed = []int32{2000} + // Angular crankshaft speed in RPM. + speed = []int32{2000} volumetricEfficiency = []int32{80} - intakeAirTemperature = []temperature.Temperature{{25, temperature.Celcius}} - // temperatureUnitIndex is used to index temperature.UnitStrings(). - temperatureUnitIndex = temperature.DefaultUnitIndex + intakeAirTemperature = []Temperature{{25, Celcius}} + temperatureUnitIndex int32 - manifoldPressure = []pressure.Pressure{pressure.Atmospheric()} - // pressureUnitIndex is used to index pressure.UnitStrings(). - pressureUnitIndex = pressure.DefaultUnitIndex + manifoldPressure = []Pressure{AtmosphericPressure()} + pressureUnitIndex int32 ) var pressureRatio []float32 func pressureRatioAt(point int) float32 { - u := pressure.Pascal + u := Pascal m := manifoldPressure[point] / u - a := pressure.Atmospheric() / u + a := AtmosphericPressure() / u return float32(m / a) } func init() { @@ -55,42 +46,41 @@ func init() { } var ( - engineMassFlowRate []mass.FlowRate - // selectedMassFlowRateUnit is used to index mass.FlowRateUnitStrings(). - selectedMassFlowRateUnit = mass.DefaultFlowRateUnitIndex + massFlowRateAir []MassFlowRate + massFlowRateUnitIndex int32 ) -func massFlowRateAt(point int) mass.FlowRate { - rpm := float32(engineSpeed[point]) - disp := float32(displacement / volume.CubicMetre) +func massFlowRateAt(point int) MassFlowRate { + rpm := float32(speed[point]) + disp := float32(displacement / CubicMetre) ve := float32(volumetricEfficiency[point]) / 100.0 cubicMetresPerMin := (rpm / 2.0) * disp * ve - iat, err := intakeAirTemperature[point].AsUnit(temperature.Kelvin) - util.Check(err) - pres := manifoldPressure[point] / pressure.Pascal + iat, err := intakeAirTemperature[point].AsUnit(Kelvin) + Check(err) + pres := manifoldPressure[point] / Pascal molsPerMin := (float32(pres) * cubicMetresPerMin) / (gasConstant * iat) kgPerMin := molsPerMin * airMolarMass - mfr := mass.FlowRate(kgPerMin/60.0) * mass.KilogramsPerSecond + mfr := MassFlowRate(kgPerMin/60.0) * KilogramsPerSecond return mfr } func init() { - engineMassFlowRate = append(engineMassFlowRate, massFlowRateAt(0)) + massFlowRateAir = append(massFlowRateAir, massFlowRateAt(0)) } var ( compressorImage *image.RGBA compressorTexture *g.Texture - selectedCompressor compressor.Compressor + selectedCompressor Compressor ) func init() { manufacturer := "garrett" series := "g" model := "25-660" - c, ok := compressor.Compressors()[manufacturer][series][model] + c, ok := Compressors[manufacturer][series][model] if !ok { fmt.Printf("compressor.Compressors()[\"%s\"][\"%s\"][\"%s\"] does not exist.\n", manufacturer, series, model, @@ -113,13 +103,13 @@ func main() { wnd.Run(loop) } -func setCompressor(c compressor.Compressor) { +func setCompressor(c Compressor) { f, err := os.Open(c.FileName) - util.Check(err) + Check(err) defer f.Close() j, _, err := image.Decode(f) - util.Check(err) + Check(err) b := j.Bounds() m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy())) @@ -137,7 +127,7 @@ func loop() { g.Table(). Size(g.Auto, 190). Rows( - engineSpeedRow(), + speedRow(), volumetricEfficiencyRow(), intakeAirTemperatureRow(), manifoldPressureRow(), diff --git a/mass.go b/mass.go new file mode 100644 index 0000000..158bc37 --- /dev/null +++ b/mass.go @@ -0,0 +1,28 @@ +package main + +import ( + "errors" + "fmt" +) + +type MassFlowRate float32 + +const ( + KilogramsPerSecond MassFlowRate = 1 + PoundsPerMinute MassFlowRate = 0.007_559_872_833 +) + +var MassFlowRateUnits = []string{"kg/s", "lb/min"} + +func ParseMassFlowRateUnit(s string) (MassFlowRate, error) { + // Each case corresponds to a value in MassFlowRateUnits. + switch s { + case "kg/s": + return KilogramsPerSecond, nil + case "lb/min": + return PoundsPerMinute, nil + default: + return *new(MassFlowRate), errors.New( + fmt.Sprintf("invalid mass flow rate unit: '%s'", s)) + } +} diff --git a/mass/mass.go b/mass/mass.go deleted file mode 100644 index 46ce33e..0000000 --- a/mass/mass.go +++ /dev/null @@ -1,47 +0,0 @@ -package mass - -import ( - "errors" - "fmt" -) - -type Mass float32 - -const ( - Gram Mass = 1 - Kilogram Mass = 1_000 - Pound Mass = 453.5924 -) - -type FlowRate float32 - -const ( - KilogramsPerSecond FlowRate = 1 - PoundsPerMinute FlowRate = 0.007_559_872_833 -) - -// FlowRateUnitStrings returns a slice of strings, each representing a -// flowRate unit. -// This is necessary because giu.Combo only works with strings. -func FlowRateUnitStrings() []string { - return []string{"kg/s", "lb/min"} -} - -const ( - DefaultFlowRateUnit FlowRate = KilogramsPerSecond - // DefaultFlowRateUnitIndex is used to index FlowRateUnitStrings() - DefaultFlowRateUnitIndex int32 = 0 // kg/s -) - -func FlowRateUnitFromString(s string) (FlowRate, error) { - // Each case corresponds to a value in FlowRateUnitStrings(). - switch s { - case "kg/s": - return KilogramsPerSecond, nil - case "lb/min": - return PoundsPerMinute, nil - default: - return *new(FlowRate), errors.New( - fmt.Sprintf("invalid mass flow rate unit: '%s'", s)) - } -} diff --git a/pressure.go b/pressure.go new file mode 100644 index 0000000..cd824c5 --- /dev/null +++ b/pressure.go @@ -0,0 +1,40 @@ +package main + +import ( + "errors" + "fmt" +) + +type Pressure float32 + +const ( + Millibar Pressure = 100 + Pascal Pressure = 1 + Kilopascal Pressure = 1_000 + Bar Pressure = 100_000 + PoundsPerSquareInch Pressure = 6_894.757 +) + +var PressureUnits = []string{"mbar", "Pa", "kPa", "bar", "psi"} + +func ParsePressureUnit(s string) (Pressure, error) { + // Each case corresponds to a value in PressureUnits. + switch s { + case "mbar": + return Millibar, nil + case "Pa": + return Pascal, nil + case "kPa": + return Kilopascal, nil + case "bar": + return Bar, nil + case "psi": + return PoundsPerSquareInch, nil + default: + return *new(Pressure), errors.New(fmt.Sprintf("invalid unit: '%s'", s)) + } +} + +func AtmosphericPressure() Pressure { + return 101.325 * Pascal +} diff --git a/pressure/pressure.go b/pressure/pressure.go deleted file mode 100644 index da1ab1e..0000000 --- a/pressure/pressure.go +++ /dev/null @@ -1,48 +0,0 @@ -package pressure - -import ( - "errors" - "fmt" -) - -type Pressure float32 - -const ( - Pascal Pressure = 1 - Kilopascal Pressure = 1_000 - Bar Pressure = 100_000 - PoundsPerSquareInch Pressure = 6_894.757 -) - -// UnitStrings returns a slice of strings, each representing a -// unit. -// This is necessary because giu.Combo only works with strings. -func UnitStrings() []string { - return []string{"Pa", "kPa", "bar", "psi"} -} - -const ( - DefaultUnit Pressure = Kilopascal - // DefaultUnitIndex is used to index UnitStrings(). - DefaultUnitIndex int32 = 1 // kPa -) - -func UnitFromString(s string) (Pressure, error) { - // Each case corresponds to a value in UnitStrings(). - switch s { - case "Pa": - return Pascal, nil - case "kPa": - return Kilopascal, nil - case "bar": - return Bar, nil - case "psi": - return PoundsPerSquareInch, nil - default: - return *new(Pressure), errors.New(fmt.Sprintf("invalid unit: '%s'", s)) - } -} - -func Atmospheric() Pressure { - return 1 * Bar -} diff --git a/temperature.go b/temperature.go new file mode 100644 index 0000000..ac8cae0 --- /dev/null +++ b/temperature.go @@ -0,0 +1,60 @@ +package main + +import ( + "errors" + "fmt" +) + +type TemperatureUnit int + +const ( + Celcius TemperatureUnit = iota + Kelvin + Fahrenheit +) + +var TemperatureUnits = []string{"°C", "°K", "°F"} + +func ParseTemperatureUnit(s string) (TemperatureUnit, error) { + // Each case corresponds to a value in UnitStrings(). + switch s { + case "°C": + return Celcius, nil + case "°K": + return Kelvin, nil + case "°F": + return Fahrenheit, nil + default: + return *new(TemperatureUnit), errors.New(fmt.Sprintf("invalid unit: '%s'", s)) + } +} + +type Temperature struct { + Val float32 + Unit TemperatureUnit +} + +func (t Temperature) AsUnit(u TemperatureUnit) (float32, error) { + // Convert to celcius + var c float32 + switch t.Unit { + case Celcius: + c = t.Val + case Kelvin: + c = t.Val - 272.15 + case Fahrenheit: + c = (t.Val - 32.0) * (5.0 / 9.0) + } + + // Convert to desired unit + switch u { + case Celcius: + return c, nil + case Kelvin: + return c + 272.15, nil + case Fahrenheit: + return c*(9.0/5.0) + 32.0, nil + default: + return 0, errors.New(fmt.Sprintf("invalid unit: '%v'", u)) + } +} diff --git a/temperature/temperature.go b/temperature/temperature.go deleted file mode 100644 index 2a135df..0000000 --- a/temperature/temperature.go +++ /dev/null @@ -1,71 +0,0 @@ -package temperature - -import ( - "errors" - "fmt" -) - -type unit int - -const ( - Celcius unit = iota - Kelvin - Fahrenheit -) - -// UnitStrings returns a slice of strings, each representing a -// unit. -// This is necessary because giu.Combo only works with strings. -func UnitStrings() []string { - return []string{"°C", "°K", "°F"} -} - -const ( - DefaultUnit unit = Celcius - // DefaultUnitIndex is used to index UnitStrings(). - DefaultUnitIndex int32 = 0 // celcius -) - -func UnitFromString(s string) (unit, error) { - // Each case corresponds to a value in UnitStrings(). - switch s { - case "°C": - return Celcius, nil - case "°K": - return Kelvin, nil - case "°F": - return Fahrenheit, nil - default: - return *new(unit), errors.New(fmt.Sprintf("invalid unit: '%s'", s)) - } -} - -type Temperature struct { - Val float32 - Unit unit -} - -func (t Temperature) AsUnit(u unit) (float32, error) { - // Convert to celcius - var c float32 - switch t.Unit { - case Celcius: - c = t.Val - case Kelvin: - c = t.Val - 272.15 - case Fahrenheit: - c = (t.Val - 32.0) * (5.0 / 9.0) - } - - // Convert to desired unit - switch u { - case Celcius: - return c, nil - case Kelvin: - return c + 272.15, nil - case Fahrenheit: - return c*(9.0/5.0) + 32.0, nil - default: - return 0, errors.New(fmt.Sprintf("invalid unit: '%v'", u)) - } -} diff --git a/ui.go b/ui.go index 118069d..f218ea1 100644 --- a/ui.go +++ b/ui.go @@ -7,13 +7,6 @@ import ( "image/color" "image/draw" "strconv" - - "volute/compressor" - "volute/mass" - "volute/pressure" - "volute/temperature" - "volute/util" - "volute/volume" ) func red() color.RGBA { @@ -21,34 +14,34 @@ func red() color.RGBA { } func engineDisplacementRow() *g.RowWidget { - s := volume.UnitStrings()[volumeUnitIndex] - unit, err := volume.UnitFromString(s) - util.Check(err) + s := VolumeUnits[volumeUnitIndex] + unit, err := ParseVolumeUnit(s) + Check(err) engDisp := float32(displacement / unit) valWid, _ := g.CalcTextSize("12345.67") - unitWid, _ := g.CalcTextSize(volume.UnitStrings()[volumeUnitIndex]) + unitWid, _ := g.CalcTextSize(VolumeUnits[volumeUnitIndex]) return g.Row( g.Label("Engine Displacement"), g.InputFloat(&engDisp). Format("%.2f"). OnChange(func() { - displacement = volume.Volume(engDisp) * unit + displacement = Volume(engDisp) * unit for i := 0; i < numPoints; i++ { - engineMassFlowRate[i] = massFlowRateAt(i) + massFlowRateAir[i] = massFlowRateAt(i) go updateCompImg() } }). Size(valWid), g.Combo( "", - volume.UnitStrings()[volumeUnitIndex], - volume.UnitStrings(), + VolumeUnits[volumeUnitIndex], + VolumeUnits, &volumeUnitIndex, ).Size(unitWid*2), ) } -func engineSpeedRow() *g.TableRowWidget { +func speedRow() *g.TableRowWidget { widgets := []g.Widget{ g.Label("Engine Speed"), g.Label("rpm"), @@ -57,8 +50,8 @@ func engineSpeedRow() *g.TableRowWidget { i := i widgets = append( widgets, - g.InputInt(&engineSpeed[i]).OnChange(func() { - engineMassFlowRate[i] = massFlowRateAt(i) + g.InputInt(&speed[i]).OnChange(func() { + massFlowRateAir[i] = massFlowRateAt(i) go updateCompImg() }), ) @@ -76,7 +69,7 @@ func volumetricEfficiencyRow() *g.TableRowWidget { widgets = append( widgets, g.InputInt(&volumetricEfficiency[i]).OnChange(func() { - engineMassFlowRate[i] = massFlowRateAt(i) + massFlowRateAir[i] = massFlowRateAt(i) go updateCompImg() }), ) @@ -85,23 +78,23 @@ func volumetricEfficiencyRow() *g.TableRowWidget { } func intakeAirTemperatureRow() *g.TableRowWidget { - wid, _ := g.CalcTextSize(temperature.UnitStrings()[temperatureUnitIndex]) + wid, _ := g.CalcTextSize(TemperatureUnits[temperatureUnitIndex]) widgets := []g.Widget{ g.Label("Intake Air Temperature"), g.Combo( "", - temperature.UnitStrings()[temperatureUnitIndex], - temperature.UnitStrings(), + TemperatureUnits[temperatureUnitIndex], + TemperatureUnits, &temperatureUnitIndex, ).OnChange(func() { - s := temperature.UnitStrings()[temperatureUnitIndex] - u, err := temperature.UnitFromString(s) - util.Check(err) + s := TemperatureUnits[temperatureUnitIndex] + u, err := ParseTemperatureUnit(s) + Check(err) for i := range intakeAirTemperature { t, err := intakeAirTemperature[i].AsUnit(u) - util.Check(err) - intakeAirTemperature[i] = temperature.Temperature{t, u} + Check(err) + intakeAirTemperature[i] = Temperature{t, u} } }).Size(wid * 2), } @@ -112,7 +105,7 @@ func intakeAirTemperatureRow() *g.TableRowWidget { g.InputFloat(&intakeAirTemperature[i].Val). Format("%.2f"). OnChange(func() { - engineMassFlowRate[i] = massFlowRateAt(i) + massFlowRateAir[i] = massFlowRateAt(i) go updateCompImg() }), ) @@ -121,16 +114,16 @@ func intakeAirTemperatureRow() *g.TableRowWidget { } func manifoldPressureRow() *g.TableRowWidget { - s := pressure.UnitStrings()[pressureUnitIndex] - unit, err := pressure.UnitFromString(s) - util.Check(err) - wid, _ := g.CalcTextSize(pressure.UnitStrings()[pressureUnitIndex]) + s := PressureUnits[pressureUnitIndex] + unit, err := ParsePressureUnit(s) + Check(err) + wid, _ := g.CalcTextSize(PressureUnits[pressureUnitIndex]) widgets := []g.Widget{ g.Label("Manifold Absolute Pressure"), g.Combo( "", - pressure.UnitStrings()[pressureUnitIndex], - pressure.UnitStrings(), + PressureUnits[pressureUnitIndex], + PressureUnits, &pressureUnitIndex, ).Size(wid * 2), } @@ -141,9 +134,9 @@ func manifoldPressureRow() *g.TableRowWidget { widgets, g.InputFloat(&manPres).Format("%.2f"). OnChange(func() { - manifoldPressure[i] = pressure.Pressure(manPres * float32(unit)) + manifoldPressure[i] = Pressure(manPres * float32(unit)) pressureRatio[i] = pressureRatioAt(i) - engineMassFlowRate[i] = massFlowRateAt(i) + massFlowRateAir[i] = massFlowRateAt(i) go updateCompImg() }), ) @@ -167,23 +160,23 @@ func pressureRatioRow() *g.TableRowWidget { } func massFlowRateRow() *g.TableRowWidget { - s := mass.FlowRateUnitStrings()[selectedMassFlowRateUnit] - mfrUnit, err := mass.FlowRateUnitFromString(s) - util.Check(err) + s := MassFlowRateUnits[massFlowRateUnitIndex] + mfrUnit, err := ParseMassFlowRateUnit(s) + Check(err) - wid, _ := g.CalcTextSize(mass.FlowRateUnitStrings()[selectedMassFlowRateUnit]) + wid, _ := g.CalcTextSize(MassFlowRateUnits[massFlowRateUnitIndex]) widgets := []g.Widget{ g.Label("Mass Flow Rate"), g.Combo( "", - mass.FlowRateUnitStrings()[selectedMassFlowRateUnit], - mass.FlowRateUnitStrings(), - &selectedMassFlowRateUnit, + MassFlowRateUnits[massFlowRateUnitIndex], + MassFlowRateUnits, + &massFlowRateUnitIndex, ).Size(wid * 2), } for i := 0; i < numPoints; i++ { mfr := strconv.FormatFloat( - float64(engineMassFlowRate[i]/mfrUnit), + float64(massFlowRateAir[i]/mfrUnit), 'f', 3, 32, @@ -203,34 +196,34 @@ func duplicateDeleteRow() *g.TableRowWidget { widgets = append(widgets, g.Row( g.Button("Duplicate").OnClick(func() { numPoints++ - engineSpeed = util.Insert( - engineSpeed, - engineSpeed[i], + speed = Insert( + speed, + speed[i], i, ) - volumetricEfficiency = util.Insert( + volumetricEfficiency = Insert( volumetricEfficiency, volumetricEfficiency[i], i, ) - intakeAirTemperature = util.Insert( + intakeAirTemperature = Insert( intakeAirTemperature, intakeAirTemperature[i], i, ) - manifoldPressure = util.Insert( + manifoldPressure = Insert( manifoldPressure, manifoldPressure[i], i, ) - pressureRatio = util.Insert( + pressureRatio = Insert( pressureRatio, pressureRatio[i], i, ) - engineMassFlowRate = util.Insert( - engineMassFlowRate, - engineMassFlowRate[i], + massFlowRateAir = Insert( + massFlowRateAir, + massFlowRateAir[i], i, ) go updateCompImg() @@ -240,12 +233,12 @@ func duplicateDeleteRow() *g.TableRowWidget { return } numPoints-- - engineSpeed = util.Remove(engineSpeed, i) - volumetricEfficiency = util.Remove(volumetricEfficiency, i) - intakeAirTemperature = util.Remove(intakeAirTemperature, i) - manifoldPressure = util.Remove(manifoldPressure, i) - pressureRatio = util.Remove(pressureRatio, i) - engineMassFlowRate = util.Remove(engineMassFlowRate, i) + speed = Remove(speed, i) + volumetricEfficiency = Remove(volumetricEfficiency, i) + intakeAirTemperature = Remove(intakeAirTemperature, i) + manifoldPressure = Remove(manifoldPressure, i) + pressureRatio = Remove(pressureRatio, i) + massFlowRateAir = Remove(massFlowRateAir, i) go updateCompImg() }), )) @@ -270,14 +263,13 @@ func columns() []*g.TableColumnWidget { var compressorTree []g.Widget func init() { - compressors := compressor.Compressors() - for man := range compressors { + for man := range Compressors { man := man // Manufacturer var serNodes []g.Widget - for ser := range compressors[man] { + for ser := range Compressors[man] { ser := ser // Series var modNodes []g.Widget - for mod, c := range compressors[man][ser] { + for mod, c := range Compressors[man][ser] { mod := mod // Model c := c // Compressor modNodes = append( @@ -365,8 +357,8 @@ func copyImage(old *image.RGBA) *image.RGBA { // The position on the compressor map of an operating point. func pointPos(i int) (pos image.Point) { - const unit = mass.KilogramsPerSecond - mfr := engineMassFlowRate[i] / unit + const unit = KilogramsPerSecond + mfr := massFlowRateAir[i] / unit maxMfr := selectedCompressor.MaxFlow / unit min := selectedCompressor.MinX max := selectedCompressor.MaxX diff --git a/util.go b/util.go new file mode 100644 index 0000000..22f9cb2 --- /dev/null +++ b/util.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "os" +) + +func Check(err error) { + if err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func Insert[T any](slice []T, elem T, i int) []T { + return append(slice[:i], append([]T{elem}, slice[i:]...)...) +} + +func Remove[T any](slice []T, i int) []T { + return append(slice[:i], slice[i+1:]...) +} diff --git a/util/util.go b/util/util.go deleted file mode 100644 index b0eae51..0000000 --- a/util/util.go +++ /dev/null @@ -1,31 +0,0 @@ -package util - -import ( - "fmt" - "os" - - "volute/mass" - "volute/pressure" - "volute/temperature" -) - -func Check(err error) { - if err != nil { - fmt.Println(err) - os.Exit(1) - } -} - -func Insert[T int32 | float32 | temperature.Temperature | pressure.Pressure | mass.FlowRate](slice []T, elem T, i int) []T { - return append( - slice[:i], - append( - []T{elem}, - slice[i:]..., - )..., - ) -} - -func Remove[T int32 | float32 | temperature.Temperature | pressure.Pressure | mass.FlowRate](slice []T, i int) []T { - return append(slice[:i], slice[i+1:]...) -} diff --git a/volume.go b/volume.go new file mode 100644 index 0000000..6f5fb31 --- /dev/null +++ b/volume.go @@ -0,0 +1,33 @@ +package main + +import ( + "errors" + "fmt" +) + +type Volume float32 + +const ( + CubicCentimetre Volume = 1 + Litre Volume = 1_000 + CubicMetre Volume = 1_000_000 + CubicInch Volume = 16.38706 +) + +var VolumeUnits = []string{"cc", "L", "m³", "in³"} + +func ParseVolumeUnit(s string) (Volume, error) { + // Each case corresponds to a value in VolumeUnits. + switch s { + case "cc": + return CubicCentimetre, nil + case "L": + return Litre, nil + case "m³": + return CubicMetre, nil + case "in³": + return CubicInch, nil + default: + return *new(Volume), errors.New(fmt.Sprintf("invalid volume unit: '%s'", s)) + } +} diff --git a/volume/volume.go b/volume/volume.go deleted file mode 100644 index 48330df..0000000 --- a/volume/volume.go +++ /dev/null @@ -1,44 +0,0 @@ -package volume - -import ( - "errors" - "fmt" -) - -type Volume float32 - -const ( - CubicCentimetre Volume = 1 - Litre Volume = 1_000 - CubicMetre Volume = 1_000_000 - CubicInch Volume = 16.38706 -) - -// UnitStrings returns a slice of strings, each representing a -// unit. -// This is necessary because giu.Combo only works with strings. -func UnitStrings() []string { - return []string{"cc", "L", "m³", "in³"} -} - -const ( - DefaultUnit Volume = CubicCentimetre - // DefaulUnitIndex is used to index UnitStrings(). - DefaultUnitIndex int32 = 0 // cc -) - -func UnitFromString(s string) (Volume, error) { - // Each case corresponds to a value in UnitStrings(). - switch s { - case "cc": - return CubicCentimetre, nil - case "L": - return Litre, nil - case "m³": - return CubicMetre, nil - case "in³": - return CubicInch, nil - default: - return *new(Volume), errors.New(fmt.Sprintf("invalid volume unit: '%s'", s)) - } -} -- cgit v1.2.3 From 3c7c084774d355d9f1e5b176d0e4e4f88e02fe45 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 20 Jan 2024 18:01:28 -0500 Subject: fix typo in AbsolutePressure() --- pressure.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pressure.go b/pressure.go index cd824c5..631fd97 100644 --- a/pressure.go +++ b/pressure.go @@ -36,5 +36,5 @@ func ParsePressureUnit(s string) (Pressure, error) { } func AtmosphericPressure() Pressure { - return 101.325 * Pascal + return 101_325 * Pascal } -- cgit v1.2.3 From d33a8a46d8d00117e792608f879e30e7a4b31a37 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 20 Jan 2024 18:01:48 -0500 Subject: rename engineDisplacementRow() -> displacementRow() --- main.go | 2 +- ui.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 39483b2..6a24964 100644 --- a/main.go +++ b/main.go @@ -123,7 +123,7 @@ func setCompressor(c Compressor) { func loop() { g.SingleWindow().Layout( - engineDisplacementRow(), + displacementRow(), g.Table(). Size(g.Auto, 190). Rows( diff --git a/ui.go b/ui.go index f218ea1..28692d6 100644 --- a/ui.go +++ b/ui.go @@ -13,7 +13,7 @@ func red() color.RGBA { return color.RGBA{255, 0, 0, 255} } -func engineDisplacementRow() *g.RowWidget { +func displacementRow() *g.RowWidget { s := VolumeUnits[volumeUnitIndex] unit, err := ParseVolumeUnit(s) Check(err) -- cgit v1.2.3 From c952a096a161e991a54a569b71c7bb773b583eb3 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 20 Jan 2024 18:03:39 -0500 Subject: use variable rather than function for color constant --- ui.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ui.go b/ui.go index 28692d6..f132dd1 100644 --- a/ui.go +++ b/ui.go @@ -9,9 +9,7 @@ import ( "strconv" ) -func red() color.RGBA { - return color.RGBA{255, 0, 0, 255} -} +var red = color.RGBA{255, 0, 0, 255} func displacementRow() *g.RowWidget { s := VolumeUnits[volumeUnitIndex] @@ -303,7 +301,7 @@ func updateCompImg() { ps := img.Bounds().Dx() / 100 // Point size draw.Draw(img, image.Rect(pos.X-ps/2, pos.Y-ps/2, pos.X+ps/2, pos.Y+ps/2), - &image.Uniform{red()}, + &image.Uniform{red}, image.ZP, draw.Src, ) -- cgit v1.2.3 From 9ad538983290fbd62da7f8d6db5a6dfe123a25c3 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 20 Jan 2024 18:10:06 -0500 Subject: extract default values to constants --- main.go | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 6a24964..aaf4264 100644 --- a/main.go +++ b/main.go @@ -14,19 +14,32 @@ const ( airMolarMass = 0.0289647 // kg/mol ) +var ( + defaultDisplacement = 2 * Litre + defaultSpeed int32 = 2000 + defaultVE int32 = 80 + defaultTemperature = Temperature{25, Celcius} +) + +var ( + defaultManufacturer = "borgwarner" + defaultSeries = "efr" + defaultModel = "6258" +) + // Number of data points on the compressor map. var numPoints = 1 var ( - displacement = 2000 * CubicCentimetre + displacement = defaultDisplacement volumeUnitIndex int32 // Angular crankshaft speed in RPM. - speed = []int32{2000} + speed = []int32{defaultSpeed} - volumetricEfficiency = []int32{80} + volumetricEfficiency = []int32{defaultVE} - intakeAirTemperature = []Temperature{{25, Celcius}} + intakeAirTemperature = []Temperature{defaultTemperature} temperatureUnitIndex int32 manifoldPressure = []Pressure{AtmosphericPressure()} @@ -77,9 +90,9 @@ var ( ) func init() { - manufacturer := "garrett" - series := "g" - model := "25-660" + manufacturer := defaultManufacturer + series := defaultSeries + model := defaultModel c, ok := Compressors[manufacturer][series][model] if !ok { fmt.Printf("compressor.Compressors()[\"%s\"][\"%s\"][\"%s\"] does not exist.\n", -- cgit v1.2.3