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 org.apiguardian.api.API.Status.STABLE;
021import static org.tquadrat.foundation.i18n.I18nUtil.retrieveText;
022import static org.tquadrat.foundation.lang.CommonConstants.EMPTY_STRING;
023import static org.tquadrat.foundation.lang.DebugOutput.ifDebug;
024import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
025import static org.tquadrat.foundation.value.Speed.METER_PER_SECOND;
026import static org.tquadrat.foundation.value.internal.Tools.BASE_BUNDLE_NAME;
027import static org.tquadrat.foundation.value.internal.Tools.retrieveName;
028
029import java.util.EnumSet;
030import java.util.Locale;
031import java.util.MissingResourceException;
032import java.util.ResourceBundle;
033import java.util.Set;
034import java.util.function.Supplier;
035
036import org.apiguardian.api.API;
037import org.tquadrat.foundation.annotation.ClassVersion;
038import org.tquadrat.foundation.i18n.Text;
039import org.tquadrat.foundation.i18n.Translation;
040import org.tquadrat.foundation.lang.Lazy;
041import org.tquadrat.foundation.util.RangeMap;
042
043/**
044 *  The wind force according to the Beaufort table.
045 *
046 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
047 *  @version $Id: WindForce.java 1073 2023-10-01 11:08:51Z tquadrat $
048 *  @since 0.0.4
049 *
050 *  @UMLGraph.link
051 */
052@ClassVersion( sourceVersion = "$Id: WindForce.java 1073 2023-10-01 11:08:51Z tquadrat $" )
053@API( status = STABLE, since = "0.0.4" )
054public enum WindForce
055{
056        /*------------------*\
057    ====** Enum Declaration **=================================================
058        \*------------------*/
059    /**
060     *  Wind force 0 Bft.
061     */
062    @Text
063    (
064        description = "The name for 0 Bft.",
065        translations =
066        {
067            @Translation( language = "de", text = "Windstille" ),
068            @Translation( language = "en", text = "Calm" )
069        }
070    )
071    BFT0( 0, "0.2" ),
072
073    /**
074     *  Wind force 1 Bft.
075     */
076    @Text
077    (
078        description = "The name for 1 Bft.",
079        translations =
080        {
081            @Translation( language = "de", text = "Leiser Zug" ),
082            @Translation( language = "en", text = "Light Air" )
083        }
084    )
085    BFT1( 1, "1.5" ),
086
087    /**
088     *  Wind force 2 Bft.
089     */
090    @Text
091    (
092        description = "The name for 2 Bft.",
093        translations =
094        {
095            @Translation( language = "de", text = "Leichte Brise" ),
096            @Translation( language = "en", text = "Light Breeze" )
097        }
098    )
099    BFT2( 2, "3.3" ),
100
101    /**
102     *  Wind force 3 Bft.
103     */
104    @Text
105    (
106        description = "The name for 3 Bft.",
107        translations =
108        {
109            @Translation( language = "de", text = "Schwache Brise" ),
110            @Translation( language = "en", text = "Gentle Breeze" )
111        }
112    )
113    BFT3( 3, "5.4" ),
114
115    /**
116     *  Wind force 4 Bft.
117     */
118    @Text
119    (
120        description = "The name for 4 Bft.",
121        translations =
122        {
123            @Translation( language = "de", text = "Mäßige Brise" ),
124            @Translation( language = "en", text = "Moderate Breeze" )
125        }
126    )
127    BFT4( 4, "8.9" ),
128
129    /**
130     *  Wind force 5.
131     */
132    @Text
133    (
134        description = "The name for 5 Bft.",
135        translations =
136        {
137            @Translation( language = "de", text = "Frische Brise" ),
138            @Translation( language = "en", text = "Fresh Breeze" )
139        }
140    )
141    BFT5( 5, "11.0" ),
142
143    /**
144     *  Wind force 6.
145     */
146    @Text
147    (
148        description = "The name for 6 Bft.",
149        translations =
150        {
151            @Translation( language = "de", text = "Starker Wind" ),
152            @Translation( language = "en", text = "Strong Breeze" )
153        }
154    )
155    BFT6( 6, "14.0" ),
156
157    /**
158     *  Wind force 7.
159     */
160    @Text
161    (
162        description = "The name for 7 Bft.",
163        translations =
164        {
165            @Translation( language = "de", text = "Steifer Wind" ),
166            @Translation( language = "en", text = "Moderate Gale" )
167        }
168    )
169    BFT7( 7, "17.0" ),
170
171    /**
172     *  Wind force 8.
173     */
174    @Text
175    (
176        description = "The name for 8 Bft.",
177        translations =
178        {
179            @Translation( language = "de", text = "Stürmischer Wind" ),
180            @Translation( language = "en", text = "Gale" )
181        }
182    )
183    BFT8( 8, "21.0" ),
184
185    /**
186     *  Wind force 9.
187     */
188    @Text
189    (
190        description = "The name for 9 Bft.",
191        translations =
192        {
193            @Translation( language = "de", text = "Sturm" ),
194            @Translation( language = "en", text = "Strong Gale" )
195        }
196    )
197    BFT9( 9, "24.0" ),
198
199    /**
200     *  Wind force 10 Bft.
201     */
202    @Text
203    (
204        description = "The name for 10 Bft.",
205        translations =
206        {
207            @Translation( language = "de", text = "Schwerer Sturm" ),
208            @Translation( language = "en_GB", text = "Whole Gale" ),
209            @Translation( language = "en", text = "Storm" )
210        }
211    )
212    BFT10( 10, "28.0" ),
213
214    /**
215     *  Wind force 11 Bft.
216     */
217    @Text
218    (
219        description = "The name for 11 Bft.",
220        translations =
221        {
222            @Translation( language = "de", text = "Orkanartiger Sturm" ),
223            @Translation( language = "en_GB", text = "Storm" ),
224            @Translation( language = "en", text = "Violent Storm" )
225        }
226    )
227    BFT11( 11, "33.0" ),
228
229    /**
230     *  Wind force 12 Bft.
231     */
232    @Text
233    (
234        description = "The name for 12 Bft.",
235        translations =
236        {
237            @Translation( language = "de", text = "Orkan" ),
238            @Translation( language = "en", text = "Hurricane" )
239        }
240    )
241    BFT12( 12, "36.9" ),
242
243    /**
244     *  Wind force 13 Bft.; although it is not official, we added it to the
245     *  list.
246     */
247    @Text
248    (
249        description = "The name for 13 Bft.",
250        translations =
251        {
252            @Translation( language = "de", text = "Schwerer Orkan" ),
253            @Translation( language = "en", text = "Heavy Hurricane" )
254        }
255    )
256    BFT13( 13, EMPTY_STRING );
257
258        /*------------*\
259    ====** Attributes **=======================================================
260        \*------------*/
261    /**
262     *  The maximum wind speed in m/s.
263     */
264    @SuppressWarnings( "UseOfConcreteClass" )
265    private final SpeedValue m_MaxSpeed;
266
267    /**
268     *  The numerical value for the wind force.
269     */
270    private final int m_Number;
271
272        /*------------------------*\
273    ====** Static Initialisations **===========================================
274        \*------------------------*/
275    /**
276     *  The translation table.
277     */
278    private static final Lazy<RangeMap<WindForce>> m_TranslationTable;
279
280    static
281    {
282        @SuppressWarnings( "OverlyLongLambda" )
283        final var supplier = (Supplier<RangeMap<WindForce>>) () ->
284        {
285            final var retValue = RangeMap.of( BFT13, true );
286            double maxSpeed;
287            for( final var windForce : values() )
288            {
289                if( windForce == BFT13 ) continue;
290                maxSpeed = windForce.getMaxSpeed().baseValue().doubleValue();
291                retValue.addRange( maxSpeed, windForce );
292            }
293
294            //---* Done *------------------------------------------------------
295            return retValue;
296        };
297        m_TranslationTable = Lazy.use( supplier );
298    }
299
300        /*--------------*\
301    ====** Constructors **=====================================================
302        \*--------------*/
303    /**
304     *  Creates a new {@code WindForce} object.
305     *
306     *  @param  number  The numerical wind force.
307     *  @param  maxSpeed    The maximum wind speed for this wind force in m/s.
308     */
309    private WindForce( final int number, final String maxSpeed )
310    {
311        m_Number = number;
312        m_MaxSpeed = maxSpeed.isEmpty()
313            ? new SpeedValue( METER_PER_SECOND, Double.POSITIVE_INFINITY )
314            : new SpeedValue( METER_PER_SECOND, maxSpeed );
315    }   //  WindForce()
316
317        /*---------*\
318    ====** Methods **==========================================================
319        \*---------*/
320    /**
321     *  Returns the wind force for the given wind speed.
322     *
323     *  @param  speed   The wind speed in m/s.
324     *  @return The wind force.
325     */
326    public static WindForce determineWindForce( final double speed )
327    {
328        return determineWindForce( METER_PER_SECOND, speed );
329    }   //  determineWindForce()
330
331    /**
332     *  Returns the wind force for the given wind speed.
333     *
334     *  @param  unit    The unit for the speed value.
335     *  @param  speed   The wind speed.
336     *  @return The wind force.
337     */
338    public static WindForce determineWindForce( final Speed unit, final double speed )
339    {
340        return determineWindForce( new SpeedValue( requireNonNullArgument( unit, "unit" ), speed ) );
341    }   //  determineWindForce()
342
343    /**
344     *  Returns the wind force for the given wind speed.
345     *
346     *  @param  speed   The wind speed.
347     *  @return The wind force.
348     */
349    @SuppressWarnings( "UseOfConcreteClass" )
350    public static WindForce determineWindForce( final SpeedValue speed )
351    {
352        return m_TranslationTable.get().get( requireNonNullArgument( speed, "speed" ).baseValue().doubleValue() );
353    }   //  determineWindForce()
354
355    /**
356     *  Return an empty
357     *  {@link Set}
358     *  of {@code WindForce} instances.
359     *
360     *  @return An empty set.
361     */
362    public static Set<WindForce> emptySet() { return EnumSet.noneOf( WindForce.class ); }
363
364    /**
365     *  Returns maximum wind speed for this wind force.
366     *
367     *  @return The maximum speed.
368     */
369    public final SpeedValue getMaxSpeed() { return m_MaxSpeed; }
370
371    /**
372     *  Returns the wind force number.
373     *
374     *  @return The number.
375     */
376    public final int getNumber() { return m_Number; }
377
378    /**
379     *  {@inheritDoc}
380     */
381    @Override
382    public final String toString()
383    {
384        final var retValue = retrieveName( this );
385
386        //---* Done *----------------------------------------------------------
387        return retValue;
388    }   //  toString()
389
390    /**
391     *  Returns the String representation for this wind force for the given
392     *  language.
393     *
394     *  @param  locale  The locale.
395     *  @return The String representation.
396     */
397    public final String toString( final Locale locale )
398    {
399        String retValue;
400        try
401        {
402            final var module = getClass().getModule();
403            final var bundle = ResourceBundle.getBundle( BASE_BUNDLE_NAME, requireNonNullArgument( locale, "locale" ), module );
404            retValue = retrieveText( bundle, this );
405        }
406        catch( final MissingResourceException e )
407        {
408            ifDebug( e );
409            retValue = toString();
410        }
411
412        //---* Done *----------------------------------------------------------
413        return retValue;
414    }   //  toString()
415}
416//  class WindForce
417
418/*
419 *  End of File
420 */