conval

package module
v0.7.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2024 License: MIT Imports: 16 Imported by: 7

README

conval - The CONtest eVALuator

This little Go library helps to evaluate the log files from amateur radio contests in several ways:

  • calculate the score of a log file based on a given rule set
  • show the performance over time of a contest log file
  • calculate statistics for a contest log file

Log files can be provided in Cabrillo format. The results are either provided as plain text, YAML, or JSON, and, where applicable, as CSV.

Use as a Go Library

To include conval into your own projects as a library:

go get github.com/ftl/conval

Use as a CLI Tool

conval also includes a simple CLI tool that is mainly used to demonstrate the integration of the library.

Build it:

go build -o conval ./cmd

Simply run it:

go run ./cmd

License

This software is published under the MIT License.

Copyright Florian Thienel

Documentation

Overview

This file contains the implementation of the common properties used for contest scoring.

The package conval helps to evaluate the log files from amateur radio contests.

This file contains the implementation of the specific things for contests announced by the EUDXCC (https://eudxcc.altervista.org/).

This file contains the implementation of the specific things for contests announced by the Dutch amateur radio association VERON.

Index

Constants

View Source
const (
	SamePrefix  string = "same"
	OtherPrefix string = "other"
	NotPrefix   string = "not"
)

Variables

View Source
var (
	CallsignValidator = PropertyValidatorFunc(func(exchange string, _ PrefixDatabase) error {
		_, err := callsign.Parse(exchange)
		if err != nil {
			return err
		}
		return nil
	})
	DXCCPrefixValidator = PropertyValidatorFunc(func(exchange string, prefixes PrefixDatabase) error {
		_, entity, _, _, found := prefixes.Find(exchange)
		if !found {
			return fmt.Errorf("%s is not a valid DXCC prefix", exchange)
		}
		if exchange != string(entity) {
			return fmt.Errorf("%s is not a primary DXCC prefix", exchange)
		}
		return nil
	})
)
View Source
var EmptyValidator = PropertyValidatorFunc(func(exchange string, _ PrefixDatabase) error {
	exchange = strings.TrimSpace(exchange)
	if exchange != "" {
		return fmt.Errorf("%s is not empty", exchange)
	}
	return nil
})

Functions

func CanadianTerritory added in v0.3.4

func CanadianTerritory(call callsign.Callsign) string

func IncludedDefinitionNames

func IncludedDefinitionNames() ([]string, error)

func IsWAECountry

func IsWAECountry(call callsign.Callsign, dxccEntity DXCCEntity) bool

func NewPrefixDatabase added in v0.3.0

func NewPrefixDatabase() (*prefixDatabase, error)

func SaveDefinitionYAML added in v0.3.0

func SaveDefinitionYAML(w io.Writer, definition *Definition, withExamples bool) error

func ValidateExamples

func ValidateExamples(definition *Definition, prefixes PrefixDatabase) error

func ValidateExamplesTrace added in v0.5.0

func ValidateExamplesTrace(definition *Definition, prefixes PrefixDatabase) error

func VeronEntity added in v0.3.4

func VeronEntity(call callsign.Callsign, dxccEntity DXCCEntity) string

func WAEEntity

func WAEEntity(call callsign.Callsign, dxccEntity DXCCEntity) string

func WPXPrefix

func WPXPrefix(call callsign.Callsign) string

Types

type BandAndMode

type BandAndMode struct {
	Band ContestBand
	Mode Mode
}

type BandChangeRule

type BandChangeRule struct {
	Constraint          `yaml:",inline"`
	GracePeriod         time.Duration `yaml:"grace_period"`
	MultiplierException bool          `yaml:"multiplier_exception"`
}

type BandCount added in v0.3.3

type BandCount string
const (
	AllBands   BandCount = "all"
	SingleBand BandCount = "single"
)

func (BandCount) ToInt added in v0.3.3

func (c BandCount) ToInt() int

type BandRule

type BandRule string
const (
	Once               BandRule = "once"
	OncePerBand        BandRule = "once_per_band"
	OncePerBandAndMode BandRule = "once_per_band_and_mode"
)

type BandScore

type BandScore struct {
	QSOs   int `yaml:"qsos" json:"qsos"`
	Points int `yaml:"points" json:"points"`
	Multis int `yaml:"multis" json:"multis"`
}

type CQZone added in v0.5.0

type CQZone int

func (CQZone) String added in v0.5.0

func (z CQZone) String() string

type Category

type Category struct {
	Name      string        `yaml:"name"`
	Operator  OperatorMode  `yaml:"operator,omitempty"`
	TX        TXMode        `yaml:"tx,omitempty"`
	Power     PowerMode     `yaml:"power,omitempty"`
	BandCount BandCount     `yaml:"band_count"`
	Bands     []ContestBand `yaml:"bands,omitempty"`
	Modes     []Mode        `yaml:"modes,omitempty"`
	Assisted  bool          `yaml:"assisted,omitempty"`
	Overlay   Overlay       `yaml:"overlay,omitempty"`
	ScoreMode ScoreMode     `yaml:"score_mode,omitempty"`
	Duration  time.Duration `yaml:"duration,omitempty"`
}

type ConstrainedDuration

type ConstrainedDuration struct {
	Constraint `yaml:",inline"`
	Duration   time.Duration          `yaml:"duration"`
	Mode       DurationConstraintMode `yaml:"constraint_mode,omitempty"`
}

type Constraint

type Constraint struct {
	OperatorMode OperatorMode `yaml:"operator_mode"`
	Overlay      Overlay      `yaml:"overlay"`
}

type ContestBand

type ContestBand string
const (
	BandAll ContestBand = "all"

	Band160m ContestBand = "160m"
	Band80m  ContestBand = "80m"
	Band40m  ContestBand = "40m"
	Band20m  ContestBand = "20m"
	Band15m  ContestBand = "15m"
	Band10m  ContestBand = "10m"
)

type ContestIdentifier

type ContestIdentifier string

A ContestIdentifier aka. Cabrillo name is a unique identifier for a contest. See https://www.contestcalendar.com/cabnames.php

type Continent

type Continent string
const (
	Africa       Continent = "af"
	Antarctica   Continent = "an"
	Asia         Continent = "as"
	Europa       Continent = "eu"
	NorthAmerica Continent = "na"
	Oceania      Continent = "oc"
	SouthAmerica Continent = "sa"

	SameContinent  Continent = "same"
	OtherContinent Continent = "other"
	NotContinent   Continent = "not"
)

type Counter

type Counter struct {
	// contains filtered or unexported fields
}

func NewCounter

func NewCounter(definition Definition, setup Setup, prefixes PrefixDatabase) *Counter

func (*Counter) Add

func (c *Counter) Add(qso QSO) QSOScore

func (Counter) BandScore

func (c Counter) BandScore(band ContestBand) BandScore

func (Counter) BandsPerMulti

func (c Counter) BandsPerMulti(property Property, multi string) []ContestBand

func (*Counter) EffectiveExchangeFields

func (c *Counter) EffectiveExchangeFields(theirCall callsign.Callsign) []ExchangeField

func (Counter) EvaluateAll added in v0.2.0

func (c Counter) EvaluateAll(startTime time.Time, resolution time.Duration) []ScoreBin

func (Counter) MultiProperties

func (c Counter) MultiProperties() []Property

func (Counter) MultisPerBand

func (c Counter) MultisPerBand(property Property, band ContestBand) []string

func (Counter) MultisPerProperty

func (c Counter) MultisPerProperty(property Property) []string

func (Counter) Probe

func (c Counter) Probe(qso QSO) QSOScore

func (*Counter) SetTrace added in v0.5.0

func (c *Counter) SetTrace(trace bool)

func (Counter) Total added in v0.3.2

func (c Counter) Total(score BandScore) int

func (Counter) TotalScore

func (c Counter) TotalScore() BandScore

func (Counter) UsedBands

func (c Counter) UsedBands() []ContestBand

type DXCCEntity

type DXCCEntity string
const (
	SameCountry  DXCCEntity = "same"
	OtherCountry DXCCEntity = "other"
	NotCountry   DXCCEntity = "not"
)

func (DXCCEntity) String added in v0.5.0

func (e DXCCEntity) String() string

type Definition

type Definition struct {
	Name                string                `yaml:"name"`
	Identifier          ContestIdentifier     `yaml:"identifier"`
	OfficialRules       string                `yaml:"official_rules"`
	UploadURL           string                `yaml:"upload_url"`
	UploadFormat        string                `yaml:"upload_format"`
	Duration            time.Duration         `yaml:"duration,omitempty"`
	DurationConstraints []ConstrainedDuration `yaml:"duration-constraints,omitempty"`
	Breaks              []ConstrainedDuration `yaml:"breaks,omitempty"`
	Categories          []Category            `yaml:"categories,omitempty"`
	Overlays            []Overlay             `yaml:"overlays,omitempty"`
	Modes               []Mode                `yaml:"modes,omitempty"`
	Bands               []ContestBand         `yaml:"bands,omitempty"`
	BandChangeRules     []BandChangeRule      `yaml:"band_change_rules,omitempty"`
	Properties          []PropertyDefinition  `yaml:"properties,omitempty"`
	Exchange            []ExchangeDefinition  `yaml:"exchange"`
	Scoring             Scoring               `yaml:"scoring"`
	Examples            []Example             `yaml:"examples,omitempty"`
}

A Definition of a contest.

func IncludedDefinition

func IncludedDefinition(name string) (*Definition, error)

func LoadDefinitionFromFile

func LoadDefinitionFromFile(filename string) (*Definition, error)

func LoadDefinitionYAML

func LoadDefinitionYAML(r io.Reader) (*Definition, error)

func (Definition) ExchangeFields added in v0.3.1

func (d Definition) ExchangeFields() []ExchangeField

func (Definition) PropertyGetter added in v0.4.0

func (d Definition) PropertyGetter(property Property) (PropertyGetter, bool)

func (Definition) PropertyValidator added in v0.4.0

func (d Definition) PropertyValidator(property Property) (PropertyValidator, bool)

type DurationConstraintMode added in v0.3.2

type DurationConstraintMode string
const (
	// TotalTime counts from the timestamp of the first QSO until the timestamp of the last QSO without considering breaks.
	TotalTime DurationConstraintMode = "total_time"
	// ActiveTime counts from the timestamp of the first QSO until the timestamp of the last QSO, breaks that last at least one hour are subtracted.
	ActiveTime DurationConstraintMode = "active_time"
)

type Example

type Example struct {
	Setup SetupExample `yaml:"setup"`
	QSOs  []QSOExample `yaml:"qsos"`
	Score ScoreExample `yaml:"score"`
}

type ExchangeDefinition

type ExchangeDefinition struct {
	MyContinent           []Continent     `yaml:"my_continent,omitempty"`
	MyCountry             []DXCCEntity    `yaml:"my_country,omitempty"`
	TheirContinent        []Continent     `yaml:"their_continent,omitempty"`
	TheirCountry          []DXCCEntity    `yaml:"their_country,omitempty"`
	TheirWorkingCondition []string        `yaml:"their_working_condition,omitempty"`
	AdditionalWeight      int             `yaml:"additional_weight,omitempty"`
	Fields                []ExchangeField `yaml:"fields,omitempty"`
}

type ExchangeField

type ExchangeField []Property

func (ExchangeField) Contains added in v0.3.1

func (f ExchangeField) Contains(property Property) bool

func (ExchangeField) Strings added in v0.3.1

func (f ExchangeField) Strings() []string

type ITUZone added in v0.5.0

type ITUZone int

func (ITUZone) String added in v0.5.0

func (z ITUZone) String() string

type Mode

type Mode string
const (
	ModeALL Mode = "all"

	ModeCW      Mode = "cw"
	ModeSSB     Mode = "ssb"
	ModeFM      Mode = "fm"
	ModeRTTY    Mode = "rtty"
	ModeDigital Mode = "digital"
)

type MultiOperation added in v0.3.2

type MultiOperation string
const (
	DefaultMultiOperation MultiOperation = ""
	MultiplyMultis        MultiOperation = "multiply"
	AddMultis             MultiOperation = "add"
)

type OperatorMode

type OperatorMode string
const (
	SingleOperator OperatorMode = "single"
	MultiOperator  OperatorMode = "multi"
)

type Overlay

type Overlay string
const (
	NoOverlay                Overlay = ""
	ClassicOverlay           Overlay = "classic"
	ThreeBandAndWiresOverlay Overlay = "tb_wires"
	RookieOverlay            Overlay = "rookie"
	YouthOverlay             Overlay = "youth"
)

type PowerMode

type PowerMode string
const (
	HighPower PowerMode = "high"
	LowPower  PowerMode = "low"
	QRPPower  PowerMode = "qrp"
)

type PrefixDatabase

type PrefixDatabase interface {
	Find(s string) (Continent, DXCCEntity, CQZone, ITUZone, bool)
}

type PrefixDatabaseFunc added in v0.3.1

type PrefixDatabaseFunc func(s string) (Continent, DXCCEntity, bool)

func (PrefixDatabaseFunc) Find added in v0.3.1

type Property

type Property string
const (
	TheirCallProperty        Property = "their_call"
	RSTProperty              Property = "rst"
	SerialNumberProperty     Property = "serial"
	MemberNumberProperty     Property = "member_number"
	NoMemberProperty         Property = "nm"
	CallsignProperty         Property = "callsign" // can be used as exchange, e.g. in the silent key memorial contests
	CQZoneProperty           Property = "cq_zone"
	ITUZoneProperty          Property = "itu_zone"
	DXCCEntityProperty       Property = "dxcc_entity"
	WorkingConditionProperty Property = "working_condition"
	NameProperty             Property = "name"
	AgeProperty              Property = "age"
	PowerProperty            Property = "power"
	ClassProperty            Property = "class"
	StateProvinceProperty    Property = "state_province"
	DXCCPrefixProperty       Property = "dxcc_prefix" // can be used as exchange, e.g. in the CWops contests
	WAEEntityProperty        Property = "wae_entity"
	WPXPrefixProperty        Property = "wpx_prefix"

	GenericTextProperty   Property = "generic_text"
	GenericNumberProperty Property = "generic_number"
	EmptyProperty         Property = "empty"
)
const (
	PAProvinceProperty  Property = "pa_province"
	VeronEntityProperty Property = "veron_entity"
)
const (
	EURegionProperty Property = "eu_region"
)

type PropertyConstraint added in v0.3.2

type PropertyConstraint struct {
	Name               Property `yaml:"name"`
	Min                string   `yaml:"min,omitempty"`
	Max                string   `yaml:"max,omitempty"`
	MyValue            string   `yaml:"my_value,omitempty"`
	TheirValue         string   `yaml:"their_value,omitempty"`
	TheirValueEmpty    bool     `yaml:"their_value_empty,omitempty"`
	TheirValueNotEmpty bool     `yaml:"their_value_not_empty,omitempty"`
	SameValue          bool     `yaml:"same,omitempty"`
	OtherValue         bool     `yaml:"other,omitempty"`
}

func (PropertyConstraint) Matches added in v0.3.2

func (c PropertyConstraint) Matches(myValue string, theirValue string) bool

type PropertyDefinition added in v0.4.0

type PropertyDefinition struct {
	Name       Property `yaml:"name"`
	Label      string   `yaml:"label,omitempty"`
	Values     []string `yaml:"values,omitempty"`
	Expression string   `yaml:"expression,omitempty"`
	Source     Property `yaml:"source,omitempty"`
	// contains filtered or unexported fields
}

func (*PropertyDefinition) GetLabel added in v0.4.0

func (d *PropertyDefinition) GetLabel() string

func (*PropertyDefinition) GetProperty added in v0.4.0

func (d *PropertyDefinition) GetProperty(qso QSO, _ PrefixDatabase) string

func (*PropertyDefinition) ValidateProperty added in v0.4.0

func (d *PropertyDefinition) ValidateProperty(value string, _ PrefixDatabase) error

type PropertyGetter

type PropertyGetter interface {
	GetProperty(QSO, PrefixDatabase) string
}

type PropertyGetterFunc

type PropertyGetterFunc func(QSO, PrefixDatabase) string

func (PropertyGetterFunc) GetProperty

func (f PropertyGetterFunc) GetProperty(qso QSO, prefixes PrefixDatabase) string

type PropertyValidator

type PropertyValidator interface {
	ValidateProperty(string, PrefixDatabase) error
}

func CommonPropertyValidator added in v0.4.0

func CommonPropertyValidator(property Property) (PropertyValidator, bool)

func NumberRangeValidator

func NumberRangeValidator(from, to int, name string) PropertyValidator

func RegexpValidator

func RegexpValidator(exp *regexp.Regexp, name string) PropertyValidator

type PropertyValidatorFunc

type PropertyValidatorFunc func(string, PrefixDatabase) error

func (PropertyValidatorFunc) ValidateProperty

func (f PropertyValidatorFunc) ValidateProperty(exchange string, prefixes PrefixDatabase) error

type PropertyValidators

type PropertyValidators interface {
	PropertyValidator(Property) (PropertyValidator, bool)
}

type PropertyValidatorsFunc added in v0.4.0

type PropertyValidatorsFunc func(Property) (PropertyValidator, bool)

func (PropertyValidatorsFunc) PropertyValidator added in v0.4.0

func (f PropertyValidatorsFunc) PropertyValidator(property Property) (PropertyValidator, bool)

type QSO

type QSO struct {
	TheirCall      callsign.Callsign
	TheirContinent Continent
	TheirCountry   DXCCEntity

	Timestamp time.Time
	Band      ContestBand
	Mode      Mode

	MyExchange    QSOExchange
	TheirExchange QSOExchange
}

func (QSO) TheirPrefix added in v0.3.4

func (q QSO) TheirPrefix() string

type QSOExample

type QSOExample struct {
	TheirCall      string     `yaml:"their_call,omitempty"`
	TheirContinent Continent  `yaml:"their_continent,omitempty"`
	TheirCountry   DXCCEntity `yaml:"their_country,omitempty"`

	Timestamp time.Time   `yaml:"time,omitempty"`
	Band      ContestBand `yaml:"band,omitempty"`
	Mode      Mode        `yaml:"mode,omitempty"`

	TheirExchange []string `yaml:"their_exchange,omitempty"`

	Score QSOScore `yaml:",inline"`
}

func (QSOExample) ToQSO

func (q QSOExample) ToQSO(fields []ExchangeField, myExchange QSOExchange, prefixes PrefixDatabase, propertyValidators PropertyValidators) QSO

type QSOExchange

type QSOExchange map[Property]string

func ParseExchange

func ParseExchange(fields []ExchangeField, values []string, prefixes PrefixDatabase, propertyValidators PropertyValidators) QSOExchange

func (QSOExchange) Add

func (e QSOExchange) Add(fields []ExchangeField, values []string, prefixes PrefixDatabase, propertyValidators PropertyValidators)

type QSOScore

type QSOScore struct {
	Points           int                      `yaml:"points" json:"points"`
	Multis           int                      `yaml:"multis" json:"multis"`
	MultiValues      map[Property]string      `yaml:"-" json:"-"`
	MultiBandAndMode map[Property]BandAndMode `yaml:"-" json:"-"`
	Duplicate        bool                     `yaml:"duplicate" json:"duplicate"`
}

func (QSOScore) Equal

func (s QSOScore) Equal(other QSOScore) bool

type ScoreBin added in v0.2.0

type ScoreBin struct {
	QSOs        int                          `yaml:"qsos" json:"qsos"`
	Points      int                          `yaml:"points" json:"points"`
	Multis      int                          `yaml:"multis" json:"multis"`
	MultiValues map[Property]map[string]bool `yaml:"-" json:"-"`
	Bands       map[ContestBand]bool         `yaml:"-" json:"-"`
}

func (*ScoreBin) Add added in v0.2.0

func (b *ScoreBin) Add(qso ScoredQSO)

func (ScoreBin) Total added in v0.2.0

func (b ScoreBin) Total() int

type ScoreExample added in v0.3.2

type ScoreExample struct {
	QSOs   int `yaml:"qsos,omitempty"`
	Points int `yaml:"points,omitempty"`
	Multis int `yaml:"multis,omitempty"`
	Total  int `yaml:"total,omitempty"`
}

type ScoreMode added in v0.3.2

type ScoreMode string
const (
	// StrictScore allows only the number of bands defined in the category (single, <any number>, all). If more bands were worked, the claimed score is zero.
	StrictScore ScoreMode = "strict"
	// BestScore counts only the best n bands, according to the number of bands defined in the category (single, <any number>, all).
	BestScore ScoreMode = "best"
)

type ScoredQSO added in v0.2.0

type ScoredQSO struct {
	QSO
	QSOScore
}

type Scoring

type Scoring struct {
	QSORules       []ScoringRule  `yaml:"qsos,omitempty"`
	QSOBandRule    BandRule       `yaml:"qso_band_rule,omitempty"`
	MultiRules     []ScoringRule  `yaml:"multis,omitempty"`
	MultiOperation MultiOperation `yaml:"multi_operation,omitempty"`
}

type ScoringRule

type ScoringRule struct {
	MyContinent           []Continent          `yaml:"my_continent,omitempty"`
	MyCountry             []DXCCEntity         `yaml:"my_country,omitempty"`
	MyPrefix              []string             `yaml:"my_prefix,omitempty"`
	TheirContinent        []Continent          `yaml:"their_continent,omitempty"`
	TheirCountry          []DXCCEntity         `yaml:"their_country,omitempty"`
	TheirPrefix           []string             `yaml:"their_prefix,omitempty"`
	TheirWorkingCondition []string             `yaml:"their_working_condition,omitempty"`
	Bands                 []ContestBand        `yaml:"bands,omitempty"`
	Property              Property             `yaml:"property,omitempty"` // only useful for multis
	Except                []string             `yaml:"except,omitempty"`   // only useful for multis
	PropertyConstraints   []PropertyConstraint `yaml:"property_constraints,omitempty"`
	BandRule              BandRule             `yaml:"band_rule,omitempty"`
	AdditionalWeight      int                  `yaml:"additional_weight,omitempty"`
	Value                 int                  `yaml:"value,omitempty"`
}

type Setup

type Setup struct {
	MyCall      callsign.Callsign
	MyContinent Continent
	MyCountry   DXCCEntity

	GridLocator locator.Locator
	Operators   []callsign.Callsign

	OperatorMode OperatorMode
	Overlay      Overlay
	Power        PowerMode
	Bands        []ContestBand
	Modes        []Mode

	MyExchange QSOExchange
}

func LoadSetupFromFile

func LoadSetupFromFile(filename string) (*Setup, error)

func LoadSetupYAML

func LoadSetupYAML(r io.Reader) (*Setup, error)

func (Setup) MyPrefix added in v0.3.4

func (s Setup) MyPrefix() string

type SetupExample

type SetupExample struct {
	MyCall      string     `yaml:"my_call,omitempty"`
	MyContinent Continent  `yaml:"my_continent,omitempty"`
	MyCountry   DXCCEntity `yaml:"my_country,omitempty"`

	GridLocator string   `yaml:"grid_locator,omitempty"`
	Operators   []string `yaml:"operators,omitempty"`

	OperatorMode OperatorMode  `yaml:"operator_mode,omitempty"`
	Overlay      Overlay       `yaml:"overlay,omitempty"`
	Power        PowerMode     `yaml:"power,omitempty"`
	Bands        []ContestBand `yaml:"bands,omitempty"`
	Modes        []Mode        `yaml:"modes,omitempty"`

	MyExchange QSOExchange `yaml:"my_exchange,omitempty"`
}

func (SetupExample) ToSetup

func (s SetupExample) ToSetup() Setup

type TXMode

type TXMode string
const (
	OneTX         TXMode = "one"
	TwoTX         TXMode = "two"
	MultiTX       TXMode = "multi"
	DistributedTX TXMode = "distributed"
)

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL