Mario Doomをプレイしてみる

Mario Doomというスーパーマリオの非公式3D版というものがかなり以前からあります。イントール方法は次のとおりです。

Linux、Windowsともにgzdoomをインストールできます。gzdoomにはジャンプ機能がり、これがプレイするのに必須になります。gzdoomをインストールしたらメニューのオプションでジャンプを割り当てます。つぎにdoom IIのwadを$HOME/.config/gzdoomにコピーします。doom IIのwadがなければfreedoomのwadでも可能です。gzdoomのセットアップが済んだら本題の3Dマリオをインストールします。

このwadもgzdoomの設定ディレクトリに移します。これでセットアップは完了です。

チュートリアル:


追記:
スタートメニューに追加する(KDEの場合)
スタートアイコンを右クリックで編集を選択します。New Itemを選択して記述します。コマンド欄を環境に合わせて次のように記述します。

gzdoom ~/.config/gzdoom/mariodoom.wad

 

仮想通貨取引のテストプログラム

Botで仮想通貨取引すると思わぬバグ等で暴走・損失するケースがあるのでテスト用プログラムを作成してみます。
Pythonを使った仮想通貨取引のテストプログラムです。データベースが必要になりますがsqliteを使います。Botにデータベース接続、挿入、変更のプログラムを組み込みます。

Pythonに必要なモジュール

import time
import os
import re
import sqlite3
from contextlib import closing, suppress

テーブルは「id, pos, unixtime, price, stop, target, flag」です。
テスト用なのでidは便宜的にunixtimeを割り当てます。posはポジションで「S」か「L」を割り当てます。priceはオーダ時のBTC価格、stopの設定は今回は必要ありません。targetはlimitに相当します(データベースのクエリにlimitを入れるとエラーになります)。flagは取引状態を記録します。今回はオーダー時は「T」、利確時は「Z」になります。

データベースの作成・登録

# database 
dbname = 'database.db' 
with closing(sqlite3.connect(dbname)) as conn: 
    c = conn.cursor() 
    create_table = '''CREATE TABLE IF NOT EXISTS transactions (id INT, pos VARCHAR(1), 
                      unixtime INT, price REAL, stop REAL, target REAL, flag VARCHAR(1))''' 
    c.execute(create_table) 
    conn.commit()

オーダの登録

def test_db_pos_insert(d_id, position, unixtime, btc_close, stop, target, flag = ''):  
    if position == 'short': 
        position_cap = 'S' 
    elif position == 'long': 
        position_cap = 'L' 
    with closing(sqlite3.connect(dbname)) as conn: 
        c = conn.cursor() 
        sql = 'insert into transactions (id, pos, unixtime, price, stop, target, flag) values (?,?,?,?,?,?,?)' 
        dat = (d_id, position_cap, unixtime, btc_close, stop, target, flag) 
        c.execute(sql, dat) 
        conn.commit()

レコードの取得

def test_db_read(st=''): 
    with closing(sqlite3.connect(dbname)) as conn: 
        c = conn.cursor() 
        select_sql = 'select * from transactions ' + st 
        c.execute(select_sql) 
        rows = c.fetchall() 
    return rows

レコードのアップデート

def test_db_update(st=''): 
    with closing(sqlite3.connect(dbname)) as conn: 
        c = conn.cursor() 
        update_sql = 'update transactions ' + st 
        c.execute(update_sql) 
        conn.commit()

利確

def test_profit(d_id, btc_close): 
    st = 'set flag = "Z", target = ' + str(btc_close) + ' where id = ' + str(d_id) 
    test_db_update(st)

 

ボットにデータベースプログラムを埋め込んだら次にレポートプログラムを作成します。現時点から遡って1日、1週間、1ヶ月のレポートが可能です。(デフォルトでは1日)

#!/home/user/environments/test_env/bin/python3 

import os 
import sys 
#import subprocess 
import re 
import time 
import sqlite3 
from contextlib import closing 

dbname       = 'database.db' 
#start_hour  = 0 
#start_day   = 1 
#start_month = 'jan' 
#start_week  = 'sun' 
timezone     = 'JST-9'          # timezone: Japan 
unit         = 'daily'          # default 
c_trade_cost = 0.075            # percent (total transaction costs; transaction fee, spread, swap and so on) 
os.environ['TZ'] = timezone 
time.tzset() 
unixtime = int(time.time()) 

if len(sys.argv) > 1: 
    arg = sys.argv[1] 
    num = int() 
    unit = str() 
    matchObj = re.match( r'(\d*)(\w*)', arg, re.M|re.I) 
    if matchObj: 
        if matchObj.group(1): 
            num  = int(matchObj.group(1)) 
        unit = matchObj.group(2) 
        if re.match( r'daily$', unit, re.M|re.I): 
            unit = 'daily' 
        elif re.match( r'weekly$', unit, re.M|re.I): 
            unit = 'weekly' 
        elif re.match( r'monthly$', unit, re.M|re.I): 
            unit = 'monthly' 
#        elif re.match( r'd$|days?$', unit, re.M|re.I) and num > 0: 
#            unit = 'd' 
#        elif re.match( r'w$|weeks?$', unit, re.M|re.I) and num > 0: 
#            unit = 'w' 
#        elif re.match( r'm$|months?$', unit, re.M|re.I) and num > 0: 
#            unit = 'm' 
#        elif re.match( r'y$|years?$|yrs?$', unit, re.M|re.I) and num > 0: 
#            unit = 'y' 
#        elif re.match( r'yearly$', unit, re.M|re.I): 
#            unit = 'yearly' 
        else: 
            print('ERROR: wrong argument!') 
            exit(1)

def db_read(args): 
    with closing(sqlite3.connect(dbname)) as conn: 
        c = conn.cursor() 
        select_sql = 'select * from transactions where ' +  str(args) 
        c.execute(select_sql) 
        rows = c.fetchall() 
    return rows 

def db_read_one(args): 
    with closing(sqlite3.connect(dbname)) as conn: 
        c = conn.cursor() 
        select_sql = str(args) 
        c.execute(select_sql) 
        row = c.fetchone() 
    return row

# TABLE: id, pos, unixtime, price, stop, target, flag 
def get_data(t_start, t_end): 
    profit = float() 
    price_high = float() 
    price_low = float()
    fee = float()
    st = 'unixtime > ' + str(t_start) + ' and unixtime < ' + str(t_end) + ' and flag = "Z"' 
    rows       = db_read(st) 
    _a         = db_read_one('select max(price) from transactions where ' + st) 
    price_high = _a[0] 
    _a         = db_read_one('select min(price) from transactions where ' + st)
    price_low  = _a[0]
    _a         = db_read_one('select count(*) from transactions where ' + st)
    count      = _a[0] 
    for d in rows: 
        if d[1] == 'L': 
            profit = profit + (d[5] - d[3]) 
        elif d[1] == 'S': 
            profit = profit + (d[3] - d[5]) 
        fee = fee + d[3] * c_trade_cost / 100
    return profit, price_high, price_low, count, fee

def calc(unit): 
    if unit == 'daily': 
        t_start = unixtime - (1 * 24 * 60 * 60) 
        t_end = unixtime 
    elif unit == 'weekly': 
        t_start = unixtime - (1 * 24 * 60 * 60 * 7) 
        t_end = unixtime  
    elif unit == 'monthly': 
        t_end = unixtime 
        t_end_customized = time.localtime(t_end) 
        t_m = str(time.strftime("%m", t_end_customized)) 
        t_y = str(time.strftime("%y", t_end_customized)) 
        t_y_leap = int(t_y) % 4 
        if re.match( r'^1$|^5$|^7$|^8$|^10$|^12$', t_m): 
            t_d = 30 
        elif re.match( r'^2$|^4$|^6$|^9$|^11$', t_m): 
            t_d = 31 
        elif re.match( r'^3$', t_m) and t_y_leap != 0: 
            t_d = 28 
        elif re.match( r'^3$', t_m) and t_y_leap == 0: 
            t_d = 29 
        t_start = unixtime - (1 * 24 * 60 * 60 * t_d) 
    return t_start, t_end 

def report(unit): 
    t_start, t_end = calc(unit)
    profit, price1, price2, count, fee = get_data(t_start, t_end) 
    print("\n")
    print(' Action       :', unit, 'profit') 
    print(' From         :', time.strftime('%X %x %Z', time.localtime(int(t_start)))) 
    print(' TO           :', time.strftime('%X %x %Z', time.localtime(int(t_end)))) 
    print(' Transactions :', '{:>5}'.format(count))
    print(' Price(high)  :', '{:>8.2f}'.format(price1)) 
    print(' Price(low)   :', '{:>8.2f}'.format(price2))
    print(' Fee          :', '{:>8.2f}'.format(fee))
    print(' Profit       :', '{:>8.2f}'.format(profit - fee))
    print("\n") 

report(unit)

価格差が200ドル開いていて36ドルの利益ではアルゴリズムを改良する必要があるのがわかります。

[追記 1]

手数料を追加で計算に入れてみると取引が多くなるほど利益が著しく減少します。

 

 

 

wine環境を整える

Linuxデスクトップをメインに使っているとたまにWindowsアプリケーションが必要になることがあります。たとえばLireOfficeはシステムがOS全体が固まることがあるのでMS Officeを使いたいなどの場合です。VBにインストールしてあるWindows 7を使ってもよいのですが、極力お手軽に済ませたい場合はwineを使う方法があります。完全互換とは行かないまでも通常使うアプリケーションについては実用に耐えられます。そこでwine環境を整えてみました。まずはwinetricksをインストールします。ubuntuのリポジトリにもありますが最新版を使用します。

今回使用したwineのバージョン

wine --version
wine-3.0 (Ubuntu 3.0-1ubuntu1)

winetricksをインストールします。

wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
chmod +x winetricks
sudo mv winetricks /usr/local/bin

多言語フォントと.NET Frameworkをインストールします。

env WINEPREFIX=$HOME/winedotnet40 wineboot --init
env WINEPREFIX=$HOME/winedotnet40 winetricks dotnet40 corefonts
winetricks allfonts

印刷環境を整えます。wineで印刷するには32bitのcupsライブラリが必要です。

sudo apt-get install libcups2:i386 printer-driver-cups-pdf

DirectX9.0cをインストールします。

winetricks d3dx9
winetricks dxdiag

Google EarthやvlcのようなアプリケーションでDirectXをテストしてみます。

以上で環境設定は終わりです。この環境で動くアプリケーションリスト

  • MS Office 2007
  • iTumes64(v10.7)
  • WinRAR5.5(64bit)
  • MP3tag
  • Subtitle edit
  • Google Earth pro
  • vlc
  • ie8

iTunesのスクリーンショット

IE8のインストール(不安定です)

IE8は32bitアプリケーションなので環境設定が必要です。

1. インストール

WINEPREFIX=~/.wine32 WINEARCH=win32 winetricks ie8

2. 実行

WINEPREFIX=~/.wine32 wine $HOME/.wine32/drive_c/Program\ Files/Internet\ Explorer/iexplore.exe

MS Office 2007

これは設定が少し込み入っています。オフィス用の環境を作ります。

WINEARCH=win32 WINEPREFIX=$HOME/msoffice wineboot --init

Wineの設定をXPに設定しインストールします

WINEARCH=win32 WINEPREFIX=$HOME/msoffice winecfg
WINEARCH=win32 WINEPREFIX=$HOME/msoffice wine setup.exe
WINEARCH=win32 WINEPREFIX=$HOME/msoffice wine {sp1..sp3}.exe /passive

MS Officeがインストールできたらwinecfgの設定をします。この設定でPowerPointとOutlookの設定が出来るようになります。

WINEPREFIX=$HOME/msoffice winecfg

“New override for library” にriched20.dllをタイプします。

Editボタン押してNative (Windows)を選択します。

macOSの場合、apple scriptでApplicationスクリプトを作ります。MS Excelの例です。(テンプレートとしても使えます)

on run
  
  --edit this to be the correct location and file to run (typically only edit after the "drive_c")
  set toRun to "$WINEPREFIX/drive_c/Program Files/Microsoft Office/Office12/EXCEL.EXE"
  
  --edit winePrefix if you are not using the default prefix
  set winePrefix to "$HOME/msoffice"
  
  --edit wineLocation if your wine install is not the default location
  set wineLocation to "/usr/local/bin"
  
  --edit dyldFallbackLibraryPath to your X11 lib folder, this one is set for XQuartz on 10.6+
  set dyldFallbackLibraryPath to "/opt/X11/lib"
  -------------------------------------------------------
  --DO NOT EDIT ANYTHING BELOW THIS LINE
  -------------------------------------------------------
  set toRunPath to do shell script "WINEPREFIX=\"" & winePrefix & "\"; TEMPVAR=\"" & toRun & "\"; echo \"${TEMPVAR%/*}\""
  set toRunFile to do shell script "WINEPREFIX=\"" & winePrefix & "\"; TEMPVAR=\"" & toRun & "\"; TEMPVAR2=\"" & toRunPath & "\"; echo \"${TEMPVAR#$TEMPVAR2/}\""
  do shell script "PATH=\"" & wineLocation & ":$PATH\"; export WINCEARCH=win32; export WINEPREFIX=\"" & winePrefix & "\"; export DYLD_FALLBACK_LIBRARY_PATH=\"" & dyldFallbackLibraryPath & "\"; cd \"" & toRunPath & "\"; wine \"" & toRunFile & "\" > /dev/null 2>&1 &"
  
end run

Word、Excel, Power Pointを登録して起動した例

OutlookでHotmailの設定

Configure Outlook with an Outlook.com (Hotmail), Gmail, Office 365, Yahoo, AOL or iCloud account

[海外ドラマ] Corazón Salvaje (1993) – 和訳:野生の心

 

Yo soy Betty, la feaに続いて名作のドラマにCorazón Salvajeがあります。いくつかのバージョンがあるのですが1993年版が秀逸との評判なので最初の数回のエピソードを見たところ納得がいきました。理屈抜きで面白いです。Corazón Salvaje (1993)はメキシコで制作された典型的なラテンドラマの時代劇でドロドロとした恋愛関係が主題です。

農場主のフランシスコ・アルカザル(Francisco Alcazar)には一人息子のアンドレ(Andres)がいて、女々しい性格から物足りなさを感じていたが、ある時、かつて人妻と関係して儲けた子供、ジュアン(Juan)がいると告げられる。実際に会ってみると、なる程、自分と似ていて端正で度胸もあるので可愛く思ったのか、友人の弁護士のノエル(Noel)に目を掛けてやるように頼んだ。程なくしてフランシスコは落馬で命を落とし、15年の月日が流れた。。。

​​フランシスコの妻ソフィア(Sofia)には、親戚のカタリーナ(Catalina)にふたりの娘がいたが、その姉妹の姉、モニカ(Monica)とアンドレと15年前に婚約の約束をしていた。ところがアンドレがスペインの士官学校から戻ったとき、妹のアイミー(Aimee)に惚れ込んで婚約する。そして失意のモニカは修道院に行ってしまう。

ジュアンのほうは悪党に成長して、密輸したり海賊行為を生業としていた。今で言えば麻薬カルテルのボスのような存在で、まわりから悪魔のジュアン(Juan del Diablo)と呼ばれて恐れられていた。そんなときアイミーが海岸を散策していたときにジュアンを見かけて興味を持ち、程なくして関係を持つようになる。ジュアンが仕事で外国から戻ったときに結婚しようと約束したが、戻ってきたらエイミーとアンドレが結婚していることを知って、約束を成就するために誘拐を企てる。このことを知ったモニカがスキャンダルになるのを防ぐために、修道院から戻りジュアンと婚約する。独占欲の強い利己的なアイミーが嫉妬に駆られ結婚しないように策略を練っていたところ、旦那のアンドレにジュアンとの関係がバレてしまう。ドロドロの関係が続いて最後にハッピーエンドで終わる。

このドラマはYouTubeで直接みるかダウンロードして見ることになりますが、英訳の字幕が最初のいくつかのエピソードにしかなく、あとはトランススクリプトを使うことになります。残念ながらすべてのエピソードにトランススクリプトはありません。