嘘です。コンパネを真っ二つにする裁断を1回だけやりました(Unidyでやってもらった)。
使った材料は、1800x900のコンパネ3枚と、4X2の1800の角材5本、木ネジ60本、自宅の庭に放置されていたコンクリートの固定具です。制作時間は2時間強くらいでした。


江端智一のホームページ
嘘です。コンパネを真っ二つにする裁断を1回だけやりました(Unidyでやってもらった)。
使った材料は、1800x900のコンパネ3枚と、4X2の1800の角材5本、木ネジ60本、自宅の庭に放置されていたコンクリートの固定具です。制作時間は2時間強くらいでした。
『6ヶ月』 ―― これが、私が計算と経験則から導き出した結論です。
Six months" is the conclusion I have drawn from my calculations and rule of thumb.
【新着記事】「江バ電」で人身事故をシミュレーションしてみた https://t.co/Qxr14X4COB pic.twitter.com/oJlAOsppaG
— EE Times Japan編集部 (@eetimes_jp) June 29, 2016
上記の私のコラムの5ページ目に、以下の記載があります。
You will find the following statement on page 5 of my column above.
■「この私」が、3・11の震災(東日本大震災)をどのように忘れていったのかを、定量的に知りたいと思いました。
- I wanted to know quantitatively how "this I" had forgotten about the 3/11 disaster (the Great East Japan)
■そこで、私がここ何年間、1日も欠かさずに記録し続けているブログを使って、以下のような調査をやってみました。
- I did the following survey using my blog, which I have kept track of without missing a single day for the past years.
-----
高齢者介護 ~医療の進歩の代償なのかhttps://t.co/R1DV5OshVJ pic.twitter.com/IiQbaWM0tR
— EE Times Japan編集部 (@eetimes_jp) July 30, 2018
上記の私のコラムの6ページ目に、以下の記載があります。
You will find the following statement on page 6 of my column above.
■ここから導かれる一つの仮説は、江戸時代以前の"寝たきり"とは、どんなに長くても半年程度であったということです。
- One hypothesis derived from this is that "bedridden" was only for about six months before the Edo period.
■当時の介護技術で、"寝たきり"を3年とか10年のオーダーで成立させるのは、無理だったはずです。
- With the care technology available at the time, it would have been impossible to keep a person "bedridden" for three or ten years.
-----
ウクライナ支援についても、各国の「支援疲れ」は、厳然たる事実です。
As for support for Ukraine, it is a stark fact that countries are "tired of supporting" Ukraine.
期限が定められていない支援に耐えられるほど、私たちは強くないのです。
We are not strong enough to withstand support without a set deadline.
-----
結論:
Conclusion:
(1)「他人への、条件のない愛情(無償の愛)のストックには上限がある」
(1) "There is an upper limit to the stock of unconditional love (free love) for others."
(2)「そのストックは、概ね6ヶ月で尽きる」
(2) "Its stock generally runs out in six months."
(3)「被災地支援、寝たきりの人への介護が「無償」で継続できる期間は、最長で"半年"である」
(3) "The maximum period during which support for disaster-affected areas and care for bedridden people can continue "free of charge" is "six months.
この現実をベースに、私たちは、被災者支援や高齢者介護を計画しなければならないと思います。
Based on this reality, we must plan to support the affected population and care for older people.
「無償の愛」を『無期限』とする計画は、必ず破綻します ―― "必ず"です。
The plan to make "free love" "indefinite" will surely fail -- "surely."
■fastapi側プログラム dummy2.py
from fastapi import FastAPI
from pydantic import BaseModel
import asyncio # asyncio モジュールをインポート
app = FastAPI()
class InputMessage(BaseModel):
value: int
class OutputMessage(BaseModel):
response: int # 数値を含むレスポンスメッセージ
@app.post("/process")
async def process(input_message: InputMessage):
# 5秒間の待機
await asyncio.sleep(5)
# サーバー側で数値を受け取り、同じ数値を含むレスポンスメッセージを返す
response_value = input_message.value
output_message = OutputMessage(response=response_value)
return output_message
起動方法は、
uvicorn dummy2:app --host 0.0.0.0 --reload
■メッセージ送信側(クライアント)プログラム dummy3.py
import httpx
import sys
import asyncio # asyncio モジュールをインポート
async def send_message_to_api(value: int):
url = "http://localhost:8000/process" # FastAPIサーバーのエンドポイントURLを指定
input_message = {"value": value} # 送信する数値をJSONメッセージに含める
async with httpx.AsyncClient() as client:
response = await client.post(url, json=input_message, timeout=10.0)
if response.status_code == 200:
data = response.json()
print(f"APIからのレスポンス: {data['response']}")
else:
print(f"エラーが発生しました。ステータスコード: {response.status_code}")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("使用法: python send.py <数値>")
sys.exit(1)
try:
value_to_send = int(sys.argv[1]) # コマンドライン引数から数値を取得
except ValueError:
print("数値を指定してください。")
sys.exit(1)
asyncio.run(send_message_to_api(value_to_send))
起動方法は、
>python dummy3.py 10
平行に3つ起動しても、正確に非同期処理してくれるようです。
昨夜から、デッドロック問題で、困っていたので、原点に戻って考え中です。
Win32 Disk Imager
"Win32 Disk Imager"の使いかたが結構分けわからん
まず、SDカード→PCへのコピーは、
Deviceでドライブ"e.f.[G\]"を選んで→
Image Fileの方にテキトーな名前を(d:\testtest20231010とか、絶対に存在しないファイル名にして)つけて
"Read"ボタンを押す。絶対存在しないファイル名にすることによって、間違った読み込みをすることはなくなる(はず)
PC→SDカードへのコピーは、
上記の逆転をやって
"Write"をボタンを押す。
この"Read"と"Write"を間違えて、ハードディスク丸ごと破壊したことを、ゆめゆめ忘れるな
プロセスを強制終了しなければならないAPIを作っているのですが、「pythonからPIDをkillできない件」で困っていました。
で、以下の実験用プログラムを作成しました。
import sys
import os
import signal
def kill_process(pid):
try:
os.kill(pid, signal.SIGKILL) # 指定したプロセスIDをSIGKILLシグナルで終了
print(f"Process with PID {pid} has been killed.")
except OSError:
print(f"Failed to kill process with PID {pid}.")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python kill_process.py <PID>")
sys.exit(1)
try:
pid = int(sys.argv[1])
kill_process(pid)
except ValueError:
print("Invalid PID. Please enter a valid integer PID.")
で、
python3 kill_process.py 7870
を連発したのですが、全くプロセスが消えません(ps -ef | grep xxxxxなどでレビュー)
どうやら、最初に"sudo"を付けて、
sudo python3 kill_process.py 7870
で、起動してくれることが分かりました。
で、本家の問題ですが、fastapiを使ったプログラムを試してみたのですが、
sudo uvicorn test:app --host 0.0.0.0 --reload
では、エラーになります。これは環境変数を引きついでいない、とのことで、"-E"を付与することで、動くことを確認しました。
sudo -E uvicorn test:app --host 0.0.0.0 --reload
持っていかれた時間は4時間くらいかなぁ。
それでも、とりあえず動いて、次の開発に進めるので、安堵しています。
(こういう案件を夜に残すと、夜の眠りが浅くなる)。
curl -X POST -H "Content-Type: application/json" -d "{\"count\": \"5\"}" http://localhost:8000/execute-command
curl -X POST -H "Content-Type: application/json" -d "{\"pid\": \"10164\"}" http://localhost:8000/terminate-process
# curl -X POST -H "Content-Type: application/json" -d "{\"count\": \"5\"}" http://localhost:8000/execute-command
# curl -X POST -H "Content-Type: application/json" -d "{\"pid\": \"10164\"}" http://localhost:8000/terminate-process
import subprocess
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ExecuteRequest(BaseModel):
count: int # pingコマンドの実行回数を指定
class TerminateRequest(BaseModel):
pid: int # 終了させるプロセスのPID
# 実行中のプロセスを格納する辞書
running_processes = {}
@app.post("/execute-command")
def execute_command(request: ExecuteRequest):
count = request.count
try:
command = f"ping -n {count} kobore.net" # pingコマンドの回数をcountに指定
# コマンドを非同期で実行し、プロセスを取得
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pid = process.pid # プロセスのPIDを取得
running_processes[pid] = process
return {"pid": pid} # PIDのみを返す
except Exception as e:
return {"message": f"コマンドの実行中にエラーが発生しました: {str(e)}"}
@app.post("/terminate-process")
def terminate_process(request: TerminateRequest):
pid = request.pid
print("pid in terminate-process", pid)
try:
# プロセスを取得し、終了させる
process = running_processes.get(pid)
process.terminate() # プロセスを終了させる(SIGTERMを送信)
process.wait()
del running_processes[pid] # プロセスを辞書から削除
# 成功の場合は1を返す
return {"status": 1}
except Exception as e:
return {"status": -1} # 失敗の場合は-1を返す
if __name__ == "__main__":
# FastAPIサーバーを開始
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
出力結果
C:\Users\ebata\fastapi7>curl -X POST -H "Content-Type: application/json" -d "{\"count\": \"100\"}" http://localhost:8000/execute-command
{"pid":1784}
C:\Users\ebata\fastapi7>curl -X POST -H "Content-Type: application/json" -d "{\"pid\": \"1784\"}" http://localhost:8000/terminate-process
{"status":1}
C:\Users\ebata\fastapi7>curl -X POST -H "Content-Type: application/json" -d "{\"pid\": \"1784\"}" http://localhost:8000/terminate-process
{"status":-1}
起動したプロセスを監視して、プロセスが予定通り/突然停止した場合、それを通知する仕組みを追加しました。
# curl -X POST -H "Content-Type: application/json" -d "{\"count\": \"5\"}" http://localhost:8000/execute-command
# curl -X POST -H "Content-Type: application/json" -d "{\"pid\": \"10164\"}" http://localhost:8000/terminate-process
# C:\Users\ebata\fastapi7>uvicorn test:app --host 0.0.0.0 --reload
import subprocess
import os
import time
import multiprocessing # multiprocessingモジュールを追加
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ExecuteRequest(BaseModel):
count: int # pingコマンドの実行回数を指定
class TerminateRequest(BaseModel):
pid: int # 終了させるプロセスのPID
# 実行中のプロセスを格納する辞書
running_processes = {}
process_monitor_processes = {}
@app.post("/execute-command")
def execute_command(request: ExecuteRequest):
count = request.count
try:
command = f"ping -n {count} kobore.net" # pingコマンドの回数をcountに指定
# コマンドを非同期で実行し、プロセスを取得
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pid = process.pid # プロセスのPIDを取得
running_processes[pid] = process
# プロセスを監視するプロセスを起動
monitor_process = multiprocessing.Process(target=monitor_process_status, args=(pid,))
monitor_process.start()
process_monitor_processes[pid] = monitor_process
return {"pid": pid} # PIDのみを返す
except Exception as e:
return {"message": f"コマンドの実行中にエラーが発生しました: {str(e)}"}
@app.post("/terminate-process")
def terminate_process(request: TerminateRequest):
pid = request.pid
print("pid in terminate-process", pid)
try:
# プロセスを取得し、終了させる
process = running_processes.get(pid)
process.terminate() # プロセスを終了させる(SIGTERMを送信)
process.wait()
del running_processes[pid] # プロセスを辞書から削除
# 成功の場合は1を返す
return {"status": 1}
except Exception as e:
return {"status": -1} # 失敗の場合は-1を返す
def monitor_process_status(pid):
while True:
if not is_process_running(pid):
# プロセスが存在しない場合
# メッセージを生成して出力(または送信)
message = {
"status": "Process Disappeared",
"pid": pid
}
print("Process Disappeared:", message)
# プロセス監視プロセスを停止
### del process_monitor_processes[pid]
break
# 一定の待機時間を設定して監視を継続
time.sleep(10) # 10秒ごとに監視
def is_process_running(pid):
#try:
# os.kill(pid, 0) # PIDを使ってプロセスにシグナルを送信し、存在を確認
# return True
#except OSError:
# return False
try:
# ここの部分Windows特有のやりかたなので、後で、例の、os.kill(pid,0)を試してみること
# tasklistコマンドを実行してプロセス一覧を取得
result = subprocess.check_output(["tasklist", "/fi", f"PID eq {pid}"], universal_newlines=True)
# 結果から指定したPIDの行を検索
lines = result.splitlines()
for line in lines:
if f"{pid}" in line:
return True
# 指定したPIDが見つからない場合
# ここに、停止時のメッセージ送信を組み込めばO.K.のはず
return False
except Exception as e:
return False
if __name__ == "__main__":
# FastAPIサーバーを開始
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
指定されたコマンド "ping -100 kobore.net" をFastAPIのエンドポイントから実行し、それが終了したらAPIを正常に終了させるコードは以下のようになります:
test.py
import subprocess
import threading
import os
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class CommandRequest(BaseModel):
command: str
@app.post("/execute-command")
def execute_command(request: CommandRequest):
command = request.command
# コマンドを非同期で実行
execution_thread = threading.Thread(target=execute_command_async, args=(command,))
execution_thread.start()
return {"message": f"コマンド '{command}' の実行を開始しました"}
def execute_command_async(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.wait() # コマンドの終了を待つ
print(f"コマンド '{command}' の実行が終了しました")
# os._exit(0) # FastAPIサーバーを終了させる
if __name__ == "__main__":
# FastAPIサーバーを開始
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
$ uvicorn test:app --host 0.0.0.0 --reload
C:\Users\ebata\fastapi7>curl -X POST -H "Content-Type: application/json" -d "{\"command\": \"ping -n 20 kobore.net\"}" http://localhost:8000/execute-command
以下のtest.csvファイルを、gunplotで3D表示させたくて、色々やっています。
test.csv
#lat,lng,datetime,distance,speed
35.681100,139.758600,2023-05-22 02:10:30,313.307785,37.596934
35.683300,139.759900,2023-05-22 02:11:00,271.347933,32.561752
35.685300,139.760900,2023-05-22 02:11:30,240.030143,28.803617
35.685400,139.761000,2023-05-22 02:12:00,14.325264,1.719032
35.685400,139.761000,2023-05-22 02:12:30,0.000000,0.000000
35.685400,139.761100,2023-05-22 02:13:00,9.031610,1.083793
35.685200,139.763500,2023-05-22 02:13:30,217.896760,26.147611
35.684700,139.765700,2023-05-22 02:14:00,206.328362,24.759403
35.684200,139.768000,2023-05-22 02:14:30,215.040983,25.804918
35.685400,139.768400,2023-05-22 02:15:00,138.238013,16.588562
で、まあ、こんなgpファイルを使って試していましたが、上手く動きませんでした。
# Function to parse datetime string into a numerical value
strptime_datetime(x) = strptime('%Y-%m-%d %H:%M:%S', x)
# Set the output terminal to a 3D plot (you can change the output format if needed)
set terminal pngcairo enhanced size 800,600
# Set the data file separator to a comma
set datafile separator ','
# Set the axis labels
set xlabel 'Longitude (lng)'
set ylabel 'Latitude (lat)'
set zlabel 'Date and Time (datetime)'
# Set the view to a 3D perspective
set view 50,30,1,1
# Get the minimum and maximum datetime values from the data
stats 'test.csv' using (strptime_datetime(stringcolumn(3))) nooutput
min_datetime = STATS_min
max_datetime = STATS_max
# Set the range for the Z axis (datetime)
set zrange [min_datetime:max_datetime]
# Plot the data using the specified columns
#splot 'test.csv' using 2:1:(timecolumn(stringcolumn(3))) with points pointtype 7 pointsize 1 title 'Data Points'
#splot 'test.csv' using 2:1:(timecolumn(stringcolumn(3))) with points pointtype 7 pointsize 1 title 'Data Points'
#splot 'test.csv' using 2:1:(timecolumn(stringcolumn(3))):(0) with points pointtype 7 pointsize 1 title 'Data Points'
splot 'test.csv' using 2:1:(timecolumn(stringcolumn(3)))
時間のパース(strptime_datetime(x) = strptime('%Y-%m-%d %H:%M:%S', x))がやっぱり上手く動きませんでした。
でまあ、しょうがないので、"2023-05-22 02:10:30"を秒数に変換するプログラムを作成しました。
/* "2023-05-22 02:10:30"を秒数に変換するプログラムを作成しました
c:\Users\ebata\gnuplot\convert_datetime.go
*/
package main
import (
"encoding/csv"
"fmt"
"os"
"time"
)
func main() {
// 入力ファイル名と出力ファイル名を指定
inputFileName := "test.csv"
outputFileName := "formatted_test.csv"
// 入力ファイルを開く
inputFile, err := os.Open(inputFileName)
if err != nil {
fmt.Println("ファイルを開けませんでした:", err)
return
}
defer inputFile.Close()
// 出力ファイルを作成または上書き
outputFile, err := os.Create(outputFileName)
if err != nil {
fmt.Println("ファイルを作成できませんでした:", err)
return
}
defer outputFile.Close()
// CSVリーダーとライターを作成
reader := csv.NewReader(inputFile)
writer := csv.NewWriter(outputFile)
// ヘッダーを読み込み、書き込み
header, err := reader.Read()
if err != nil {
fmt.Println("ヘッダーを読み込めませんでした:", err)
return
}
writer.Write(header)
// データを読み込んで秒数に変換して書き込み
for {
record, err := reader.Read()
if err != nil {
break
}
// datetime列をパースして秒数に変換
datetime := record[2] // datetime列のインデックスを確認してください
parsedTime, err := time.Parse("2006-01-02 15:04:05", datetime)
if err != nil {
fmt.Println("日時をパースできませんでした:", err)
return
}
seconds := parsedTime.Unix()
// 秒数に変換した値を新しい列として書き込み
record = append(record, fmt.Sprintf("%d", seconds))
writer.Write(record)
}
// ライターをフラッシュしてクローズ
writer.Flush()
if err := writer.Error(); err != nil {
fmt.Println("書き込みエラー:", err)
return
}
fmt.Println("変換が完了しました。出力ファイル:", outputFileName)
}
で、こんなのができました。
formatted_test.csv
#lat,lng,datetime,distance,speed
35.681100,139.758600,2023-05-22 02:10:30,313.307785,37.596934,1684721430
35.683300,139.759900,2023-05-22 02:11:00,271.347933,32.561752,1684721460
35.685300,139.760900,2023-05-22 02:11:30,240.030143,28.803617,1684721490
35.685400,139.761000,2023-05-22 02:12:00,14.325264,1.719032,1684721520
35.685400,139.761000,2023-05-22 02:12:30,0.000000,0.000000,1684721550
35.685400,139.761100,2023-05-22 02:13:00,9.031610,1.083793,1684721580
35.685200,139.763500,2023-05-22 02:13:30,217.896760,26.147611,1684721610
35.684700,139.765700,2023-05-22 02:14:00,206.328362,24.759403,1684721640
スクリプトではなく、コマンドで一つづつ入れていきました。
gnuplot> set datafile separator ',' ← これ凄く重要
gnuplot> splot "formatted_test.csv" using 2:1:6
の結果は以下の通りでした。
エリア限定
# x軸の範囲を指定
set xrange [139.6119000:139.6312000]
# y軸の範囲を指定
set yrange [35.3627000:35.3737000] ←これだと、地図のイメージと逆転するので
set yrange [35.3737000:35.3627000] ← y軸の範囲を逆転させる
上記のxrangeとyrangeの範囲を地図で示すと、
の範囲となる。
領域の範囲内でのトラッキングデータの様子
gnuplotでx軸とy軸の範囲を指定解除するには、以下のコマンドを使用する。
gnuplot> set xrange [*:*]
gnuplot> set yrange [*:*]
gnuplot> splot "2023-topLatLngCounts4-1.csv" using 2:1:3
gnuplot> set yrange [35.3737000:35.3627000] ← 軸の大小を引っくり返す
gnuplot> splot "2023-topLatLngCounts4-1.csv" using 2:1:3 ← 点を表示
gnuplot> replot "2023-topLatLngCounts4-1.csv" using 2:1:3 with impulses ← 縦軸表示
ちなみに、文字列が入っているcsvだと表示されないことが多いようだ。
運行情報(ダイヤグラム)を反映した最短時間で到着する計算方法は、通常のダイクストラ法を拡張して実行することができます。以下は、ダイヤ情報を考慮する最短到着時間を計算する一般的なアプローチです:
このアプローチを使用すると、ダイヤ情報を反映した最短到着時間を計算できます。ダイヤ情報は、駅への到着時間や運行間隔を正確に取得し、計算に組み込む必要があります。また、プライオリティキューの実装や適切なデータ構造の設計も重要です。
/*
簡易バスダイヤ作成プログラム c:\users\ebata\dummy1.go
(1)バス路線があり、5つの停留所("A0", "A1", "A2", "A3", "A4", "A5")があります。
(2)このバスは始点から運行を開始し、路線の終点でで一定時間停車した後、再び逆方向に運行を開始します。
(3)バスは朝6時に出発して、5分単位で次の停留所で停止し、終端で10分間停止します。
(4)これを3往復するものとします。
*/
package main
import (
"fmt"
"strings" // strings パッケージをインポート
"time"
)
// バスのダイヤグラム
type BusSchedule struct {
Route []string // 停留所のリスト
DepartureTime time.Time // 出発時刻
ArrivalTimeStops map[string][]string // 各停留所の到着時刻
ArrivalTimeRounds int // 往復回数
}
// バスのダイヤグラムを生成する関数
func GenerateBusSchedule(route []string, departureTime time.Time, numRoundTrips int) *BusSchedule {
schedule := &BusSchedule{
Route: route,
DepartureTime: departureTime,
ArrivalTimeStops: make(map[string][]string),
ArrivalTimeRounds: numRoundTrips,
}
currentTime := departureTime
reverse := false // 逆向き運行を切り替えるフラグ
for round := 0; round < numRoundTrips; round++ {
routeOrder := make([]string, 0, len(route)*2-1)
if reverse {
// 逆向き運行の場合、終点から始点に戻る
for i := len(route) - 1; i >= 0; i-- {
stop := route[i]
arrivalTime := currentTime.Format("15:04")
schedule.ArrivalTimeStops[stop] = append(schedule.ArrivalTimeStops[stop], arrivalTime)
routeOrder = append(routeOrder, fmt.Sprintf("%s(%d): %s", stop, len(schedule.ArrivalTimeStops[stop]), arrivalTime))
if i > 0 {
currentTime = currentTime.Add(5 * time.Minute)
}
}
reverse = false
} else {
// 正向き運行の場合、始点から終点に向かう
for i := 0; i < len(route); i++ {
stop := route[i]
arrivalTime := currentTime.Format("15:04")
schedule.ArrivalTimeStops[stop] = append(schedule.ArrivalTimeStops[stop], arrivalTime)
routeOrder = append(routeOrder, fmt.Sprintf("%s(%d): %s", stop, len(schedule.ArrivalTimeStops[stop]), arrivalTime))
if i < len(route)-1 {
currentTime = currentTime.Add(5 * time.Minute)
}
}
reverse = true
}
fmt.Println(strings.Join(routeOrder, "->"))
currentTime = currentTime.Add(10 * time.Minute) // 終点での停止時間
}
return schedule
}
func main() {
route := []string{"A0", "A1", "A2", "A3", "A4", "A5"}
departureTime := time.Date(2024, 1, 6, 6, 0, 0, 0, time.UTC)
numRoundTrips := 3
schedule := GenerateBusSchedule(route, departureTime, numRoundTrips)
// routeOrder を表示
fmt.Println("routeOrder:")
for _, stop := range schedule.Route {
fmt.Printf("%s:\n", stop)
for i, arrivalTime := range schedule.ArrivalTimeStops[stop] {
fmt.Printf(" 通過%d: %s\n", i+1, arrivalTime)
}
}
}
出力結果
C:\Users\ebata>go run dummy1.go
A0(1): 06:00->A1(1): 06:05->A2(1): 06:10->A3(1): 06:15->A4(1): 06:20->A5(1): 06:25
A5(2): 06:35->A4(2): 06:40->A3(2): 06:45->A2(2): 06:50->A1(2): 06:55->A0(2): 07:00
A0(3): 07:10->A1(3): 07:15->A2(3): 07:20->A3(3): 07:25->A4(3): 07:30->A5(3): 07:35
routeOrder:
A0:
通過1: 06:00
通過2: 07:00
通過3: 07:10
A1:
通過1: 06:05
通過2: 06:55
通過3: 07:15
A2:
通過1: 06:10
通過2: 06:50
通過3: 07:20
A3:
通過1: 06:15
通過2: 06:45
通過3: 07:25
A4:
通過1: 06:20
通過2: 06:40
通過3: 07:30
A5:
通過1: 06:25
通過2: 06:35
通過3: 07:35