001/*
002 * ============================================================================
003 * Copyright © 2002-2023 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 * Licensed to the public under the agreements of the GNU Lesser General Public
007 * License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *      http://www.gnu.org/licenses/lgpl.html
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 * License for the specific language governing permissions and limitations
015 * under the License.
016 */
017
018package org.tquadrat.foundation.value;
019
020import static java.lang.String.format;
021import static java.util.Arrays.stream;
022import static org.apiguardian.api.API.Status.STABLE;
023import static org.tquadrat.foundation.lang.Objects.requireNotEmptyArgument;
024import static org.tquadrat.foundation.value.api.DimensionedValue.MATH_CONTEXT;
025import static org.tquadrat.foundation.value.internal.Tools.V0p8;
026import static org.tquadrat.foundation.value.internal.Tools.V0t525;
027import static org.tquadrat.foundation.value.internal.Tools.V100;
028import static org.tquadrat.foundation.value.internal.Tools.V1p5;
029import static org.tquadrat.foundation.value.internal.Tools.V1t3;
030import static org.tquadrat.foundation.value.internal.Tools.V273;
031import static org.tquadrat.foundation.value.internal.Tools.V32;
032import static org.tquadrat.foundation.value.internal.Tools.V5t9;
033import static org.tquadrat.foundation.value.internal.Tools.V7p5;
034import static org.tquadrat.foundation.value.internal.Tools.retrieveName;
035
036import java.math.BigDecimal;
037import java.util.function.UnaryOperator;
038
039import org.apiguardian.api.API;
040import org.tquadrat.foundation.annotation.ClassVersion;
041import org.tquadrat.foundation.i18n.Text;
042import org.tquadrat.foundation.i18n.Translation;
043import org.tquadrat.foundation.value.api.Dimension;
044
045/**
046 *  The various instances of temperature …
047 *
048 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
049 *  @version $Id: Temperature.java 1072 2023-09-30 20:44:38Z tquadrat $
050 *  @since 0.1.0
051 *
052 *  @UMLGraph.link
053 */
054@ClassVersion( sourceVersion = "$Id: Temperature.java 1072 2023-09-30 20:44:38Z tquadrat $" )
055@API( status = STABLE, since = "0.1.0" )
056public enum Temperature implements Dimension
057{
058        /*------------------*\
059    ====** Enum Declaration **=================================================
060        \*------------------*/
061    /**
062     *  Kelvin.
063     */
064    @Text
065    (
066        description = "Kelvin",
067        translations =
068        {
069            @Translation( language = "de", text = "Kelvin" ),
070            @Translation( language = "en", text = "Kelvin" )
071        }
072    )
073    KELVIN( kelvinValue -> kelvinValue, kelvinValue -> kelvinValue, "K", 2 ),
074
075    /**
076     *  Celsius.
077     */
078    @Text
079    (
080        description = "Celsius",
081        translations =
082        {
083            @Translation( language = "de", text = "Grad Celsius" ),
084            @Translation( language = "en", text = "Celsius" )
085        }
086    )
087    CELSIUS( kelvinValue -> kelvinValue.subtract( V273 ), celsiusValue -> celsiusValue.add( V273 ), "C", 1 )
088    {
089        /**
090         *  {@inheritDoc}
091         */
092        @Override
093        public final String unitSymbolForPrinting() { return "°C"; }
094    },
095
096    /**
097     *  Fahrenheit
098     */
099    @Text
100    (
101        description = "Fahrenheit",
102        translations =
103        {
104            @Translation( language = "de", text = "Grad Fahrenheit" ),
105            @Translation( language = "en", text = "Fahrenheit" )
106        }
107    )
108    FAHRENHEIT( kelvinValue -> kelvinValue.subtract( V273 ).divide( V5t9, MATH_CONTEXT ).add( V32 ), fahrenheitValue -> fahrenheitValue.subtract( V32 ).multiply( V5t9 ).add( V273 ), "F" )
109    {
110        /**
111         *  {@inheritDoc}
112         */
113        @Override
114        public final String unitSymbolForPrinting() { return "°F"; }
115    },
116
117    /**
118     *  Rankine.
119     */
120    @Text
121    (
122        description = "Rankine",
123        translations =
124        {
125            @Translation( language = "de", text = "Grad Rankine" ),
126            @Translation( language = "en", text = "Rankine" )
127        }
128    )
129    RANKINE( kelvinValue -> kelvinValue.divide( V5t9, MATH_CONTEXT ), rankineValue -> rankineValue.multiply( V5t9 ), "Ra", 1 )
130    {
131        /**
132         *  {@inheritDoc}
133         */
134        @Override
135        public final String unitSymbolForPrinting() { return "°Ra"; }
136    },
137
138    /**
139     *  Delisle.
140     */
141    @Text
142    (
143        description = "Delisle",
144        translations =
145        {
146            @Translation( language = "de", text = "Grad Delisle" ),
147            @Translation( language = "en", text = "Delisle" )
148        }
149    )
150    DELISLE( kelvinValue -> kelvinValue.subtract( V273 ).multiply( V1p5 ).subtract( V100 ), delisleValue -> delisleValue.add( V100 ).divide( V1p5, MATH_CONTEXT ).add( V273 ) ,"De", 1 )
151    {
152        /**
153         *  {@inheritDoc}
154         */
155        @Override
156        public final String unitSymbolForPrinting() { return "°De"; }
157    },
158
159    /**
160     *  Réaumur.
161     */
162    @Text
163    (
164        description = "Réaumur",
165        translations =
166        {
167            @Translation( language = "de", text = "Grad Réaumur" ),
168            @Translation( language = "en", text = "Réaumur" )
169        }
170    )
171    REAUMUR( kelvinValue -> kelvinValue.subtract( V273 ).multiply( V0p8 ), reaumurValue -> reaumurValue.divide( V0p8, MATH_CONTEXT ).add( V273 ),"Re" )
172    {
173        /**
174         *  {@inheritDoc}
175         */
176        @Override
177        public final String unitSymbolForPrinting() { return "°Ré"; }
178    },
179
180    /**
181     *  <p>{@summary Newton.}</p>
182     *  <p>Yes, there is really a unit &quot;<i>Newton</i>&quot; for
183     *  temperatures! It was introduced by Isaac Newton at the beginning of the
184     *  18<sup>th</sup> century, but was not well established.</p>
185     */
186    @Text
187    (
188        description = "Newton",
189        translations =
190        {
191            @Translation( language = "de", text = "Grad Newton" ),
192            @Translation( language = "en", text = "Newton" )
193        }
194    )
195    NEWTON( kelvinValue -> kelvinValue.subtract( V273 ).multiply( V1t3 ), newtonValue -> newtonValue.divide( V1t3, MATH_CONTEXT ).add( V273 ),"N" )
196    {
197        /**
198         *  {@inheritDoc}
199         */
200        @Override
201        public final String unitSymbolForPrinting() { return "°N"; }
202    },
203
204    /**
205     *  Rømer.
206     */
207    @SuppressWarnings( "NonAsciiCharacters" ) @Text
208    (
209        description = "Rømer",
210        translations =
211        {
212            @Translation( language = "de", text = "Grad Rømer" ),
213            @Translation( language = "en", text = "Rømer" )
214        }
215    )
216    RØMER( kelvinValue -> kelvinValue.subtract( V273 ).multiply( V0t525 ).add( V7p5 ), romerValue -> romerValue.subtract( V7p5 ).divide( V0t525, MATH_CONTEXT ).add( V273 ), "Ro" )
217    {
218        /**
219         *  {@inheritDoc}
220         */
221        @Override
222        public final String unitSymbolForPrinting() { return "°Rø"; }
223    };
224
225        /*------------*\
226    ====** Attributes **=======================================================
227        \*------------*/
228    /**
229     *  The conversion for the given value from Kelvin to this unit.
230     */
231    private final UnaryOperator<BigDecimal> m_FromKelvin;
232
233    /**
234     *  The conversion for the given value from this unit to Kelvin.
235     */
236    private final UnaryOperator<BigDecimal> m_ToKelvin;
237
238    /**
239     *  The default precision.
240     */
241    private final int m_Precision;
242
243    /**
244     *  The unit string.
245     */
246    private final String m_UnitSymbol;
247
248        /*--------------*\
249    ====** Constructors **=====================================================
250        \*--------------*/
251    /**
252     *  Creates a new {@code Temperatur} instance, with a default precision of
253     *  zero mantissa digits.
254     *
255     *  @param  fromKelvin  The conversion from Kelvin.
256     *  @param  toKelvin    The conversion to Kelvin.
257     *  @param  unitSymbol    The unit symbol String.
258     */
259    private Temperature( final UnaryOperator<BigDecimal> fromKelvin, final UnaryOperator<BigDecimal> toKelvin, final String unitSymbol )
260    {
261        this( fromKelvin, toKelvin, unitSymbol, 0 );
262    }   //  Temperature()
263
264    /**
265     *  Creates a new {@code Temperatur} instance.
266     *
267     *  @param  fromKelvin  The conversion from Kelvin.
268     *  @param  toKelvin    The conversion to Kelvin.
269     *  @param  unitSymbol    The unit symbol String.
270     *  @param  precision   The default precision.
271     */
272    private Temperature( final UnaryOperator<BigDecimal> fromKelvin, final UnaryOperator<BigDecimal> toKelvin, final String unitSymbol, final int precision )
273    {
274        m_FromKelvin = fromKelvin;
275        m_ToKelvin = toKelvin;
276        m_UnitSymbol = unitSymbol;
277        m_Precision = precision;
278    }   //  Temperature()
279
280        /*---------*\
281    ====** Methods **==========================================================
282        \*---------*/
283    /**
284     *  {@inheritDoc}
285     */
286    @SuppressWarnings( "unchecked" )
287    @Override
288    public final Temperature baseUnit() { return KELVIN; }
289
290    /**
291     *  {@inheritDoc}
292     */
293    @Override
294    public final UnaryOperator<BigDecimal> fromBase() { return m_FromKelvin; }
295
296    /**
297     *  {@inheritDoc}
298     */
299    @Override
300    public final int getPrecision() { return m_Precision; }
301
302    /**
303     *  {@inheritDoc}
304     */
305    @Override
306    public final UnaryOperator<BigDecimal> toBase() { return m_ToKelvin; }
307
308    /**
309     *  {@inheritDoc}
310     */
311    @Override
312    public final String toString()
313    {
314        final var retValue = retrieveName( this );
315
316        //---* Done *----------------------------------------------------------
317        return retValue;
318    }   //  toString()
319
320    /**
321     *  {@inheritDoc}
322     */
323    @Override
324    public final String unitSymbol() { return m_UnitSymbol; }
325
326    /**
327     *  Returns the {@code Temperature} instance for the given unit symbol.
328     *
329     *  @param  unitSymbol  The unit symbol.
330     *  @return The respective instance.
331     *  @throws IllegalArgumentException    The given unit is unknown.
332     */
333    public static final Temperature forUnit( final String unitSymbol ) throws IllegalArgumentException
334    {
335        requireNotEmptyArgument( unitSymbol, "unitSymbol" );
336
337        final var retValue = stream( values() )
338            .filter( v -> v.unitSymbol().equals( unitSymbol ) )
339            .findFirst()
340            .orElseThrow( () -> new IllegalArgumentException( format( MSG_UnknownUnit, unitSymbol ) ) );
341
342        //---* Done *----------------------------------------------------------
343        return retValue;
344    }   //  forUnit()
345}
346//  enum Area
347
348/*
349 *  End of File
350 */