public byte[] CompressQso(Qso q) { if (q == null) throw new ArgumentNullException("q", "QSO to compress is null"); // 0: start byte // 1-2: date time offset // 3: band and operator // 4: mode and callsign length // 5-(n-1): callsign (ASCII) int callsignLength = Encoding.ASCII.GetByteCount(q.Callsign); int compressedLength = callsignLength + c_HeaderLength; byte[] compressedBytes = new byte[compressedLength]; // Byte 0: start byte, always 0xFF compressedBytes[0] = 0xFF; // Bytes 1-2: number of minutes since epoch TimeSpan timeOffset = q.QsoTime.Subtract(s_DateTimeEpoch); byte[] dateTimeBytes = BitConverter.GetBytes((uint)timeOffset.TotalMinutes); Buffer.BlockCopy(dateTimeBytes, 0, compressedBytes, 1, 2); // Byte 3: band and operator, 4 bits each compressedBytes[3] = (byte)((GetBandByte(q.Band) & 0x0F) | (GetOperatorByte(q.Operator) << 4 & 0xF0)); // Byte 4: mode (bits 6-7) and callsign length (bits 0-5) compressedBytes[4] = (byte)((GetModeByte(q.Mode) << 6 & 0xC0) | callsignLength & 0x3F); // Bytes 5 onwards: callsign byte[] callsignBytes = Encoding.ASCII.GetBytes(q.Callsign); Buffer.BlockCopy(callsignBytes, 0, compressedBytes, 5, callsignBytes.Length); return compressedBytes; }
public void TwoQsoCompression() { Qso source1 = new Qso { Callsign = "JW1ABC", QsoTime = new DateTime(2015, 07, 13, 15, 17, 0), Band = Band.B40m, Mode = Mode.CW, Operator = "M0VFC", }; byte[] compressedQso1 = new QsoCompressor().CompressQso(source1); Qso source2 = new Qso { Callsign = "K3LR", QsoTime = new DateTime(2015, 07, 18, 3, 1, 0), Band = Band.B12m, Mode = Mode.Phone, Operator = "G3ZAY", }; byte[] compressedQso2 = new QsoCompressor().CompressQso(source2); byte[] bothQsos = new byte[compressedQso1.Length + compressedQso2.Length]; Buffer.BlockCopy(compressedQso1, 0, bothQsos, 0, compressedQso1.Length); Buffer.BlockCopy(compressedQso2, 0, bothQsos, compressedQso1.Length, compressedQso2.Length); int decompressPosition = 0; Qso output1 = new QsoCompressor().UncompressQso(bothQsos, ref decompressPosition); Qso output2 = new QsoCompressor().UncompressQso(bothQsos, ref decompressPosition); AssertQsosEqual(source1, output1); AssertQsosEqual(source2, output2); }
private static void ExportContact(Qso contact, StringBuilder writer) { WriteField("call", contact.Callsign, writer); WriteField("qso_date", contact.QsoTime.ToString("yyyyMMdd"), writer); WriteField("time_on", contact.QsoTime.ToString("HHmm"), writer); WriteField("mode", ModeText(contact.Mode), writer); WriteField("band", BandText(contact.Band), writer); WriteField("rst_sent", RstFromMode(contact.Mode), writer); WriteField("rst_rcvd", RstFromMode(contact.Mode), writer); writer.AppendLine("<EOR>"); writer.AppendLine(); }
public void DeleteQso(Qso q) { using (SQLiteConnection conn = GetConnection()) { using (SQLiteCommand cmd = conn.CreateCommand()) { cmd.CommandText = "DELETE FROM qsos WHERE band=@band AND callsign=@callsign AND mode=@mode AND operator=@operator AND qsotime=@qsotime;"; AddStandardParameters(q, cmd); cmd.ExecuteNonQuery(); } } }
public void MarkQsoProcessed(Qso q) { using (SQLiteConnection conn = GetConnection()) { using (SQLiteCommand cmd = conn.CreateCommand()) { cmd.CommandText = "UPDATE qsos SET processed=1 WHERE band=@band AND callsign=@callsign AND mode=@mode AND operator=@operator AND qsotime=@qsotime;"; AddStandardParameters(q, cmd); cmd.ExecuteNonQuery(); } } }
public void AddQso(Qso q) { using (SQLiteConnection conn = GetConnection()) { using (SQLiteCommand cmd = conn.CreateCommand()) { cmd.CommandText = "INSERT INTO qsos (band, callsign, mode, operator, qsotime, processed) VALUES (@band, @callsign, @mode, @operator, @qsotime, @processed);"; AddStandardParameters(q, cmd); cmd.Parameters.AddWithValue("@processed", false); cmd.ExecuteNonQuery(); } } }
public void BasicExportToAdif() { Qso source = new Qso { Callsign = "JW1ABC", QsoTime = new DateTime(2015, 07, 13, 15, 17, 0), Band = Band.B40m, Mode = Mode.CW, Operator = "M0VFC", }; string adif = AdifHandler.ExportContacts(new List<Qso> { source }); }
public void AddQso() { Qso source = new Qso { Callsign = "JW1ABC", QsoTime = new DateTime (2015, 07, 13, 15, 17, 0), Band = Band.B40m, Mode = Mode.CW, Operator = "M0VFC", }; var store = new QsoStore(); store.AddQso(source); }
public void BasicQsoCompression() { Qso source = new Qso { Callsign = "JW1ABC", QsoTime = new DateTime (2015, 07, 13, 15, 17, 0), Band = Band.B40m, Mode = Mode.CW, Operator = "M0VFC", }; byte[] compressedQso = new QsoCompressor().CompressQso(source); Qso output = new QsoCompressor().UncompressQso(compressedQso, 0); AssertQsosEqual(source, output); }
public bool QsoExists(Qso q) { using (SQLiteConnection conn = GetConnection()) { using (SQLiteCommand cmd = conn.CreateCommand()) { cmd.CommandText = "SELECT * FROM qsos WHERE band=@band AND callsign=@callsign AND mode=@mode AND operator=@operator AND qsotime=@qsotime;"; AddStandardParameters(q, cmd); using (SQLiteDataReader reader = cmd.ExecuteReader()) { return reader.Read(); } } } }
public static Qso GetContact(AdifFileReader.Record record) { Qso c = new Qso(); c.Callsign = record["call"]; // This parsing is horrid. TODO: Figure out how to use IFormatProvider properly. string dateStr = record["qso_date"]; string timeOnStr = record["time_on"]; DateTime? date = AdifFileReader.ParseAdifDate(dateStr, timeOnStr); c.QsoTime = date.Value; c.Band = ParseBand(record["band"]); c.Operator = record["operator"]; c.Mode = ParseMode(record["mode"]); return c; }
public void BasicRoundtripAdif() { Qso source = new Qso { Callsign = "JW1ABC", QsoTime = new DateTime(2015, 07, 13, 15, 17, 0), Band = Band.B40m, Mode = Mode.CW, Operator = "M0VFC", }; string adif = AdifHandler.ExportContacts(new List<Qso> { source }); List<Qso> qsos = AdifHandler.ImportAdif(adif); Assert.AreEqual(1, qsos.Count); }
public void WebServiceSubmission() { Qso source1 = new Qso { Callsign = "JW1ABC", QsoTime = new DateTime(2015, 07, 13, 15, 17, 0), Band = Band.B40m, Mode = Mode.CW, Operator = "M0VFC", }; byte[] compressedQso1 = new QsoCompressor().CompressQso(source1); HttpWebRequest req = HttpWebRequest.CreateHttp("http://localhost:55950/logs/submit?qsoCount=1&hash=something"); req.Method = "POST"; using (Stream reqStream = req.GetRequestStream()) { reqStream.Write(compressedQso1, 0, compressedQso1.Length); } req.GetResponse(); }
public Qso UncompressQso(byte[] buff, ref int start) { if (buff == null) throw new ArgumentNullException("buff", "Compressed data buffer null"); if (start >= buff.Length) throw new ArgumentOutOfRangeException("start", "Start position beyond end of compressed data buffer"); if (start >= (buff.Length - c_HeaderLength)) throw new ArgumentOutOfRangeException("start", "Start position does not leave enough data for QSO header in buffer"); // Byte 0: start byte, always 0xFF if (buff[start] != 0xFF) throw new ArgumentException("buff", "Compressed data does not begin with expected start byte"); Qso q = new Qso(); // Byte 1-2: minutes since epoch UInt16 minutesSinceEpoch = BitConverter.ToUInt16(buff, start + 1); q.QsoTime = s_DateTimeEpoch.AddMinutes(minutesSinceEpoch); // Byte 3: band and operator, 4 bits each byte band = (byte)(buff[start + 3] & 0x0F); q.Band = GetBand(band); byte op = (byte)((buff[start + 3] & 0xF0) >> 4); q.Operator = GetOperator(op); // Byte 4: mode (bits 6-7) and callsign length (bits 0-5) byte modeByte = (byte)((buff[start + 4] & 0xC0) >> 6); q.Mode = GetMode(modeByte); int callsignLength = buff[start + 4] & 0x3F; if (buff.Length < (start + c_HeaderLength + callsignLength)) throw new ArgumentException("buff", "Callsign length runs beyond end of compressed data"); // Byte 5+: callsign, ASCII q.Callsign = Encoding.ASCII.GetString(buff, start + 5, callsignLength); start += c_HeaderLength + callsignLength; return q; }
public void ProcessedTest() { Qso source = new Qso { Callsign = "JW1ABC", QsoTime = new DateTime(2015, 07, 13, 15, 17, 0), Band = Band.B40m, Mode = Mode.CW, Operator = "M0VFC", }; var store = new QsoStore(); if (store.QsoExists(source)) store.DeleteQso(source); Assert.IsFalse(store.QsoExists(source)); store.AddQso(source); Assert.IsTrue(store.QsoExists(source)); int unprocessedCount = store.GetUnprocessedQsos().Count; store.MarkQsoProcessed(source); int unprocessedCountAfterProcessing = store.GetUnprocessedQsos().Count; Assert.AreEqual(unprocessedCount - 1, unprocessedCountAfterProcessing, "Expected unprocessed count to go down after processing"); }
private void AssertQsosEqual(Qso source, Qso target) { Assert.AreEqual(source.Band, target.Band); Assert.AreEqual(source.Callsign, target.Callsign); Assert.AreEqual(source.Mode, target.Mode); Assert.AreEqual(source.Operator, target.Operator); Assert.AreEqual(source.QsoTime, target.QsoTime); }
private void AddStandardParameters(Qso q, SQLiteCommand cmd) { cmd.Parameters.AddWithValue("@band", q.Band.ToString()); cmd.Parameters.AddWithValue("@callsign", q.Callsign); cmd.Parameters.AddWithValue("@mode", q.Mode.ToString()); cmd.Parameters.AddWithValue("@operator", q.Operator); cmd.Parameters.AddWithValue("@qsotime", q.QsoTime); }
private Qso LoadFromDataReader(SQLiteDataReader dr) { Qso q = new Qso(); q.Band = (Band)Enum.Parse(typeof(Band), dr.GetString(dr.GetOrdinal("band"))); q.Callsign = dr.GetString(dr.GetOrdinal("callsign")); q.Mode = (Mode)Enum.Parse(typeof(Mode), dr.GetString(dr.GetOrdinal("mode"))); q.Operator = dr.GetString(dr.GetOrdinal("operator")); q.QsoTime = dr.GetDateTime(dr.GetOrdinal("qsotime")); return q; }