Skip to content
Snippets Groups Projects
main.py 4.27 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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
    
    from pydyton import Network, NodeFactory
    from pydyton.traces import types as traces
    from pydyton.routers import types as routers
    from pydyton.communities import types as communities
    
    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
    
            self.__start = None
            self.__times = []
    
            self.__last_print_len = 0
    
        def print(self):
            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)
    
        @property
        def bar(self):
            progress = round(self.tick / self.ticks * self.length)
            return '[' + '='*progress + ' '*(self.length - progress) + ']'
    
        @property
        def time(self):
            ema = sum([
                value * (self.alpha**(len(self.__times) - i + 1))
                for i, value in enumerate(self.__times)
            ])
            remains = (self.ticks - self.tick) * ema
    
            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:
                self.__times.append(now - self.__start)
            self.__start = now
    
            self.tick += 1
            if self.tick > self.ticks:
                raise StopIteration
    
            self.print()
            return self.tick
    
        def __iter__(self):
            return self
    
    Jarrod Pas's avatar
    Jarrod Pas committed
    
    def main(args):
        args = parse_args(args)
        print(args)
    
        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.9)
        time_per_tick = []
    
    Jarrod Pas's avatar
    Jarrod Pas committed
        while True:
            try:
    
    Jarrod Pas's avatar
    Jarrod Pas committed
                line = '\r'
                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:]))