001/*
002 * Units of Measurement Systems
003 * Copyright (c) 2005-2021, Jean-Marie Dautelle, Werner Keil and others.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-385, Units of Measurement nor the names of their contributors may be used to
017 *    endorse or promote products derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package systems.uom.common.historic;
031
032import static javax.measure.MetricPrefix.KILO;
033import static tech.units.indriya.unit.Units.JOULE;
034import static tech.units.indriya.unit.Units.KILOGRAM;
035import static tech.units.indriya.unit.Units.PASCAL;
036import static tech.units.indriya.unit.Units.WATT;
037import static systems.uom.common.historic.CGS.DYNE;
038
039import javax.measure.Quantity;
040import javax.measure.Unit;
041import javax.measure.quantity.Energy;
042import javax.measure.quantity.Force;
043import javax.measure.quantity.Length;
044import javax.measure.quantity.Mass;
045import javax.measure.quantity.Power;
046import javax.measure.quantity.Pressure;
047import javax.measure.quantity.Speed;
048import javax.measure.quantity.Time;
049
050import si.uom.quantity.Impulse;
051import tech.units.indriya.AbstractSystemOfUnits;
052import tech.units.indriya.AbstractUnit;
053import tech.units.indriya.format.SimpleUnitFormat;
054import tech.units.indriya.function.MultiplyConverter;
055import tech.units.indriya.unit.ProductUnit;
056import tech.units.indriya.unit.TransformedUnit;
057import tech.units.indriya.unit.Units;
058
059/**
060 * <p>
061 * This class contains the Gravitational metric system of units.
062 * </p>
063 * 
064 * <p>
065 * This class is not intended to be implemented by clients.
066 * </p>
067 * 
068 * @noextend This class is not intended to be extended by clients.
069 * 
070 * @author <a href="mailto:werner@uom.systems">Werner Keil</a>
071 * @version 1.0, $Date: 2021-03-28$
072 * @see <a href= "https://en.wikipedia.org/wiki/Gravitational_metric_system">Wikipedia: Gravitational metric system</a>
073 * @see <a href= "http://ww2.cnam.fr/physique/PHR011_ELECTRICITE/ap2/SI_Anglo.htm">Systèmes de mesure - Measure systems</a>
074 *      
075 * @since 2.1
076 */
077public final class MKpS extends AbstractSystemOfUnits {
078    private static final String SYSTEM_NAME = "Gravitational metric system";
079
080    private static final MKpS INSTANCE = new MKpS();
081    
082    /**
083     * Default constructor (prevents this class from being instantiated).
084     */
085    private MKpS() {
086    }
087
088    /**
089     * Returns the unique instance of this class.
090     * 
091     * @return the NonSI instance.
092     */
093    public static MKpS getInstance() {
094        return INSTANCE;
095    }
096
097
098    ////////////
099    // Length //
100    ////////////    
101        /**
102         * The unit of length is the metre, defined by the distance, at 0°, between the axes of the <br>
103         * two central lines marked on the bar of platinum–iridium kept at the Bureau International des Poids et Mesures <br>
104         * and declared Prototype of the metre by the 1st Conférence Générale des Poids et Mesures,<br>
105         * this bar being subject to standard atmospheric pressure and supported on two cylinders of at least one centimetre diameter, symmetrically placed in the same horizontal plane at a distance of 571 mm from each other.        
106         */
107        public static final Unit<Length> METRE = addUnit(Units.METRE, Length.class);
108
109    //////////
110    // Mass //
111    //////////
112        /**
113         * The hyl, metric slug (mug), or TME (German: technische Masseneinheit, lit. 'technical mass unit'), is the mass that accelerates at 1 m/s2 under a force of 1 kgf.[4] The hyl has also been used as the unit of mass in a metre–gram-force–second (mgfs) system.
114         */
115        public static final Unit<Mass> HYL = addUnit(KILOGRAM.multiply(9.80665), "Hyl", "hyl", Mass.class);
116        
117        /**
118         * The TME (German: technische Masseneinheit, lit. 'technical mass unit'), is the mass that accelerates at 1 m/s2 under a force of 1 kgf.[4] The hyl has also been used as the unit of mass in a metre–gram-force–second (mgfs) system.
119         */
120        public static final Unit<Mass> TME = addUnit(new TransformedUnit<Mass>("Technical mass unit", "TME", HYL, MultiplyConverter.identity()));
121        
122    //////////
123    // Time //
124    //////////
125    /**
126     * The SI base unit for duration quantities (standard name <code>s</code>). It is defined as the duration of 9,192,631,770 cycles of radiation
127     * corresponding to the transition between two hyperfine levels of the ground state of cesium (1967 Standard).
128     * 
129     */
130    public static final Unit<Time> SECOND = addUnit(Units.SECOND, Time.class);
131
132    //////////////
133    // Speed    //
134    //////////////
135        /**
136         * The standard unit for speed quantities (standard name <code>m/s</code>).
137         */
138        public static final Unit<Speed> METRE_PER_SECOND = addUnit(new ProductUnit<>(METRE.divide(SECOND)), Speed.class);
139
140    ////////////
141    // Energy //
142    ////////////
143    /**
144     * There is no dedicated name for the unit of energy, "metre" is simply appended to "kilopond", but usually the symbol of the kilopond-metre is written without the middle dot.
145     * 
146     * <code>1 kp⋅m = gn kg⋅m = 9.806 65 kg⋅m2/s2 = 9.806 65 J</code>
147     */
148    public static final Unit<Energy> KILOPOND_METRE = addUnit(JOULE.multiply(9.80665), "Kilopond-metre", "kpm", Energy.class);
149
150    ///////////
151    // Force //
152    ///////////        
153    /**
154     * In English contexts the unit of force is usually formed by simply appending the suffix "force" to the name of the unit of mass, thus gram-force (gf) or kilogram-force (kgf), which follows the tradition of pound-force (lbf). In other, international, contexts the special name pond (p) or kilopond (kp) respectively is more frequent.
155     */
156    public static final Unit<Force> POND = addUnit(DYNE.multiply(980.665), "Pond", "p", Force.class);
157
158    ///////////
159    // Power //
160    ///////////
161    /**
162     * Horsepower (HP) is the name of several units of measurement of power. The most common definitions equal between 735.5 and 750 watts. Horsepower
163     * was originally defined to compare the output of steam engines with the power of draft horses. The unit was widely adopted to measure the output
164     * of piston engines, turbines, electric motors, and other machinery. The definition of the unit varied between geographical regions. Most
165     * countries now use the SI unit watt for measurement of power. With the implementation of the EU Directive 80/181/EEC on January 1, 2010, the use
166     * of horsepower in the EU is only permitted as supplementary unit.
167     * @see #PONCELET
168     */
169    public static final Unit<Power> HORSEPOWER = addUnit(WATT.multiply(735.499), "Horsepower", "HP");
170
171    /**
172     * In 19th-century France there was as a unit of power, the poncelet, which was defined as the power required to raise a mass of 1 quintal (1 q = 100 kg) at a velocity of 1 m/s.<br>
173     * The German or metric horsepower (PS, Pferdestärke) is arbitrarily selected to be three quarters thereof.
174     * <p>
175     * <code>1 pq = 1 qf⋅m/s = 100 kp⋅m/s = 100 × gn kg⋅m/s = 980.665 kg⋅m2/s3 = 0.980 665 kW</code>
176     * 
177     * @see #HORSEPOWER
178     */
179    public static final Unit<Power> PONCELET = addUnit(WATT.multiply(980.665), "Poncelet", "Pq", Power.class);
180
181    //////////////
182    // Pressure //
183    //////////////
184    /**
185     * The gravitational unit of pressure is the technical atmosphere (at). It is the gravitational force of one kilogram, i.e. 1 kgf, exerted on an area of one square centimetre.
186     * <code>1 at = 1 kp/cm2 = 10 000 × gn kg/m2 = 98 066.5 kg/(m⋅s2) = 98.066 5 kPa</code>
187     */
188    public static final Unit<Pressure> TECHNICAL_ATMOSPHERE = addUnit(KILO(PASCAL).multiply(98.06650), "Technical atmosphere", "at", Pressure.class);
189    
190    /**
191     * A metre, centimetre or millimetre of water are less commonly used measures of pressure derived from pressure head.
192     *
193     * @see <a href="https://en.wikipedia.org/wiki/Centimetre_or_millimetre_of_water">Wikipedia: Centimetre or millimetre of water</a>
194     */
195    public static final Unit<Pressure> METER_OF_WATER_COLUMN = addUnit(KILO(PASCAL).multiply(980665).divide(100000));
196
197    /////////////
198    // Impulse //
199    /////////////
200        /**
201     * The kilopond-second unit of impulse.<br>
202         * 
203         * <code>1 kps = 1 kp·s = 9,806 65 kg·m/s</code>
204         * 
205         * @see <a href="https://en.wikipedia.org/wiki/Impulse_(physics)">Wikipedia: Impulse (physics)</a>
206         */
207        public static final Unit<Impulse> KILOPOND_SECOND = addUnit(
208                        new ProductUnit<Impulse>(KILO(POND).multiply(SECOND)), Impulse.class);
209    
210    /////////////////////
211    // Collection View //
212    /////////////////////
213
214    public String getName() {
215        return SYSTEM_NAME;
216    }
217
218    /**
219     * Adds a new unit not mapped to any specified quantity type.
220     *
221     * @param unit
222     *            the unit being added.
223     * @return <code>unit</code>.
224     */
225    private static <U extends Unit<?>> U addUnit(U unit) {
226        INSTANCE.units.add(unit);
227        return unit;
228    }
229
230    /**
231     * Adds a new unit not mapped to any specified quantity type and puts a text as symbol or label.
232     *
233     * @param unit
234     *            the unit being added.
235     * @param name
236     *            the string to use as name
237     * @param text
238     *            the string to use as label or symbol
239     * @param isLabel
240     *            if the string should be used as a label or not
241     * @return <code>unit</code>.
242     */
243    private static <U extends Unit<?>> U addUnit(U unit, String name, String text, boolean isLabel) {
244        if (isLabel && text != null) {
245            SimpleUnitFormat.getInstance().label(unit, text);
246        }
247        if (name != null && unit instanceof AbstractUnit) {
248            return Helper.addUnit(INSTANCE.units, unit, name);
249        } else {
250            INSTANCE.units.add(unit);
251        }
252        return unit;
253    }
254
255    /**
256     * Adds a new unit not mapped to any specified quantity type and puts a text as symbol or label.
257     *
258     * @param unit
259     *            the unit being added.
260     * @param name
261     *            the string to use as name
262     * @param text
263     *            the string to use as label
264     * @return <code>unit</code>.
265     */
266    private static <U extends Unit<?>> U addUnit(U unit, String name, String text) {
267        return addUnit(unit, name, text, true);
268    }
269    
270    /**
271     * Adds a new unit not mapped to any specified quantity type and puts a text as symbol or label.
272     *
273     * @param unit
274     *            the unit being added.
275     * @param name
276     *            the string to use as name
277     * @param text
278     *            the string to use as label
279     * @param type the quantity type.
280     * @return <code>unit</code>.
281     */
282    private static <U extends Unit<?>> U addUnit(U unit, String name, String text, Class<? extends Quantity<?>> type) {
283        INSTANCE.quantityToUnit.put(type, unit);
284        return addUnit(unit, name, text, true);
285    }
286    
287        /**
288         * Adds a new unit and maps it to the specified quantity type.
289         *
290         * @param unit the unit being added.
291         * @param type the quantity type.
292         * @return <code>unit</code>.
293         */
294        private static <U extends Unit<?>> U addUnit(U unit, Class<? extends Quantity<?>> type) {
295                INSTANCE.units.add(unit);
296                INSTANCE.quantityToUnit.put(type, unit);
297                return unit;
298        }
299}