def run(results, cmdenv, tdb):
    """
    Fetch all the data needed to display the results of a "rares"
    command. Does not actually print anything.

    Command execution is broken into two steps:
        1. cmd.run(results, cmdenv, tdb)
            Gather all the data required but generate no output,
        2. cmd.render(results, cmdenv, tdb)
            Print output to the user.

    This separation of concerns allows modularity; you can write
    a command that calls another command to fetch data for you
    and knowing it doesn't generate any output. Then you can
    process the data and return it and let the command parser
    decide when to turn it into output.

    It also opens a future door to commands that can present
    their data in a GUI as well as the command line by having
    a custom render() function.

    Parameters:
        results
            An object to be populated and returned
        cmdenv
            A CommandEnv object populated with the parameters
            for the command.
        tdb
            A TradeDB object to query against.

    Returns:
        None
            End execution without any output
        results
            Proceed to "render" with the output.
    """

    # Lookup the system we're currently in.
    start = cmdenv.nearSystem
    # Hoist the padSize parameter for convenience
    padSize = cmdenv.padSize
    # How far we're want to cast our net.
    maxLy = float(cmdenv.maxLyPer or 0.0)

    if cmdenv.illegal:
        wantIllegality = "Y"
    elif cmdenv.legal:
        wantIllegality = "N"
    else:
        wantIllegality = "YN?"

    awaySystems = set()
    if cmdenv.away or cmdenv.awayFrom:
        if not cmdenv.away or not cmdenv.awayFrom:
            raise CommandLineError("Invalid --away/--from usage. See --help")
        minAwayDist = cmdenv.away
        for sysName in cmdenv.awayFrom:
            system = tdb.lookupPlace(sysName).system
            awaySystems.add(system)

    # Start to build up the results data.
    results.summary = ResultRow()
    results.summary.near = start
    results.summary.ly = maxLy
    results.summary.awaySystems = awaySystems

    distCheckFn = start.distanceTo

    # Look through the rares list.
    for rare in tdb.rareItemByID.values():
        if not rare.illegal in wantIllegality:
            continue
        if padSize:  # do we care about pad size?
            if not rare.station.checkPadSize(padSize):
                continue
        rareSys = rare.station.system
        # Find the un-sqrt'd distance to the system.
        dist = distCheckFn(rareSys)
        if 0 < maxLy < dist:
            continue

        if awaySystems:
            awayCheck = rareSys.distanceTo
            if any(awayCheck(away) < minAwayDist for away in awaySystems):
                continue

        # Create a row for this item
        row = ResultRow()
        row.rare = rare
        row.dist = dist
        results.rows.append(row)

    # Was anything matched?
    if not results:
        print("No matches found.")
        return None

    if cmdenv.sortByPrice:
        results.rows.sort(key=lambda row: row.dist)
        results.rows.sort(key=lambda row: row.rare.costCr, reverse=True)
    else:
        results.rows.sort(key=lambda row: row.rare.costCr, reverse=True)
        results.rows.sort(key=lambda row: row.dist)

    if cmdenv.reverse:
        results.rows.reverse()

    limit = cmdenv.limit or 0
    if limit > 0:
        results.rows = results.rows[:limit]

    return results
Example #2
0
def run(results, cmdenv, tdb):
    """
    Fetch all the data needed to display the results of a "rares"
    command. Does not actually print anything.

    Command execution is broken into two steps:
        1. cmd.run(results, cmdenv, tdb)
            Gather all the data required but generate no output,
        2. cmd.render(results, cmdenv, tdb)
            Print output to the user.

    This separation of concerns allows modularity; you can write
    a command that calls another command to fetch data for you
    and knowing it doesn't generate any output. Then you can
    process the data and return it and let the command parser
    decide when to turn it into output.

    It also opens a future door to commands that can present
    their data in a GUI as well as the command line by having
    a custom render() function.

    Parameters:
        results
            An object to be populated and returned
        cmdenv
            A CommandEnv object populated with the parameters
            for the command.
        tdb
            A TradeDB object to query against.

    Returns:
        None
            End execution without any output
        results
            Proceed to "render" with the output.
    """

    # Lookup the system we're currently in.
    start = cmdenv.nearSystem
    # Hoist the padSize, noPlanet and planetary parameter for convenience
    padSize = cmdenv.padSize
    noPlanet = cmdenv.noPlanet
    planetary = cmdenv.planetary
    # How far we're want to cast our net.
    maxLy = float(cmdenv.maxLyPer or 0.)

    if cmdenv.illegal:
        wantIllegality = 'Y'
    elif cmdenv.legal:
        wantIllegality = 'N'
    else:
        wantIllegality = 'YN?'

    awaySystems = set()
    if cmdenv.away or cmdenv.awayFrom:
        if not cmdenv.away or not cmdenv.awayFrom:
            raise CommandLineError("Invalid --away/--from usage. See --help")
        minAwayDist = cmdenv.away
        for sysName in cmdenv.awayFrom:
            system = tdb.lookupPlace(sysName).system
            awaySystems.add(system)

    # Start to build up the results data.
    results.summary = ResultRow()
    results.summary.near = start
    results.summary.ly = maxLy
    results.summary.awaySystems = awaySystems

    distCheckFn = start.distanceTo

    # Look through the rares list.
    for rare in tdb.rareItemByID.values():
        if not rare.illegal in wantIllegality:
            continue
        if padSize:  # do we care about pad size?
            if not rare.station.checkPadSize(padSize):
                continue
        if planetary:  # do we care about planetary?
            if not rare.station.checkPlanetary(planetary):
                continue
        if noPlanet and rare.station.planetary != 'N':
            continue
        rareSys = rare.station.system
        # Find the un-sqrt'd distance to the system.
        dist = distCheckFn(rareSys)
        if maxLy > 0. and dist > maxLy:
            continue

        if awaySystems:
            awayCheck = rareSys.distanceTo
            if any(awayCheck(away) < minAwayDist for away in awaySystems):
                continue

        # Create a row for this item
        row = ResultRow()
        row.rare = rare
        row.dist = dist
        results.rows.append(row)

    # Was anything matched?
    if not results:
        print("No matches found.")
        return None

    if cmdenv.sortByPrice:
        results.rows.sort(key=lambda row: row.dist)
        results.rows.sort(key=lambda row: row.rare.costCr, reverse=True)
    else:
        results.rows.sort(key=lambda row: row.rare.costCr, reverse=True)
        results.rows.sort(key=lambda row: row.dist)

    if cmdenv.reverse:
        results.rows.reverse()

    limit = cmdenv.limit or 0
    if limit > 0:
        results.rows = results.rows[:limit]

    return results