0.4.0 add Nether rails + day mode

This commit is contained in:
Yusur 2026-04-07 13:19:00 +02:00
parent 212e415ead
commit f0617f741b
4 changed files with 70 additions and 19 deletions

View file

@ -1,3 +1,8 @@
# 0.4.0
+ Added nether lines
+ Added "day mode" colors
# 0.3.0 # 0.3.0
+ Added colors + Added colors

View file

@ -6,7 +6,7 @@ from .utils import HourMin
from .rails import main_rails from .rails import main_rails
from .triwat import main_triwat from .triwat import main_triwat
__version__ = "0.3.0" __version__ = "0.4.0"
def build_parser(): def build_parser():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
@ -18,8 +18,10 @@ def build_parser():
parser_r.add_argument('start', help='station of start', default=None, nargs='?') parser_r.add_argument('start', help='station of start', default=None, nargs='?')
parser_r.add_argument('end', help='station of end', default=None, nargs='?') parser_r.add_argument('end', help='station of end', default=None, nargs='?')
parser_r.add_argument('-t', '--time', help='time of start', type=HourMin, default=HourMin(0)) parser_r.add_argument('-t', '--time', help='time of start', type=HourMin, default=HourMin(0))
parser_r.add_argument('-n', '--nether', help='use the Nether', action='store_true')
parser_r.add_argument('--legacy', action='store_true', help="use legacy network") parser_r.add_argument('--legacy', action='store_true', help="use legacy network")
parser_r.add_argument('-q', '--search', help='search a station by its name') parser_r.add_argument('-q', '--search', help='search a station by its name')
parser_r.add_argument('--day', help='day mode', action='store_true')
parser_t = parsers.add_parser('triwat', aliases=('t',)) parser_t = parsers.add_parser('triwat', aliases=('t',))
parser_t.add_argument('--multi', help="multiple posts", action='store_true') parser_t.add_argument('--multi', help="multiple posts", action='store_true')

View file

@ -7,7 +7,7 @@ from math import ceil
from heapq import heapify, heappush, heappop from heapq import heapify, heappush, heappop
from suou import chalk from suou import chalk
from .utils import HourMin from .utils import HourMin, take_first
ALL_DATA = json.load(open('data/network.json')) ALL_DATA = json.load(open('data/network.json'))
LEGACY_DATA = json.load(open('data/network.1.json')) LEGACY_DATA = json.load(open('data/network.1.json'))
@ -40,19 +40,18 @@ class RouteStep:
line: str line: str
def find_station(code: str) -> Station | None: def find_station(code: str) -> Station | None:
st_name = ALL_DATA.get('stations', {}).get(code) if not code:
return
if code.startswith('N-'):
st_name = take_first(ALL_DATA.get('stations', {}).get(code[2:], code[2:])) + ' Nether'
else:
st_name = take_first(ALL_DATA.get('stations', {}).get(code, code))
if st_name: if st_name:
return Station( return Station(
name = st_name, name = st_name,
code = code code = code
) )
def take_first(s):
if isinstance(s, (str, bytes)):
return s
elif hasattr(s, '__iter__'):
return list(s)[0]
return s
def build_route_list(line_stops: list, line_code): def build_route_list(line_stops: list, line_code):
route_list = [] route_list = []
@ -76,9 +75,9 @@ def build_route_list(line_stops: list, line_code):
last_step = cur_step last_step = cur_step
return route_list return route_list
def build_all_lines(): def build_all_lines(dim = 'overworld'):
lines = {} lines = {}
for line_data in ALL_DATA['lines']['overworld']: for line_data in ALL_DATA['lines'][dim]:
lines[line_data['code']] = Line( lines[line_data['code']] = Line(
code = line_data['code'], code = line_data['code'],
@ -88,12 +87,13 @@ def build_all_lines():
return lines return lines
ALL_LINES = build_all_lines() ALL_LINES = build_all_lines()
NETHER_LINES = build_all_lines('the_nether')
## TODO algorithms of research ## TODO algorithms of research
def find_route(start: str, stop: str): def find_route(start: str, stop: str, nether = False):
steps_i = [] steps_i = []
dist, prev = dijkstra(start) dist, prev = dijkstra(start, nether=nether)
cur = stop cur = stop
steps_i.append((find_station(stop), dist[stop])) steps_i.append((find_station(stop), dist[stop]))
@ -105,8 +105,10 @@ def find_route(start: str, stop: str):
return steps_i return steps_i
NETHER_DELAY = 2
@lru_cache() @lru_cache()
def find_neighbors(start): def find_neighbors(start: str, *, nether = False):
neighs = [] neighs = []
for line in ALL_LINES.values(): for line in ALL_LINES.values():
@ -118,10 +120,28 @@ def find_neighbors(start):
neighs.append((rs.target.code, rs.time)) neighs.append((rs.target.code, rs.time))
if rs.target.code == start: if rs.target.code == start:
neighs.append((rs.origin.code, rs.time)) neighs.append((rs.origin.code, rs.time))
if nether:
if start.startswith('N-'):
for line in NETHER_LINES.values():
line: Line
if start[2:] in line:
for rs in line.route:
rs: RouteStep
if rs.origin.code == start[2:]:
neighs.append(('N-' + rs.target.code, rs.time))
if rs.target.code == start[2:]:
neighs.append(('N-' + rs.origin.code, rs.time))
neighs.append((start[2:], NETHER_DELAY))
else:
for line in NETHER_LINES.values():
line: Line
if start in line:
neighs.append((f'N-{start}', NETHER_DELAY))
break
return neighs return neighs
def dijkstra(start: str): def dijkstra(start: str, *, nether: bool = False):
dist = {node: INFINITY for node in ALL_DATA['stations']} dist = {node: INFINITY for node in ALL_DATA['stations']}
dist[start] = 0 dist[start] = 0
prev = {node: None for node in ALL_DATA['stations']} prev = {node: None for node in ALL_DATA['stations']}
@ -138,7 +158,7 @@ def dijkstra(start: str):
continue continue
visited.add(cur_node) visited.add(cur_node)
for neigh, time in find_neighbors(cur_node): for neigh, time in find_neighbors(cur_node, nether = nether):
tentative_dist = cur_dist + time tentative_dist = cur_dist + time
if tentative_dist < dist.setdefault(neigh, INFINITY): if tentative_dist < dist.setdefault(neigh, INFINITY):
dist[neigh] = tentative_dist dist[neigh] = tentative_dist
@ -147,6 +167,14 @@ def dijkstra(start: str):
return dist, prev return dist, prev
def hm_color(hm: HourMin):
if hm < 6 * 60 or hm >= 20 * 60:
return chalk.blue
if hm < 10 * 60:
return chalk.cyan
if hm < 16 * 60:
return chalk.yellow
return chalk.purple
def main_rails(args): def main_rails(args):
@ -170,7 +198,16 @@ def main_rails(args):
print('**', f'{chalk.red(f'Missing stations')}') print('**', f'{chalk.red(f'Missing stations')}')
return return
route = find_route(st_start.code, st_end.code) try:
route = find_route(st_start.code, st_end.code, nether=args.nether)
except KeyError as k:
print('**', f'{chalk.red(f'Route {k} is impassable')}')
return
for st_step, time in route: for st_step, time in route:
print(chalk.cyan(f'{HourMin(st_time + time)}'), chalk.bold(st_step.code), st_step.name) hm_time = HourMin(st_time + time)
print(
(hm_color(hm_time) if args.day else chalk.yellow)(f'{hm_time}'),
f'{chalk.red('N-')}{chalk.bold(st_step.code[2:])}' if st_step.code.startswith('N-') else chalk.bold(st_step.code),
st_step.name
)

View file

@ -8,4 +8,11 @@ class HourMin(int):
if len(args) == 1 and isinstance(args[0], str) and ':' in args[0]: if len(args) == 1 and isinstance(args[0], str) and ':' in args[0]:
h, m = args[0].split(':') h, m = args[0].split(':')
return super().__new__(cls, int(h) * 60 + int(m)) return super().__new__(cls, int(h) * 60 + int(m))
return super().__new__(cls, *args) return super().__new__(cls, *args)
def take_first(s):
if isinstance(s, (str, bytes)):
return s
elif hasattr(s, '__iter__'):
return next(iter(s))
return s