require 'rspec'

require 'tempfile'

$: << File::join(File::dirname(__FILE__), '..', 'build_SWIG')
require 'GPS.so'

describe 'GPS solver' do
  let(:input){{
    :rinex_nav => Tempfile::open{|f|
      if true then
        f.write(<<-__RINEX_NAV_TEXT__)
     2.10           N: GPS NAV DATA                         RINEX VERSION / TYPE
teqc  2013Mar15     BKG Frankfurt       20150617 00:16:14UTCPGM / RUN BY / DATE
Linux 2.4.21-27.ELsmp|Opteron|gcc -static|Linux x86_64|=+   COMMENT
     2.10           N: GPS NAV DATA                         COMMENT
teqc  2008Feb15                         20150617 00:10:22UTCCOMMENT
Linux 2.4.20-8|Pentium IV|gcc -static|Linux|486/DX+         COMMENT
    1.3970D-08  2.2352D-08 -1.1921D-07 -1.1921D-07          ION ALPHA
    1.1059D+05  1.6384D+05 -6.5536D+04 -5.2429D+05          ION BETA
    3.725290298462D-09 1.509903313490D-14   319488     1849 DELTA-UTC: A0,A1,T,W
    16                                                      LEAP SECONDS
Concatenated RINEX files (28/)                              COMMENT
Original file name: brdc1670.15n                            COMMENT
                                                            END OF HEADER
31 15  6 16  0  0  0.0 3.128303214908D-04-1.136868377216D-12 0.000000000000D+00
    7.800000000000D+01 1.292812500000D+02 4.074098273975D-09 1.410690806649D+00
    6.768852472305D-06 8.027532137930D-03 4.271045327187D-06 5.153535821915D+03
    1.728000000000D+05 9.872019290924D-08 8.650894583569D-01 8.940696716309D-08
    9.750288799237D-01 3.013750000000D+02-5.268559212524D-01-8.036049019412D-09
    3.664438352852D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
    2.000000000000D+00 0.000000000000D+00-1.350417733192D-08 7.800000000000D+01
    1.663560000000D+05 4.000000000000D+00
24 15  6 16  0  0  0.0-4.998780786991D-05-5.684341886081D-13 0.000000000000D+00
    9.000000000000D+01 1.401250000000D+02 4.642336229081D-09 2.380519254182D+00
    7.258728146553D-06 3.228595596738D-03 3.971159458160D-06 5.153673912048D+03
    1.728000000000D+05-2.980232238770D-08 8.160388274984D-01-1.490116119385D-08
    9.533772739559D-01 2.969375000000D+02 3.612098431884D-01-8.379634759709D-09
    4.025167664390D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
    2.900000000000D+00 0.000000000000D+00 2.328306436539D-09 9.000000000000D+01
    1.656600000000D+05 4.000000000000D+00
12 15  6 16  0  0  0.0 3.018006682396D-04 3.183231456205D-12 0.000000000000D+00
    9.000000000000D+01-8.984375000000D+01 4.146244136282D-09 1.019955493515D+00
   -4.906207323074D-06 5.596161005087D-03 2.166256308556D-06 5.153664655685D+03
    1.728000000000D+05-3.352761268616D-08 1.926955253672D+00 9.685754776001D-08
    9.895896897770D-01 3.531562500000D+02 6.166481681571D-01-8.222842514396D-09
   -2.525105180766D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
    2.000000000000D+00 0.000000000000D+00-1.210719347000D-08 9.000000000000D+01
    1.708800000000D+05 4.000000000000D+00
25 15  6 16  0  0  0.0-2.291053533554D-06-4.206412995700D-12 0.000000000000D+00
    4.300000000000D+01-8.231250000000D+01 4.456614188797D-09 3.514302168106D-01
   -4.393979907036D-06 4.659408819862D-03 1.480802893639D-06 5.153666315079D+03
    1.728000000000D+05 0.000000000000D+00 1.880081553172D+00 1.080334186554D-07
    9.780612252959D-01 3.641250000000D+02 7.406192694225D-01-8.389992700586D-09
   -1.742929689463D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
    2.000000000000D+00 0.000000000000D+00 5.587935447693D-09 4.300000000000D+01
    1.728000000000D+05
18 15  6 15 23 59 44.0 4.096841439605D-04 2.955857780762D-12 0.000000000000D+00
    0.000000000000D+00-2.200000000000D+01 5.964177003340D-09-4.658085121885D-01
   -1.063570380211D-06 1.631921075750D-02 5.243346095085D-06 5.153597631454D+03
    1.727840000000D+05-9.499490261078D-08-1.282443549024D+00 1.769512891769D-07
    9.246030417022D-01 2.601875000000D+02-1.955724914307D+00-8.981445541829D-09
   -4.760912596834D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
    2.000000000000D+00 0.000000000000D+00-1.117587089539D-08 0.000000000000D+00
    1.696560000000D+05 4.000000000000D+00
29 15  6 16  0  0  0.0 6.168931722641D-04 2.273736754432D-12 0.000000000000D+00
    7.300000000000D+01-1.041875000000D+02 4.061597753278D-09 5.907941646969D-01
   -5.280598998070D-06 1.195417135023D-03 1.201778650284D-05 5.153755130768D+03
    1.728000000000D+05 9.313225746155D-09 2.981267878597D+00-1.303851604462D-08
    9.739471617229D-01 1.573125000000D+02-5.419126340021D-01-7.659961925303D-09
    2.107230631757D-10 1.000000000000D+00 1.849000000000D+03 0.000000000000D+00
    2.000000000000D+00 0.000000000000D+00-9.778887033463D-09 7.300000000000D+01
    1.656180000000D+05 4.000000000000D+00
__RINEX_NAV_TEXT__
      else # equivalent
        open(File::join(File::dirname(__FILE__), "..", "..", "test_log", "brdc1670.15n"), 'r'){|io|
          while (str = io.readline)
            f.puts("%-80s"%[str.chomp])
            break if str =~ /END OF HEADER/
          end
          while !io.eof?
            entry = 8.times.collect{io.readline}
            next unless entry[0] =~ /^([ \d]\d) /
            prn = $1.to_i
            next unless entry[6] =~ /(\d\.\d{12})D([+-]\d{2})\s*$/
            iode = ($1.to_f * (10 ** $2.to_i)).to_i
            next unless [[12, 90], [18, 0], [24, 90], [25, 43], [29, 73], [31, 78]] \
                .include?([prn, iode])
            entry.each{|str|
              f.print("%-80s\n"%[str.chomp])
            }
          end
        }
      end
      f.path
    },
    :measurement => proc{
      l1p = GPS::Measurement::L1_PSEUDORANGE
      l1d = GPS::Measurement::L1_RANGE_RATE
      {
        12 => {l1p => 23707858.8131, l1d => -466.953123206},
        18 => {l1p => 25319310.9754, l1d => -453.797772239},
        24 => {l1p => 25683081.3903, l1d => -579.768048832},
        25 => {l1p => 21551698.5927, l1d => -847.86674626},
        29 => {l1p => 23637198.3968, l1d => -1560.30646593},
        31 => {l1p => 23707474.1231, l1d => -1423.67588761},
      }
    }.call,
    :rinex_obs => Tempfile::open{|f|
      if true then
        f.write(<<-__RINEX_OBS_TEXT__)
     2.11           OBSERVATION DATA    M (MIXED)           RINEX VERSION / TYPE
BINEX2RINEX  1.00   GSI, JAPAN          20150617 18:30:58UTCPGM / RUN BY / DATE
0228                                                        MARKER NAME
GSI, JAPAN          GEOSPATIAL INFORMATION AUTHORITY OF JAPAOBSERVER / AGENCY
00000               TRIMBLE NETR9       4.93,26/NOV/2014    REC # / TYPE / VERS
                    TRM59800.80     GSI                     ANT # / TYPE
 -3952590.4754  3360273.8926  3697987.2632                  APPROX POSITION XYZ
        0.0000        0.0000        0.0000                  ANTENNA: DELTA H/E/N
     1     1                                                WAVELENGTH FACT L1/2
     6    L1    C1    L2    P2    S1    S2                  # / TYPES OF OBSERV
  2015     6    16     0     0    0.0000000     GPS         TIME OF FIRST OBS
    30.000                                                  INTERVAL
    16                                                      LEAP SECONDS
smtt on  - smooth time tag (ms jumps in phase and range)    COMMENT
                                                            END OF HEADER
 15  6 16  0  0  0.0000000  0 13R04R14G22G18G25G14R03G12R13G29R23R24 0.000000000
                                G26
 107962537.996 8  20161244.813    83970896.187 7  20161248.340          53.100  
        45.700  
 108292688.703 7  20315410.305    84227597.491 6  20315417.836          44.900  
        38.600  
 120164532.762 7  22866559.250    93634735.08845  22866565.0164         44.800  
        31.9004 
 127657315.100 5  24292417.195    99473356.27642  24292426.4844         33.000  
        16.9004 
 107108718.011 8  20382088.883    83461307.35447  20382098.2114         52.700  
        44.8004 
 106665594.451 8  20297781.844    83116060.16147  20297788.3284         48.500  
        43.6004 
 112247722.253 8  20968815.328    87303792.973 7  20968819.930          48.200  
        43.900  
 119180856.024 7  22679363.352    92868240.86845  22679370.8554         46.000  
        34.4004 
 113219403.456 7  21202362.125    88059583.077 7  21202366.582          43.300  
        42.600  
 116573807.952 8  22183256.359    90836814.38846  22183263.8554         48.000  
        37.2004 
 118068213.681 8  22071607.477    91830908.595 5  22071616.434          48.300  
        34.300  
 122821571.168 6  22968227.047    95527813.562 5  22968231.008          41.000  
        33.400  
 126887720.863 7  24145939.008    98873654.81144  24145951.6954         42.000  
        24.8004 
 15  6 16  0  0 30.0000000  0 13R04R14G22G18G25G14R03G12R13G29R23R24 0.000000000
                                G26
 107953906.562 8  20159632.578    83964182.831 7  20159636.547          52.900  
        45.500  
 108275524.990 7  20312191.531    84214247.928 6  20312198.477          46.000  
        37.900  
 120243117.022 7  22881512.617    93695969.52045  22881519.3444         43.200  
        30.0004 
 127752623.271 5  24310554.234    99547622.25842  24310562.6254         34.300  
        14.8004 
 107148475.172 8  20389654.469    83492286.95147  20389663.6914         53.000  
        44.7004 
 106649633.973 8  20294744.781    83103623.41147  20294751.4144         49.800  
        44.5004 
 112354437.822 8  20988750.797    87386793.909 7  20988756.371          48.000  
        44.200  
 119276901.051 7  22697639.727    92943081.07945  22697647.7704         47.500  
        34.6004 
 113277695.919 7  21213278.297    88104921.616 7  21213283.438          43.800  
        42.700  
 116499708.794 8  22169155.719    90779074.87246  22169163.7704         48.500  
        37.6004 
 118027431.830 8  22063984.773    91799189.430 5  22063991.707          49.300  
        35.100  
 122710898.974 6  22947531.234    95441735.252 5  22947536.609          40.900  
        33.600  
 126789541.785 6  24127256.484    98797151.68444  24127268.9224         41.900  
        25.3004 
 15  6 16  0  1  0.0000000  0 13R04R14G22G18G25G14R03G12R13G29R23R24 0.000000000
                                G26
 107946098.362 8  20158174.969    83958109.762 7  20158178.289          53.200  
        44.900  
 108258590.494 7  20309014.148    84201076.653 6  20309021.145          46.000  
        38.700  
 120321906.821 7  22896506.344    93757364.10145  22896512.2934         44.600  
        30.2004 
 127847866.993 6  24328677.648    99621838.11742  24328687.3954         37.300  
        16.9004 
 107188670.264 8  20397303.531    83523607.79247  20397312.3054         53.700  
        44.3004 
 106634143.554 8  20291797.133    83091552.94947  20291803.6724         49.900  
        44.0004 
 112461605.174 7  21008771.203    87470146.236 7  21008775.176          47.500  
        43.900  
 119373111.958 8  22715948.289    93018050.54445  22715955.9534         48.100  
        34.1004 
 113336078.148 7  21224212.609    88150329.998 7  21224216.957          43.000  
        42.500  
 116425964.067 7  22155122.617    90721611.48746  22155131.1914         46.200  
        37.6004 
 117987330.119 7  22056486.641    91767999.260 5  22056494.809          46.900  
        34.500  
 122600398.977 6  22926865.672    95355790.881 5  22926871.977          39.700  
        32.500  
 126691542.694 6  24108607.188    98720788.84544  24108620.5234         41.700  
        24.8004 
__RINEX_OBS_TEXT__
      else # equivalent
        # GEONET Setagaya from https://terras.gsi.go.jp/data_service.php#11/35.663712/139.630394
        open(File::join(File::dirname(__FILE__), "..", "..", "test_log", "02281670.15o"), 'r'){|io|
          99.times{|i|
            break unless str = io.readline
            f.write(str)
          }
        }
      end
      f.path
    },
    :sp3 => Tempfile::open{|f|
      f.write(<<-__SP3_TEXT__)
#cP2015  6 16  0  0  0.00000000      96 ORBIT IGb08 HLM  IGS
## 1849 172800.00000000   900.00000000 57189 0.0000000000000
+   32   G01G02G03G04G05G06G07G08G09G10G11G12G13G14G15G16G17
+        G18G19G20G21G22G23G24G25G26G27G28G29G30G31G32  0  0
+          0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
+          0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
+          0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
++         2  2  2  2  2  2  2  0  2  2  2  3  2  2  2  2  2
++         2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  0  0
++         0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
++         0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
++         0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
%c G  cc GPS ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc
%c cc cc ccc ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc
%f  1.2500000  1.025000000  0.00000000000  0.000000000000000
%f  0.0000000  0.000000000  0.00000000000  0.000000000000000
%i    0    0    0    0      0      0      0      0         0
%i    0    0    0    0      0      0      0      0         0
/* FINAL ORBIT COMBINATION FROM WEIGHTED AVERAGE OF:        
/* cod emr esa gfz grg jpl mit ngs sio                      
/* REFERENCED TO IGS TIME (IGST) AND TO WEIGHTED MEAN POLE: 
/* PCV:IGS08_1848 OL/AL:FES2004  NONE     Y  ORB:CMB CLK:CMB
*  2015  6 16  0  0  0.00000000
PG01  21477.204419  11282.581331  10982.666329     -4.224052 10  9  5  88       
PG02 -12947.386225 -21737.519960   9157.412040    572.334531 11  9  9  92       
PG03  15091.272344   2635.335027  21713.458097    350.710803  5  7  5 106       
PG04  19856.311038  17713.928768   1945.134852    -19.579715  8  4  7 110       
PG05  -5028.958918 -21535.647757 -14619.836324   -228.975511  6  6  8 130       
PG06     43.183960 -18726.862044  18839.608728    185.417169  9  5  7 118       
PG07  17287.852835  -1614.468072 -20102.036060    468.894353  7  6  9 116       
PG08  -7526.428030  25336.071960   -245.225055 999999.999999
PG09  25592.191216  -7119.852791   -684.470086   -170.790925 11  4  5  85       
PG10   8847.115692 -24659.480635   2225.055266   -179.067962  9  6  9  88       
PG11  24364.312740  10558.140769   1439.121385   -585.254884 12  9  7  95       
PG12 -13123.844385  -6477.031146  22071.429026    301.796773  8  9 10  93       
PG13  -9339.292125 -13217.275814 -21176.552360   -123.730302  9  9  8 122       
PG14 -14836.144028  14380.662771  16842.481371     55.763000 11  5  8 126       
PG15 -20449.064495  -6178.529584 -16069.113276   -255.187297  9  9  9 125       
PG16   2754.103102  21634.705923 -14967.352446   -118.509573  7  9  5 100       
PG17  14291.286810 -14775.679540  16998.771557   -176.046900  8  5  7 115       
PG18 -14912.214427  16679.406498 -13581.838805    409.684054 10  7  9  95       
PG19  18186.236969   9260.919982 -17444.978749   -513.455728  8  7  9 109       
PG20 -13708.481723 -10140.408823 -20549.806986    329.972500  8  9  6 117       
PG21 -16310.214424   4505.474102 -19851.246022   -455.613502  9  7  5 121       
PG22  -9140.171474  24554.172420  -3496.039791    361.363708  8  5  8 126       
PG23  25005.294805    917.699796   9692.016699   -115.088944  9  8  7 104       
PG24 -21619.917392 -13093.113260   8361.648626    -49.986148  9 11 10 115       
PG25 -15926.363688   8086.632412  19499.639094     -2.293761  9  7  6 117       
PG26  -3444.306835  25822.029845  -5170.649066     28.992311  7  3  5 115       
PG27   7030.047838  13625.959589 -21718.367990     -2.586803  9  8  8 112       
PG28  12589.599269 -22200.918417  -6564.241144    447.108354  7  6  9 106       
PG29 -26145.500336   4393.700952   1101.532432    616.888621  9  5  7 126       
PG30   9603.268484 -12222.107844 -21542.569444    -42.995526  7  6  7 110       
PG31   2516.152098  20041.355033  17195.270451    312.823331  6  7  9 101       
PG32   7816.149081  17455.765714  18623.743215   -124.425901  7  7  6  87       
*  2015  6 16  0 15  0.00000000
PG01  22125.898696  12210.710646   8434.382990     -4.223620 10  8  5  92       
PG02 -11951.321019 -21155.258586  11604.487814    572.336520 11  8  8 105       
PG03  14493.617968   5043.109433  21691.742487    350.717279  5  7  5 110       
PG04  19726.940481  17995.510562   -852.233761    -19.581230  8  5  7 100       
PG05  -4433.415203 -22986.447296 -12414.534400   -228.971826  6  6  8 129       
PG06   1730.013897 -17267.497150  20110.925682    185.424997  8  5  6 117       
PG07  18796.845135     34.482430 -18810.071658    468.896277  8  6  9 104       
PG08  -7688.377243  25126.780691   2663.720428 999999.999999
PG09  25584.496369  -6843.675160   2162.214539   -170.794879 10  5  5 104       
PG10   9066.202161 -24124.908678   5023.880148   -179.068357  9  6  9  95       
PG11  24246.405305  10980.607409  -1269.558391   -585.257201 11  8  7 103       
PG12 -12391.481603  -8883.994994  21674.458648    301.799930  8  9  9  94       
PG13  -6955.547005 -13679.190935 -21805.910302   -123.733389  9  8  7 121       
PG14 -16610.996969  14579.862564  14855.386958     55.760359 10  5  7 123       
PG15 -18694.826324  -6973.975468 -17769.669719   -255.189168  9  9  9 128       
PG16   2129.074463  23092.067912 -12674.278891   -118.505842  7  8  5 111       
PG17  16065.480708 -15044.473471  15011.389296   -176.048587  8  5  7 109       
PG18 -14804.612202  14891.262012 -15586.058534    409.686464 10  7  9 109       
PG19  16206.849722   9737.602172 -19039.158930   -513.456824  6  7  9 112       
PG20 -13210.049028 -12362.603203 -19622.713070    329.975853  8  9  6 113       
PG21 -17947.302833   2815.947196 -18790.297528   -455.616542  9  6  5 125       
PG22  -9371.981345  23899.167229  -6208.337263    361.366953  7  5  8 125       
PG23  23895.554890   1459.524021  12116.482481   -115.090983  8  8  6 107       
PG24 -22038.737047 -13825.881887   5682.662530    -49.986052  8 10 10 121       
PG25 -15459.686294   5814.198097  20659.615093     -2.297478  8  7  6 112       
PG26  -3792.792452  26179.536375  -2358.958812     28.990278  7  3  5 103       
PG27   4644.915207  14334.491875 -21892.391922     -2.584354  8  8  8 119       
PG28  12459.481059 -21209.059613  -9283.872183    447.110302  7  6  9 103       
PG29 -25914.740695   4114.379895   3966.925642    616.890669  8  4  7 115       
PG30  11269.116559 -10393.315220 -21701.261909    -42.989457  6  6  6 103       
PG31    988.656450  18670.855259  18856.340317    312.822220  6  6  9 106       
PG32   7038.403242  19337.703519  17057.294350   -124.417256  7  6  6  78       
*  2015  6 16  0 30  0.00000000
PG01  22598.904313  12909.166888   5742.253300     -4.223157  9  7  5  97       
PG02 -10725.048337 -20460.182827  13859.879905    572.338767 10  7  7 109       
PG03  14025.757280   7455.832663  21297.248477    350.723680  5  7  5 111       
PG04  19372.515409  18081.570715  -3635.218943    -19.583289  8  6  7  92       
PG05  -3955.644181 -24207.804792  -9994.086575   -228.967777  5  5  8 122       
PG06   3585.681199 -15817.855899  21036.307779    185.432810  8  5  5 113       
PG07  20267.885162   1487.156443 -17195.575383    468.898268  8  6  9 101       
PG08  -7796.832888  24603.012536   5526.024667 999999.999999
PG09  25289.984960  -6459.300547   4971.730196   -170.798785  9  5  5 110       
PG10   9252.556199 -23290.526219   7733.185245   -179.067844  8  5  8  89       
PG11  23867.497297  11295.612872  -3956.648072   -585.259273 10  7  7  98       
PG12 -11811.938676 -11261.327882  20902.008631    301.802728  7  8  9  87       
PG13  -4553.234371 -14281.604583 -22064.441251   -123.735636  9  8  7 122       
PG14 -18145.114411  14810.031014  12614.672755     55.758283 10  6  6 121       
PG15 -16819.068235  -7919.955165 -19169.829661   -255.191052  9  8  9 119       
PG16   1652.289121  24317.264577 -10159.806075   -118.502129  6  8  5 102       
PG17  17597.487698 -15338.435396  12768.046849   -176.050100  8  5  7 110       
PG18 -14742.697494  12887.260615 -17309.277093    409.689721  9  6  9 106       
PG19  14098.742291  10362.083162 -20315.548205   -513.458037  5  7  8 120       
PG20 -12829.771689 -14485.831618 -18362.877776    329.979186  8  8  6 120       
PG21 -19547.826731   1300.360022 -17390.044597   -455.619675 10  6  5 127       
PG22  -9584.802238  22957.368342  -8811.946628    361.370738  7  6  8 119       
PG23  22569.765865   2143.299692  14338.664004   -115.093124  8  7  5 107       
PG24 -22257.498211 -14339.836555   2906.629814    -49.986621  7  9 10 117       
PG25 -15097.169747   3410.855409  21459.674732     -2.301153  8  6  6 112       
PG26  -4064.800382  26239.180135    493.344111     28.988250  7  3  5 102       
PG27   2301.320549  15168.991908 -21690.431483     -2.581992  8  7  7 125       
PG28  12311.949451 -19913.472199 -11838.736557    447.112865  7  6  8 116       
PG29 -25391.228568   3732.101422   6763.871575    616.892908  8  4  7 120       
PG30  13023.956057  -8655.194652 -21486.959784    -42.983373  6  6  6  95       
PG31   -733.645733  17272.367833  20192.738059    312.821310  7  6  8 106       
PG32   6409.358298  21068.389882  15202.804981   -124.408473  7  6  6  62       
*  2015  6 16  0 45  0.00000000
PG01  22861.512106  13394.645177   2952.296261     -4.222726  9  7  5  99       
PG02  -9271.578205 -19691.359425  15886.663754    572.340964  9  6  7 107       
PG03  13691.115613   9825.043065  20536.639173    350.730056  5  7  4 108       
PG04  18775.028186  18002.898410  -6356.968732    -19.585179  8  6  6 107       
PG05  -3569.639695 -25169.453169  -7400.211477   -228.963650  5  4  7 126       
PG06   5582.362123 -14417.027488  21599.830046    185.440645  8  5  5 119       
PG07  21656.663954   2732.846117 -15287.177128    468.900536  9  6  9  99       
PG08  -7891.322905  23766.409877   8291.399530 999999.999999
PG09  24728.702544  -5935.295950   7695.776313   -170.802729  8  5  6  95       
PG10   9441.982986 -22164.251924  10304.245434   -179.067506  8  5  8 101       
PG11  23222.803074  11534.901219  -6576.745716   -585.261991  9  6  7  87       
PG12 -11385.964974 -13558.287712  19768.202113    301.805798  6  8  9 105       
PG13  -2180.944790 -15016.374946 -21948.174706   -123.739380  9  7  6 119       
PG14 -19416.247238  15034.322334  10157.922439     55.755931  9  6  6 120       
PG15 -14864.849705  -9017.447047 -20245.388241   -255.192612  9  8  8 127       
PG16   1297.147177  25275.350767  -7467.422295   -118.498585  6  7  5 116       
PG17  18865.768749 -15619.546069  10306.157528   -176.051841  8  5  8 113       
PG18 -14752.942078  10702.289189 -18719.891876    409.692029  9  6  9 110       
PG19  11907.352809  11140.152075 -21252.074103   -513.458935  4  7  8 121       
PG20 -12556.343097 -16467.994598 -16791.164399    329.981902  8  8  7 116       
PG21 -21068.376150    -27.912715 -15677.875460   -455.622502 10  6  5 125       
PG22  -9812.422851  21740.110902 -11260.974761    361.374424  8  6  8 120       
PG23  21063.934504   2986.543526  16321.294321   -115.095157  7  7  4 107       
PG24 -22246.326758 -14656.822746     80.990475    -49.986660  7  9 10 115       
PG25 -14857.981935    923.194467  21886.246597     -2.304847  7  6  7 101       
PG26  -4296.516125  25992.458671   3337.152534     28.986232  7  4  5 109       
PG27     44.719670  16109.996663 -21115.590308     -2.579591  8  7  7 123       
PG28  12186.497187 -18329.635938 -14182.165525    447.115229  7  6  8 124       
PG29 -24597.546625   3214.851035   9444.147403    616.894657  8  3  6 121       
PG30  14831.253542  -7039.559984 -20903.552144    -42.977300  6  6  6  91       
PG31  -2629.350085  15889.128540  21182.549527    312.820354  7  6  7 104       
PG32   5914.853410  22608.601876  13092.460715   -124.399970  7  5  6  73       
*  2015  6 16  1  0  0.00000000
PG01  22884.292928  13690.755795    112.086191     -4.222253  9  7  5 109       
PG02  -7601.639813 -18887.587505  17651.605295    572.342837  8  6  6 109       
PG03  13485.067045  12102.889339  19422.869157    350.736528  5  7  4 111       
PG04  17923.652695  17794.137860  -8971.961457    -19.586759  7  7  6 103       
PG05  -3244.715097 -25848.259363  -4677.770848   -228.959846  5  4  7 114       
PG06   7685.581063 -13099.374092  21791.787407    185.448446  8  5  4 114       
PG07  22919.191892   3769.440959 -13118.300955    468.902792  9  6  8  97       
PG08  -8010.759834  22628.103059  10911.111183 999999.999999
PG09  23927.944568  -5245.142850  10287.510817   -170.806556  7  4  6 105       
PG10   9668.705550 -20762.955841  12690.606600   -179.068186  8  5  7  95       
PG11  22314.920222  11731.313790  -9086.085585   -585.263968  9  6  7 104       
PG12 -11105.731064 -15725.824970  18293.364229    301.808899  6  8  9  92       
PG13    114.807073 -15867.395188 -21459.424182   -123.742395  9  7  6 117       
PG14 -20410.340608  15213.531025   7526.654712     55.753038  9  7  5 115       
PG15 -12875.879469 -10259.709427 -20977.470768   -255.194859  9  8  8 130       
PG16   1031.377366  25938.822880  -4643.994240   -118.494860  7  7  5 110       
PG17  19857.090743 -15847.598073   7667.166678   -176.053488  8  5  8 116       
PG18 -14856.080242   8377.126912 -19792.135862    409.694893  8  6  9 113       
PG19   9679.448638  12069.482122 -21832.093387   -513.459887  4  7  7 122       
PG20 -12371.776485 -18270.545083 -14933.757028    329.985335  8  7  7 128       
PG21 -22466.063330  -1164.070764 -13686.577182   -455.625680 11  6  6 124       
PG22 -10086.450522  20266.885901 -13512.120313    361.377666  8  6  8 122       
PG23  19418.002915   3999.756614  18030.924287   -115.097325  6  7  4 105       
PG24 -21981.505235 -14804.701545  -2746.032419    -49.987655  7  8 10 115       
PG25 -14753.387602  -1599.168569  21932.351913     -2.308551  7  6  7 113       
PG26  -4525.185834  25439.666023   6123.494061     28.984272  7  4  5 114       
PG27  -2083.503629  17130.923784 -20177.385928     -2.577193  8  7  7 125       
PG28  12119.822978 -16482.473595 -16270.860450    447.117348  7  6  8 118       
PG29 -23563.660238   2535.815564  11961.583514    616.896722  8  2  6 135       
PG30  16650.082915  -5571.518007 -19961.248240    -42.971202  5  6  5  77       
PG31  -4669.569943  14560.701530  21809.911183    312.819333  8  6  6 105       
PG32   5534.090930  23923.841879  10762.439771   -124.391523  7  4  6  40       
*  2015  6 16  1 15  0.00000000
PG01  22644.291493  13826.933539  -2730.036867     -4.221821  8  6  4 110       
PG02  -5733.460709 -18085.945575  19125.625930    572.344881  7  6  5 114       
PG03  13395.183095  14243.789995  17974.971293    350.742908  5  7  4 114       
PG04  16815.246563  17492.338640 -11436.700119    -19.588377  7  8  5 102       
PG05  -2946.892654 -26229.084898  -1873.982369   -228.956014  5  4  6 111       
PG06   9855.357631 -11893.288578  21608.861845    185.456292  7  5  4 118       
PG07  24013.435035   4603.260614 -10726.552863    468.904730  9  7  8  84       
PG08  -8191.703867  21208.391635  13338.899596 999999.999999
PG09  22921.179460  -4368.462963  12702.354820   -170.810546  7  4  6 104       
PG10   9963.770294 -19111.940234  14849.044134   -179.068526  8  6  7 104       
PG11  21153.749054  11917.371366 -11443.197259   -585.266382  8  6  7 111       
PG12 -10955.274148 -17718.304695  16503.617230    301.811970  6  7  9  96       
PG13   2291.152264 -16811.167433 -20606.726885   -123.745281  9  6  6 118       
PG14 -21121.976175  15307.720567   4765.662623     55.750457  9  7  4 111       
PG15 -10894.991898 -11632.355406 -21352.880295   -255.196686  9  7  7 129       
PG16    818.496931  26288.699010  -1738.924558   -118.491482  7  7  5 114       
PG17  20566.946526 -15981.856544   4895.904019   -176.055176  8  5  8 120       
PG18 -15066.146731   5956.975409 -20506.629777    409.697456  7  6  8 116       
PG19   7461.539306  13139.556940 -22044.710056   -513.460673  5  7  7 118       
PG20 -12252.187688 -19859.810546 -12821.765435    329.988288  8  7  7 122       
PG21 -23700.173314  -2111.743940 -11453.534970   -455.628580 11  6  7 116       
PG22 -10434.867770  18564.714880 -15525.500180    361.381441  8  7  8 119       
PG23  17674.443103   5185.838912  19438.452369   -115.099556  6  7  4 107       
PG24 -21446.475593 -14816.109005  -5526.236059    -49.988265  7  8 10 111       
PG25 -14786.317502  -4105.336631  21597.698724     -2.312244  6  6  7 113       
PG26  -4787.476559  24589.922923   8804.376735     28.982273  7  5  5 104       
PG27  -4047.447403  18199.042063 -18891.612034     -2.574743  7  6  7 126       
PG28  12144.149382 -14405.604003 -18065.849448    447.119898  7  6  9 108       
PG29 -22325.753461   1674.619987  14272.861920    616.898738  7  2  6 125       
PG30  18436.582502  -4268.668915 -18676.390691    -42.965072  5  6  5  95       
PG31  -6818.898991  13321.547590  22065.202282    312.818520  8  6  5 109       
PG32   5240.619068  24985.498105   8252.302757   -124.382851  7  4  6  51       
*  2015  6 16  1 30  0.00000000
PG01  22125.984442  13837.136700  -5525.763483     -4.221390  8  6  4 113       
PG02  -3692.286064 -17320.412550  20284.218171    572.347023  6  5  5 116       
PG03  13401.795063  16206.012722  16217.739040    350.749263  5  7  4 107       
PG04  15454.576075  17135.443401 -13710.360487    -19.590362  8  8  5 106       
PG05  -2640.432195 -26305.346414    962.418401   -228.951985  6  4  6 125       
PG06  12047.572288 -10820.194456  21054.180374    185.464105  7  5  4 113       
PG07  24900.874401   5248.570838  -8153.056869    468.906732  9  7  8  77       
PG08  -8466.719136  19536.063865  15531.857973 999999.999999
PG09  21746.746251  -3292.008626  14898.758978   -170.814610  6  4  6 105       
PG10  10353.582606 -17244.069500  16740.463114   -179.070408  8  6  7 105       
PG11  19756.157565  12123.901865 -13609.501489   -585.268387  7  6  7 100       
PG12 -10911.265981 -19495.091536  14430.381231    301.815004  6  7  9 103       
PG13   4310.294191 -17817.664082 -19404.689035   -123.748133  8  7  6 113       
PG14 -21554.493252  15277.908661   1922.278197     55.748016  8  7  3 120       
PG15  -8962.655686 -13113.723875 -21364.363423   -255.198691  9  6  6 126       
PG16    619.454877  26315.274299   1196.754805   -118.487836  8  7  6 121       
PG17  20999.650200 -15982.773564   2039.855146   -176.056748  7  5  8 122       
PG18 -15389.815484   3489.801762 -20850.782260    409.700287  6  6  8 118       
PG19   5298.290997  14331.906213 -21885.020426   -513.461819  6  7  7 121       
PG20 -12168.817130 -21208.146817 -10490.744229    329.991833  8  6  7 118       
PG21 -24733.696407  -2882.500417  -9019.873502   -455.632051 11  7  7 107       
PG22 -10880.736512  16667.226924 -17265.416380    361.384936  7  7  7 127       
PG23  15876.764689   6539.781587  20519.602097   -115.101877  6  7  4 111       
PG24 -20632.580039 -14727.043697  -8212.237936    -49.988620  7  7  9 104       
PG25 -14951.281527  -6544.919923  20888.651669     -2.315891  6  6  7 107       
PG26  -5117.861344  23460.878015  11333.618311     28.980295  7  5  5 120       
PG27  -5817.891754  19276.696326 -17280.091485     -2.572329  7  6  8 123       
PG28  12285.712645 -12140.217141 -19533.377698    447.122156  8  6  9 108       
PG29 -20924.838503    618.311870  16338.261838    616.900925  7  3  7 129       
PG30  20145.533388  -3140.604023 -17071.166204    -42.959023  5  6  5  95       
PG31  -9036.616077  12199.813040  21945.130425    312.817364  8  6  5 109       
PG32   5003.516299  25771.791891   5604.349748   -124.374137  7  4  6  69       
*  2015  6 16  1 45  0.00000000
PG01  21321.967739  13758.385379  -8227.606461     -4.220992  8  6  4 127       
PG02  -1509.653225 -16620.607871  21107.810028    572.349216  6  5  5 114       
PG03  13478.848619  17953.113358  14181.308970    350.755609  5  7  4 111       
PG04  13854.259780  16760.767075 -15755.388263    -19.592286  8  8  4 100       
PG05  -2289.437353 -26079.251967   3782.050755   -228.947916  7  5  6 119       
PG06  14215.498776  -9893.826219  20137.262800    185.471896  7  5  4 114       
PG07  25547.932115   5726.806417  -5441.751546    468.908874  9  7  8  75       
PG08  -8862.893713  17647.380032  17451.250873 999999.999999
PG09  20446.376945  -2010.378654  16838.918343   -170.818636  5  3  6 105       
PG10  10858.640948 -15198.584012  18330.712623   -179.070018  7  5  6 107       
PG11  18145.410487  12378.760795 -15549.840656   -585.270768  7  6  7 107       
PG12 -10944.069218 -21021.939075  12109.792399    301.817568  7  7  9 107       
PG13   6140.741419 -18851.444144 -17873.739902   -123.751258  8  7  6 105       
PG14 -21719.778822  15087.743508   -954.427718     55.745373  8  7  3 120       
PG15  -7115.569755 -14675.537238 -21010.787488   -255.200568  8  6  5 128       
PG16    394.390687  26018.516485   4111.333908   -118.484635  8  7  6 124       
PG17  21168.097141 -15813.689388   -851.638749   -176.058494  7  5  8 120       
PG18 -15826.069944   1024.569816 -20819.026077    409.703145  5  6  8 115       
PG19   3230.998452  15620.648316 -21354.277879   -513.462524  6  7  6 114       
PG20 -12089.254670 -22294.878874  -7980.130852    329.994877  7  6  7 127       
PG21 -25534.683079  -3495.044881  -6429.569786   -455.634878 11  8  7 103       
PG22 -11441.106320  14613.473892 -18701.044299    361.388544  7  7  7 127       
PG23  14067.986832   8048.651216  21255.340711   -115.103479  6  7  5 107       
PG24 -19539.512421 -14575.336281 -10758.260665    -49.989351  7  7  9 102       
PG25 -15234.626645  -8869.796569  19818.080453     -2.319600  5  6  7 104       
PG26  -5547.092689  22078.091338  13667.644547     28.978288  7  5  5 120       
PG27  -7373.242501  20322.740871 -15370.322478     -2.569880  7  6  8 122       
PG28  12563.499661  -9733.611675 -20645.699174    447.124129  8  6  9 104       
PG29 -19405.193343   -637.945038  18122.339592    616.902563  7  3  7 122       
PG30  21731.998888  -2188.718410 -15173.219218    -42.952986  5  6  5  89       
PG31 -11278.084106  11216.380259  21452.714377    312.816400  9  6  6 101       
PG32   4788.732831  26268.482136   2862.952955   -124.365395  7  4  6  99       
*  2015  6 16  2  0  0.00000000
PG01  20233.348484  13629.194257 -10789.676668     -4.220562  7  5  5 128       
PG02    777.556162 -16010.692492  21582.075535    572.351271  6  5  6 108       
PG03  13595.017826  19455.179341  11900.649915    350.761968  5  7  4 112       
PG04  12034.436020  16403.520506 -17538.041715    -19.594147  8  9  3 110       
PG05  -1859.474012 -25561.702165   6535.778728   -228.944077  7  5  6 116       
PG06  16311.445084  -9119.817432  18873.860017    185.479747  7  5  5 108       
PG07  25927.214413   6065.534460  -2638.658561    468.910793  9  8  7  87       
PG08  -9400.587101  15584.760342  19063.251083 999999.999999
PG09  19063.600635   -526.431067  18489.423436   -170.822590  5  3  6 111       
PG10  11492.528897 -13019.648952  19591.289231   -179.070356  7  5  6 106       
PG11  16350.387804  12705.686309 -17232.943454   -585.273100  7  7  6 116       
PG12 -11019.037738 -22272.133150   9582.051192    301.820693  7  7  9  98       
PG13   7758.302905 -19872.983416 -16039.798293   -123.754514  8  7  6 105       
PG14 -21637.729183  14705.103859  -3814.497904     55.742885  8  7  3 119       
PG15  -5385.399289 -16283.825851 -20297.222778   -255.202399  8  5  5 129       
PG16    104.434368  25408.082035   6953.399056   -118.480683  9  7  7 116       
PG17  21093.191351 -15442.451590  -3728.240845   -176.060365  7  5  7 120       
PG18 -16366.218735  -1390.559434 -20412.885121    409.706210  5  6  8 116       
PG19   1296.169874  16973.327115 -20459.969711   -513.463309  6  7  6 112       
PG20 -11978.822564 -23106.990938  -5332.608667    329.998263  7  5  7 119       
PG21 -26077.373942  -3974.155066  -3728.564042   -455.637336 11  8  7  97       
PG22 -12126.174504  12446.531805 -19807.025111    361.392250  7  7  7 128       
PG23  12289.127439   9691.870569  21632.232169   -115.105680  6  6  5 101       
PG24 -18175.463222 -14399.059020 -13120.890056    -49.989711  7  7  9 118       
PG25 -15615.126509 -11035.777175  18405.092531     -2.323319  5  6  6  98       
PG26  -6100.824441  20474.123672  15766.242473     28.976320  7  5  6 119       
PG27  -8700.181001  21294.126874 -13195.022353     -2.567487  7  5  8 113       
PG28  12988.297366  -7237.454640 -21381.739406    447.126649  8  6  9  98       
PG29 -17812.688580  -2090.494976  19594.531426    616.904478  7  4  7 125       
PG30  23152.962870  -1406.344184 -13015.175331    -42.947046  6  6  5  95       
PG31 -13496.289143  10384.210310  20597.169249    312.815369  9  6  6 108       
PG32   4560.540435  26469.305624     73.872429   -124.356654  7  4  6  73       
__SP3_TEXT__
      # https://cddis.nasa.gov/archive/gnss/products/1849/igs18492.sp3.Z
      # mirrored: ftp://garner.ucsd.edu/pub/products/1849/igs18492.sp3.Z
      f.path
    },
    :antex => Tempfile::open{|f|
      f.write(<<-__ANTEX_TEXT__)
     1.4            M                                       ANTEX VERSION / SYST
A                                                           PCV TYPE / REFANT   
                                                            END OF HEADER       
                                                            START OF ANTENNA    
BLOCK IIR-M         G12                 G058      2006-052A TYPE / SERIAL NO    
                                             0    29-JAN-17 METH / BY / # / DATE
     0.0                                                    DAZI                
     0.0  17.0   1.0                                        ZEN1 / ZEN2 / DZEN  
     2                                                      # OF FREQUENCIES    
  2006    11    17     0     0    0.0000000                 VALID FROM          
IGS14_2196                                                  SINEX CODE          
   G01                                                      START OF FREQUENCY  
     10.20     -5.60    767.80                              NORTH / EAST / UP   
   NOAZI   10.70   10.10    8.00    4.60    0.50   -3.80   -7.50   -9.70  -10.30   -9.50   -7.40   -4.10    0.30    6.00   12.10   22.00   30.40   40.60
   G01                                                      END OF FREQUENCY    
   G02                                                      START OF FREQUENCY  
     10.20     -5.60    767.80                              NORTH / EAST / UP   
   NOAZI   10.70   10.10    8.00    4.60    0.50   -3.80   -7.50   -9.70  -10.30   -9.50   -7.40   -4.10    0.30    6.00   12.10   22.00   30.40   40.60
   G02                                                      END OF FREQUENCY    
                                                            END OF ANTENNA      
                                                            START OF ANTENNA    
BLOCK IIR-A         G18                 G054      2001-004A TYPE / SERIAL NO    
                                             0    29-JAN-17 METH / BY / # / DATE
     0.0                                                    DAZI                
     0.0  17.0   1.0                                        ZEN1 / ZEN2 / DZEN  
     2                                                      # OF FREQUENCIES    
  2001     1    30     0     0    0.0000000                 VALID FROM          
  2018     1    23    23    59   59.9999999                 VALID UNTIL         
IGS14_2196                                                  SINEX CODE          
   G01                                                      START OF FREQUENCY  
     13.90      0.30   1248.60                              NORTH / EAST / UP   
   NOAZI   -6.10   -5.20   -3.30   -1.00    1.40    3.50    4.70    4.90    4.10    2.80    0.80   -1.00   -2.10   -2.10   -1.40   -0.80    2.00    6.40
   G01                                                      END OF FREQUENCY    
   G02                                                      START OF FREQUENCY  
     13.90      0.30   1248.60                              NORTH / EAST / UP   
   NOAZI   -6.10   -5.20   -3.30   -1.00    1.40    3.50    4.70    4.90    4.10    2.80    0.80   -1.00   -2.10   -2.10   -1.40   -0.80    2.00    6.40
   G02                                                      END OF FREQUENCY    
                                                            END OF ANTENNA      
                                                            START OF ANTENNA    
BLOCK IIF           G24                 G065      2012-053A TYPE / SERIAL NO    
                                             0    29-JAN-17 METH / BY / # / DATE
     0.0                                                    DAZI                
     0.0  17.0   1.0                                        ZEN1 / ZEN2 / DZEN  
     2                                                      # OF FREQUENCIES    
  2012    10     4     0     0    0.0000000                 VALID FROM          
IGS14_2196                                                  SINEX CODE          
   G01                                                      START OF FREQUENCY  
    394.00      0.00   1407.10                              NORTH / EAST / UP   
   NOAZI    6.10    4.40    2.80    1.30   -0.20   -1.40   -2.80   -3.90   -4.40   -4.40   -3.70   -2.30   -0.20    3.00    5.70   12.40   18.20   23.50
   G01                                                      END OF FREQUENCY    
   G02                                                      START OF FREQUENCY  
    394.00      0.00   1407.10                              NORTH / EAST / UP   
   NOAZI    6.10    4.40    2.80    1.30   -0.20   -1.40   -2.80   -3.90   -4.40   -4.40   -3.70   -2.30   -0.20    3.00    5.70   12.40   18.20   23.50
   G02                                                      END OF FREQUENCY    
                                                            END OF ANTENNA      
                                                            START OF ANTENNA    
BLOCK IIF           G25                 G062      2010-022A TYPE / SERIAL NO    
                                             0    29-JAN-17 METH / BY / # / DATE
     0.0                                                    DAZI                
     0.0  17.0   1.0                                        ZEN1 / ZEN2 / DZEN  
     2                                                      # OF FREQUENCIES    
  2010     5    28     0     0    0.0000000                 VALID FROM          
IGS14_2196                                                  SINEX CODE          
   G01                                                      START OF FREQUENCY  
    394.00      0.00   1517.40                              NORTH / EAST / UP   
   NOAZI    6.10    4.40    2.80    1.30   -0.20   -1.40   -2.80   -3.90   -4.40   -4.40   -3.70   -2.30   -0.20    3.00    5.70   12.40   18.20   23.50
   G01                                                      END OF FREQUENCY    
   G02                                                      START OF FREQUENCY  
    394.00      0.00   1517.40                              NORTH / EAST / UP   
   NOAZI    6.10    4.40    2.80    1.30   -0.20   -1.40   -2.80   -3.90   -4.40   -4.40   -3.70   -2.30   -0.20    3.00    5.70   12.40   18.20   23.50
   G02                                                      END OF FREQUENCY    
                                                            END OF ANTENNA      
                                                            START OF ANTENNA    
BLOCK IIR-M         G29                 G057      2007-062A TYPE / SERIAL NO    
                                             0    29-JAN-17 METH / BY / # / DATE
     0.0                                                    DAZI                
     0.0  17.0   1.0                                        ZEN1 / ZEN2 / DZEN  
     2                                                      # OF FREQUENCIES    
  2007    12    20     0     0    0.0000000                 VALID FROM          
IGS14_2196                                                  SINEX CODE          
   G01                                                      START OF FREQUENCY  
     10.90     -4.50    791.80                              NORTH / EAST / UP   
   NOAZI   10.70   10.10    8.00    4.60    0.50   -3.80   -7.50   -9.70  -10.30   -9.50   -7.40   -4.10    0.30    6.00   12.10   22.00   30.40   40.60
   G01                                                      END OF FREQUENCY    
   G02                                                      START OF FREQUENCY  
     10.90     -4.50    791.80                              NORTH / EAST / UP   
   NOAZI   10.70   10.10    8.00    4.60    0.50   -3.80   -7.50   -9.70  -10.30   -9.50   -7.40   -4.10    0.30    6.00   12.10   22.00   30.40   40.60
   G02                                                      END OF FREQUENCY    
                                                            END OF ANTENNA      
                                                            START OF ANTENNA    
BLOCK IIR-M         G31                 G052      2006-042A TYPE / SERIAL NO    
                                             0    29-JAN-17 METH / BY / # / DATE
     0.0                                                    DAZI                
     0.0  17.0   1.0                                        ZEN1 / ZEN2 / DZEN  
     2                                                      # OF FREQUENCIES    
  2006     9    25     0     0    0.0000000                 VALID FROM          
IGS14_2196                                                  SINEX CODE          
   G01                                                      START OF FREQUENCY  
     -0.80      5.80    912.50                              NORTH / EAST / UP   
   NOAZI   10.70   10.10    8.00    4.60    0.50   -3.80   -7.50   -9.70  -10.30   -9.50   -7.40   -4.10    0.30    6.00   12.10   22.00   30.40   40.60
   G01                                                      END OF FREQUENCY    
   G02                                                      START OF FREQUENCY  
     -0.80      5.80    912.50                              NORTH / EAST / UP   
   NOAZI   10.70   10.10    8.00    4.60    0.50   -3.80   -7.50   -9.70  -10.30   -9.50   -7.40   -4.10    0.30    6.00   12.10   22.00   30.40   40.60
   G02                                                      END OF FREQUENCY    
                                                            END OF ANTENNA      
__ANTEX_TEXT__
      # https://files.igs.org/pub/station/general/igs14.atx
      f.path
    },
    :rinex_clk => Tempfile::open{|f|
      f.write(<<-__RINEX_CLK_TEXT__)
     3.00           C                                       RINEX VERSION / TYPE
CCLOCK              IGSACC @ NOAA NGS                       PGM / RUN BY / DATE 
GPS week: 1849   Day: 2   MJD: 57189                        COMMENT             
THE COMBINED CLOCKS ARE A WEIGHTED AVERAGE OF:              COMMENT             
  cod emr esa gfz grg jpl                                   COMMENT             
THE FOLLOWING REFERENCE CLOCKS WERE USED BY ACs:            COMMENT             
  WSRT AMC2 BRUX HRAO                                       COMMENT             
THE COMBINED CLOCKS ARE ALIGNED TO GPS TIME                 COMMENT             
USING THE SATELLITE BROADCAST EPHEMERIDES                   COMMENT             
All clocks have been re-aligned to the IGS time scale: IGST COMMENT             
    16                                                      LEAP SECONDS        
     1    AS                                                # / TYPES OF DATA   
IGS  IGSACC @ NOAA NGS                                      ANALYSIS CENTER     
     6                                                      # OF SOLN SATS      
G12 G18 G24 G25 G29 G31                                     PRN LIST            
G                   igs08_1848.atx                          SYS / PCVS APPLIED  
                                                            END OF HEADER       
AS G12  2015 06 15 23 45  0.000000  2    3.017937472687e-04  1.069824072610e-11
AS G18  2015 06 15 23 45  0.000000  2    4.096815344517e-04  9.225410060960e-12
AS G24  2015 06 15 23 45  0.000000  2   -4.998574751545e-05  2.372704308220e-11
AS G25  2015 06 15 23 45  0.000000  2   -2.290169594092e-06  1.683218228880e-11
AS G29  2015 06 15 23 45  0.000000  2    6.168866864097e-04  1.206217360840e-11
AS G31  2015 06 15 23 45  0.000000  2    3.128244102077e-04  2.173867579920e-11
AS G12  2015 06 15 23 50  0.000000  2    3.017948525918e-04  1.300769315700e-11
AS G18  2015 06 15 23 50  0.000000  2    4.096823340968e-04  8.242414325510e-12
AS G24  2015 06 15 23 50  0.000000  2   -4.998578937856e-05  3.095238106380e-11
AS G25  2015 06 15 23 50  0.000000  2   -2.291410963946e-06  2.242880773880e-11
AS G29  2015 06 15 23 50  0.000000  2    6.168873857128e-04  1.695910016600e-11
AS G31  2015 06 15 23 50  0.000000  2    3.128241216228e-04  1.904362802980e-11
AS G12  2015 06 15 23 55  0.000000  2    3.017958412577e-04  1.171495359430e-11
AS G18  2015 06 15 23 55  0.000000  2    4.096833491457e-04  1.008770038860e-11
AS G24  2015 06 15 23 55  0.000000  2   -4.998596967628e-05  2.600074192880e-11
AS G25  2015 06 15 23 55  0.000000  2   -2.292650290468e-06  2.671557682290e-11
AS G29  2015 06 15 23 55  0.000000  2    6.168880208367e-04  1.729095211710e-11
AS G31  2015 06 15 23 55  0.000000  2    3.128236493567e-04  1.807462018720e-11
AS G12  2015 06 16 00 00  0.000000  2    3.017967728708e-04  1.000801049580e-11
AS G18  2015 06 16 00 00  0.000000  2    4.096840539308e-04  1.041670195750e-11
AS G24  2015 06 16 00 00  0.000000  2   -4.998614775959e-05  1.699628132880e-11
AS G25  2015 06 16 00 00  0.000000  2   -2.293760646361e-06  1.805118466830e-11
AS G29  2015 06 16 00 00  0.000000  2    6.168886213338e-04  2.220055594770e-11
AS G31  2015 06 16 00 00  0.000000  2    3.128233311248e-04  1.215284180360e-11
AS G12  2015 06 16 00 05  0.000000  2    3.017980078016e-04  1.152529430320e-11
AS G18  2015 06 16 00 05  0.000000  2    4.096851745816e-04  1.517949585220e-11
AS G24  2015 06 16 00 05  0.000000  2   -4.998569129850e-05  1.987308774570e-11
AS G25  2015 06 16 00 05  0.000000  2   -2.295014987154e-06  1.568891027900e-11
AS G29  2015 06 16 00 05  0.000000  2    6.168894672506e-04  1.906237292480e-11
AS G31  2015 06 16 00 05  0.000000  2    3.128231387506e-04  1.007829428500e-11
AS G12  2015 06 16 00 10  0.000000  2    3.017987334831e-04  8.726251168980e-12
AS G18  2015 06 16 00 10  0.000000  2    4.096859333261e-04  1.403166740100e-11
AS G24  2015 06 16 00 10  0.000000  2   -4.998597422529e-05  1.727695888430e-11
AS G25  2015 06 16 00 10  0.000000  2   -2.296262879345e-06  1.460867818340e-11
AS G29  2015 06 16 00 10  0.000000  2    6.168900483001e-04  1.556536485070e-11
AS G31  2015 06 16 00 10  0.000000  2    3.128226535741e-04  1.258498073020e-11
AS G12  2015 06 16 00 15  0.000000  2    3.017999301583e-04  1.006627990480e-11
AS G18  2015 06 16 00 15  0.000000  2    4.096864636193e-04  1.460541676660e-11
AS G24  2015 06 16 00 15  0.000000  2   -4.998605241609e-05  1.970841363000e-11
AS G25  2015 06 16 00 15  0.000000  2   -2.297477664413e-06  1.598459869060e-11
AS G29  2015 06 16 00 15  0.000000  2    6.168906691983e-04  1.729396319140e-11
AS G31  2015 06 16 00 15  0.000000  2    3.128222195893e-04  1.358710059900e-11
__RINEX_CLK_TEXT__
      # modified version. original data are
      # https://cddis.nasa.gov/archive/gnss/products/1849/igs1849[12].clk.Z
      # mirrored: ftp://garner.ucsd.edu/pub/products/1849/igs1849[12].clk.Z
      f.path
    },
  }}
  let(:solver){
    res = GPS::Solver::new
    res.correction = {:gps_ionospheric => :klobuchar, :gps_tropospheric => :hopfield}
    res
  }
  
  describe 'demo' do
    it 'calculates position without any error' do
      sn = solver.gps_space_node
      puts "RINEX NAV read: %d items."%[sn.read(input[:rinex_nav])]
      meas = GPS::Measurement::new
      input[:measurement].each{|prn, items|
        items.each{|k, v|
          meas.add(prn, k, v)
        }
      }
      expect(meas.to_hash).to eq(proc{|array|
            res = {}
            array.each{|prn, k, v|
              (res[prn][k] = v) rescue (res[prn] = {k => v})
            }
            res
          }.call(meas.to_a))
      expect(GPS::Measurement::new(meas.to_a).to_a.sort).to eq(meas.to_a.sort) # accept [[prn, k, v], ...]
      expect(GPS::Measurement::new(meas.to_hash).to_a.sort).to eq(meas.to_a.sort) # accept {prn => {k => v, ...}, ...}
      expect{GPS::Measurement::new({:sym => {1 => 2}})}.to raise_error
      expect{GPS::Measurement::new({1 => {:sym => 2}})}.to raise_error
      expect{GPS::Measurement::new({1 => [2, 3]})}.to raise_error
      
      t_meas = GPS::Time::new(1849, 172413)
      puts "Measurement time: #{t_meas.to_a} (a.k.a #{"%d/%d/%d %02d:%02d:%02d UTC"%[*t_meas.c_tm]})"
      expect(t_meas.c_tm).to eq([2015, 6, 15, 23, 53, 33])
      expect(GPS::Time::new(0, t_meas.serialize)).to eq(t_meas)
      
      sn.update_all_ephemeris(t_meas)
      
      [:alpha, :beta].each{|k|
        puts "Iono #{k}: #{sn.iono_utc.send(k)}"
      }
      proc{|raw|
        expect(raw.size).to eq(10)
        puts "Raw(IONO): #{raw.collect{|v| "0x%08X" % [v]}.join(', ')}"
        iono2 = GPS::Ionospheric_UTC_Parameters::parse(raw)
        [:alpha, :beta].collect{|f|
          sn.iono_utc.send(f).zip(iono2.send(f))
        }.flatten(1).zip([-30, -27, -24, -24, 11, 14, 16, 16]).each{|(a, b), sf|
          expect(a).to be_within((2 ** sf) * 2).of(b)
        }
        [
          [:A1, 2 ** -50], [:A0, 2 ** -30],
        ].each{|k, sf|
          #p [k, sf.to_f, sn.iono_utc.send(k) - iono2.send(k), sn.iono_utc.send(k), iono2.send(k)]
          expect(sn.iono_utc.send(k)).to be_within((sf || 1).to_f * 2).of(iono2.send(k))
        }
      }.call(sn.iono_utc.dump(t_meas))
      
      meas.each{|prn, k, v|
        eph = sn.ephemeris(prn)
        expect(eph.valid?(t_meas)).to eq(true)
        sc2rad = 3.1415926535898
        proc{|raw|
          expect(raw.size).to eq(30)
          eph2 = GPS::Ephemeris::new
          raw.each_slice(10).with_index{|subframe, i|
            puts "Raw(PRN:#{prn},SF:#{i+1}): #{subframe.collect{|v| "0x%08X" % [v]}.join(', ')}"
            eph2.parse(subframe)
          }
          expect(eph.WN % 1024).to be(eph2.WN % 1024)
          [
            #:URA,
            :SV_health, :iodc,
            [:t_GD, 2 ** -31], [:t_oc, 2 ** 4], # SF1
            [:a_f0, 2 ** -31], [:a_f1, 2 ** -43], [:a_f2, 2 ** -55], # SF1
            :iode, # SF2
            [:c_rs, 2 ** -5], [:delta_n, sc2rad * 2 ** -43], # SF2
            [:M0, sc2rad * 2 ** -31], [:c_uc, 2 ** -29], [:e, 2 ** -33], # SF2
            [:c_us, 2 ** -29], [:sqrt_A, 2 ** -19], [:t_oe, 2 ** 4], # SF2
            :fit_interval, # SF2
            [:c_ic, 2 ** -29], [:Omega0, sc2rad * 2 ** -31], [:c_is, 2 ** -29], # SF3
            [:i0, sc2rad * 2 ** -31], [:c_rc, 2 ** -5], [:omega, sc2rad * 2 ** -31], # SF3
            [:dot_Omega0, sc2rad * 2 ** -43], [:dot_i0, sc2rad * 2 ** -43], # SF3
          ].each{|k, sf|
            #p [k, sf.to_f, eph.send(k) - eph2.send(k), eph.send(k), eph2.send(k)]
            expect(eph.send(k)).to be_within((sf || 1).to_f * 2).of(eph2.send(k))
          }
        }.call(eph.dump(t_meas))
        proc{|raw| # Almanac -> Ephemeris
          expect(raw.size).to eq(10)
          puts "Raw(PRN:#{prn},Almanac): #{raw.collect{|v| "0x%08X" % [v]}.join(', ')}"
          eph2 = GPS::Ephemeris::new
          eph2.parse_almanac(raw)
          [
            :SV_health,
            [:t_oc, 2 ** 12], [:a_f0, 2 ** -20], [:a_f1, 2 ** -38], 
            [:M0, sc2rad * 2 ** -23], [:e, 2 ** -21],
            [:sqrt_A, 2 ** -11], [:t_oe, 2 ** 12],
            [:Omega0, sc2rad * 2 ** -23], [:i0, sc2rad * 2 ** -19],
            [:omega, sc2rad * 2 ** -23], [:dot_Omega0, sc2rad * 2 ** -38],
          ].each{|k, sf|
            #p [k, sf.to_f, eph.send(k) - eph2.send(k), eph.send(k), eph2.send(k)]
            expect(eph.send(k)).to be_within((sf || 1).to_f * 2).of(eph2.send(k))
          }
        }.call(eph.dump_almanac(t_meas))
        puts "XYZ(PRN:#{prn}): #{eph.constellation(t_meas)[0].to_a} (iodc: #{eph.iodc}, iode: #{eph.iode})"
      }
      
      run_solver = proc{
        pvt = solver.solve(meas, t_meas)
        [
          :error_code,
          :position_solved?,
          [:receiver_time, proc{|v| v.to_a}],
          :used_satellite_list,
          [:llh, proc{|llh| llh.to_a.zip([180.0 / Math::PI] * 2 + [1]).collect{|v, sf| v * sf}}],
          :receiver_error,
          [:velocity, proc{|xyz| xyz.to_a}],
          :receiver_error_rate,
          [:G_enu, proc{|mat| mat.to_s}],
          :fd,
          :fde_min,
          :fde_2nd,
        ].each{|fun, task|
          task ||= proc{|v| v}
          puts "pvt.#{fun}: #{task.call(pvt.send(fun))}"
        }
        pvt
      }

      puts "Normal solution ..."
      pvt = run_solver.call
      puts

      expect(pvt.position_solved?).to be(true)
      expect(pvt.receiver_time.to_a).to eq([1849, 172413])
      expect(pvt.llh.to_a).to eq([:lat, :lng, :alt].collect{|k| pvt.llh.send(k)})
      expect(pvt.llh.lat / Math::PI * 180).to be_within(1E-3).of(35.7) # latitude
      expect(pvt.llh.lng / Math::PI * 180).to be_within(1E-3).of(139.542) # longitude
      expect(pvt.llh.alt)                 .to be_within(1E-1).of(104.3) # altitude
      expect(pvt.receiver_error).to be_within(1E-1).of(1259087.8)
      expect(pvt.gdop).to be_within(1E-2).of(2.42)
      expect(pvt.pdop).to be_within(1E-2).of(2.17)
      expect(pvt.hdop).to be_within(1E-2).of(1.11)
      expect(pvt.vdop).to be_within(1E-2).of(1.87)
      expect(pvt.tdop).to be_within(1E-2).of(1.08)
      expect(pvt.velocity.to_a).to eq([:e, :n, :u].collect{|k| pvt.velocity.send(k)})
      expect(pvt.velocity.north).to be_within(1E-2).of(-0.86) # north
      expect(pvt.velocity.east) .to be_within(1E-2).of(-1.10) # east
      expect(pvt.velocity.down) .to be_within(1E-2).of(-0.22) # down
      expect(pvt.receiver_error_rate).to be_within(1E-2).of(-1061.86)
      expect(pvt.G.rows).to eq(6)
      expect(pvt.W.rows).to eq(6)
      expect(pvt.delta_r.rows).to eq(6)
      expect(pvt.G_enu.rows).to eq(6)
      expect(Math::sqrt(pvt.C[3, 3])).to be_within(1E-10).of(pvt.tdop)
      expect(Math::sqrt(pvt.C_enu[2, 2])).to be_within(1E-10).of(pvt.vdop)
      pvt.S.to_a.flatten.zip(
          ((pvt.G.t * pvt.W * pvt.G).inv * (pvt.G.t * pvt.W)).to_a.flatten).each{|a, b|
        expect(a).to be_within(1E-10).of(b)
      }
      pvt.S_enu.to_a.flatten.zip(
          ((pvt.G_enu.t * pvt.W * pvt.G_enu).inv * (pvt.G_enu.t * pvt.W)).to_a.flatten).each{|a, b|
        expect(a).to be_within(1E-10).of(b)
      }
      expect([:rows, :columns].collect{|f| pvt.slope_HV_enu.send(f)}).to eq([6, 2])
      expect(pvt.used_satellites).to eq(6)
      expect(pvt.used_satellite_list).to eq([12,18, 24, 25, 29, 31])

      meas.each{|prn, k, v|
        solver.gps_options.exclude(prn)
        puts "Excluded(PRN: #{solver.gps_options.excluded.join(', ')}) solution ..."
        run_solver.call
        solver.gps_options.excluded.each{|prn|
          solver.gps_options.include(prn)
        }
        puts
      }
    end
    
    it 'can be modified through hooks' do
      sn = solver.gps_space_node
      expect(solver.options).to be_a_kind_of(Hash)
      expect(solver.options.keys).to include(:skip_exclusion)
      expect{solver.options = {:skip_exclusion => true}}.not_to raise_error
      expect(solver.options[:skip_exclusion]).to eq(true)
      expect(solver.correction[:gps_ionospheric]).to include(:klobuchar)
      expect(solver.correction[:gps_tropospheric]).to include(:hopfield)
      expect{solver.correction = nil}.to raise_error(RuntimeError)
      expect{solver.correction = {
        :gps_ionospheric => [proc{|t, usr_pos, sat_pos|
              expect(t).to be_a_kind_of(GPS::Time)
              expect(usr_pos).to be_a_kind_of(Coordinate::XYZ) unless usr_pos
              expect(sat_pos).to be_a_kind_of(Coordinate::ENU) unless sat_pos
              false
            }, :klobuchar, :no_correction],
        :options => {:f_10_7 => 10},
      }}.not_to raise_error
      expect(solver.correction[:gps_ionospheric]).to include(:no_correction)
      expect(solver.correction[:options][:f_10_7]).to eq(10)
      expect(solver.gps_options.exclude_L2C?).to eq(true) #default
      solver.gps_options.exclude_L2C = false
      expect(solver.gps_options.exclude_L2C?).to eq(false)
      sn.read(input[:rinex_nav])
      t_meas = GPS::Time::new(1849, 172413)
      sn.update_all_ephemeris(t_meas)
      solver.hooks[:relative_property] = proc{|prn, rel_prop, meas, rcv_e, t_arv, usr_pos, usr_vel|
        expect(input[:measurement]).to include(prn)
        expect(meas).to be_a_kind_of(Hash)
        expect(t_arv).to be_a_kind_of(GPS::Time)
        expect(usr_pos).to be_a_kind_of(Coordinate::XYZ)
        expect(usr_vel).to be_a_kind_of(Coordinate::XYZ)
        weight, range_c, range_r, rate_rel_neg, *los_neg = rel_prop
        weight = 1
        [weight, range_c, range_r, rate_rel_neg] + los_neg
      }
      solver.hooks[:update_position_solution] = proc{|mat_G, mat_W, mat_delta_r, temp_pvt|
        expect(temp_pvt).to be_a_kind_of(GPS::PVT)
        [mat_G, mat_W, mat_delta_r].each{|mat|
          expect(mat).to be_a_kind_of(SylphideMath::MatrixD)
          expect(mat.rows).to be >= temp_pvt.used_satellites
          expect(mat).to respond_to(:resize!)
        }
      }
      pvt = solver.solve(
          input[:measurement].collect{|prn, items|
            items.collect{|k, v| [prn, k, v]}
          }.flatten(1),
          t_meas)
      expect(pvt.W).to eq(SylphideMath::MatrixD::I(pvt.W.rows))
    end
    
    it 'calculates position without any error with RINEX obs file' do
      sn = solver.gps_space_node
      puts "RINEX NAV read: %d items."%[sn.read(input[:rinex_nav])]
      GPS::RINEX_Observation::read(input[:rinex_obs]){|item|
        t_meas = item[:time]
        puts "Measurement time: #{t_meas.to_a} (a.k.a #{"%d/%d/%d %02d:%02d:%02d UTC"%[*t_meas.c_tm]})"
        sn.update_all_ephemeris(t_meas)
        
        meas = GPS::Measurement::new
        types = (item[:meas_types]['G'] || item[:meas_types][' ']).collect.with_index{|type_, i|
          case type_
          when "C1"
            [i, GPS::Measurement::L1_PSEUDORANGE]
          when "D1"
            [i, GPS::Measurement::L1_RANGE_RATE]
          else
            nil 
          end
        }.compact
        item[:meas].each{|k, v|
          sys, prn = k
          next unless sys == 'G' # GPS only
          types.each{|i, type_|
            meas.add(prn, type_, v[i][0]) if v[i]
          }
        }

        pvt = solver.solve(meas, t_meas)
        expect(pvt.position_solved?).to eq(true)

        puts pvt.llh.to_a.zip([180.0 / Math::PI] * 2 + [1]).collect{|v, sf| v * sf}.inspect
        if approx_pos = proc{
          next false unless res = item[:header].select{|k, v| k =~ /APPROX POSITION XYZ/}.values[0]
          next false unless res = res.collect{|item|
            item.scan(/([+-]?\d+(?:\.\d+)?)\s*/).flatten
          }.reject{|item|
            item.empty?
          }[0]
          Coordinate::XYZ::new(*(res.collect{|str| str.to_f}))
        }.call then
          approx_pos.to_a.zip(pvt.xyz.to_a).each{|a, b|
            expect(a).to be_within(1E+1).of(b) # 10 m
          } 
        end

        pvt.used_satellite_list.each{|prn|
          eph = sn.ephemeris(prn)
          puts "XYZ(PRN:#{prn}): #{eph.constellation(t_meas)[0].to_a} (iodc: #{eph.iodc}, iode: #{eph.iode})"
        }
      }
    end
    it 'calculates satellites position based on SP3 with ANTEX' do
      sp3, sn = [GPS::SP3::new, solver.gps_space_node]
      expect(sp3.read(input[:sp3])).to eq(32 * 9)
      proc{|sats|
        expect(sats.kind_of?(Array)).to eq(true) 
        expect(sats[sp3.class::SYS_GPS]).to eq(32)
      }.call(sp3.satellites)
      expect(sp3.apply_antex(input[:antex])).to eq(6 * 9)
      sn.read(input[:rinex_nav])
        
      t0 = GPS::Time::new(1849, 172800)
      sn.update_all_ephemeris(t0)
      
      (0..120).step(10){|dt_min|
        t = t0 + (dt_min * 60)
        [12, 18, 24, 25, 29, 31].each{|sat_id|
          eph_pos_vel = sn.ephemeris(sat_id).constellation(t)
          delta = {
            :pos => (sp3.position(sat_id, t) - eph_pos_vel[0]).to_a,
            :vel => (sp3.velocity(sat_id, t) - eph_pos_vel[1]).to_a,
          }
          puts "SP3 delta(#{t.seconds}, #{sat_id}): #{delta}"
          delta[:pos].each{|v|
            expect(v.abs).to be < 5 # 5m
          }
          delta[:vel].each{|v|
            expect(v.abs).to be < 1E-2 # 10mm
          }
        }
      }
    end
    it 'calculates position without any error with SP3 and ANTEX' do
      sn = solver.gps_space_node
      sp3 = GPS::SP3::new
      sp3.read(input[:sp3])
      sp3.apply_antex(input[:antex])
      expect(sp3.push(solver, sp3.class::SYS_GPS)).to eq(true)
      GPS::RINEX_Observation::read(input[:rinex_obs]){|item|
        t_meas = item[:time]
        sn.update_all_ephemeris(t_meas)
        
        meas = GPS::Measurement::new
        types = (item[:meas_types]['G'] || item[:meas_types][' ']).collect.with_index{|type_, i|
          type_ = {
            "C1" => :L1_PSEUDORANGE,
            "D1" => :L1_RANGE_RATE,
          }[type_]
          type_ && [i, GPS::Measurement::const_get(type_)]
        }.compact
        item[:meas].each{|k, v|
          sys, prn = k
          next unless sys == 'G' # GPS only
          types.each{|i, type_|
            meas.add(prn, type_, v[i][0]) if v[i]
          }
        }

        pvt = solver.solve(meas, t_meas)
        expect(pvt.position_solved?).to eq(true)
        [-3952590.4754, 3360273.8926, 3697987.2632].zip(pvt.xyz.to_a).each{|a, b|
          expect(a).to be_within(1E+2).of(b) # 10 m
        }
        puts ([:lat, :lng].collect{|f| pvt.llh.send(f) / Math::PI * 180} + [pvt.llh.alt]).inspect
      }
    end
    it 'calculates satellite clock error based on RINEX clock' do
      clk, sn = [GPS::RINEX_Clock::new, solver.gps_space_node]
      expect(clk.read(input[:rinex_clk])).to eq(6 * 7)
      proc{|sats|
        expect(sats.kind_of?(Array)).to eq(true) 
        expect(sats[clk.class::SYS_GPS]).to eq(6)
      }.call(clk.satellites)
      sn.read(input[:rinex_nav])
      t0 = GPS::Time::new(1849, 172800)
      sn.update_all_ephemeris(t0)
      (-5..5).step(1){|dt_min|
        t = t0 + (dt_min * 60)
        [12, 18, 24, 25, 29, 31].each{|sat_id|
          eph = sn.ephemeris(sat_id).constellation(t)
          expect(clk.clock_error(sat_id, t)).to be_within(1E-7).of(eph[2]) # 100 ns
          expect(clk.clock_error_dot(sat_id, t)).to be_within(1E-10).of(eph[3]) # 100 ps
        }
      }
    end
    it 'calculates position without any error with RINEX NAV and CLK' do
      sn = solver.gps_space_node
      sn.read(input[:rinex_nav])
      clk = GPS::RINEX_Clock::new
      clk.read(input[:rinex_clk])
      expect(clk.push(solver, clk.class::SYS_GPS)).to eq(true)
      GPS::RINEX_Observation::read(input[:rinex_obs]){|item|
        t_meas = item[:time]
        sn.update_all_ephemeris(t_meas)
        meas = GPS::Measurement::new
        types = (item[:meas_types]['G'] || item[:meas_types][' ']).collect.with_index{|type_, i|
          type_ = {
            "C1" => :L1_PSEUDORANGE,
            "D1" => :L1_RANGE_RATE,
          }[type_]
          type_ && [i, GPS::Measurement::const_get(type_)]
        }.compact
        item[:meas].each{|k, v|
          sys, prn = k
          next unless sys == 'G' # GPS only
          types.each{|i, type_|
            meas.add(prn, type_, v[i][0]) if v[i]
          }
        }
        pvt = solver.solve(meas, t_meas)
        expect(pvt.position_solved?).to eq(true)
        [-3952590.4754, 3360273.8926, 3697987.2632].zip(pvt.xyz.to_a).each{|a, b|
          expect(a).to be_within(1E+2).of(b) # 10 m
        }
      }
    end
  end
end