Skip to content
Snippets Groups Projects
main.py 4.34 KiB
Newer Older
Jarrod Pas's avatar
Jarrod Pas committed
from argparse import ArgumentParser
Jarrod Pas's avatar
Jarrod Pas committed
from datetime import datetime
Jarrod Pas's avatar
Jarrod Pas committed
import random
Jarrod Pas's avatar
Jarrod Pas committed
import sys
Jarrod Pas's avatar
Jarrod Pas committed

import simpy
Jarrod Pas's avatar
Jarrod Pas committed
import yaml
Jarrod Pas's avatar
Jarrod Pas committed

Jarrod Pas's avatar
Jarrod Pas committed
from pydtn import Network, NodeFactory
from pydtn.traces import types as traces
from pydtn.routers import types as routers
from pydtn.communities import types as communities
Jarrod Pas's avatar
Jarrod Pas committed

def parse_args(args):
    parser = ArgumentParser()

    parser.add_argument('--seed', '-s', metavar='seed', type=int,
                        default=42)

    parser.add_argument('--trace', '-t', metavar='type', default='random',
                        choices=[t for t in traces])
    parser.add_argument('--trace-args', '-ta', metavar='arg', nargs='+')

    parser.add_argument('--router', '-r', metavar='type', default='direct',
                        choices=[t for t in routers])
    parser.add_argument('--router-args', '-ra', metavar='arg', nargs='+')

    parser.add_argument('--community', '-c', metavar='type', default='none',
                        choices=[t for t in communities])
    parser.add_argument('--community-args', '-ca', metavar='arg', nargs='+')

    parser.add_argument('--node-args', '-na', metavar='arg', nargs='+')

Jarrod Pas's avatar
Jarrod Pas committed
    parser.add_argument('--packet-args', '-pa', metavar='arg', nargs='+')

Jarrod Pas's avatar
Jarrod Pas committed
    def list_to_args(args):
        if args is None:
            return {}
        else:
            args = '\n'.join(args).replace('=',': ')
            return yaml.safe_load(args)

    args = parser.parse_args(args)

    args.trace_args = list_to_args(args.trace_args)
    args.router_args = list_to_args(args.router_args)
    args.community_args = list_to_args(args.community_args)
    args.node_args = list_to_args(args.node_args)
Jarrod Pas's avatar
Jarrod Pas committed
    args.packet_args = list_to_args(args.packet_args)
Jarrod Pas's avatar
Jarrod Pas committed

    return args

Jarrod Pas's avatar
Jarrod Pas committed
class Progress:
    def __init__(self, length, ticks, alpha):
        self.length = length
        self.alpha = alpha

        self.tick = 0
        self.ticks = ticks

Jarrod Pas's avatar
Jarrod Pas committed
        self.average = 0
Jarrod Pas's avatar
Jarrod Pas committed
        self.__start = None

        self.__last_print_len = 0

    @property
    def bar(self):
        progress = round(self.tick / self.ticks * self.length)
        return '[' + '='*progress + ' '*(self.length - progress) + ']'

    @property
    def time(self):
Jarrod Pas's avatar
Jarrod Pas committed
        remains = (self.ticks - self.tick) * self.average
Jarrod Pas's avatar
Jarrod Pas committed

        ranges = [
            ('day', 24*60*60),
            ('hour', 60*60),
            ('minute', 60),
            ('second', 1),
        ]

        for unit, weight in ranges:
            if remains >= weight:
                remains = round(remains / weight)
                plural = 's' if remains != 1 else ''
                return f'{remains} {unit}{plural}'

        return '0 seconds'

    def __next__(self):
        now = datetime.now().timestamp()
        if self.__start is not None:
Jarrod Pas's avatar
Jarrod Pas committed
            dt = now - self.__start
            self.average = self.average + self.alpha * (dt - self.average)
Jarrod Pas's avatar
Jarrod Pas committed
        self.__start = now

        self.tick += 1
        if self.tick > self.ticks:
            raise StopIteration

        print('\r' + ' '*self.__last_print_len, end='\r')
        line = f'{self.bar} {self.time} to go...'
        print(line, end=' ', flush=True)
        self.__last_print_len = len(line)

Jarrod Pas's avatar
Jarrod Pas committed
        return self.tick

    def __iter__(self):
        return self
Jarrod Pas's avatar
Jarrod Pas committed

def main(args):
    args = parse_args(args)
    print(args)

    out = {
        'seed': args.seed,
        'router': args.router,
        'community': args.community,
    }
    if args.trace == 'csv':
        out['trace'] = args.trace_args['path']

    for k, v in out.items():
        print(f'{k}: {v}')

Jarrod Pas's avatar
Jarrod Pas committed
    random.seed(args.seed)
    env = simpy.Environment()

    trace = traces[args.trace](**args.trace_args)
    router = routers[args.router]
    community = communities[args.community](**args.community_args)

    node_factory = NodeFactory(router, **args.node_args)

    network = Network(env,
Jarrod Pas's avatar
Jarrod Pas committed
                      packets=args.packet_args,
Jarrod Pas's avatar
Jarrod Pas committed
                      node_factory=node_factory,
                      community=community,
                      trace=trace)

Jarrod Pas's avatar
Jarrod Pas committed
    progress = Progress(50, 500, 0.75)
Jarrod Pas's avatar
Jarrod Pas committed
    while True:
        try:
Jarrod Pas's avatar
Jarrod Pas committed
            for tick in progress:
                until = tick / progress.ticks * trace.duration
                env.run(until=until)
Jarrod Pas's avatar
Jarrod Pas committed
            print(' Done!')
Jarrod Pas's avatar
Jarrod Pas committed
            print(str(network.packets))
Jarrod Pas's avatar
Jarrod Pas committed
            return 0
        except KeyboardInterrupt:
            print('\nBye!')
            return 0

if __name__ == '__main__':
    exit(main(sys.argv[1:]))