Home | First | Prev | Next | Last |
EasterDate main.go メインプログラム・ソース main ビルドした実行ファイル start.sh スタート・スクリプト index.html スタート画面 result.html 結果表示画面 readme.txt 説明ファイル
#/bin/bash /usr/bin/xdg-open index.html go run main.go上記では、xdg-open を使って index.html をブラウザに表示させ、そのあと main.go を動かしています。Windows PC のためにはファイル名を start.bat とし、main.go から main.exe を作った上で、次のように書きました。
start index.html .\main.exe
<!DOCTYPE html> <html> <head> </head> <body bgcolor='honeydew'> <h3>Find Easter Date</h3> <form action='/process' method='post'> Year: <input type='text' name='year' style='width:4em'> <button type='submit'>Send</button> </form> <br> </body> </html>
<!DOCTYPE html> <html> <head> <style> table { border-collapse: collapse; } th { text-align:center; font-size:14pt; font-weight:bold; color:white; background-color:green; } td { padding:0 1em } </style> </head> <body bgcolor='honeydew'> <h3>Find Easter Date</h3> <form action='/process' method='post'> Year: <input type='text' name='year' style='width:4em'> <button type='submit'>Send</button> </form> <br> Results:<br /> <br /> <table> <tr><th colspan='2'>{{.YR}}</th></tr> <tr bgcolor='violet'><td>Ash Wednesday</td><td>{{.AW}}</td></tr> <tr bgcolor='white'><td>Easter</td><td>{{.EA}}</td></tr> <tr bgcolor='red'><td>Pentecost</td><td>{{.PE}}</td></tr> </table> <br /> </body> </html>template 機能では {{.key}} に main.go の連想配列(map)で指定した値が入ります。
func findEaster(year int)(int, int) { a := year % 19 b := year / 100 c := year % 100 d := b / 4 e := b % 4 f := (b + 8) / 25 g := (b - f + 1) / 3 h := (19 * a + b - d - g + 15) % 30 i := c / 4 j := c % 4 k := (32 + 2 * e + 2 * i - h - j) % 7 l := (a + 11 * h + 22 * k) / 451 month := (h + k - 7 * l + 114) / 31 day := ((h + k - 7 * l + 114) % 31) + 1 return month, day }これに加えて、イースターの40日前の「灰の水曜日」と50日後の「ペンテコステ」の月日も次で得るようにしました。
func findOthers(y, m, d, offset int) (int, int, int) { t := time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.UTC) t2 := t.AddDate(0, 0, offset) year := t2.Year() month := int(t2.Month()) day := t2.Day() return year, month, day }y, m, d はイースターの日付です。t.AddDate(0, 0, offset) の offset に「灰の水曜日」の場合は "-46" を、「ペンテコステ」の場合は "49" を指定します。
func HandlerInput(w http.ResponseWriter, r *http.Request) { template := template.Must(template.ParseFiles("index.html")) values := map[string]string{} err := template.ExecuteTemplate(w, "index.html", values) if err != nil { log.Fatalln(err) } }
func HandlerProcess(w http.ResponseWriter, r *http.Request) { template := template.Must(template.ParseFiles("result.html")) yearstr := r.FormValue("year") year, _ := strconv.Atoi(yearstr) month, day := findEaster(year) ayear, amonth, aday := findOthers(year, month, day, -46) AW := fmt.Sprintf("%d - %02d - %02d", ayear, amonth, aday) EA := fmt.Sprintf("%d - %02d - %02d", year, month, day) pyear, pmonth, pday := findOthers(year, month, day, 49) PE := fmt.Sprintf("%d - %02d - %02d", pyear, pmonth, pday) YR := fmt.Sprintf("%d", year) values := map[string]string{ "AW" : AW, "EA" : EA, "PE" : PE, "YR" : YR, } err := template.ExecuteTemplate(w, "result.html", values) if err != nil { log.Fatalln(err) } }form からの year は文字配列で送られてきますので、yearstr := r.FormValue("year") で year の値を取り出し、year, _ := strconv.Atoi(yearstr) で整数に変換しました。計算結果(value)に key を付け、 map (連想配列)に 格納しました。これを template 機能を使って、result.html では、{{.key}} の中に 値(value)を出力させました。
func main() { http.HandleFunc("/", HandlerInput) http.HandleFunc("/process", HandlerProcess) http.ListenAndServe(":8080", nil) }
import ( "fmt" "html/template" "log" "net/http" "strconv" "time" )
Function findPlayTime($mp3file) { $out = & ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $mp3file $seconds = [double]$out $sec = [int]$seconds $min = [int]($sec / 60) $sec = $sec % 60 return $min, $sec }
func findPlayTime(mp4file string)(int, int, int) { app := "ffprobe" args := []string{"-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", mp4file} cmd := exec.Command(app, args...) out, err := cmd.Output() if err != nil { log.Fatal(err) } result := string(out) result = strings.TrimRight(result, "\n") seconds, err := strconv.ParseFloat(result, 8) sec := int(seconds) min := sec / 60 sec = sec % 60 hur := min / 60 min = min % 60 return hur, min, sec }cmd.Output で得られる out は byte で返ってくるので、string(out) で string にしました。ところが、これは末尾に '\n' を含んでいるので、strings.TrimRight で '\n' を取り除いてから strconv.ParseFloat で数値に直しました。秒以下を切り捨てるため、int を使って整数値にして、再生時間を seconds で得てから、hur, min, sec を得るようにしました。最初、何度やっても再生時間の数値が '0' になるので、おかしいと思い、'\n' を取り除かなければならないことに気付きました。
$ sudo apt install python3-opencv
func main() { date := "June 12, 2023" re := regexp.MustCompile(`^([A-z]+) ([0-9]+), ([0-9]+)$`) group := re.FindStringSubmatch(date) month_str := group[1] date_str := group[2] year_str := group[3] fmt.Printf("%s %s, %s\n", month_str, date_str, year_str) }
func main() { date := "June 12, 2023" re := regexp.MustCompile(`^(?P<month>[A-z]+) (?P<day>[0-9]+), (?P<year>[0-9]+)$`) group := re.FindStringSubmatch(date) month_str := group[re.SubexpIndex("month")] date_str := group[re.SubexpIndex("day")] year_str := group[re.SubexpIndex("year")] fmt.Printf("%s %s, %s\n", month_str, date_str, year_str) }?P<month> ?P<dat> ?P<year>でパターンに名前をつけておいて、group[1] group[2] group[3]の代わりにgroup[re.SubexpIndex("month")] group[re.SubexpIndex("day")] group[re.SubexpIndex("year")]のように、group の要素をパターンの名前で取り出しています。コード量が増えますが、要素の指定が明確になります。
year := 2023 month := 1 prevyear := year - (month == 1) prevmonth := month - 1 + 12 * (month == 1) nextyear := year + (month == 12) nextmonth := month + 1 - 12 * (month == 12)代わりに if 文を使います。
var ( year int month int prevyear int prevmonth int prevyear int prevmonth int ) year = 2023 month = 1 if month == 1 { prevyear = year - 1 prevmonth = 12 } else { prevyear = year prevmonth = month - 1 } if month == 12 { nextyear = year + 1 nextmonth = 1 } else { nextyear = year nextmonth = month + 1 }
package main import ( "fmt" ) func check1(month int) (int) { if month == 1 { return 1 } else { return 0 } } func check12(month int) (int) { if month == 12 { return 1 } else { return 0 } } func show(year, month int) { prevyear := year - check1(month) prevmonth := month - 1 + 12 * check1(month) nextyear := year + check12(month) nextmonth := month + 1 - 12 * check12(month) fmt.Println("Now:", year, month, " Prev:", prevyear, prevmonth, "Next:", nextyear, nextmonth) } func main() { year := 2023 for month := 1; month <= 12; month++ { show(year, month) } }func check1 で、month が 1 であるかどうかを判定し、func check12 では month が 12 であるかどうかを判定し、それぞれ True なら 1、False なら 0 を返しています。数値に 1 を掛けてももとの数値のままですが、0 を掛ければ 0 になるのを利用して if 文なしで、求めている数値を得るようにしてみました。Golang になくても他の言語にある書式に似せて書くことができることが分かりました。
12月8日 12月25日 1月2日 1月15日 5月5日「ナチュラル・ソート」という手法を使う必要があるのですが、そんなに多用するわけではないので、面倒なコードを書かないで、月と日の数値を取り出してソートキーを作り、それを先頭においてソートし、ソートした後はソートキーを取り除いてもとに戻すという方法を使いました。
package main import ( "fmt" "regexp" "sort" "strconv" "strings" ) func get_sortkey (line string) (string) { // 月日の数字を取り出す re := regexp.MustCompile(`([\d]+)月([\d]+)日`) group := re.FindStringSubmatch(line) // 数字から数値を得る month, _ := strconv.Atoi(group[1]) day, _ := strconv.Atoi(group[2]) // 数値を数字に戻しソートキーをつくる sortkey := fmt.Sprintf("%02d%02d", month, day) // ソートキーを返す return sortkey } func main() { datelines := []string {"12月8日", "12月25日", "1月2日", "1月15日", "5月5日"} fmt.Println("Original:") for i, dateline := range datelines { fmt.Println(dateline) // ソートキーを得る sortkey := get_sortkey(dateline) // ソートキーをデータの先頭につけ、データに格納 datelines[i] = sortkey + "," + dateline } // ソートする sort.Strings(datelines) fmt.Println("Sorted:") for i, dateline := range datelines { // ソートキーを切り離し、元アイテムを得る items := strings.Split(dateline, ",") dateline = items[1] fmt.Println(dateline) // 元アイテムをデータに戻す datelines[i] = dateline } }
16 color: simple solarized cmc-16 cmc-paper geany 256 color: monokai (default) zenburn gruvbox darcula twilight railscast bubblegum (light theme) True color: solarized-tc atom-dark cmc-tc gruvbox-tc material-tc
>>> print(ord("🐑"))とすれば、HTML エンティティの 10進の数値を得ることができます。しかし、絵文字には複数の Unicode 文字を組み合わせているものがあるので、次の for 文で 1文字づつ処理し、それらを連結して HTML エンティティ を得るようにしました。次の Python スクリプトの emoji = "" に絵文字をペーストして実行して使います。
emoji = "" entity = "" for emoji_part in emoji: charcode = str(ord(emoji_part)) entity = entity + "" + charcode + ";" html_entity = entity.replace("&", "&") print(emoji) print(html_entity)
#!/usr/bin/python3 # from http.server import HTTPServer, CGIHTTPRequestHandler class Handler(CGIHTTPRequestHandler): cgi_directories = ["/cgi-bin"] PORT = 8080 HOST = "127.0.0.1" print("Connecting to http://127.0.0.1:8080/") httpd = HTTPServer((HOST, PORT), Handler) httpd.serve_forever()
$ exiftool -T -ImageSize "Tucker on X.mp4"結果は 1920x1080 でした。
for vfile in *; do if [ -f "$vfile" ]; then vsize=`exiftool -T -ImageSize "${vfile}"` if [[ $vsize != "-" ]]; then echo "${vfile}" $vsize fi fi donemp4 の他、mkv や webm などのビデオファイル、また jpg や png などの画像ファイルからも画像サイズを得ることができました。また、オプションを -ImageHeight にして、それが 1080 であれば、HD 映像なので、1080 の代わりに HD と表示させることもできます。
out=`exiftool -b -Duration ${fname}` out=${out%.*} min=$(($out / 60)) sec=$(($out % 60)) mp3name=`basename ${fname}` printf "%s %d:%02d\n" $mp3name $min $secmp3info と違って、exiftool で -b オプションを使うと、演奏時間を小数点以下4桁(ミリ秒)まで出力するので、out=${out%.*} を使って小数点以下を切り捨てました。
out=`exiftool -T -Duration ${fname}` out=${out% *} mp3name=`basename ${fname}` printf "%s %s\n" $mp3name $outout=${out% *} は、-T オプションでは (approx) が末尾についてくるので、それを削除するためのものです。
<audio controls src="Oh_Susanna.mp3"></audio>といった具合です。デフォルトのままだと、バーの幅が短いように感じたので、CSS を使って少し長くしてみました。ついでに角も丸めました。
audio { width: 400px; border-radius: 6px; }CSS では「プレヤー」の細部までは変更できません。JS を使えばなんとかなるようですが、面倒なことはしたくなかったので、やめました。
$ wget https://zoom.us/client/latest/zoom_amd64.deb $ sudo apt install ./zoom_amd64.deb次のエラーメッセージが出ました。
パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています... 完了 状態情報を読み取っています... 完了 これらを直すためには 'apt --fix-broken install' を実行する必要があるかもしれません。 以下のパッケージには満たせない依存関係があります: zoom : 依存: libgl1-mesa-glx しかし、インストールすることができません 依存: libegl1-mesa しかし、インストールすることができません 依存: libxcb-xtest0 しかし、インストールされていません 依存: libxcb-cursor0 しかし、インストールされていません E: 未解決の依存関係です。'apt --fix-broken install' を実行してみてください (または解法を明示してください)。それで、
$ sudo apt --fix-broken installとしてみましたが、インストールに失敗しました。Snap に `zoom-client` があったので、そちらをインストールしたら、Zoom が使えるようになりました。ただし、このバージョンでは、`Virtual background` を使うことができませんでした。私がダウンロードした Zoom のバージョンは `5.16.2(8828)` でした。バージョンアップによって問題が解決するかもしれません。
[Documents 文書] pdfarranger … PDF の分割・結合 GUI pdftk … PDF の分割や結合など sigil … ePub 作成 GUI texlive-extra-utils … TeX 補助 [Graphics グラフィックス] graphicsmagick … コマンドライン画像処理 gthumb … 画像閲覧 GUI [Japanese 日本語] fcitx5-mozc … 日本語入力と変換 fonts-ipafont … IPA 日本語フォント ttf-mscorefonts-installer … MS 英語フォント [Multi-media マルチメディア] audacious … オーディオプレーヤー GUI audacity … 録音アプリ GUI lame … MP3 変換 mp3info … MP3 情報 [Network ネットワーク] apache2 … ウェブサーバー filezilla … FTP クライエント GUI [System システム] default-jre … JAVA 実行環境 gdebi-gtk … パッケージ・マネージャー GUI hardinfo … システム情報 GUI papirus-icon-theme … アイコン・テーマ printer-drive-dymo … Dymo LabelWriter ドライバー python-is-python3 … Python リンク作成 sqlite3 … データベース・プログラム sqlitebrowser … SQLite データベース閲覧 GUI [Tools ツール] micro … ターミナルで作動するテキストエディター notepadqq … プログラミング・テキストエディター GUI
balenaEtcher-1.18.4-x64_55c91cd6bd9c5e76ba286c5536cca86d.AppImage … ディスクイメージ作成 GUI glabels-qt … ラベル印刷 GUI Go version 1.21.3 … プログラミング言語 marktext_e94cf48168e949ee60b95bed54505f33.AppImage … マークダウン文書エディター GUI
foliate … ePub reader GUI losslesscut … 動画の切り取りと結合 GUI zoom-client … ZOOM ミーティング GUI
ルビを<ruby><rb>振</rd><rt>ふ</rt></ruby>るなどとします。Chrome や Edge ではうまく表示されたのですが、Firefox ではルビとベースの文字の間隔が空きすぎてしまいました。
rt { transform:translateY(.5em); }を試したのですがだめでした。それで
rt { position:relative;top:.5em; }としたら、ちょうど良い位置に収まりました。
p { line-height: 2.5; }と書いて広げました。line-height は 2 〜 2.5 が良さそうです。
<?xml version="1.0" encoding="utf-8"?> <AddressBook Version="8.0" DefaultPermutation="true" Format="Native"> <AddressEntry> <AddressData>David Souza 6655 Peachtree Dunwoody Rd Atlanta, GA 30328</AddressData> <Name> <FirstName>David</FirstName> <LastName>Souza</LastName> <FileAs>Souza, David</FileAs> </Name> </AddressEntry> .... </AddressBook>これに基づいて、CSV ファイルから ABX ファイルに直接変換するプログラムを Python で次のように書きました。
#!/usr/bin/python # # abookmaker.py import csv, os, shutil, sys if len(sys.argv) < 2: inpfile = input("Input File: ") else: inpfile = sys.argv[1] outfile = inpfile.replace(".csv", ".ABX") if os.path.isfile(outfile): bakfile = outfile.replace(".ABX", ".ABX.BAK") shutil.copyfile(outfile, bakfile) with open(outfile, "w") as out: out.write("""<?xml version="1.0" encoding=\"utf-8\"?> <AddressBook Version=\"8.0\" DefaultPermutation=\"true\" Format=\"Native\">\n""") with open(inpfile) as inp: rows = csv.reader(inp) i = 0 for row in rows: lastname = row[0] firstname = row[1] address1 = row[2] address2 = row[3] firstname = firstname.replace("&", "&") out.write(f""" <AddressEntry> <AddressData>{firstname} {lastname} {address1} {address2}</AddressData> <Name> <FirstName>{firstname}<
Home | First | Prev | Next | Last |