1   /* Copyright 2022-2025 Luc Maisonobe
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.gnss;
18  
19  import java.util.Locale;
20  
21  /** Container for satellite system and PRN.
22   * @author Luc Maisonobe
23   * @since 12.0
24   */
25  public class SatInSystem {
26  
27      /** Value representing all PRNs in the system. */
28      public static final int ANY_PRN = -1;
29  
30      /** PRN shift for SBAS system. */
31      private static final int SBAS_SHIFT = 100;
32  
33      /** PRN shift for QZSS system. */
34      private static final int QZSS_SHIFT = 192;
35  
36      /** Satellite system. */
37      private final SatelliteSystem system;
38  
39      /** PRN number. */
40      private final int prn;
41  
42      /** Simple constructor.
43       * @param system satellite system
44       * @param prn Pseudo Random Number or {@link #ANY_PRN} to represent any satellite in the system
45       */
46      public SatInSystem(final SatelliteSystem system, final int prn) {
47          this.system = system;
48          this.prn    = prn;
49      }
50  
51      /** Simple constructor.
52       * <p>
53       * The RINEX 3 characters code starts with a letter representing the
54       * {@link SatelliteSystem#getKey() satellite system key} followed
55       * by a 2 digits integer which represents either
56       * </p>
57       * <ul>
58       *   <li>the Pseudo Random Number in the general case</li>
59       *   <li>the Pseudo Random Number minus 100 for {@link SatelliteSystem#SBAS}</li>
60       *   <li>the Pseudo Random Number minus 192 for {@link SatelliteSystem#QZSS}</li>
61       * </ul>
62       * <p>
63       * if only the letter is present, then prn is set to {@link #ANY_PRN}
64       * </p>
65       * @param rinexCode RINEX 3 characters code
66       * @since 13.0
67       */
68      public SatInSystem(final String rinexCode) {
69  
70          // parse system
71          this.system = SatelliteSystem.parseSatelliteSystem(rinexCode.substring(0, 1));
72  
73          // parse PRN
74          final String trimmed = rinexCode.substring(1).trim();
75          if (trimmed.isEmpty()) {
76              this.prn = ANY_PRN;
77          } else {
78              final int index = Integer.parseInt(trimmed);
79              if (system == SatelliteSystem.SBAS) {
80                  this.prn = index + SBAS_SHIFT;
81              } else if (system == SatelliteSystem.QZSS) {
82                  this.prn = index + QZSS_SHIFT;
83              } else {
84                  this.prn = index;
85              }
86          }
87  
88      }
89  
90      /** Get the system this satellite belongs to.
91       * @return system this satellite belongs to
92       */
93      public SatelliteSystem getSystem() {
94          return system;
95      }
96  
97      /** Get the Pseudo Random Number of the satellite.
98       * @return Pseudo Random Number of the satellite, or {@link #ANY_PRN} to represent
99       * any PRN in the system
100      */
101     public int getPRN() {
102         return prn;
103     }
104 
105     /** Get a 2-digits Pseudo Random Number for RINEX files.
106      * @return 2-digits Pseudo Random Number for RINEX files
107      */
108     public int getTwoDigitsRinexPRN() {
109         return system == SatelliteSystem.SBAS ?
110                prn - SBAS_SHIFT :
111                (system == SatelliteSystem.QZSS ? prn - QZSS_SHIFT : prn);
112     }
113 
114     /** {@inheritDoc} */
115     @Override
116     public String toString() {
117         return prn < 0 ?
118                String.format(Locale.US, "%c  ", system.getKey()) :
119                String.format(Locale.US, "%c%02d", system.getKey(), getTwoDigitsRinexPRN());
120     }
121 
122     @Override
123     public boolean equals(final Object object) {
124         if (object instanceof SatInSystem) {
125             final SatInSystem other = (SatInSystem) object;
126             return getSystem().equals(other.getSystem()) && getPRN() == other.getPRN();
127         }
128         return false;
129     }
130 
131     @Override
132     public int hashCode() {
133         return Character.hashCode(getSystem().getKey()) ^ getPRN();
134     }
135 
136 }