~registry/gcalctool/trunk

« back to all changes in this revision

Viewing changes to src/unit.vala

  • Committer: Robert Ancell
  • Date: 2012-10-14 03:31:40 UTC
  • Revision ID: git-v1:12ba2c81b0a81bb3ac776d1034a3c41b3173196a
Port to Vala

https://bugzilla.gnome.org/show_bug.cgi?id=640685

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008-2012 Robert Ancell.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it under
 
5
 * the terms of the GNU General Public License as published by the Free Software
 
6
 * Foundation, either version 2 of the License, or (at your option) any later
 
7
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
 
8
 * license.
 
9
 */
 
10
 
 
11
private UnitManager? default_unit_manager = null;
 
12
 
 
13
public class UnitManager : Object
 
14
{
 
15
    private List<UnitCategory> categories;
 
16
    
 
17
    public UnitManager ()
 
18
    {
 
19
        categories = new List<UnitCategory> ();
 
20
    }
 
21
 
 
22
    public static UnitManager get_default ()
 
23
    {
 
24
        if (default_unit_manager != null)
 
25
            return default_unit_manager;
 
26
 
 
27
        default_unit_manager = new UnitManager ();
 
28
 
 
29
        var angle_category = default_unit_manager.add_category ("angle", _("Angle"));
 
30
        var length_category = default_unit_manager.add_category ("length", _("Length"));
 
31
        var area_category = default_unit_manager.add_category ("area", _("Area"));
 
32
        var volume_category = default_unit_manager.add_category ("volume", _("Volume"));
 
33
        var weight_category = default_unit_manager.add_category ("weight", _("Weight"));
 
34
        var duration_category = default_unit_manager.add_category ("duration", _("Duration"));
 
35
        var temperature_category = default_unit_manager.add_category ("temperature", _("Temperature"));
 
36
 
 
37
        /* FIXME: Approximations of 1/(units in a circle), therefore, 360 deg != 400 grads */
 
38
        angle_category.add_unit (new Unit ("degree", _("Degrees"), dpgettext2 (null, "unit-format", "%s degrees"), "π*x/180", "180x/π", dpgettext2 (null, "unit-symbols", "degree,degrees,deg")));
 
39
        angle_category.add_unit (new Unit ("radian", _("Radians"), dpgettext2 (null, "unit-format", "%s radians"), "x", "x", dpgettext2 (null, "unit-symbols", "radian,radians,rad")));
 
40
        angle_category.add_unit (new Unit ("gradian", _("Gradians"), dpgettext2 (null, "unit-format", "%s gradians"), "π*x/200", "200x/π", dpgettext2 (null, "unit-symbols", "gradian,gradians,grad")));
 
41
        length_category.add_unit (new Unit ("parsec", _("Parsecs"), dpgettext2 (null, "unit-format", "%s pc"), "30857000000000000x", "x/30857000000000000", dpgettext2 (null, "unit-symbols", "parsec,parsecs,pc")));
 
42
        length_category.add_unit (new Unit ("lightyear", _("Light Years"), dpgettext2 (null, "unit-format", "%s ly"), "9460730472580800x", "x/9460730472580800", dpgettext2 (null, "unit-symbols", "lightyear,lightyears,ly")));
 
43
        length_category.add_unit (new Unit ("astronomical-unit", _("Astronomical Units"), dpgettext2 (null, "unit-format", "%s au"), "149597870691x", "x/149597870691", dpgettext2 (null, "unit-symbols", "au")));
 
44
        length_category.add_unit (new Unit ("nautical-mile", _("Nautical Miles"), dpgettext2 (null, "unit-format", "%s nmi"), "1852x", "x/1852", dpgettext2 (null, "unit-symbols", "nmi")));
 
45
        length_category.add_unit (new Unit ("mile", _("Miles"), dpgettext2 (null, "unit-format", "%s mi"), "1609.344x", "x/1609.344", dpgettext2 (null, "unit-symbols", "mile,miles,mi")));
 
46
        length_category.add_unit (new Unit ("kilometer", _("Kilometers"), dpgettext2 (null, "unit-format", "%s km"), "1000x", "x/1000", dpgettext2 (null, "unit-symbols", "kilometer,kilometers,km,kms")));
 
47
        length_category.add_unit (new Unit ("cable", _("Cables"), dpgettext2 (null, "unit-format", "%s cb"), "219.456x", "x/219.456", dpgettext2 (null, "unit-symbols", "cable,cables,cb")));
 
48
        length_category.add_unit (new Unit ("fathom", _("Fathoms"), dpgettext2 (null, "unit-format", "%s ftm"), "1.8288x", "x/1.8288", dpgettext2 (null, "unit-symbols", "fathom,fathoms,ftm")));
 
49
        length_category.add_unit (new Unit ("meter", _("Meters"), dpgettext2 (null, "unit-format", "%s m"), "x", "x", dpgettext2 (null, "unit-symbols", "meter,meters,m")));
 
50
        length_category.add_unit (new Unit ("yard", _("Yards"), dpgettext2 (null, "unit-format", "%s yd"), "0.9144x", "x/0.9144", dpgettext2 (null, "unit-symbols", "yard,yards,yd")));
 
51
        length_category.add_unit (new Unit ("foot", _("Feet"), dpgettext2 (null, "unit-format", "%s ft"), "0.3048x", "x/0.3048", dpgettext2 (null, "unit-symbols", "foot,feet,ft")));
 
52
        length_category.add_unit (new Unit ("inch", _("Inches"), dpgettext2 (null, "unit-format", "%s in"), "0.0254x", "x/0.0254", dpgettext2 (null, "unit-symbols", "inch,inches,in")));
 
53
        length_category.add_unit (new Unit ("centimeter", _("Centimeters"), dpgettext2 (null, "unit-format", "%s cm"), "x/100", "100x", dpgettext2 (null, "unit-symbols", "centimeter,centimeters,cm,cms")));
 
54
        length_category.add_unit (new Unit ("millimeter", _("Millimeters"), dpgettext2 (null, "unit-format", "%s mm"), "x/1000", "1000x", dpgettext2 (null, "unit-symbols", "millimeter,millimeters,mm")));
 
55
        length_category.add_unit (new Unit ("micrometer", _("Micrometers"), dpgettext2 (null, "unit-format", "%s μm"), "x/1000000", "1000000x", dpgettext2 (null, "unit-symbols", "micrometer,micrometers,um")));
 
56
        length_category.add_unit (new Unit ("nanometer", _("Nanometers"), dpgettext2 (null, "unit-format", "%s nm"), "x/1000000000", "1000000000x", dpgettext2 (null, "unit-symbols", "nanometer,nanometers,nm")));
 
57
        area_category.add_unit (new Unit ("hectare", _("Hectares"), dpgettext2 (null, "unit-format", "%s ha"), "10000x", "x/10000", dpgettext2 (null, "unit-symbols", "hectare,hectares,ha")));
 
58
        area_category.add_unit (new Unit ("acre", _("Acres"), dpgettext2 (null, "unit-format", "%s acres"), "4046.8564224x", "x/4046.8564224", dpgettext2 (null, "unit-symbols", "acre,acres")));
 
59
        area_category.add_unit (new Unit ("square-meter", _("Square Meters"), dpgettext2 (null, "unit-format", "%s m²"), "x", "x", dpgettext2 (null, "unit-symbols", "m²")));
 
60
        area_category.add_unit (new Unit ("square-centimeter", _("Square Centimeters"), dpgettext2 (null, "unit-format", "%s cm²"), "0.0001x", "10000x", dpgettext2 (null, "unit-symbols", "cm²")));
 
61
        area_category.add_unit (new Unit ("square-millimeter", _("Square Millimeters"), dpgettext2 (null, "unit-format", "%s mm²"), "0.000001x", "1000000x", dpgettext2 (null, "unit-symbols", "mm²")));
 
62
        volume_category.add_unit (new Unit ("cubic-meter", _("Cubic Meters"), dpgettext2 (null, "unit-format", "%s m³"), "1000x", "x/1000", dpgettext2 (null, "unit-symbols", "m³")));
 
63
        volume_category.add_unit (new Unit ("gallon", _("Gallons"), dpgettext2 (null, "unit-format", "%s gal"), "3.785412x", "x/3.785412", dpgettext2 (null, "unit-symbols", "gallon,gallons,gal")));
 
64
        volume_category.add_unit (new Unit ("litre", _("Litres"), dpgettext2 (null, "unit-format", "%s L"), "x", "x", dpgettext2 (null, "unit-symbols", "litre,litres,liter,liters,L")));
 
65
        volume_category.add_unit (new Unit ("quart", _("Quarts"), dpgettext2 (null, "unit-format", "%s qt"), "0.9463529x", "x/0.9463529", dpgettext2 (null, "unit-symbols", "quart,quarts,qt")));
 
66
        volume_category.add_unit (new Unit ("pint", _("Pints"), dpgettext2 (null, "unit-format", "%s pt"), "0.4731765x", "x/0.4731765", dpgettext2 (null, "unit-symbols", "pint,pints,pt")));
 
67
        volume_category.add_unit (new Unit ("millilitre", _("Millilitres"), dpgettext2 (null, "unit-format", "%s mL"), "0.001x", "1000x", dpgettext2 (null, "unit-symbols", "millilitre,millilitres,milliliter,milliliters,mL,cm³")));
 
68
        volume_category.add_unit (new Unit ("microlitre", _("Microlitres"), dpgettext2 (null, "unit-format", "%s μL"), "0.000001x", "1000000x", dpgettext2 (null, "unit-symbols", "mm³,μL,uL")));
 
69
        weight_category.add_unit (new Unit ("tonne", _("Tonnes"), dpgettext2 (null, "unit-format", "%s T"), "1000x", "x/1000", dpgettext2 (null, "unit-symbols", "tonne,tonnes")));
 
70
        weight_category.add_unit (new Unit ("kilograms", _("Kilograms"), dpgettext2 (null, "unit-format", "%s kg"), "x", "x", dpgettext2 (null, "unit-symbols", "kilogram,kilograms,kilogramme,kilogrammes,kg,kgs")));
 
71
        weight_category.add_unit (new Unit ("pound", _("Pounds"), dpgettext2 (null, "unit-format", "%s lb"), "0.45359237x", "x/0.45359237", dpgettext2 (null, "unit-symbols", "pound,pounds,lb")));
 
72
        weight_category.add_unit (new Unit ("ounce", _("Ounces"), dpgettext2 (null, "unit-format", "%s oz"), "0.02834952x", "x/0.02834952", dpgettext2 (null, "unit-symbols", "ounce,ounces,oz")));
 
73
        weight_category.add_unit (new Unit ("gram", _("Grams"), dpgettext2 (null, "unit-format", "%s g"), "0.001x", "1000x", dpgettext2 (null, "unit-symbols", "gram,grams,gramme,grammes,g")));
 
74
        duration_category.add_unit (new Unit ("year", _("Years"), dpgettext2 (null, "unit-format", "%s years"), "31557600x", "x/31557600", dpgettext2 (null, "unit-symbols", "year,years")));
 
75
        duration_category.add_unit (new Unit ("day", _("Days"), dpgettext2 (null, "unit-format", "%s days"), "86400x", "x/86400", dpgettext2 (null, "unit-symbols", "day,days")));
 
76
        duration_category.add_unit (new Unit ("hour", _("Hours"), dpgettext2 (null, "unit-format", "%s hours"), "3600x", "x/3600", dpgettext2 (null, "unit-symbols", "hour,hours")));
 
77
        duration_category.add_unit (new Unit ("minute", _("Minutes"), dpgettext2 (null, "unit-format", "%s minutes"), "60x", "x/60", dpgettext2 (null, "unit-symbols", "minute,minutes")));
 
78
        duration_category.add_unit (new Unit ("second", _("Seconds"), dpgettext2 (null, "unit-format", "%s s"), "x", "x", dpgettext2 (null, "unit-symbols", "second,seconds,s")));
 
79
        duration_category.add_unit (new Unit ("millisecond", _("Milliseconds"), dpgettext2 (null, "unit-format", "%s ms"), "0.001x", "1000x", dpgettext2 (null, "unit-symbols", "millisecond,milliseconds,ms")));
 
80
        duration_category.add_unit (new Unit ("microsecond", _("Microseconds"), dpgettext2 (null, "unit-format", "%s μs"), "0.000001x", "1000000x", dpgettext2 (null, "unit-symbols", "microsecond,microseconds,us,μs")));
 
81
        temperature_category.add_unit (new Unit ("degree-celcius", _("Celsius"), dpgettext2 (null, "unit-format", "%s ˚C"), "x+273.15", "x-273.15", dpgettext2 (null, "unit-symbols", "degC,˚C")));
 
82
        temperature_category.add_unit (new Unit ("degree-farenheit", _("Farenheit"), dpgettext2 (null, "unit-format", "%s ˚F"), "(x+459.67)*5/9", "x*9/5-459.67", dpgettext2 (null, "unit-symbols", "degF,˚F")));
 
83
        temperature_category.add_unit (new Unit ("degree-kelvin", _("Kelvin"), dpgettext2 (null, "unit-format", "%s K"), "x", "x", dpgettext2 (null, "unit-symbols", "K")));
 
84
        temperature_category.add_unit (new Unit ("degree-rankine", _("Rankine"), dpgettext2 (null, "unit-format", "%s ˚R"), "x*5/9", "x*9/5", dpgettext2 (null, "unit-symbols", "degR,˚R,˚Ra")));
 
85
 
 
86
        var currency_category = default_unit_manager.add_category ("currency", _("Currency"));
 
87
        var currencies = CurrencyManager.get_default ().get_currencies ();
 
88
        currencies.sort ((a, b) => { return strcmp (a.display_name, b.display_name); });
 
89
        foreach (var currency in currencies)
 
90
        {
 
91
            /* Translators: result of currency conversion, %s is the symbol, %%s is the placeholder for amount, i.e.: USD100 */
 
92
            var format = _("%s%%s").printf (currency.symbol);
 
93
            var unit = new Unit (currency.name, currency.display_name, format, null, null, currency.name);
 
94
            currency_category.add_unit ( unit);
 
95
        }
 
96
 
 
97
        return default_unit_manager;
 
98
    }
 
99
 
 
100
    public UnitCategory add_category (string name, string display_name)
 
101
    {
 
102
        var category = new UnitCategory (name, display_name);
 
103
        categories.append (category);
 
104
        return category;
 
105
    }
 
106
 
 
107
    public List<UnitCategory> get_categories ()
 
108
    {
 
109
        var r = new List<UnitCategory> ();
 
110
        foreach (var c in categories)
 
111
            r.append (c);
 
112
        return r;
 
113
    }
 
114
 
 
115
    public UnitCategory? get_category (string category)
 
116
    {
 
117
        foreach (var c in categories)
 
118
            if (c.name == category)
 
119
                return c;
 
120
 
 
121
        return null;
 
122
    }
 
123
 
 
124
    public Unit? get_unit_by_name (string name)
 
125
    {
 
126
        foreach (var c in categories)
 
127
        {
 
128
            var u = c.get_unit_by_name (name);
 
129
            if (u != null)
 
130
                return u;
 
131
        }
 
132
 
 
133
        return null;
 
134
    }
 
135
 
 
136
    public Unit? get_unit_by_symbol (string symbol)
 
137
    {
 
138
        foreach (var c in categories)
 
139
        {
 
140
            var u = c.get_unit_by_symbol (symbol);
 
141
            if (u != null)
 
142
                return u;
 
143
        }
 
144
 
 
145
        return null;
 
146
    }
 
147
 
 
148
    public Number? convert_by_symbol (Number x, string x_symbol, string z_symbol)
 
149
    {
 
150
        foreach (var c in categories)
 
151
        {
 
152
            var x_units = c.get_unit_by_symbol (x_symbol);
 
153
            var z_units = c.get_unit_by_symbol (z_symbol);
 
154
            if (x_units != null && z_units != null)
 
155
                return c.convert (x, x_units, z_units);
 
156
        }
 
157
 
 
158
        return null;
 
159
    }
 
160
}
 
161
 
 
162
public class UnitCategory : Object
 
163
{
 
164
    private List<Unit> units;
 
165
 
 
166
    private string _name;
 
167
    public string name { owned get { return _name; } }
 
168
 
 
169
    private string _display_name;
 
170
    public string display_name { owned get { return _display_name; } }
 
171
 
 
172
    public UnitCategory (string name, string display_name)
 
173
    {
 
174
        _name = name;
 
175
        _display_name = display_name;
 
176
        units = new List<Unit> ();
 
177
    }
 
178
 
 
179
    public void add_unit (Unit unit)
 
180
    {
 
181
        units.append (unit);
 
182
    }
 
183
 
 
184
    public Unit? get_unit_by_name (string name)
 
185
    {
 
186
        foreach (var unit in units)
 
187
            if (unit.name == name)
 
188
                return unit;
 
189
 
 
190
        return null;
 
191
    }
 
192
 
 
193
    public Unit? get_unit_by_symbol (string symbol)
 
194
    {
 
195
        foreach (var unit in units)
 
196
            if (unit.matches_symbol (symbol))
 
197
                return unit;
 
198
 
 
199
        return null;
 
200
    }
 
201
 
 
202
    public unowned List<Unit> get_units ()
 
203
    {
 
204
        return units;
 
205
    }
 
206
 
 
207
    public Number? convert (Number x, Unit x_units, Unit z_units)
 
208
    {
 
209
        var t = x_units.convert_from (x);
 
210
        if (t == null)
 
211
            return null;
 
212
        return z_units.convert_to (t);
 
213
    }
 
214
}
 
215
 
 
216
public class Unit : Object
 
217
{
 
218
    private string _name;
 
219
    public string name { owned get { return _name; } }
 
220
 
 
221
    private string _display_name;
 
222
    public string display_name { owned get { return _display_name; } }
 
223
 
 
224
    private string _format;
 
225
    private List<string> _symbols;
 
226
    private string? from_function;
 
227
    private string? to_function;
 
228
    private Serializer serializer;
 
229
 
 
230
    public Unit (string name, string display_name, string format, string? from_function, string? to_function, string symbols)
 
231
    {
 
232
        serializer = new Serializer (DisplayFormat.AUTOMATIC, 10, 2);
 
233
        serializer.set_leading_digits (6);
 
234
 
 
235
        _name = name;
 
236
        _display_name = display_name;
 
237
        this._format = format;
 
238
        this.from_function = from_function;
 
239
        this.to_function = to_function;
 
240
        _symbols = new List<string> ();
 
241
        var symbol_names = symbols.split (",", 0);
 
242
        foreach (var symbol_name in symbol_names)
 
243
            _symbols.append (symbol_name);
 
244
    }
 
245
 
 
246
    public bool matches_symbol (string symbol)
 
247
    {
 
248
        foreach (var s in _symbols)
 
249
            if (s == symbol)
 
250
                return true;
 
251
 
 
252
        return false;
 
253
    }
 
254
 
 
255
    public unowned List<string> get_symbols ()
 
256
    {
 
257
        return _symbols;
 
258
    }
 
259
 
 
260
    public Number? convert_from (Number x)
 
261
    {
 
262
        if (from_function != null)
 
263
            return solve_function (from_function, x);
 
264
        else
 
265
        {
 
266
            // FIXME: Hack to make currency work
 
267
            var r = CurrencyManager.get_default ().get_value (name);
 
268
            if (r == null)
 
269
                return null;
 
270
            return x.divide (r);
 
271
        }
 
272
    }
 
273
 
 
274
    public Number? convert_to (Number x)
 
275
    {
 
276
        if (to_function != null)
 
277
            return solve_function (to_function, x);
 
278
        else
 
279
        {
 
280
            // FIXME: Hack to make currency work
 
281
            var r = CurrencyManager.get_default ().get_value (name);
 
282
            if (r == null)
 
283
                return null;
 
284
            return x.multiply (r);
 
285
        }
 
286
    }
 
287
 
 
288
    public string format (Number x)
 
289
    {
 
290
        var number_text = serializer.to_string (x);
 
291
        return _format.printf (number_text);
 
292
    }
 
293
 
 
294
    private Number? solve_function (string function, Number x)
 
295
    {
 
296
        var equation = new UnitSolveEquation (function, x);
 
297
        equation.base = 10;
 
298
        equation.wordlen = 32;
 
299
 
 
300
        var z = equation.parse ();
 
301
        if (z == null)
 
302
            warning ("Failed to convert value: %s", function);
 
303
 
 
304
        return z;
 
305
    }
 
306
}
 
307
 
 
308
private class UnitSolveEquation : Equation
 
309
{
 
310
    private Number x;
 
311
 
 
312
    public UnitSolveEquation (string function, Number x)
 
313
    {
 
314
        base (function);
 
315
        this.x = x;
 
316
    }
 
317
    
 
318
    public override bool variable_is_defined (string name)
 
319
    {
 
320
        return true;
 
321
    }
 
322
 
 
323
    public override Number? get_variable (string name)
 
324
    {
 
325
        return x;
 
326
    }
 
327
}
 
 
b'\\ No newline at end of file'