def _get_removable_railroads(): railroads_info = get_railroad_info(g.game_name) return { name for name, attribs in railroads_info.items() if attribs.get("is_removable") }
def removable_railroads(): LOG.info("Removable railroads request.") removable_railroads = _get_removable_railroads() LOG.info(f"Removable railroads response: {removable_railroads}") railroads_info = get_railroad_info(g.game_name) return jsonify({ "railroads": list(sorted(removable_railroads)), "home-cities": { railroad: railroads_info[railroad]["home"] for railroad in removable_railroads } })
def closable_railroads(): LOG.info("Closable railroads request.") game = get_game(g.game_name) closable_railroads = _get_closable_railroads(game) LOG.info(f"Closable railroads response: {closable_railroads}") railroads_info = get_railroad_info(game) return jsonify({ "railroads": list(sorted(closable_railroads)), "home-cities": { railroad: railroads_info[railroad]["home"] for railroad in closable_railroads } })
def legal_railroads(): LOG.info("Legal railroads request.") existing_railroads = { railroad for railroad in json.loads(request.args.get("railroads", "{}")) if railroad } railroads_info = get_railroad_info(g.game_name) legal_railroads = set(railroads_info.keys()) - existing_railroads LOG.info(f"Legal railroads response: {legal_railroads}") return jsonify({ "railroads": list(sorted(legal_railroads)), "home-cities": { railroad: railroads_info[railroad]["home"] for railroad in legal_railroads } })
def _validate_migration_data(migration_data): if not isinstance(migration_data, dict): LOG.debug( f"Migration validation failure: migration_data is not a dict") return {"error": "Failed to load migration data."} game = get_game("1846") railroad_info = get_railroad_info(game) private_companies = game.get_game_submodule("private_companies") for key, value in migration_data.items(): # Make sure no control characters or non-ASCII characters are present. if not key.isascii() or not key.isprintable() or not value.isascii( ) or not value.isprintable(): LOG.debug( f"Migration failure: key or value is not printable ASCII") return False try: migration_data[key] = json.dumps(json.loads(value)) except Exception as exc: LOG.debug( f"Migration validation failure[{key}]: value not valid JSON: {value}" ) return False if key == "placedTilesTable": tiles_json = json.loads(value) if not all(len(row) == 3 for row in tiles_json) or not all( str(col).isalnum() for row in tiles_json for col in row): LOG.debug(f"Migration validation failure[{key}]: {value}") return False elif key == "railroadsTable": railroads_json = json.loads(value) for row in railroads_json: if len(row) not in (3, 4) or row[0].strip() not in railroad_info: LOG.debug( f"Migration validation failure[{key}]: row wrong length, or railroad name invalid: {value}" ) return False if row[1] and row[1].strip(): train_strs = [ train_str.strip().split("/", 1) for train_str in row[1].strip().split(",") ] if not all(val.strip().isdigit() for train_str in train_strs for val in train_str): LOG.debug( f"Migration validation failure[{key}]: trains malformed: {value}" ) return False if row[2] and row[2].strip(): if not all(station_str.strip().isalnum() for station_str in row[2].strip().split(",")): LOG.debug( f"Migration validation failure[{key}]: stations malformed: {value}" ) return False elif key == "removedRailroadsTable": removed_railroads = json.loads(value) for railroad in removed_railroads: if railroad.strip() not in railroad_info: LOG.debug( f"Migration validation failure[{key}]: railroad name invalid: {value}" ) return False elif key == "privateCompaniesTable": private_companies_json = json.loads(value) for row in private_companies_json: if len(row) != 3 \ or row[0].strip() not in private_companies.COMPANIES \ or (row[1] and row[1].strip() not in railroad_info) \ or (row[2] and not row[2].strip().isalnum()): LOG.debug( f"Migration validation failure[{key}]: invalid row: {row}" ) return False elif key == "hideCityPaths": if value not in ("true", "false"): LOG.debug(f"Migration validation failure[{key}]: {value}") return False else: LOG.debug(f"Migration validation failure: invalid key: {key}") return False return True
def _get_closable_railroads(game): return set(get_railroad_info( game).keys()) if game.rules.railroads_can_close else set()
def board_space_info(): coord = request.args["coord"].strip() tile_id = request.args.get("tileId", "").strip() orientation = request.args.get("orientation", "").strip() phase = request.args.get("phase") game = get_game(g.game_name) board = get_board(game) railroad_info = get_railroad_info(game) cell = board.cell(coord) station_offsets = get_station_offsets(game) if tile_id and orientation: offset_data = station_offsets.get("tile", {}) offset = _get_station_offset(offset_data, tile_id) space = placedtile.PlacedTile.place(cell, game.tiles[tile_id], orientation, board.get_space(cell)) if isinstance(space, placedtile.SplitCity): # In the offset file, branches are indicated by side. To translate # into cells, add the orientation, and modulo by 6 to retrieve its # neighbor given the orientation. offset = { str(cell.neighbors[(int(exit) + int(orientation)) % 6]): offsetCoords for exit, offsetCoords in offset.items() } if "rotation" in offset: offset["rotation"] = math.radians(offset["rotation"]) else: offset_data = station_offsets.get("board", {}) offset = _get_station_offset(offset_data, coord) space = board.get_space(cell) if "rotation" in offset: offset["rotation"] = math.radians(offset["rotation"]) if hasattr(space, "capacity"): # Stop-gap. I need to figure out what to actually do with capacity keys. capacity = sum(space.capacity.values()) if isinstance( space.capacity, dict) else space.capacity else: capacity = 0 home = [ railroad for railroad, info_dict in railroad_info.items() if info_dict.get("home") == coord ] if not phase or (game.rules.stations_reserved_until and game.compare_phases( game.rules.stations_reserved_until, phase) < 0): reserved = [ railroad for railroad, info_dict in railroad_info.items() if coord in info_dict.get("reserved", []) ] else: reserved = [] info = { "capacity": capacity, "offset": offset, "phase": getattr(space, "upgrade_level", 0), "is-split-city": isinstance(space, (boardtile.SplitCity, placedtile.SplitCity)), "home-to": home, "reserved-for": reserved } return jsonify({"info": info})