<commit_before>package ru.r2cloud.jradio.tubix20;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

import ru.r2cloud.jradio.crc.Crc16Ccitt;
import ru.r2cloud.jradio.fec.Crc16CcittFec;
import ru.r2cloud.jradio.fec.ccsds.UncorrectableException;
import ru.r2cloud.jradio.mobitex.MobitexBeacon;
import ru.r2cloud.jradio.util.GapData;

public class TUBiX20Beacon extends MobitexBeacon {

	private static final int TOTAL_CALLSIGN_BYTES = 6 + 2;
	public static final int MAX_SIZE = 1 + 1 + 1 + TOTAL_CALLSIGN_BYTES + 32 * 30;

	private String callsign;

	@Override
	public void readBeacon(byte[] data) throws IOException, UncorrectableException {
		callsign = readCallsign(data);

		// re-shuffle data for proper mobitex beacon
		byte[] mobitexData = new byte[data.length - TOTAL_CALLSIGN_BYTES];
		System.arraycopy(data, 0, mobitexData, 0, 3);
		System.arraycopy(data, 3 + TOTAL_CALLSIGN_BYTES, mobitexData, 3, mobitexData.length - 3);
		super.readBeacon(mobitexData);
	}

	@Override
	public void readBeacon(GapData data) throws IOException, UncorrectableException {
		// read until first gap
		// Technosat can recover some SourcePacket from the begining of frames
		int total = 0;
		for (byte[] cur : data.getChunks()) {
			if (cur == null) {
				break;
			}
			total += cur.length;
		}
		byte[] payload = new byte[total];
		int totalWritten = 0;
		for (byte[] cur : data.getChunks()) {
			if (cur == null) {
				break;
			}
			System.arraycopy(cur, 0, payload, totalWritten, cur.length);
			totalWritten += cur.length;
		}
		readBeacon(new DataInputStream(new ByteArrayInputStream(payload)));
	}

	private static String readCallsign(byte[] data) {
		byte[] callsignBytes = new byte[6];
		System.arraycopy(data, 3, callsignBytes, 0, callsignBytes.length);
		int expectedCallsignCrc = ((data[9] & 0xFF) << 8) | (data[10] & 0xFF);
		int crc16 = Crc16Ccitt.calculate(callsignBytes);
		boolean crcMatched = (crc16 == expectedCallsignCrc);
		if (!crcMatched) {
			crcMatched = Crc16CcittFec.fix1bitUsingCrc(callsignBytes, expectedCallsignCrc);
		}
		// callsign is not covered by FEC blocks and most likely would be corrupted
		// continue further as callsign is not that important
		// set it up only if CRC matched
		if (crcMatched) {
			return new String(callsignBytes, StandardCharsets.ISO_8859_1);
		}
		return null;
	}

	public String getCallsign() {
		return callsign;
	}

	public void setCallsign(String callsign) {
		this.callsign = callsign;
	}

}<commit_msg>better debug for tubix beacons<commit_after>package ru.r2cloud.jradio.tubix20;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

import ru.r2cloud.jradio.crc.Crc16Ccitt;
import ru.r2cloud.jradio.fec.Crc16CcittFec;
import ru.r2cloud.jradio.fec.ccsds.UncorrectableException;
import ru.r2cloud.jradio.mobitex.MobitexBeacon;
import ru.r2cloud.jradio.util.GapData;

public class TUBiX20Beacon extends MobitexBeacon {

	private static final int TOTAL_CALLSIGN_BYTES = 6 + 2;
	public static final int MAX_SIZE = 1 + 1 + 1 + TOTAL_CALLSIGN_BYTES + 32 * 30;

	private String callsign;

	@Override
	public void readBeacon(byte[] data) throws IOException, UncorrectableException {
		callsign = readCallsign(data);

		// re-shuffle data for proper mobitex beacon
		byte[] mobitexData = new byte[data.length - TOTAL_CALLSIGN_BYTES];
		System.arraycopy(data, 0, mobitexData, 0, 3);
		System.arraycopy(data, 3 + TOTAL_CALLSIGN_BYTES, mobitexData, 3, mobitexData.length - 3);
		super.readBeacon(mobitexData);
	}

	@Override
	public void readBeacon(GapData data) throws IOException, UncorrectableException {
		// read until first gap
		// Technosat can recover some SourcePacket from the begining of frames
		int total = 0;
		for (byte[] cur : data.getChunks()) {
			if (cur == null) {
				break;
			}
			total += cur.length;
		}
		byte[] payload = new byte[total];
		int totalWritten = 0;
		for (byte[] cur : data.getChunks()) {
			if (cur == null) {
				break;
			}
			System.arraycopy(cur, 0, payload, totalWritten, cur.length);
			totalWritten += cur.length;
		}
		readBeacon(new DataInputStream(new ByteArrayInputStream(payload)));
	}

	private static String readCallsign(byte[] data) {
		byte[] callsignBytes = new byte[6];
		System.arraycopy(data, 3, callsignBytes, 0, callsignBytes.length);
		int expectedCallsignCrc = ((data[9] & 0xFF) << 8) | (data[10] & 0xFF);
		int crc16 = Crc16Ccitt.calculate(callsignBytes);
		boolean crcMatched = (crc16 == expectedCallsignCrc);
		if (!crcMatched) {
			crcMatched = Crc16CcittFec.fix1bitUsingCrc(callsignBytes, expectedCallsignCrc);
		}
		// callsign is not covered by FEC blocks and most likely would be corrupted
		// continue further as callsign is not that important
		// set it up only if CRC matched
		if (crcMatched) {
			return new String(callsignBytes, StandardCharsets.ISO_8859_1);
		}
		return null;
	}

	public String getCallsign() {
		return callsign;
	}

	public void setCallsign(String callsign) {
		this.callsign = callsign;
	}

	@Override
	public String toString() {
		if (callsign != null) {
			return callsign + " " + super.toString();
		}
		return super.toString();
	}

}
{'fraction_non_alphanumeric': 0.10729206228636537, 'fraction_numerical': 0.020888720091150777, 'mean_word_length': 4.358087487283825, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4624848', 'n_tokens_mistral': 2044, 'n_tokens_neox': 1828, 'n_words': 456}