@echo off
rem ------------------------------
rem huangyongxing@yeah.net
rem 项目编译及启停控制工具
rem ------------------------------

cd %~dp0/../
set DIR_ERL=%cd%
cd ../
set DIR_MAIN=%cd%

rem 注意设置SRV_ID、HOST、PORT，
rem 一般HOST用自己的IP，SRV_ID推荐使用自己的工号数字【保证唯一】
rem 同时，需要在下方指定对应版本的erl安装路径

set SRV_ID=1
set HOST=
set COOKIE=mrzj_%SRV_ID%
set PORT=9110
set NODE_NAME_PREFIX=mrzj_dev_

set NODE_NAME=%NODE_NAME_PREFIX%%SRV_ID%@%HOST%

set CENTER_NODE_NAME=mrzj_dev_center@%HOST%
set CENTER_COOKIE=mrzj_dev_center
set CENTER_PORT=9111

title 明日战纪源码管理(%NODE_NAME%, %PORT%)

rem 协议生成工具
set PROTO_TOOL=%DIR_MAIN%\doc\proto_auto\ProtoBuilder.exe
if not exist %PROTO_TOOL% set PROTO_TOOL=

rem 指定erl路径，会自动计算对应的werl和escript路径

rem 使用otp 18.3示例
rem set ERL=D:\Program Files\erl7.3\bin\erl.exe

rem 使用otp 19.3示例
rem set ERL=D:\Program Files\erl8.3\bin\erl

rem 使用otp 23.3示例
set ERL=D:\Program Files\erl-23.3.4.4\bin\erl

rem 使用环境变量中的erl
rem set ERL=erl

rem 设置游戏服使用的config，便于在本地配置多个服测试
set GS_CONFIG=gsrv.config

rem 客户端路径
set CLIENT=%DIR_MAIN%\code\u3d\app\localTest\ClientApp.exe
if "%HOST%"=="" (
    call :fun_error HOST未配置
    goto :EOF
)

rem 客户端目录
set CLIENT_DIR=%DIR_MAIN%\code
rem 服务端目录
set SERV_DIR=%DIR_ERL%
rem svn程序目录(视实际安装目录而异)
set SVN_EXE=C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe

rem 调用初始化脚本执行环境的接口
call :fun_init_calc
rem dialyzer相关配置
rem plt file
set PLTFILE=%DIR_ERL%\script\.dialyzer_plt_v%OTP_VER%
rem dialyzer 分析日志输出文件名前缀
set DIALYZER_OUTFILE_PREFIX=dialyzer_v%OTP_VER%

echo.

rem --------- 开始主循环: 等待指令->输入指令->执行指令->等待指令 ---------

:fun_main
    echo erts version: %ERTS_VER%
    echo otp  version: %OTP_VER%
    echo werl.exe    : %WERL%
    echo server root : %DIR_ERL%
    set inp=
    echo ---------------------------------------------------------------------------
    echo  make^|m       编译                   ^| dialyzer^|dlz    运行dialyzer静态分析
    echo  mmm          快速编译(powershell)   ^| mm              编译与版本库差异文件
    echo  start        启动游戏服及跨服       ^| stop            关闭游戏服及跨服
    echo  restart      重启服务器及跨服       ^| hot             热更服务器及跨服
    echo  hot_master   热更游戏服             ^| hot_center      热更跨服
    echo  master       启动游戏服             ^| stop_master     关闭游戏服
    echo  center       启动跨服服务器         ^| stop_center     关闭跨服服务器
    echo  werl         开启一个werl窗口       ^| kill^|k          强行结束所有werl.exe
    echo  dir          打开server目录         ^| clean_logs^|cl   清理本地游戏服日志
    echo  client^|c     开户PC版客户端         ^| attr            重新生成attr_conv模块
    if "%PROTO_TOOL%" NEQ "" echo  pt           协议生成工具           ^| su ^| cu         svn更新 服务端^|客户端
    echo  clear^|cls    清屏                   ^| quit^|q          退出
    echo ---------------------------------------------------------------------------
    set /p inp=请输入指令:
    cd %DIR_ERL%
    goto fun_routing

:fun_routing
    if "%inp%"=="make" call :fun_make
    if "%inp%"=="m" call :fun_make
    if "%inp%"=="mm" call :fun_mm
    if "%inp%"=="mmm" call :fun_mmm
    if "%inp%"=="start" call :fun_start
    if "%inp%"=="stop" call :fun_stop
    if "%inp%"=="master" call :fun_start_master
    if "%inp%"=="stop_master" call :fun_stop_master
    if "%inp%"=="hot" call :fun_hot
    if "%inp%"=="hot_master" call :fun_hot_master
    if "%inp%"=="hot_center" call :fun_hot_center
    if "%inp%"=="restart" call :fun_restart
    if "%inp%"=="center" call :fun_start_center
    if "%inp%"=="stop_center" call :fun_stop_center
    if "%inp%"=="kill" call :fun_kill
    if "%inp%"=="k" call :fun_kill
    if "%inp%"=="clean_logs" call :fun_clean_logs
    if "%inp%"=="cl" call :fun_clean_logs
    if "%inp%"=="werl" call :fun_start_werl
    if "%inp%"=="client" call :fun_start_client
    if "%inp%"=="c" call :fun_start_client
    if "%inp%"=="pt" call :fun_proto_tool
    if "%inp%"=="attr" call :fun_create_attr_conv
    if "%inp%"=="dir" call :fun_dir_server
    if "%inp%"=="su" call :server_svn_update
    if "%inp%"=="cu" call :client_svn_update
    if "%inp%"=="dlz" call :fun_run_dialyzer
    if "%inp%"=="dialyzer" call :fun_run_dialyzer
    if "%inp%"=="cls" cls
    if "%inp%"=="clear" cls
    if "%inp%"=="quit" goto :EOF
    if "%inp%"=="q" goto :EOF
    echo.
    goto fun_main

rem --------- 后面为相关指令操作接口封装 ---------

rem 初始化计算脚本一些工具路径和设置一些全局变量
rem 包括以下变量值：
rem ERL、WERL、ESCRIPT、ERTS_VER、ERTS_VER_MAIN
rem ERL_OPT_NORMAL
rem ERL_OPT_S_SINGLE
:fun_init_calc
    rem 如果%erl%等于erl说明有设置环境变量，理论上escript也找得到
    if "%ERL%"=="erl" set envTrue=1
    if "%ERL%"=="erl.exe" set envTrue=1
    setlocal enabledelayedexpansion
    if "!envTrue!"=="1" (
        for /f "delims=" %%i in ('where erl') do (set ERL=%%i)
    )
    rem 给文件补上后缀，便于判断是否存在
    if "!ERL:~-4!" NEQ ".exe" set ERL=!ERL!.exe
    if NOT EXIST !ERL! (
        echo "文件不存在"!ERL!
        goto :EOF
    ) ELSE (
        set ERL_BIN_ROOT=!ERL:erl.exe=!
        set ESCRIPT=!ERL_BIN_ROOT!escript.exe
        set WERL=!ERL_BIN_ROOT!werl.exe
        set DIALYZER=!ERL_BIN_ROOT!dialyzer.exe
        rem 避免自动计算的路径用'\'，手写的可能用'/'，所以两类都先尝试去除
        set ERL_INST_TMP=!ERL_BIN_ROOT:bin\=!
        set ERL_INST=!ERL_INST_TMP:bin/=!
    )
    rem 取得erts version
    call :fun_calc_erts_ver ERTS_VER ERTS_VER_MAIN "!ERL!"
    rem call :fun_calc_otp_ver OTP_VER "!ERL!" "!ERL_INST!"
    call :fun_calc_otp_ver_simple OTP_VER "!ERL_INST!"
    endlocal & (
        rem 如果是作为全局变量，需要在这里set（否则仍是局部变量）
        rem set ERL_BIN_ROOT=%ERL_BIN_ROOT%
        set ERL=%ERL%
        set WERL=%WERL%
        set ESCRIPT=%ESCRIPT%
        set DIALYZER=%DIALYZER%
        set ERTS_VER=%ERTS_VER%
        set ERTS_VER_MAIN=%ERTS_VER_MAIN%
        set OTP_VER=%OTP_VER%
        set ERL_INST=%ERL_INST%
        rem echo erlang root: %ERL_BIN_ROOT%
        echo erl.exe     : %ERL%
        echo werl.exe    : %WERL%
        echo escript.exe : %ESCRIPT%
        rem 设置一些执行参数
        if %ERTS_VER_MAIN% LEQ 8 (
            set ERL_OPT_NORMAL=+P 204800 +K true +A 100 +spp true -smp enable -hidden +sbwt none
            set ERL_OPT_S_SINGLE=+P 204800 +K true +A 100 +spp true -smp disable -hidden +sbwt none
        ) ELSE (
            set ERL_OPT_NORMAL=+P 204800 +K true +A 100 +spp true +S 0 -hidden +sbwt none
            set ERL_OPT_S_SINGLE=+P 204800 +K true +A 100 +spp true +S 1 -hidden +sbwt none
        )
    ) & goto :EOF

:fun_make
    cd %DIR_ERL%
    set startTime=%time%
    call :get_localtime startTimeStr
    echo [%startTimeStr%] start make
    echo.
    rem xcopy /d 只更新比目标新的源文件
    xcopy "dep\ebin\*.beam" "ebin\" /h /r /k /q /y /d
    rem 判断编译参数，决定真实使用的文件（目前windows版都使用release版，需要其他版本的手工拷贝文件）
    setlocal enabledelayedexpansion
    set needCopy=FALSE
    if NOT EXIST "ebin\game_logger.beam" (
        SET needCopy=TRUE
    ) ELSE (
        rem SET fileCmpRet=
        rem FOR /F %%i IN ('comp /M dep\ebin\debug\game_logger.beam ebin\game_logger.beam') DO set fileCmpRet=%%i
        rem if "!fileCmpRet!"=="文件的大小不同。" SET needCopy=TRUE
        call :calc_md5 "dep\ebin\release\game_logger.beam" "fMD51"
        call :calc_md5 "ebin\game_logger.beam" "fMD52"
        if "!fMD51!" NEQ "!fMD52!" SET needCopy=TRUE
    )
    if "!needCopy!"=="TRUE" xcopy "dep\ebin\release\*.beam" "ebin\" /e /h /r /k /q /y
    endlocal
    rem 在编译、热更等简单操作中可直接使用halt(0)直接退出erlangVM，比c:q()优雅中止服务的速度更快
    rem set makeOptions=[{d, 'DEV_SERVER'}],
    rem 通常可增加的选项 {d,'DEV_SERVER'}, {d,'CP_VER',"TW"}, ...
    set makeOptions=[]
    "%ERL%" -noinput -pa ./ebin -eval "mmake:all(2, %makeOptions%),halt(0)"
    call :calc_time_diff "%startTime%" "%time%" "runTime"
    call :get_localtime EndTimeStr
    echo.
    echo cost time: %runTime%
    echo.
    echo [%EndTimeStr%] finish make
    echo "%EndTimeStr%" > %DIR_ERL%/script/timefile
    goto :EOF

:fun_mm
    cd %DIR_ERL%
    set startTime=%time%
    call :get_localtime startTimeStr
    echo [%startTimeStr%] start mm
    echo.
    svn status "./src" > "./svn_status.log"
    cd %DIR_ERL%
    "%ERL%" -noinput -pa ./ebin -eval "make_file:make_file(),halt(0)"
    call :calc_time_diff "%startTime%" "%time%" "runTime"
    call :get_localtime EndTimeStr
    echo.
    echo cost time: %runTime%
    echo.
    echo [%EndTimeStr%] finish make
    goto :EOF

:fun_start
    call :fun_start_center & call :fun_start_master
    goto :EOF

:fun_stop
    call :fun_stop_master & call :fun_stop_center
    goto :EOF

:fun_mmm
    cd %DIR_ERL%
    set startTime=%time%
    call :get_localtime startTimeStr
    echo [%startTimeStr%] start mmm
    echo.
    cd script
    echo %cd%
    PowerShell.exe -file mm.ps1
    call :calc_time_diff "%startTime%" "%time%" "runTime"
    call :get_localtime EndTimeStr
    echo.
    echo cost time: %runTime%
    echo.
    echo [%EndTimeStr%] finish make
    goto :EOF

:fun_start_master
    cd %DIR_ERL%\config
    rem start cmd /C ""%ERL%" %ERL_OPT_NORMAL% -name %NODE_NAME% -setcookie %COOKIE% -boot start_sasl -config %GS_CONFIG% -pa ../ebin -s main start -extra %HOST% %PORT% & pause"
    start "" "%WERL%" %ERL_OPT_NORMAL% -name %NODE_NAME% -setcookie %COOKIE% -boot start_sasl -config %GS_CONFIG% -pa ../ebin -s main start -extra %HOST% %PORT%
    goto :EOF

:fun_stop_master
    cd %DIR_ERL%\config
    set STOP_NODE_NAME=%NODE_NAME_PREFIX%%SRV_ID%_stop_%RANDOM%@%HOST%
    "%ERL%" -hidden -name %STOP_NODE_NAME% -setcookie %COOKIE% -pa ../ebin -s main stop_server -extra %NODE_NAME%
    rem start "" "%WERL%" -hidden -name %STOP_NODE_NAME% -setcookie %COOKIE% -pa ../ebin -s main stop_server -extra %NODE_NAME%
    goto :EOF

:fun_hot
    call :fun_hot_master & call :fun_hot_center
    goto :EOF

:fun_hot_master
    cd %DIR_ERL%\config
    set hotNodeName=%NODE_NAME_PREFIX%%SRV_ID%_hot_%RANDOM%@%HOST%
    "%ERL%" -hidden -name %hotNodeName% -setcookie %COOKIE% -pa ../ebin -eval "rpc:call('%NODE_NAME%', u, u, []), halt(0)"
    rem start "" "%WERL%" -hidden -name %hotNodeName% -setcookie %COOKIE% -pa ../ebin -eval "rpc:call('%NODE_NAME%', u, u, []), halt(0)"
    goto :EOF

:fun_hot_center
    cd %DIR_ERL%\config
    set hotNodeName=%NODE_NAME_PREFIX%center_hot_%RANDOM%@%HOST%
    "%ERL%" -hidden -name %hotNodeName% -setcookie %CENTER_COOKIE% -pa ../ebin -eval "rpc:call('%CENTER_NODE_NAME%', u, u, []), halt(0)"
    rem start "" "%WERL%" -hidden -name %hotNodeName% -setcookie %CENTER_COOKIE% -pa ../ebin -eval "rpc:call('%CENTER_NODE_NAME%', u, u, []), halt(0)"
    goto :EOF

:fun_restart
    call :fun_stop
    choice /t 2 /d y /n >nul
    call :fun_start
    goto :EOF

:fun_start_center
    cd %DIR_ERL%\config
    rem start cmd /C ""%ERL%" %ERL_OPT_NORMAL% -name %CENTER_NODE_NAME% -setcookie %CENTER_COOKIE% -boot start_sasl -config cls.config -pa ../ebin -s main start -extra %HOST% %CENTER_PORT% & pause"
    start "" "%WERL%" %ERL_OPT_NORMAL% -name %CENTER_NODE_NAME% -setcookie %CENTER_COOKIE% -boot start_sasl -config cls.config -pa ../ebin -s main start -extra %HOST% %CENTER_PORT%
    goto :EOF

:fun_stop_center
    cd %DIR_ERL%\config
    set STOP_NODE_NAME=center_stop_%RANDOM%@%HOST%
    "%ERL%" -hidden -name %STOP_NODE_NAME% -setcookie %CENTER_COOKIE% -pa ../ebin -s main stop_server -extra %CENTER_NODE_NAME%
    rem start "" "%WERL%" -hidden -name %STOP_NODE_NAME% -setcookie %CENTER_COOKIE% -pa ../ebin -s main stop_server -extra %CENTER_NODE_NAME%
    goto :EOF

rem 强制关闭werl进程（在异常崩溃的情况下，windows中会残留werl进程）
:fun_kill
    taskkill /F /IM werl.exe
    goto :EOF

rem 清理本地游戏服日志
:fun_clean_logs
    cd %DIR_ERL%\logs
    DEL /Q *.*
    goto :EOF

rem 随机节点名的werl
:fun_start_werl
    cd %DIR_ERL%\config
    if %time:~0,2% leq 9 (set hour=0%time:~1,1%) else (set hour=%time:~0,2%)
    set randomNode=werl_%hour%%time:~3,2%%time:~6,2%_%RANDOM%@%HOST%
    if not exist gsrv.config (
        start "" "%WERL%" -hidden -name %randomNode% -setcookie %COOKIE% -pa ../ebin
    ) else (
        start "" "%WERL%" -hidden -name %randomNode% -setcookie %COOKIE% -pa ../ebin -config gsrv.config
    )
    goto :EOF

rem dialyzer静态分析工具 初始化持久查询表文件plt file
:fun_init_plt
    echo [init] build plt file
    "%DIALYZER%" --build_plt --apps erts kernel stdlib sasl compiler mnesia crypto inets ssl public_key eunit tools --output_plt "%PLTFILE%"
    goto :EOF

rem dialyzer静态分析工具 执行分析
:fun_analyse_code
    call :get_datetime_str dt
    set outfile=%DIR_ERL%\script\%DIALYZER_OUTFILE_PREFIX%_%dt%.txt
    set erlLib=%ERL_INST%\lib
    set serverDir=%DIR_ERL%
    echo 正在执行dialyzer分析
    echo 输出分析日志文件：%outfile%
    rem "D:/Program Files/erl-23.2.5/bin/dialyzer.exe" -I server/include --src server/src -r server/src -pa "D:/Program Files/erl-23.2.5/lib" --plt ./.dialyzer_plt_mrzj > dialyzer_%dt%.txt
    "%DIALYZER%" -I %serverDir%\include --src %serverDir%\src -r %serverDir%\src -pa "%erlLib%" --plt "%PLTFILE%" > "%outfile%"
    goto :EOF

rem dialyzer静态分析工具调用
:fun_run_dialyzer
    if NOT EXIST "%PLTFILE%" call :fun_init_plt
    call :fun_analyse_code
    goto :EOF

rem 协议生成工具
:fun_proto_tool
    rem 需要开启变量延迟，否则else括号块首次执行时变量解析有问题
    setlocal enabledelayedexpansion
    if "!PROTO_TOOL!"=="" (
        call :fun_error 未配置协议生成工具
    ) else (
        for /f "delims=" %%t in ('echo !PROTO_TOOL!') do (set dirProtoTool=%%~dpt)
        echo ---------------------------------
        echo change to directory: [!dirProtoTool!]
        cd !dirProtoTool!
        "!PROTO_TOOL!"
    )
    endlocal
    goto :EOF

rem 开户客户端
:fun_start_client
    if NOT EXIST %CLIENT% (
        call :fun_error 没有找到客户端可执行文件[%CLIENT%]
        goto :EOF
    )
    setlocal enabledelayedexpansion
    for /f "delims=" %%t in ('echo !CLIENT!') do (set dirClient=%%~dpt)
    rem 客户端从某个版本开始，似乎用了绝对路径来查找资源，必须在exe所在目录启动才行
    cd /d "!dirClient!"
    start "" cmd /C "%CLIENT%"
    endlocal
    goto :EOF

rem 生成attr_conv模块
:fun_create_attr_conv
    if NOT EXIST src\tool\attr_tool.erl (
        echo "未找到attr_tool.erl文件"
    ) ELSE (
        "%ESCRIPT%" src\tool\attr_tool.erl
    )
    goto :EOF

rem 打开服务端工作目录 %DIR_ERL%
:fun_dir_server
    start "" explorer "%DIR_ERL%"
    goto :EOF

rem 服务端更新
:server_svn_update
    start "" "%SVN_EXE%" /command:update /path:"%SERV_DIR%" /closeonend:0
    goto :EOF

rem 客户端更新
:client_svn_update
    start "" "%SVN_EXE%" /command:update /path:"%CLIENT_DIR%" /closeonend:0
    goto :EOF

rem node name split
rem call :node_name_split "%node%" "nodePrefix" "nodeHost"
:node_name_split
    set input=%~1
    set sep=@
    set nPre=
    set nHost=
    setlocal enabledelayedexpansion
    for /F "delims=%sep% tokens=1-2" %%a in ("%input%") do (
        set nPre=%%a
        set nHost=%%b
    )
    endlocal & set "%~2=%nPre%" & set "%~3=%nHost%" & goto :EOF

rem 计算两个时间差值
rem 调用示例:
rem set startTime=%time%
rem echo do something
rem call :calc_time_diff "%startTime%" "%time%" "runTime"
rem echo cost time %runTime%
:calc_time_diff
    setlocal
    set /a n=0
    for /f "tokens=1-8 delims=.: " %%a in ("%~1:%~2") do (
            set /a n-=1%%a*3600000+1%%b*60000+1%%c*1000+1%%d*10
            set /a n+=1%%e*3600000+1%%f*60000+1%%g*1000+1%%h*10
    )
    set /a s=n/3600000,n=n%%3600000,f=n/60000,n=n%%60000,m=n/1000,n=n%%1000
    set "ok=%s% 小时 %f% 分钟 %m% 秒 %n% 毫秒"
    endlocal & set "%~3=%ok%" & goto :EOF

rem 获取本地时间
:get_localtime
    setlocal
    if %time:~0,2% leq 9 (set hour=0%time:~1,1%) else (set hour=%time:~0,2%)
    set lt=%date:~0,4%-%date:~5,2%-%date:~8,2% %hour%:%time:~3,2%:%time:~6,2%
    endlocal & set "%~1=%lt%" & goto :EOF

rem 获取日期
rem call :get_datetime_str var
:get_datetime_str
    setlocal
    if %time:~0,2% leq 9 (set hour=0%time:~1,1%) else (set hour=%time:~0,2%)
    set dt=%date:~0,4%%date:~5,2%%date:~8,2%_%hour%%time:~3,2%%time:~6,2%
    endlocal & set "%~1=%dt%" & goto :EOF

rem 计算文件md5
rem call :calc_md5 "filePath" "fMD5"
rem echo %fMD5%
:calc_md5
    setlocal
    FOR /F %%i IN ('certutil -hashfile "%~1" MD5 ^| findstr /V 哈希 ^| findstr /V 完成') DO set fMD5=%%i
    endlocal & set "%~2=%fMD5%" & goto :EOF

rem 计算erts版本
rem call :fun_calc_erts_ver "ERTS_VER" "ERTS_VER_MAIN" "%ERL%"
:fun_calc_erts_ver
    rem 注意，pattern最后面本身有空格需要保留（bat语法奇葩，两侧加引号又会出问题）
    rem 但是为防止不小心格式化代码时去掉了空格，
    rem 所以改为无空格，并在替换后，多进行一次替换空格操作
    set pattern=Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version
    set replace=
    set erlbin=%3
    setlocal enabledelayedexpansion
    for /f "usebackq delims=" %%i in (`"%erlbin%" +V 2^>^&1`) do (set allstr=%%i)
    set "ertsVer=!allstr:%pattern%=%replace%!"
    set "ertsVer=!ertsVer: =!"
    for /f "usebackq delims=." %%i in (`echo !ertsVer!`) do (
        if defined ertsVerMain goto break_calc_erts_ver
        set ertsVerMain=%%i
    )
    :break_calc_erts_ver
    endlocal & set "%~1=%ertsVer%" & set "%~2=%ertsVerMain%" & goto :EOF

rem 查找otp version【调用erl获取主版本号，再定位版本号文件】
rem call :fun_calc_otp_ver OTP_VER "%ERL%" "%ERL_INST%"
:fun_calc_otp_ver
    rem erlang:system_info(otp_release) 在OTP 17之后，只能获取主版本号
    rem Win和Linux通行的方案是通过 os:find_executable("erl") 找到erl.exe，
    rem 然后读取这个文件 ../../release/MainOTPVerion/OTP_VERSION
    rem 在Win上可以简化为安装路径下的 releases/MainOTPVerion/OTP_VERSION
    set erlbin=%2
    set erlInst=%3
    setlocal enabledelayedexpansion
    for /f "usebackq delims=" %%i in (`"%erlbin% -noshell -eval ""io:fwrite(""""^~s"""",[erlang:system_info(otp_release)]),halt(0)"""`) do (
        set otpMainVer=%%i
    )
    set releaseFile=%erlInst%\releases\%otpMainVer%\OTP_VERSION
    for /f "usebackq delims=" %%i in (`type %releaseFile%`) do (
        set otpVer=%%i
    )
    endlocal & set "%~1=%otpVer%" & goto :EOF

rem 查找otp version【不调用erl获取主版本号，依赖文件系统下仅存一个版本号目录来定位文件】
:fun_calc_otp_ver_simple OTP_VER "%ERL_INST%"
    set erlInst=%2
    set releaseDir=%erlInst%\releases
    setlocal enabledelayedexpansion
    cd /d %releaseDir%
    for /f "usebackq delims=" %%i in (`dir /AD /B`) do (
        set releaseFile=%releaseDir%\%%i\OTP_VERSION
    )
    for /f "usebackq delims=" %%i in (`type %releaseFile%`) do (
        set otpVer=%%i
    )
    endlocal & set "%~1=%otpVer%" & goto :EOF

:fun_error
    echo ---------------------
    if "%1"=="" (
        echo 出错了!
    ) ELSE (
        echo %1
    )
    echo ---------------------
    echo.
    pause
    goto :EOF
