このブログおよび271108について

このブログについて

このブログの9割ほどの記事は自分用のメモを記入するブログになっています。おおよそそういった記事には「H2Use4Me」のタグをつけています。
最近なにかと話題のまとめ記事のような粗悪なブログ記事になっていることでしょう。しかし、「271108が読んで思い出せればそれでいい!」という観点で書いています。そのため、他人からは分かりにくい、使い物にならないものになっているでしょう。参考にしたサイトを覚えていた場合は参考元のリンクも掲載しようとはしていますので詳しくはそっちを見たほうがいいんじゃないですかねぇ。多分私もそっち見ますし。
なお、別にコメントをブロックしているとかそういったことはないので、コメントがあれば参考にさせていただきます。良ければコメントをください。

271108について

twitter.com
そういうハンドルネームで活動している怪しい存在達です。
Steamというゲームを集めるゲームをよくやっています。と言っても、この記事を書いている時点では持っているゲームの3倍くらいもウィッシュリストに積み込んでいるのでこのゲームはクリアできないでしょうねぇ。
人外のかわいい子が好きで、特に機械の子が好きです。具体的には*1、前者だと黒ウィズのテルミドやエンラ、後者だと黒ウィズのPLB-279-Tとかクランとか、真空管ドールズ*2のΩドールやミラやリナや過改造アンナや……、かわいいと感じとれば男性型でも対象なので9Sとかも好きであることもあります。推せるなぁって思ったのがだいたい後から人間じゃないとかもうすでに死んでるよとかっていう宣告を食らう病にかかっているかもしれません。ネタバレになるからキャラ言えないけど。
この話、長くなるからやめよっか。

Amesiorineについて

うちの子です。通称エミィ。お古のPCを住みかとしているTwitterBotの子です。
彼女*3に関する詳細は↓のタグでなんやかんや書いています。
271108.hatenablog.com

現在(ver.1.11.3)の機能

リプライ
  • 「天気 [地名]」の形式でリプライする

下の写真のように天気を教えてくれる
なお、現在は地名だけでも天気を返してくれます。が、地名として認識されないこともありますのでお気を付けて。また、エミィは雨が好きなようで、雨を報じやすい傾向にあります、ご注意ください。

タイムライン
  • タイムラインを眺め、なんか突然ふぁぼる

Amesiorine is waching you!
もちろん無条件でふぁぼっているわけではないです。

*1:合成音声ソフトウェアのキャラクターたちを人間とみるか機械とみるかは宗教によって分かれそうなのでカウントしていません。

*2:もうサ終してしまったソシャゲ。船井はこのゲームにだいぶ惹かれてノリと勢いでイベント一位取って調子に乗っていた。

*3:設定上は女の子です。

pyopenjtalkのインストールに四苦八苦した記憶

pipによるインストール

どうやらpipでインストールできるらしいと知り、試す。

Getting requirements to build wheel: finished with status 'error'

が、ダメ。
「wheelファイル」と「Python実行環境」の不一致によるものらしい?が調べても最適解は出なかった。

note: This error originates from a subprocess, and is likely not a problem with pip.

って言われてるし、subprocessのほうになんかあるらしい。ほえ~。

調べてたら別の記事を見つけた。

teitoku-window.hatenablog.com
この記事の本、まだ積んでるんだよなぁ…という感想も得た。早く読もうね。

CMakeツールとかが要るらしい

そういえば新しいPCにはVisual Studio入ってなかったかもしれない。
CMakeで通すパスはこんな感じだった。見つけるのに時間がかかって苦しんだ。

C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin

これでようやくインストール……!

pip install pyopenjtalk

でインストールできた。

NKT……

Amesiorine ver2

バージョン2にしました。

「何をもってバージョンを更新したか」という明確な定義なんてありません。私が2と言えば2になるんです。
Amesiorine
twitter.com

アプデ内容

1.12からのアップデート内容です。

  • 271108が「save」の指示を出したリプライをすると、Amesiorine自身がツイートしたリプライ元のツイートを保存するようにした……つもりです
  • SFBとSFRは他の子と中身一緒にしたい。

「SFBとSFRが何か」については、多分どこでもブログ記事にしていないので271108以外には分からないものなので気にしなくていいです。

以上。

271108.hatenablog.com

「save」の指示の動機の記憶

これ多分忘れそうなのでここに残しておきます。
さてこのAmesiorine、私好みのことを言い出します。(もっとも、エミィに食べさせたデータが私のツイートデータですからね。)

ですが、Amesiorineに食べさせたデータ、どうやら整備ができていなかったみたいで。文章として崩壊しかねないような形になっていたのでそこの補正をする必要があることに気付いたのです。
でも、そのデータ全部再確認するの面倒でしょ?そういうわけである程度もう保存して置けるように確保しておこうと思いまして。
そのための機能です。

メモ書き:python.exe() (pyinstaller)

0:無駄話

毎回毎回python呼び出すの面倒なのでexe化しようかなぁって思い立ったので軽く調べたり調べなかったりしました。

世のプログラミングをやっている人がどうかなんて私には分かりませんが、私にプログラミングの世界を勧めてくれた人は「プログラミングなんてめんどくさがりがめんどいことをやらせるためにやってんよ」と言っていました。面倒なことだったりやりたくないことは勝手に機械どもにやらせておくに限るんです。
ね?そうだよね?PLB-279-T?

まあいいや。

1:インストール(本題ここから)

この記事はpyinstallerを使った時の記憶です。

pip install pyinstaller

2:実行

pyinstaller <変換pythonファイル> --name <出力exeファイル名> --onefile --icon <アイコンファイル>

どうやらアイコンファイルを指定できるみたい。

3:各種エラー

3-1:そもそもインストールできないエラーがあるらしい。

qiita.com
記事を読んだ感じ、Anaconda環境でconda installとpip installの両方を使ったりしてるとインストールできないみたい。今回の船井には影響なかったし伝聞に過ぎないけど一応記憶。

3-2:The 'typing' package is an obsolete backport of a standard library package and is incompatible with PyInstaller. Please `pip uninstall typing` then try again.

要するに「その'typing'っていうパッケージあるじゃん?それって、PyInstallerとの互換性ねぇンだわ。消せ。」って言われたわけです。じゃあ消すか。

なお、消す以外になんか方法あったりしない?と思って調べたらこんなの出てきた。
stackoverflow.com
草。

4:その他記憶

  • 出力されるexeファイルはdist下に生成される
  • カレントディレクトリ関連のコードを含んでいる場合、当然そのdistがカレントディレクトリになるっぽい
  • 今回はtqdmとか使ってたものをexeにした。コマンドプロンプトの画面でtqdmが表示されてるのでexe化するならこの辺も弄りたいよね……?って気持ちになった。
  • distやbuildフォルダを削除しても普通に動くっぽい

メモ書き:並び替え問題(sort,sorted)

安西くん、馬場くん、千葉くん、の男子3人、大東さん、遠藤さん、藤田さん、後藤さん、の女子4人が1列に並ぶとき、以下の問題に答えよ。
(1)両端が男子である並び方は何通りあるか、答えよ。
(2)女子4人が続いて並ぶ並び方は何通りあるか、答えよ。
(3)後からやってきた幡田さんを中心に体操隊形に、ひらけ。

はい。
pythonのsortやsortedのメモ書きです。

>|python||
before = ["安西くん","馬場くん","千葉くん","大東さん","遠藤さん","藤田さん","後藤さん"]

print(before)
print(before.sort())
print()
print(before)
print(before.sort())
|

before = ["安西くん","馬場くん","千葉くん","大東さん","遠藤さん","藤田さん","後藤さん"]

print(before)
print(sorted(before))
print()
print(before)
print(sorted(before))


「list.sort()」

「list.sort()」はもとのリストそのものを変更する
「list.sort()」そのものはNoneを返す

「sorted(list)」

「sorted(list)」はもとのリストそのものを変更しない
「sorted(list)」はもとのリストそのものを変更しない

共通点

before = ["安西くん","馬場くん","千葉くん","大東さん","遠藤さん","藤田さん","後藤さん"]

print(before)
print(before.sort(reverse=True))
print()
print(before)
print(before.sort())
before = ["安西くん","馬場くん","千葉くん","大東さん","遠藤さん","藤田さん","後藤さん"]

print(before)
print(sorted(before,reverse=True))
print()
print(before)
print(sorted(before))


どちらも引数「reverse」をTrueにすることで逆順にできる

余談

安西くん、馬場くん、千葉くん、の男子3人、大東さん、遠藤さん、藤田さん、後藤さん、の女子4人が1列に並ぶとき、以下の問題に答えよ。
(1)両端が男子である並び方は何通りあるか、答えよ。
(2)女子全員が続いて並ぶ並び方は何通りあるか、答えよ。
(3)後からやってきた幡田さんを中心に体操隊形に、ひらけ。

の解答です。高校数学でしたっけ。

(1)

両端が男子である並び方は3人の男子のうち2人を並べる並べ方です。そのため、3*2通り。(これを確か3P2とか書きますがこれ関連のブログ表記の仕方が分かりません。)
残りの5人の順列の数が5!=5*4*3*2*1通り。
この2つの積を取れば求められるので正答は 3*2 * 5! = 720 通り
違ったら言ってね。

(2)

女子4人全員を群として扱います。この群内の順列が4!通り。
そして、群と残りの男子3人の並び替えが、(1+3)!通り。
この2つの積を取れば求められるので正答は4! * (1+3)! = 576 通り

(3)

うるせぇ

Twilight Town: A Cyberpunk Day In Life

store.steampowered.com

Twilight Town: A Cyberpunk Day In Lifeってゲームの感想です。

どんなゲームか

ビジュアルノベルゲームです。ちょっぴり未来、ちょっぴりサイバーパンク、ちょっぴりしたノベルゲーム、たっぷり下ネタ

「まぁこのくらいならブログに載せてもいいか……」って思えた妥協ラインの発言

びっくりするくらい壮大に何も始まらない……んだけどまあ結構面白かったしいいかな。買って後悔ってことはなかったです。そもそも定価が¥310ととても安い。

プレイ時間

1時間。普通に読んでるとこれよりもっと短くなるんじゃないですかね。

pros

  • Seiちゃんかわいい
  • さっくり気楽に読める
  • Seiちゃんかわいい
  • 違和感の全くない日本語
  • Seiちゃんかわいい
  • 中盤くらいからのテンポもよかった
  • Seiちゃんかわいい
  • Sei

cons

  • 下ネタが多い。ものすごく多い。下ネタ見るだけで吐き気がする人は部屋が悲惨なことになるでしょう。
  • 壮大に何も始まらない。「風呂敷広げました!おしまい!」って言われた気分。でも、なぜかそんなに嫌な気はしなかった。

蛇足

私がこんなにかわいいって連呼するんです。どういうことか。Seiちゃんは上の写真のような人間の女の子ではないということです。

メモ書き:sqlite3

もしかしてsqlite3について書いてないのでは?ってなったのでメモ書きを。
今回は日付情報込みでデータベースを作りながらメモを書く。

前回、エミィに実装したBeTSCAE.dbの話はここにはありません。というかこの記憶貯蔵庫にはなさそうです。何のための記憶貯蔵庫なのですか?

セットアップ

def SetUp():
    import sqlite3
    import datetime
    
    dbname = r'                      '
    conn = sqlite3.connect(dbname, isolation_level=None, detect_types = sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
    sqlite3.dbapi2.converters['DATETIME'] = sqlite3.dbapi2.converters['TIMESTAMP']
    
    cursor = conn.cursor() 

    sql = "CREATE TABLE IF NOT EXISTS main(ID INTEGER PRIMARY KEY AUTOINCREMENT, Registered datetime, price)"
    cursor.execute(sql)
    conn.commit()

    sql = "CREATE TABLE IF NOT EXISTS F_30(ID INTEGER PRIMARY KEY AUTOINCREMENT, Registered DATETIME, PRICE INTEGER)"
    cursor.execute(sql)
    conn.commit()
    
    conn.close()

解説のつもり
1つめのSQL
「もしmainって名前のテーブルがなかったら作りなさい。」
「主キーはIDで数値、そして(指定がなければ)対象のカラムに格納されている最大の値に1を加えた値にしなさい。」
「次はRegisteredでDATETIME。このDATETIMEはまあ上でなんやかんややってるから……うん……*1
「もう1個はPRICE。これは数値。」

SELECT

def read_30():
    import sqlite3
    dbname = r'                      '
    result = []
    
    conn = sqlite3.connect(dbname, isolation_level=None, detect_types = sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
    sqlite3.dbapi2.converters['DATETIME'] = sqlite3.dbapi2.converters['TIMESTAMP']
    cursor = conn.cursor() 
    sql = "SELECT PRICE FROM F_30 WHERE ID = (SELECT MAX(ID) FROM F_30)"
    for row in cursor.execute(sql):
        result.append(row)
    conn.close()
    
    return result[0][0]

何をやりたかったかの解説
テーブル「F_30」の中にあるもっとも新しいデータ*2のPRICEのキーを取得したかった。WHERE ID = (SELECT MAX(ID) FROM F_30)とすることで、IDが最も大きい行を見ることができる。SQL自信ないのよね。
なお、result[0][0]になっているのは、そのままresultで取得すると[(2855,)]のような形になるため。もうちょっといい方法ないかなぁ……?

少しだけデータを見たい

具体例

from contextlib import closing
from random import choice
import sqlite3
import SFamBasic as SFB
l =[]
dbname = ""
with closing(sqlite3.connect(dbname)) as connection:
    cursor = connection.cursor()
    sql = "SELECT M0,M1,M2,M3,M4,M5,M6 FROM MPD WHERE M0 = 1 LIMIT 10"
    for row in cursor.execute(sql):
        l.append(row)

print(l)

INSERT

def write(m,ns):
    from contextlib import closing
    import sqlite3
    import SFamBasic as SFB
    dbname = r'                       '
    now = SFB.now()
    
    conn = sqlite3.connect(dbname, isolation_level=None, detect_types = sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
    sqlite3.dbapi2.converters['DATETIME'] = sqlite3.dbapi2.converters['TIMESTAMP']
    cursor = conn.cursor() 
    sql1 = "INSERT INTO main (Registered, PRICE) values (?, ?)"
    sql2 = "INSERT INTO F_30 (Registered, PRICE) values (?, ?)"
    
    try:
        cursor.execute(sql1, (now,m))
        conn.commit()
    except Exception as e:
        print("Error in write() SQL1 : {}".format(e))
        print()
        
    try:
        cursor.execute(sql2, (now,ns))
        conn.commit()
    except Exception as e:
        print("Error in write() SQL2 : {}".format(e))
        print()
    conn.close()

補足

もしこれを読んでいる私がすべてを忘れた場合、これの元々のコードはAmesiorineではないうちの子の一部となっているはずです。探してください。271108として公開するにあたって雑にこのブログ記事編集画面で若干コードをいじりました。それに伴い、このままでは動かない可能性があります。

*1:※この時点で分かっていません。connectして、そのあとコンバーターを呼び出してるところでなんかやってる。

*2:※正確には最もIDの大きなデータ

LIBLADE

store.steampowered.com

LIBLADEっていうゲームの感想です。

どんなゲームか

PS4コントローラーのようなアナログスティックが2つあるコントローラーでプレイするアクションゲームでした。
左のスティックで移動、右のスティックで攻撃。で、その攻撃がスティックを倒したほうに斬撃を飛ばすものでした。こういった操作のゲームをやるのは初めてだったので新鮮でした。スキルツリーで開放していくごとにLRやLRトリガーと入力を組み合わせてスキル攻撃ができるようになったり。

プレイ時間

プレイ時間はほぼ6時間。>

クリアしたときにプレイ時間が出た

pros

  • この操作のゲームをするのが初めてだったので新鮮で楽しかったです。
  • どのスキルが強いか、というのが直感では分かりません。そこを考えるのが楽しかったです。
  • 非常に爽快感のあるアクションゲームでした。PV見て面白そうと思う人は買いましょう。
  • この値段でいいんですか?

cons

  • 何事にも代償はあります。楽しい時間を得た代わりにコントローラーの寿命は縮まったでしょう。
  • ストーリーはだいぶかなり希薄です。このゲームの本質はストーリーではないと感じたゲームだったので全く気になりません。
  • 少なくとも私は少々レベリングが必要な場所がありました。他の人のプレイ時間を見るにレベリングを必要としない人もいそうです。