Class: TCD::StationParser

Inherits:
Object
  • Object
show all
Defined in:
lib/tcd/station.rb

Overview

Parser for station records from bit-packed binary data

Instance Method Summary collapse

Constructor Details

#initialize(bit_buffer, header, lookup_tables) ⇒ StationParser

Returns a new instance of StationParser.



123
124
125
126
127
# File 'lib/tcd/station.rb', line 123

def initialize(bit_buffer, header, lookup_tables)
    @bit = bit_buffer
    @header = header
    @lookup = lookup_tables
end

Instance Method Details

#parse(record_number) ⇒ Object

Parse a single station record at current position



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/tcd/station.rb', line 130

def parse(record_number)
    start_pos = @bit.pos

    # ============================================
    # Partial header (common to all record types)
    # Per libtcd unpack_partial_tide_record()
    # ============================================

    # Record size and type
    record_size = @bit.read_uint(@header.record_size_bits)
    record_type = @bit.read_uint(@header.record_type_bits)

    # Geographic coordinates
    latitude = @bit.read_int(@header.latitude_bits).to_f / @header.latitude_scale
    longitude = @bit.read_int(@header.longitude_bits).to_f / @header.longitude_scale

    # Timezone file index (comes BEFORE name in TCD format)
    tzfile_idx = @bit.read_uint(@header.tzfile_bits)
    tzfile = @lookup.timezone(tzfile_idx)

    # Station name (null-terminated string)
    name = @bit.read_cstring

    # Reference station index (-1 for reference stations referring to themselves)
    reference_station = @bit.read_int(@header.station_bits)

    # ============================================
    # Extended fields (V2 format)
    # Per libtcd unpack_tide_record() case 2
    # ============================================

    # Country
    country_idx = @bit.read_uint(@header.country_bits)
    country = @lookup.country(country_idx)

    # Source string
    source = @bit.read_cstring

    # Restriction
    restriction_idx = @bit.read_uint(@header.restriction_bits)
    restriction = @lookup.restriction(restriction_idx)

    # Comments and notes
    comments = @bit.read_cstring
    notes = @bit.read_cstring

    # Legalese
    legalese_idx = @bit.read_uint(@header.legalese_bits)
    legalese = @lookup.legalese_text(legalese_idx)

    # Station ID fields
    station_id_context = @bit.read_cstring
    station_id = @bit.read_cstring

    # Date imported (YYYYMMDD integer)
    date_imported = @bit.read_uint(@header.date_bits)

    # xfields (extended fields string)
    xfields = @bit.read_cstring

    # Direction units
    direction_units_idx = @bit.read_uint(@header.direction_unit_bits)
    direction_units = @lookup.direction_unit(direction_units_idx)

    # Min/max direction
    min_direction = @bit.read_uint(@header.direction_bits)
    max_direction = @bit.read_uint(@header.direction_bits)
    min_direction = nil if min_direction == NULL_DIRECTION
    max_direction = nil if max_direction == NULL_DIRECTION

    # Level units
    level_units_idx = @bit.read_uint(@header.level_unit_bits)
    level_units = @lookup.level_unit(level_units_idx)

    # Build base station
    station = Station.new(
        record_number: record_number,
        record_size: record_size,
        record_type: record_type,
        latitude: latitude,
        longitude: longitude,
        tzfile: tzfile,
        name: name,
        reference_station: reference_station,
        country: country,
        source: source,
        restriction: restriction,
        comments: comments,
        notes: notes,
        legalese: legalese,
        station_id_context: station_id_context,
        station_id: station_id,
        date_imported: date_imported,
        xfields: xfields,
        direction_units: direction_units,
        min_direction: min_direction,
        max_direction: max_direction,
        level_units: level_units
    )

    # Parse type-specific fields
    if record_type == 1
        parse_reference_fields(station)
    else
        parse_subordinate_fields(station)
    end

    # Ensure we're at the right position for the next record
    # Record size is total bytes from start of record
    expected_end = start_pos + record_size
    @bit.seek(expected_end)

    station
end