shingoushori's dialy

音信号処理を専ら研究していた元博士後期課程の学生によるメモ

PythonでSimutransの全乗り物の待機を上書きしてみた

GUIでぽちぽち1000台以上のバスの情報を設定するのは苦しいので、Pythonでやってみました。
正しくは、とりあえずやれたのが、まずこれだけ。

最大の苦戦どころが、
xmlデータだって言っても、CDATA なるものに対応するのが辛い
 → いっそテキストで全読み込み -> 文字列変換でElement化、パースできるように
というところです。
荒技感が強いですが、数日ググってあれこれやってみて明快な対応しているパーサや設定方法が見当たりませんでした。

さらに、あれこれやるのに苦しそうなのが、xmlデータのElementの要素名が最小限以外ほぼ無意味っぽいってことです。
convoi, haltestelle, fabrik ... あとは i64 とかだらけで、
バイナリから最小限に引っ張り出してきた感満載です。


↓サンプルコードです。
↓※絶対に元のデータを上書きしないでください。
↓※データや設定が破壊されても、責任は一切負えません。
↓version=0.120.4, 自作改造パック pak.japan_custom 用になっていますが ... 適宜正しい値になっていないと、面白いくらい開けないデータになります、多分
↓私はそれで苦戦しました
↓さらに、文字コードとかあれこれ読み込みが繊細です。

# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import xml.etree.ElementTree as ET

filename_in = 'test_in.sve'
filename_out = 'test_out.sve'

f = open(filename_in)
data1 = f.read()  # ファイル終端まで全て読んだデータを返す
f.close()

data2 = data1.replace("<![CDATA[","<CDATA>")
data2 = data2.replace("]]>","</CDATA>")

root = ET.fromstring(unicode(data2.encode('utf-8')))

for convoi in root.iter('convoi_t'):
  for fahrplan in convoi.iter('fahrplan_t'):
    fahrplan_iter = fahrplan.iter()
    elemdist = 0
    for elem in fahrplan_iter:
      if elem.tag == "koord3d":
        elemdist = 1
      elif elemdist == 5:
        # 積むまで待機(%)
        elem.text = "10"
      elif elemdist == 6:
        # 最大待ち時間(月)
        # elem.text = "6" # 1/1024
        # elem.text = "7" # 1/512
        elem.text = "8" # 1/256
      elemdist = elemdist + 1

data3 = ET.tostring(root, encoding="utf-8")

data4 = "<?xml version=\"1.0\"?>\n" + data3
data4 = data4.replace("<CDATA>","<![CDATA[")
data4 = data4.replace("</CDATA>","]]>")
data4 = data4.replace("<CDATA />","<![CDATA[]]>")
data4 = data4.replace("<Simutrans pak=\"pak.japan_custom\" version=\"0.120.4\">","<Simutrans version=\"0.120.4\" pak=\"pak.japan_custom\">")
# 元々のセーブデータのバージョンに合わせる

f = open(filename_out,'w') # 書き込みモードで開く
f.write(data4)  # 引数の文字列をファイルに書き込む
f.close()