QxSL is a Java library for processing amateur-radio log files, including scoring and tabulation frameworks for ham radio contests.
- provides log en/decoders for QXML, ADIF, Cabrillo, zLog, CTESTWIN, HAMLOG, etc.
- provides tabulation & scoring frameworks for amateur-radio contests and awards.
- provides the rulekit framework which allows you to write contest rules in JS, Ruby, Python, and LISP.
Because we are Scalalians, please be patient to read Scala codes!
The package qxsl.model
defines the structure of log files, where each communication is handled as an Item
object, while the entire log is represented as List[Item]
.
Each Item
contains some Field
objects, which indicate properties such as Time
, Mode
and Band
.
In addition, each Item
holds two Node
objects, namely Rcvd
and Sent
, which involve some messages (Field
s) exchanged by the operator and the contacted station.
import qxsl.model.{Item, Rcvd, Sent}
val item: Item = new Item
val rcvd: Rcvd = item.getRcvd
val sent: Sent = item.getSent
The package qxsl.field
provides a management framework for Field
implementations.
The class FieldManager
detects FieldFactory
implementations from the class path automatically, and each FieldFactory
provides en/decoders for individual Field
implementation.
val fields = new qxsl.field.FieldManager()
item.set(fields.cache(new QName("qxsl.org", "mode")).field("CW"))
item.set(fields.cache(new QName("adif.org", "MODE")).field("CW"))
val mode = item.value(new QName("qxsl.org", "mode"))
This mechanism is utilized for en/decoding the QXML format, which is an alternative log format proposed by the qxsl development team. QXML is extensible, and supports namespaces which have been prohibited in the traditional ADIF:
<?xml version="1.0" encoding="UTF-8"?>
<list xmlns:qxsl="qxsl.org">
<item qxsl:time="2017-06-03T16:17:00Z" qxsl:call="QV1DOK" qxsl:band="14000" qxsl:mode="CW">
<rcvd qxsl:rstq="599" qxsl:code="120103"/>
<sent qxsl:rstq="599" qxsl:code="100110"/>
</item>
<item qxsl:time="2017-06-04T00:01:00Z" qxsl:call="QD1QXB" qxsl:band="21000" qxsl:mode="CW">
<rcvd qxsl:rstq="599" qxsl:code="110117"/>
<sent qxsl:rstq="599" qxsl:code="100110"/>
</item>
</list>
The package qxsl.table
provides a basic framework for en/decoding log files including QXML and ADIF.
The class TableManager
detects individual formats (TableFactory
s) from the class path automatically, and also provides the decode
method for automatic format detection.
val tables = new qxsl.table.TableManager()
val table: java.util.List[Item] = tables.decode(Files.readAllBytes(path))
tables.factory("qxml").encoder(Files.newOutputStream(path)).encode(table)
The package qxsl.sheet
provides an en/decoding framework similar to the qxsl.table
package, except that qxsl.sheet
handles contest summary sheets such as Cabrillo and JARL summary sheet R2.0.
The class SheetManager
manages individual SheetFactory
implementations.
The class SheetOrTable
provides the unpack
method useful for extracting table items from a summary sheet.
val sheets = new qxsl.sheet.SheetOrTable()
val table: java.util.List[Item] = sheets.unpack(Files.readAllBytes(path))
The package qxsl.ruler
provides a rulemaking framework for amateur radio awards and contests.
Each contest is represented as a Contest
object, which is provided by a RuleKit
object or a script engine to define the contest.
import qxsl.ruler.{Contest, RuleKit}
val engine = RuleKit.forName("elva")
val stream = engine.getClass().getResourceAsStream("allja1.lisp")
val allja1 = engine.eval(new InputStreamReader(stream)).contest()
Each contest involves multiple Section
objects.
The Section
object accepts List[Item]
and validates the communications one by one, by invoking the summarize
method.
import qxsl.ruler.{Section, Summary}
for(section: Section <- allja1.asScala) {
val summary: Summary = section.summarize(table)
println(section.code())
println(section.name())
summary.accepted().asScala.foreach(println)
summary.rejected().asScala.foreach(println)
println(summary.score())
println(summary.total())
}
Currently, the RuleKit
class supports some domain specific languages, including JS, Ruby, Python, and Elva.
Elva is a special LISP for the purpose of contest definition.
The following LISP programs are bundled inside the JAR file, as sample codes in Elva.
type | format | ext |
---|---|---|
qxml |
QXML | |
item |
QxSL | |
jarl |
JARL LOG | |
jswl |
JARL SWL | |
adis |
ADIF | .adi |
adxs |
ADIF | .adx |
cqww |
CQWW | .cbr |
zbin |
zLog | .zlo |
znew |
zLog | .zlox |
zdos |
zLog | .txt |
zall |
zLog | .all |
hbin |
HAMLOG | .hdb |
cbin |
CTESTWIN | .lg8 |
ctxt |
CTESTWIN | .txt |
type | format |
---|---|
jarl |
JARL R2.0 |
cab3 |
Cabrillo3 |
If you want to use the latest build, configure the build.gradle
as follows:
repositories.maven {
url('https://autodyne.github.io/qxsl/mvn/')
}
dependencies {
implementation('qxsl:qxsl:+')
}
Gradle retrieves dependent libraries, runs tests, and generates a JAR file automatically.
$ gradle build javadoc publish
You can create a native command line application instead of a JAR file. GraalVM must be installed before compilation. Then run the commands manually as follows:
$ native-image -jar build/libs/qxsl.jar
$ qxsl.exe source.zlox target.qxml qxml
Pull requests are not accepted. QxSL is a highly extensible library and in most cases QxSL itself does not need to be modified. If you need enhancements, feel free to make issues at nextzlog/todo.
-
This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-
This library is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the GNU Lesser General Public License for more details.
-
You should have received a copy of the GNU Lesser General Public License along with this library. If not, see http://www.gnu.org/licenses/.