ssscoring.cli

Command line tools package.

  1# See: https://github.com/pr3d4t0r/SSScoring/blob/master/LICENSE.txt
  2
  3"""
  4Command line tools package.
  5"""
  6
  7
  8from ssscoring import __VERSION__
  9from ssscoring.calc import aggregateResults
 10from ssscoring.calc import processAllJumpFiles
 11from ssscoring.calc import roundedAggregateResults
 12from ssscoring.constants import FT_IN_M
 13from ssscoring.flysight import getAllSpeedJumpFilesFrom
 14
 15import os
 16import pathlib
 17import sys
 18
 19import click
 20
 21
 22# +++ implementation +++
 23
 24def die(message: str, exitCode: int, isUnitTest = False) -> int:
 25    """
 26    Display an end-user `message` and exit the program with `exitCode`.
 27
 28    Arguments
 29    ---------
 30        message
 31    A string, most often with a descriptive error message.
 32
 33        exitCode
 34    An exit code, where `0` is normal exit, and any other value is an error
 35    condition.
 36
 37        isUnitTest
 38    A Boolean; if `True`, the program returns the value of `exitCode` to the
 39    caller, otherwise it terminates with `sys.exit(exitCode)`.
 40    """
 41    if isUnitTest:
 42        return exitCode
 43    else:
 44        click.secho('%s - exit code %d' % (message, exitCode))
 45        sys.exit(exitCode)
 46
 47
 48def _assertDataLake(dataLake: str, isUnitTest = False) -> bool:
 49    """
 50    Assert that the path exists and that the program has read access permission
 51    for at least the topmost directory.
 52
 53    Arguments
 54    ---------
 55        dataLake
 56    A string path corresponding to the data lake, used as the basis to create
 57    an instance of `pathlib.Path` to test path validity.
 58
 59    Returns
 60    -------
 61    `True` if the path exists and is accessible.
 62
 63
 64    Raises
 65    ------
 66    Various system-level exceptions depending on file system conditions and
 67    command line argument validity.  `FileNotFound` is a common one.
 68    """
 69    retVal = False
 70    try:
 71        path = pathlib.Path(dataLake)
 72        if not path.exists():
 73            die('%s - data lake not found' % dataLake, 2, isUnitTest)
 74        elif not path.is_dir():
 75            die('%s - please specify a directory' % dataLake, 3, isUnitTest)
 76        elif not os.access(path.as_posix(), os.R_OK):
 77            die('%s - ssscore lacks permission to read the track files', 4, isUnitTest)
 78        else:
 79            retVal = True
 80    except Exception as e:
 81        die('Data lake assertion failed - %s' % str(e), 1, isUnitTest)
 82    return retVal
 83
 84
 85def ssscore(elevation: float, trainingOutput: bool, dataLake: str) -> int:
 86    """
 87    Process all the speed skydiving files contained in `dataLakeSpec`.  This
 88    function implements the business logic for the `/usr/local/bin/ssscore`
 89    command.  See `pyproject.toml` for command details.
 90
 91    Arguments
 92    ---------
 93        elevation
 94    The drop zone elevation MSL in feet.
 95
 96        trainingOutput
 97    If `True`, output will use rounded values.
 98
 99        dataLake
100    Command line argument with the path to the data lake.
101
102    Returns
103    -------
104    The number of jump results from processing all the FlySight files in the
105    data lake.
106    """
107    _assertDataLake(dataLake)
108
109    elevationMeters = elevation/FT_IN_M
110    click.secho("elevation = %.2f m (%.2f')" % (elevationMeters, elevation))
111    click.secho('Processing speed tracks in %s...\n' % dataLake)
112    jumpResults = processAllJumpFiles(getAllSpeedJumpFilesFrom(dataLake), altitudeDZMeters=elevationMeters)
113    if jumpResults:
114        if trainingOutput:
115            resultsSummary = roundedAggregateResults(aggregateResults(jumpResults))
116        else:
117            resultsSummary = aggregateResults(jumpResults)
118        click.secho(resultsSummary, fg = 'bright_green')
119        click.secho('\nTotal score = %5.2f, mean speed = %5.2f\n' % (resultsSummary.score.sum(), resultsSummary.score.mean()), fg = 'bright_white')
120    else:
121        click.secho('There were no speed track files to score in %s', fg = 'bright_red')
122    return len(jumpResults)
123
124
125@click.command('ssscore')
126@click.argument('datalake', nargs = 1, type = click.STRING)
127@click.version_option(__VERSION__, prog_name = 'ssscore')
128@click.option('-e', '--elevation', default=0.0, show_default=True, help='DZ elevation in ft')
129@click.option('-t', '--training', is_flag=True, show_default=True, default=False, help='Show training output values')
130def _ssscoreCommand(elevation: float, training: bool, datalake: str) -> int:
131    return ssscore(elevation, training, datalake)
132
133
134# +++ main +++
135
136# For interactive testing and symbolic debugging:
137if '__main__' == __name__:
138    _ssscoreCommand()
def die(message: str, exitCode: int, isUnitTest=False) -> int:
25def die(message: str, exitCode: int, isUnitTest = False) -> int:
26    """
27    Display an end-user `message` and exit the program with `exitCode`.
28
29    Arguments
30    ---------
31        message
32    A string, most often with a descriptive error message.
33
34        exitCode
35    An exit code, where `0` is normal exit, and any other value is an error
36    condition.
37
38        isUnitTest
39    A Boolean; if `True`, the program returns the value of `exitCode` to the
40    caller, otherwise it terminates with `sys.exit(exitCode)`.
41    """
42    if isUnitTest:
43        return exitCode
44    else:
45        click.secho('%s - exit code %d' % (message, exitCode))
46        sys.exit(exitCode)

Display an end-user message and exit the program with exitCode.

Arguments

message

A string, most often with a descriptive error message.

exitCode

An exit code, where 0 is normal exit, and any other value is an error condition.

isUnitTest

A Boolean; if True, the program returns the value of exitCode to the caller, otherwise it terminates with sys.exit(exitCode).

def ssscore(elevation: float, trainingOutput: bool, dataLake: str) -> int:
 86def ssscore(elevation: float, trainingOutput: bool, dataLake: str) -> int:
 87    """
 88    Process all the speed skydiving files contained in `dataLakeSpec`.  This
 89    function implements the business logic for the `/usr/local/bin/ssscore`
 90    command.  See `pyproject.toml` for command details.
 91
 92    Arguments
 93    ---------
 94        elevation
 95    The drop zone elevation MSL in feet.
 96
 97        trainingOutput
 98    If `True`, output will use rounded values.
 99
100        dataLake
101    Command line argument with the path to the data lake.
102
103    Returns
104    -------
105    The number of jump results from processing all the FlySight files in the
106    data lake.
107    """
108    _assertDataLake(dataLake)
109
110    elevationMeters = elevation/FT_IN_M
111    click.secho("elevation = %.2f m (%.2f')" % (elevationMeters, elevation))
112    click.secho('Processing speed tracks in %s...\n' % dataLake)
113    jumpResults = processAllJumpFiles(getAllSpeedJumpFilesFrom(dataLake), altitudeDZMeters=elevationMeters)
114    if jumpResults:
115        if trainingOutput:
116            resultsSummary = roundedAggregateResults(aggregateResults(jumpResults))
117        else:
118            resultsSummary = aggregateResults(jumpResults)
119        click.secho(resultsSummary, fg = 'bright_green')
120        click.secho('\nTotal score = %5.2f, mean speed = %5.2f\n' % (resultsSummary.score.sum(), resultsSummary.score.mean()), fg = 'bright_white')
121    else:
122        click.secho('There were no speed track files to score in %s', fg = 'bright_red')
123    return len(jumpResults)

Process all the speed skydiving files contained in dataLakeSpec. This function implements the business logic for the /usr/local/bin/ssscore command. See pyproject.toml for command details.

Arguments

elevation

The drop zone elevation MSL in feet.

trainingOutput

If True, output will use rounded values.

dataLake

Command line argument with the path to the data lake.

Returns

The number of jump results from processing all the FlySight files in the data lake.