- 投稿日:2020-02-25T23:35:45+09:00
TypeScript 3.7のNullish Coalescingで少し嵌った話
概要
TypeScript 3.7で追加されたNullish Coalescingは現場で使用しておりとても重宝しています。
nullとunderstandのみ判定できるので簡単に任意の型にすることが出来るのですが、
今回、愚直に使用した結果、発生した現象がありました。今回は例文とそれをトランスパイルした実際に実行されたコードも出して解説?したいと思います。
もし、今後同じようなことは起きる人がいた時にこの記事で解決の糸口になれば良いなとって思います。事象
先ずは実際に判定できなかった時のコードと同等のものになります。
typescriptinterface MyFavorite { lastName?: string; firstName?: string; } const myFavorite: MyFavorite = {}; const result = myFavorite.lastName && myFavorite.firstName ? myFavorite.lastName + " " + myFavorite.firstName : myFavorite.lastName ?? "" + myFavorite.firstName ?? "" ; console.log(result )とします。
この場合、trueの場合は説明するまでもないと思います。問題なのはfalse判定だった時です。
この場合、実装者(今回は僕)の期待値としては空文字列を期待していました、しかし実際に出力された文字は"undefined"と表示されてしました。
もうダメだ。。。
救いはないんですか!?ってなりました。
原因
この現象を見たとき、処理の評価順がどーなっているかを調べました。
TypeScriptをコンパイルしてJavaScriptに変換してみました。そしたら以下コードになりました。
javaScriptvar _a, _b; const myFavorite = {}; const result = myFavorite.lastName && myFavorite.firstName ? myFavorite.lastName + " " + myFavorite.firstName : (_b = (_a = myFavorite.lastName, (_a !== null && _a !== void 0 ? _a : "" + myFavorite.firstName)), (_b !== null && _b !== void 0 ? _b : "")); console.log(result);となりました。
問題のコードは三項演算子のfalseの部分ですね。
( _b = ( _a = myFavorite.lastName, (_a !== null && _a !== void 0 ? _a : "" + myFavorite.firstName) ), (_b !== null && _b !== void 0 ? _b : "") )これをみた瞬間全てを理解しました。
処理の順番としては
1. aにmyFavorite.lastNameを代入(_aにはundefined)
2. _aがnull又はunderstandではない場合、_aはそのまま(今回はこっちではない)
3. _aがnull又はunderstandだった場合、空文字列とmyFavorite.firstNameを結合してaに代入 ← ここ
4. 以下はそのまま(決してめんどくさいわけではない)
つまり僕の脳内では(myFavorite.lastName ?? "") + (myFavorite.firstName ?? "")このようなイメージでいたのですが実際は
((myFavorite.lastName ?? "") + myFavorite.firstName) ?? ""このように評価されていたそうです。
間違えていたらこっそり教えてくださいこれでは空文字列とunderstandを結合していることになる為、
"understand"の文字列を生成しておりました。確かに遅延評価なので理解はしましたが、納得はちょっと・・・てなりました。
まぁ~サボって愚直な実装した僕が悪いんですけどね・・・最後に
ちょっと使いなれたからって愚直な実装は良くないですね。
このおかげで学ぶ機会があったので良かったですが、改めて慣れって怖いですね。
皆さんも予期せぬ落とし穴に嵌らないように気を付けましょう!!
- 投稿日:2020-02-25T23:24:06+09:00
ブラウザでウェブカメラ映像のタッチのから色をRGBY-BK-WH判別
ブラウザでカメラ映像から色を判別するときに利用したチップスをメモ
ウェブカメラ動画の取得
videoタグ配置しJSでカメラ取得
※localhost,127.0.0.1 や HTTPS の環境がないと動作しないでした。。<video id="videoInput" width="640" height="480" autoplay></video>var video = document.getElementById('videoInput') navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment", }, audio: false, }) .then(function (stream) { video.srcObject = stream; video.play(); }) .catch(function (err) { console.error(err); });カンバスへ変換(描画)
HTMLでカンバスを設置
<canvas id="canvasOutputVideo" width="640" height="480"></canvas>IntervalでVideoタグの内容をカンバスへ描画
var canvas = document.getElementById("canvasOutputVideo"); var context = canvas.getContext("2d"); setInterval(updateCap, 100); function updateCap() { context.drawImage(video, 0, 0, 640, 480); };タッチ箇所の取得
下記のどれかで取得となるはず
console.log("screen:" + e.screenX + "," + e.screenY); console.log("client:" + e.clientX + "," + e.clientY); console.log("offset:" + e.offsetX + "," + e.offsetY);平均の色を取得
クリック箇所を中心に3*3の9ドットの平均を算出
カンバスから取得let imageData = document.getElementById("videoCanvas").getContext("2d").getImageData(click.x-1 , click.y-1 , 3, 3); let rgba = [0, 0, 0, 0]; imageData.data.forEach((v, i) => { rgba[i % 4] = rgba[i % 4] + v }); const r = rgba[0] / (iW * iH); const g = rgba[1] / (iW * iH); const b = rgba[2] / (iW * iH); const a = rgba[3] / (iW * iH); let resRGBA = [Math.ceil(r), Math.ceil(g), Math.ceil(b), Math.ceil(a)];RGBをHSVへ変換
色を純粋に判定したい場合はHSVが便利
- H:色相 RGB的な色を判定に利用
- S:彩度 白の判定に利用
- V:明度 黒の判定に利用
function rgb2hsv (rgb) { var r = rgb[0] / 255; var g = rgb[1] / 255; var b = rgb[2] / 255; var max = Math.max(r, g, b); var min = Math.min(r, g, b); var diff = max - min; var h = 0; switch (min) { case max: h = 0; break; case r: h = (60 * ((b - g) / diff)) + 180; break; case g: h = (60 * ((r - b) / diff)) + 300; break; case b: h = (60 * ((g - r) / diff)) + 60; break; } var s = max == 0 ? 0 : diff / max; var v = max; return [h, s, v]; }RGBY,BK,WHに判別
色相0~360、彩度0~1、明度0~1を利用して判別
やんわり力技なので、Sinとか使ってうまいことできないか、模索したが挫折しこの状態へ。。
function checkColor (rgba) { var ret = ""; var hsvRGBA = U.rgb2hsv(rgba);//色相 var hRGBA = hsvRGBA[0];//色相 var sRGBA = hsvRGBA[1];//彩度0で白 var vRGBA = hsvRGBA[2];//明度0で黒 if (sRGBA < 0.2) { ret = "White"; } else if (vRGBA < 0.2) { ret = "Black"; } else if ( (315 < hRGBA && hRGBA <= 360) || (0 < hRGBA && hRGBA <= 45) ) { ret = "Red"; } else if ( (45 < hRGBA && hRGBA <= 135) ) { ret = "Yellow"; } else if ( (135 < hRGBA && hRGBA <= 200) ) { ret = "Green"; } else if ( (200 < hRGBA && hRGBA <= 315) ) { ret = "Blue"; } return ret; }参考サイト
HSV色空間
https://www.peko-step.com/html/hsv.htmlRGBをHSVに変換する方法
https://lab.syncer.jp/Web/JavaScript/Snippet/66/
- 投稿日:2020-02-25T22:34:02+09:00
GASを試して図書館のサイトをスクレイピングしようとしたけど断念した
概要
GASを試した。
図書館のサイトをスクレイピングしようとしたけど断念した。
なぜか、セッションをキープできない。
fetchのたびにIPが変わっちゃうから?(他に原因がある可能性あり。)はじめに
GASに興味あって、少し触ってみた。
シンプルなことやってる人のサイトを参考にいくつか試してみた。
前からやりたかった、図書館のサイトのスクレイピングも試してみた。試しにGoogle SheetsでGAS
試しに、Google SheetsでGAS使う練習をしてみた。
この人のを見て、真似してみる。
【GAS初級者向け】Google Apps Scriptで バイトの給与を予測するアプリを作ろう - Qiita
時間を測りたいわけではないので、イベント名だけ表示する関数にしてみた。コードはこんな感じ。
code.gsfunction myFunction() { var objSpreadsheet = SpreadsheetApp.getActiveSpreadsheet(); var objSheet = objSpreadsheet.getActiveSheet(); var myCal = CalendarApp.getCalendarById('xx@yy'); var today = new Date(); var date = today.setDate(1); var startDate = new Date(date); var endDate = new Date(date); endDate.setMonth(endDate.getMonth()+1); myEvents = myCal.getEvents(startDate,endDate); for (var i in myEvents) { var title = myEvents[i].getTitle(); objSheet.getRange(i+1,1,1,1).setValue(i); objSheet.getRange(i+1,2,1,1).setValue(title); } }作業画面はこんな感じ。
結果はこんな感じ。
なぜか、10行ごとに入力される。なぜに?こんな感じで書くと、ちゃんと1行おきに表示されるんやけど、なぜに??
var hoge = [10,11,12,13]; for (var i in hoge){ for (var i=1; i<4; i++){ objSheet.getRange(i+1,1).setValue(i); objSheet.getRange(i+1,2).setValue(hoge[i]); }試しにメール送信
初心者でも簡単!Google Apps ScriptでGmailを操作してメールを送る方法
この人のコードをコピペ。
すんなり動いた。GETしてほしい情報を取得
Google App ScriptでWebスクレイピングしたら楽だった - phicdy devlog
このサイトを参考に、ほしい情報取得した。JavaScript 正規表現まとめ - Qiita
正規表現は、ここら確認した。ログインセッションをキープして情報取得
- Form Authentication, keep session Google Apps Script - Stack Overflow
- 【初心者向けのGAS】スクレイピングのためにログインページで自動ログインする方法 | よこのじ.work
- GoogleSpreadSheetでのスクレイピング時にサイトにログインした後のソースを取得 | katsulog
ここらを参考にクッキーを保存して試してみたけれど、うまくいかなかった。
GoogleスプレッドシートでGET/POST通信を行いコンテンツを取得する - ソフラボの技術ブログ
いろいろ試してみたあと、このサイトにたどり着いた。GoogleAppsScriptは、サーバーサイド言語ですのでサーバー側で実行されます。fetch毎にサーバーのIPアドレスが変わる仕様のようで、セッションを維持する必要のあるサイトへ接続し、一連の処理を行おうとしても、IPアドレスが変わっているため同一セッションと扱われないので注意してください。
これのせいな気がする。ブラウザとサーバーとで、Cookieだけじゃなくて、
authenticity_token
ってのをやりとりしてるっぽくて、それが変わっちゃってるんじゃないかと思う。半分、想像やけど。
デバッグ環境がよくわからないので、調査するの大変そう。ということで、諦めた。一応、試行錯誤の結果のコードをおいておく。
function getKobeLibInfo(){ var url = 'https://www.lib.city.kobe.jp/opac/opacs/mypage_display'; var response = UrlFetchApp.fetch(url); var html = response.getContentText('UTF-8'); var reg = /<input type="hidden" name="authenticity_token" value="(\S*)" \/>/i; var match = reg.exec(html); var cookies = response.getAllHeaders()['Set-Cookie']; session_cookie = cookies[0].split( ';' )[0]; Logger.log(session_cookie); cookies = "locale=ja; cokkie=opac_server2; searchkan=all; " + session_cookie; // Logger.log(match[0]); var auth_token = match[1]; Logger.log(match[1]); var payload = { 'utf8': '✓', 'user[login]': 'xxx', 'user[passwd]': 'yyy', 'act_login': 'ログイン', 'nextAction': 'mypage_display', 'prevAction': '', 'prevParams': '', 'kobeid': '', 'pvolid': '', 'type': '', 'shozo_kyk': '', 'authenticity_token':auth_token }; var headers = {'Cookie' : cookies, 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded' }; var options = { "method" : "post", "headers" : headers, "payload" : payload }; response = UrlFetchApp.fetch("https://www.lib.city.kobe.jp/opac/opacs/login", options); Logger.log(response); var cookies = response.getAllHeaders()['Set-Cookie']; session_cookie = cookies[0].split( ';' )[0]; Logger.log(session_cookie); cookies = "locale=ja; cokkie=opac_server2; searchkan=all; " + session_cookie; // Logger.log(response); var headers = {'Cookie' : cookies, 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded' }; var options = { "method" : "get", "headers" : headers }; var response = UrlFetchApp.fetch("https://www.lib.city.kobe.jp/opac/opacs/mypage_display", options); var html = response.getContentText('UTF-8'); Logger.log(html); }おわりに
結構がんばったけど、やりたいことはできなかった。
まあしょうがないか。
ただ、GAS使えるようになってうれしい。
他にもいろんなことに使えそう。
- 投稿日:2020-02-25T22:34:02+09:00
GASを使って図書館のサイトから自分の借りてる本と予約してる本の情報を取得しようとしたけど断念した
概要
GASを試した。
GASを使って図書館のサイトから自分の借りてる本と予約してる本の情報を取得しようとしたけど断念した。
なぜか、セッションをキープできない。
fetchのたびにIPが変わっちゃうから?(他に原因がある可能性あり。)はじめに
GASに興味あって、少し触ってみた。
シンプルなことやってる人のサイトを参考にいくつか試してみた。
前からやりたかった、図書館のサイトのスクレイピングも試してみた。試しにGoogle SheetsでGAS
試しに、Google SheetsでGAS使う練習をしてみた。
この人のを見て、真似してみる。
【GAS初級者向け】Google Apps Scriptで バイトの給与を予測するアプリを作ろう - Qiita
時間を測りたいわけではないので、イベント名だけ表示する関数にしてみた。コードはこんな感じ。
code.gsfunction myFunction() { var objSpreadsheet = SpreadsheetApp.getActiveSpreadsheet(); var objSheet = objSpreadsheet.getActiveSheet(); var myCal = CalendarApp.getCalendarById('xx@yy'); var today = new Date(); var date = today.setDate(1); var startDate = new Date(date); var endDate = new Date(date); endDate.setMonth(endDate.getMonth()+1); myEvents = myCal.getEvents(startDate,endDate); for (var i in myEvents) { var title = myEvents[i].getTitle(); objSheet.getRange(i+1,1,1,1).setValue(i); objSheet.getRange(i+1,2,1,1).setValue(title); } }作業画面はこんな感じ。
結果はこんな感じ。
なぜか、10行ごとに入力される。なぜに?こんな感じで書くと、ちゃんと1行おきに表示されるんやけど、なぜに??
var hoge = [10,11,12,13]; for (var i in hoge){ for (var i=1; i<4; i++){ objSheet.getRange(i+1,1).setValue(i); objSheet.getRange(i+1,2).setValue(hoge[i]); }試しにメール送信
初心者でも簡単!Google Apps ScriptでGmailを操作してメールを送る方法
この人のコードをコピペ。
すんなり動いた。GETしてほしい情報を取得
Google App ScriptでWebスクレイピングしたら楽だった - phicdy devlog
このサイトを参考に、ほしい情報取得した。JavaScript 正規表現まとめ - Qiita
正規表現は、ここら確認した。ログインセッションをキープして情報取得
- Form Authentication, keep session Google Apps Script - Stack Overflow
- 【初心者向けのGAS】スクレイピングのためにログインページで自動ログインする方法 | よこのじ.work
- GoogleSpreadSheetでのスクレイピング時にサイトにログインした後のソースを取得 | katsulog
ここらを参考にクッキーを保存して試してみたけれど、うまくいかなかった。
GoogleスプレッドシートでGET/POST通信を行いコンテンツを取得する - ソフラボの技術ブログ
いろいろ試してみたあと、このサイトにたどり着いた。GoogleAppsScriptは、サーバーサイド言語ですのでサーバー側で実行されます。fetch毎にサーバーのIPアドレスが変わる仕様のようで、セッションを維持する必要のあるサイトへ接続し、一連の処理を行おうとしても、IPアドレスが変わっているため同一セッションと扱われないので注意してください。
これのせいな気がする。ブラウザとサーバーとで、Cookieだけじゃなくて、
authenticity_token
ってのをやりとりしてるっぽくて、それが変わっちゃってるんじゃないかと思う。半分、想像やけど。
デバッグ環境がよくわからないので、調査するの大変そう。ということで、諦めた。一応、試行錯誤の結果のコードをおいておく。
function getKobeLibInfo(){ var url = 'https://www.lib.city.kobe.jp/opac/opacs/mypage_display'; var response = UrlFetchApp.fetch(url); var html = response.getContentText('UTF-8'); var reg = /<input type="hidden" name="authenticity_token" value="(\S*)" \/>/i; var match = reg.exec(html); var cookies = response.getAllHeaders()['Set-Cookie']; session_cookie = cookies[0].split( ';' )[0]; Logger.log(session_cookie); cookies = "locale=ja; cokkie=opac_server2; searchkan=all; " + session_cookie; // Logger.log(match[0]); var auth_token = match[1]; Logger.log(match[1]); var payload = { 'utf8': '✓', 'user[login]': 'xxx', 'user[passwd]': 'yyy', 'act_login': 'ログイン', 'nextAction': 'mypage_display', 'prevAction': '', 'prevParams': '', 'kobeid': '', 'pvolid': '', 'type': '', 'shozo_kyk': '', 'authenticity_token':auth_token }; var headers = {'Cookie' : cookies, 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded' }; var options = { "method" : "post", "headers" : headers, "payload" : payload }; response = UrlFetchApp.fetch("https://www.lib.city.kobe.jp/opac/opacs/login", options); Logger.log(response); var cookies = response.getAllHeaders()['Set-Cookie']; session_cookie = cookies[0].split( ';' )[0]; Logger.log(session_cookie); cookies = "locale=ja; cokkie=opac_server2; searchkan=all; " + session_cookie; // Logger.log(response); var headers = {'Cookie' : cookies, 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded' }; var options = { "method" : "get", "headers" : headers }; var response = UrlFetchApp.fetch("https://www.lib.city.kobe.jp/opac/opacs/mypage_display", options); var html = response.getContentText('UTF-8'); Logger.log(html); }おわりに
結構がんばったけど、やりたいことはできなかった。
まあしょうがないか。
ただ、GAS使えるようになってうれしい。
他にもいろんなことに使えそう。
- 投稿日:2020-02-25T21:44:59+09:00
JavaScript メモ
- ###var → 変数
- ###function(){} → 関数
- ###for → 繰り返し(終わりのある)
- ###console.log → コンソールに表示
- ###alert() → 警告
- ###confirm() → 確認
- ###prompt() → 入力
- ###if(条件式) {条件式に合致する場合に行われる処理} → もし〜ならば
- ###else {条件式に合致しない場合に行われる処理} → ifがダメなら
- ###switch(条件) { case 値1: //処理 break; }
比較演算子
- ###A > B AはBより大きい
- ###A >= B AはB以上
- ###A === B AとBは等しい
- ###A !== B AとBは等しくない
論理演算子
- ###A && B AかつB (and)
- ###A || B AまたはB (or)
- ### !A Aではない(not)
- 投稿日:2020-02-25T20:55:28+09:00
chart.jsのyAxes
SNMPのグラフをchart.jsで表示しているのだが、y軸がいまいちいけてない。
yAxes: [{ ticks: { callback: function(value) { return value + " oct";}, min: 0 } }]こんな風にしてみた。
yAxes: [{ ticks: { callback: function(value) { if (value == 0) { return value + " oct";} else if (value >= 1000000) { return (value / 1000000) + " moct";} else {return (value / 1000) + " koct";}}, min: 0 } }]大きいトラフィックは外すと
もっと外すと
もっともっと外すと
とりあえず今日はこれで良しとしよう。
- 投稿日:2020-02-25T20:50:12+09:00
JavaScript メモ
var → 変数
function() {}→ 関数
for → 繰り返し(終わりのある)
- 投稿日:2020-02-25T18:58:46+09:00
スクリプト言語 KINX/基本編(1) - プログラム基礎・データ型
はじめに
前回の記事から。シリーズ第一弾は普通に基本編。概要は以下の前回の記事を参照してください。
- スクリプト言語 KINX(ご紹介)
- Kinx 基本編(1) - プログラム基礎・データ型(今回)
前回お披露目してみたら★を付けてくださった方がいて、非常に浮かれています。ありがとうございました。温かいお気持ちで行く末を見届けてやってください。
- ここ (https://github.com/Kray-G/kinx) です。「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」でお届けする スクリプト言語 KINX。オブジェクト指向と C 系シンタックスで C 系プログラマになじむ触感 を目指して。
Kinx 基本編(1) - プログラム基礎・データ型
プログラム基礎
hello, world
プログラムはトップレベルから記述可能。
hello.kxSystem.println("hello, world.");
hello.kx
という名前で保存し、以下のように実行.$ ./kinx hello.kx hello, world.コメント
コメントは C/C++ 形式と Perl のような
#
形式と両方利用可能。/* Comment */ // Comment# Comment
変数宣言
変数宣言は
var
で宣言する。var a = 10;初期化子を使って初期化するが、初期化子を書かなかった場合は
null
となる。ちなみに Kinx においてはnull
とundefined
は同じ意味(賛否あると思うが)。どちらもa.isUndefined
が true となる。データ型一覧
Kinx は動的型付け言語だが、内部に型を持っている。
Type CheckProperty Example Meaning Undefined isUndefined
null 初期化されていない値。 Integer isInteger
,isBigInteger
100, 0x02 整数。演算では自動的に Big Integer と相互変換される。 Double isDouble
1.5 実数。 String isString
"aaa", 'bbb' 文字列。 Binary isBinary
<1,2,3> バイナリ値。バイトの配列。要素は全て 0x00-0xFF に丸められる。 Array isArray
,isObject
[1,a,["aaa"]] 配列。扱える型は全て保持可能。 Object isObject
{ a: 1, b: x } JSON のようなキーバリュー構造。 Function isFunction
function(){},
&() => expr関数。
Undefined
以外であればisDefined
で true が返る。尚、真偽値としての
true
、false
は整数の 1、0 のエイリアスでしかないのに注意。
Boolean 型というのは特別に定義されていないが、オブジェクトとして真偽を表すTrue
、False
という定数が定義されているので、整数値とどうしても区別したい場合はそちらを使用する。System.println(True ? 1 : 0); // 1 System.println(False ? 1 : 0); // 0ブロックとスコープ
ブロックはスコープを持ち、内側で宣言された変数は外側のブロックからは参照不可。同じ名前で宣言した場合、外側ブロックの同名変数は隠蔽される。
var a = 10; { var a = 100; System.println(a); } System.println(a);この辺が「見た目は JavaScript」であっても中身は JavaScript ではない感じの部分。というか、JavaScript のスコープは変態過ぎて使いづらい。
式
式(エクスプレッション)は、以下の優先順位で四則演算、関数呼び出し、オブジェクト操作等が可能。
# 要素 演算子例 評価方向 1 要素 変数, 数値, 文字列, ... - 2 後置演算子 ++
,--
,[]
,.
,()
左から右 3 前置演算子 !
,+
,-
,++
,--
左から右 4 パターンマッチ =~
,!~
左から右 5 べき乗 **
右から左 6 乗除 *
,/
,%
左から右 7 加減 +
,-
左から右 8 ビットシフト <<
,>>
左から右 9 大小比較 <
,>
,>=
,<=
左から右 10 等値比較 ==
,!=
左から右 11 ビットAND &
左から右 12 ビットXOR ^
左から右 13 ビットOR |
左から右 14 論理AND &&
左から右 15 論理OR ||
左から右 16 三項演算子 ? :
,function(){}
左から右 17 代入演算子 =
,+=
,-=
,*=
./=
.%=
,&=
,|=
,^=
,&&=
,||=
右から左 いくつか特徴を以下に示す。
演算
演算結果によって型が自動的に結果に適応していく。
3/2
は1.5
になる。num = 3 + 2; // 5 num = 3 - 2; // 1 num = 3 * 2; // 6 num = 3 / 2; // 1.5 num = 3 % 2; // 1インクリメント・デクリメント
前置形式・後置形式があり、C と同様。
var a = 10; System.println(a++); // 10 System.println(++a); // 12 System.println(a--); // 12 System.println(--a); // 10データ型
数値
整数、実数
整数、実数は以下の形式。整数では可読性向上のため任意の場所に
_
を挿入可能。_
は単に無視される。var i = 2; var j = 100_000_000; var num = 1.234;文字列
基本
ダブルクォートとシングルクォートの両方が使えるが、エスケープしなければならないクォート文字が異なるだけでどちらも同じ意味になる。
var a = "\"aaa\", 'bbb'"; var b = '"aaa", \'bbb\''; System.println(a == b ? "same" : "different"); // same内部式
%{...}
の形式で内部に式を持つことができる。for (var i = 0; i < 10; ++i) { System.println("i = %{i}, i * 2 = %{i * 2}"); } // i = 0, i * 2 = 0 // i = 1, i * 2 = 2 // i = 2, i * 2 = 4 // i = 3, i * 2 = 6 // i = 4, i * 2 = 8 // i = 5, i * 2 = 10 // i = 6, i * 2 = 12 // i = 7, i * 2 = 14 // i = 8, i * 2 = 16 // i = 9, i * 2 = 18フォーマッタ
文字列に対する
%
演算子はフォーマッタ・オブジェクトを作成する。var fmt = "This is %1%, I can do %2%."; System.println(fmt % "Tom" % "cooking");
%1%
の1
はプレースホルダ番号を示し、%
演算子で適用した順に合わせて整形する。適用場所が順序通りであれば、C の printf と同様の指定の仕方も可能。さらに、C の printf と同じ指定子を使いながら同時にプレースホルダも指定したい場合は、$
の前に位置指定子を書き、'$' で区切って記述する。例えば、16進数で表示したい場合は以下のようにする。var fmt = "This is %2%, I am 0x%1$02x years old in hex."; System.println(fmt % 27 % "John"); // This is John, I am 0x1b years old in hex.フォーマッタ・オブジェクトに後から値を適用していく場合は、
%=
演算子で適用していく。var fmt = "This is %1%, I can do %2%."; fmt %= "Tom"; fmt %= "cooking"; System.println(fmt);実際のフォーマット処理は、
System.println
等で表示するとき、文字列との加算等が行われるとき、に実際に実行される。Raw 文字列
文字列内部ではなく、
%{...}
で文字列を記載することで Raw 文字列を作成することが可能。%-{...}
を使うと、先頭と末尾の改行文字をトリミングする。ヒアドキュメントのようにも使えるので、ヒアドキュメントはサポートしていない。また、%<...>
、%(...)
、%[...]
を使うこともできる。var a = 100; var b = 10; var str = %{ This is a string without escaping control characters. New line is available in this area. { and } can be nested here. }; System.println(str); var str = %-{ This is a string without escaping control characters. New line is available in this area. But newlines at the beginning and the end are removed when starting with '%-'. }; System.println(str);
\
でエスケープする必要があるのは、内部式を使う場合%{
の%
に対するものと、ネストした形にならないケースでのクォート文字である{
や}
に対するものだけとなる。また、カッコは対応する閉じカッコでクォートするが、以下の文字を使ったクォートも可能である。その場合は、開始文字と終了文字は同じ文字となる。例えば、
%|...|
のような形で使用する。
|
,!
,^
,~
,_
,.
,,
,+
,*
,@
,&
,$
,:
,;
,?
,'
,"
.正規表現リテラル
正規表現リテラルは
/.../
の形式で使う。リテラル内の/
は\
でエスケープする必要がある。以下が例。var a = "111/aaa/bbb/ccc/ddd"; while (group = (a =~ /\w+\//)) { for (var i = 0, len = group.length(); i < len; ++i) { System.println("found[%2d,%2d) = %s" % group[i].begin % group[i].end % a.subString(group[i].begin, group[i].end - group[i].begin)); } }
/
を多用するような正規表現の場合、%m
プレフィックスを付け、別のクォート文字を使うことで回避できる。例えば%m(...)
といった記述が可能。これを使って上記を書き直すと、以下のようになる。var a = "111/aaa/bbb/ccc/ddd"; while (group = (a =~ %m(\w+/))) { for (var i = 0, len = group.length(); i < len; ++i) { System.println("found[%2d,%2d) = %s" % group[i].begin % group[i].end % a.subString(group[i].begin, group[i].end - group[i].begin)); } }尚、正規表現リテラルを
while
等の条件式に入れることができるが注意点があるので補足しておく。例えば以下のように記述した場合、str
の文字列に対してマッチしなくなるまでループを回すことができる(group
にはキャプチャ一覧が入る)。その際、最後のマッチまで実行せずに途中でbreak
等でループを抜けると正規表現リテラルの対象文字列が次回のループで正しくリセットされない、という状況が発生する。while (group = (str =~ /ab+/)) { /* block */ }正規表現リテラルがリセットされるタイミングは以下の 2 パターン。
- 初回(前回のマッチが失敗して再度式が評価された場合を含む)。
str
の内容が変化した場合。将来改善を検討するかもしれないが、現在は上記の制約があることに注意。
配列
配列は任意の要素を保持するリスト。インデックスでアクセスできる。またインデックスに負の数を与えることで末尾からアクセスすることもできる。
var a = [1,2,3]; var b = [a, 1, 2]; System.println(b[0][2]); // 3 System.println(a[-1]); // 3配列構造は左辺値で使用すると右辺値の配列を個々の変数に取り込むことが可能。これを使用して値のスワップも可能。
[a, b] = [b, a]; // Swapスプレッド(レスト)演算子を使っての分割も可能。
[a, ...b] = [1, 2, 3, 4, 5]; // a = 1 // b = [2, 3, 4, 5]尚、以下の書き方はできない。変数は宣言なしで使用できる(最初に代入された時点で生成される)ため、
var
を付けない形で直接記述することは可能。ただしその際、外部のスコープで定義されていた場合、外側のスコープの変数の内容が書き換わってしまうことに注意。スコープで変数へのアクセス範囲を閉じたい場合は、予めvar a, b;
と宣言してから使うことで回避可能。// var [a, ...b] = [1, 2, 3, 4, 5]; // error. var a = 3, b = [4], x = 3, y = [4]; { var a, b; [a, ...b] = [1, 2, 3, 4, 5]; // a = 1 // b = [2, 3, 4, 5] [x, ...y] = [1, 2, 3, 4, 5]; // x = 1 // y = [2, 3, 4, 5] [z] = [1, 2, 3, 4, 5]; // okay z = 1, but scoped out... } System.println("a = ", a); // 3 System.println("b = ", b[0]); // 4 System.println("x = ", x); // 1 System.println("y = ", y[0]); // 2宣言と同時に使えると便利とは思うので、将来改善するかもしれない。
バイナリ
バイナリはバイト配列であり、
<...>
の形式で記述する。全ての要素は 0x00 ~ 0xFF の範囲にアジャストされ、配列のようにアクセス可能。バイナリと配列は相互にスプレッド演算子で分割、結合することが可能。
var bin = <0x01, 0x02, 0x03, 0x04>; var ary = [...bin]; // ary := [1, 2, 3, 4] var ary = [10, 11, 12, 257]; var bin = <...ary>; // bin := <0x0a, 0x0b, 0x0c, 0x01>ただし、バイナリになった瞬間に 0x00-0xFF に丸められるので注意。
オブジェクト
いわゆる JSON。ただし、ソースコード上のキー文字列に対してクォートする必要は無い(しても良い)。
var a = { a: 100 }; a.b = 1_000; a["c"] = 10_000; System.println(a.a); // 100 System.println(a.b); // 1000 System.println(a.c); // 10000内部的に実はオブジェクトと配列は同じであり、両方の値を同時に保持できる。
var a = { a: 100 }; a.b = 1_000; a["c"] = 10_000; a[1] = 10; System.println(a[1]); // 10 System.println(a.a); // 100 System.println(a.b); // 1000 System.println(a.c); // 10000おわりに
今回はここまで。結構疲れた。
非常に一般的な話ばかりで面白くないのだが、まずはこういうところに触れた上で色々な解説しとかないと土台が良く分からなくなりそうなので頑張ってみた。とりあえず、次は制御構造に触れて、一通りのプログラムが構築できるところまでを目指そう。そこまで行ったら関数とかクラスとかクロージャとか個別の解説をしてみる予定。
例によって★が増えるといいな、と宣伝しておく。
そして書きながらバグを見つけ修正するという...。
- 投稿日:2020-02-25T18:48:07+09:00
pythonで生徒を当てるアプリをつくる-GUI版
はじめに
以前投稿したpythonで生徒を当てるアプリをつくるをGUIソフトにしたってだけの記事.
プログラム
main.py data/ history.txt list.txt list_raw.txt web/ main.html css/ style.css js/ eel.js
main.py
main.pyimport locale import eel import random import pickle import os import sys import datetime from tkinter import filedialog, Tk import platform import copy def main(): eel.init("web") eel.start("main.html") Student_names = [] Student_FILENAME = "./data/list.txt" Student_FILENAME_raw = "./data/list_raw.txt" # Student @eel.expose def Student_load(): with open(select_file(), "r") as f: global Student_names Student_names = f.read().splitlines() Student_save(Student_FILENAME) Student_save(Student_FILENAME_raw) @eel.expose def Student_reset(): Student_names_load(Student_FILENAME_raw) @eel.expose def Student_show(): Student_names_load(Student_FILENAME) name_ls = "" a = 1 for name in Student_names: if a % 5 == 0: name_ls = name_ls + name + "<br>" else: name_ls = name_ls + name + " " a += 1 return name_ls @eel.expose def Student_choice(): Student_names_load(Student_FILENAME) global Student_names_raw Student_names_raw = copy.deepcopy(Student_names) if not Student_names: return global name name = random.choice(Student_names) Student_names.remove(name) if Student_names == []: Student_names_load(Student_FILENAME_raw) History_add(name) Student_save(Student_FILENAME) return name @eel.expose def Student_save(FILENAME): f = open(FILENAME, 'wb') pickle.dump(Student_names, f) @eel.expose def Student_names_load(FILENAME): f = open(FILENAME, "rb") global Student_names Student_names = pickle.load(f) # History History_FILENAME = "./data/history.txt" History_data = [] @eel.expose def History_load(): with open(History_FILENAME, "r") as f: global History_data History_data = f.read().splitlines() @eel.expose def History_save(): with open(History_FILENAME, "w") as f: for history in History_data: print(history, file=f) @eel.expose def History_show(): history_ls = "" History_load() for history in History_data: history_ls = history + "<br>" + history_ls return history_ls locale.setlocale(locale.LC_ALL, '') @eel.expose def History_add(name): now = datetime.datetime.now() History_data.append(f"{now:%m月%d日}:{name}") History_save() @eel.expose def History_cancel(): History_data.pop() History_save() global Student_names Student_names = copy.deepcopy(Student_names_raw) Student_save(Student_FILENAME) @eel.expose def History_clear(): global History_data History_data = [] History_save() # 名簿読み込み # ダイアログ用のルートウィンドウの作成 # (root自体はeelのウィンドウとは関係ないので非表示にしておくのが望ましい) root = Tk() # ウィンドウサイズを0にする root.geometry("0x0") # ウィンドウのタイトルバーを消す root.overrideredirect(1) # ウィンドウを非表示に root.withdraw() system = platform.system() @eel.expose def select_file(): # Windowsの場合withdrawの状態だとダイアログも # 非表示になるため、rootウィンドウを表示する if system == "Windows": root.deiconify() # macOS用にダイアログ作成前後でupdate()を呼ぶ root.update() # ダイアログを前面に # topmost指定(最前面) root.attributes('-topmost', True) root.withdraw() root.lift() root.focus_force() path_str = filedialog.askopenfilename() root.update() if system == "Windows": # 再度非表示化(Windowsのみ) root.withdraw() #path = Path(path_str) return path_str if __name__ == '__main__': main()
main.html
main.html<html> <head> <meta charset="UTF-8"> <title>生徒当てるヤツ</title> <link rel="stylesheet" type="text/css" href="./css/style.css"> <script type="text/javascript" src="/eel.js"></script> <script type="text/javascript"> async function Student_choice() { var demo2 = document.getElementById("div0"); demo2.innerHTML = ""; div0.insertAdjacentHTML('afterbegin', '<div id="name"></div>'); let val = await eel.Student_choice()(); var doc0 = document.getElementById("name"); doc0.innerHTML = val; } async function Student_load() { eel.Student_load(); } async function Student_show() { let val = await eel.Student_show()(); var doc0 = document.getElementById("div0"); doc0.innerHTML = val; } async function History_show() { let val = await eel.History_show()(); var doc0 = document.getElementById("div0"); doc0.innerHTML = val; } async function History_clear() { let val = await eel.History_clear()(); var doc0 = document.getElementById("div0"); doc0.innerHTML = val; } async function History_cancel() { let val = await eel.History_cancel()(); var doc0 = document.getElementById("div0"); doc0.innerHTML = val; } </script> </head> <body> <center> <div id="div0"> </div> <div class="bottom"> <a href="#" onclick="Student_choice()" class="btn-square">生徒を当てる</a> <a href="#" onclick="History_cancel()" class="btn-square">欠席者を飛ばす</a> <a href="#" onclick="Student_show()" class="btn-square">残りの生徒を表示</a> <a href="#" onclick="History_show()" class="btn-square">履歴の表示</a> <a href="#" onclick="History_clear()" class="btn-square">履歴の消去</a> <a href="#" onclick="Student_load()" class="btn-square">名簿を更新</a> </div> </center> <div class='markdown-preview' data-use-github-style> <details> <summary>名簿の更新方法</summary> <div> <h1 id="名簿の更新方法">名簿の更新方法</h1> <h3 id="1">1</h3> <p>任意のファイル名のテキストファイル(*.txt)を作成します.</p> <h3 id="2">2</h3> <p>その中に<br> 1.名前<br> 2.名前<br> ・<br> ・<br> ・<br> と入力します.</p> <h3 id="3">3</h3> <p>名簿を更新をクリックし,テキストファイルを選択する.</p> </div> </details> </div> </html>
style.css
style.css.btn-square { display: inline-block; padding: 0.5em 1em; text-decoration: none; background: #668ad8; /*ボタン色*/ color: #FFF; border-bottom: solid 4px #627295; border-radius: 3px; } .btn-square:active { /*ボタンを押したとき*/ -webkit-transform: translateY(4px); transform: translateY(4px); /*下に動く*/ border-bottom: none; /*線を消す*/ } #div0 { height: 300px; overflow: scroll; } #name { margin-top: 50px; font-size: 100px; } .bottom {} .markdown-preview:not([data-use-github-style]) { padding: 2em; font-size: 1.2em; color: rgb(197, 200, 198); background-color: rgb(29, 31, 33); overflow: auto; } .markdown-preview:not([data-use-github-style])> :first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-preview:not([data-use-github-style]) h2, .markdown-preview:not([data-use-github-style]) h3, .markdown-preview:not([data-use-github-style]) h4, .markdown-preview:not([data-use-github-style]) h5, .markdown-preview:not([data-use-github-style]) h6 { line-height: 1.2; margin-top: 1.5em; margin-bottom: 0.5em; color: rgb(255, 255, 255); } .markdown-preview:not([data-use-github-style]) h1 { font-size: 2.4em; font-weight: 300; } .markdown-preview:not([data-use-github-style]) h2 { font-size: 1.8em; font-weight: 400; } .markdown-preview:not([data-use-github-style]) h3 { font-size: 1.5em; font-weight: 500; } .markdown-preview:not([data-use-github-style]) h4 { font-size: 1.2em; font-weight: 600; } .markdown-preview:not([data-use-github-style]) h5 { font-size: 1.1em; font-weight: 600; } .markdown-preview:not([data-use-github-style]) h6 { font-size: 1em; font-weight: 600; } .markdown-preview:not([data-use-github-style]) strong { color: rgb(255, 255, 255); } .markdown-preview:not([data-use-github-style]) del { color: rgb(155, 160, 157); } .markdown-preview:not([data-use-github-style]) a, .markdown-preview:not([data-use-github-style]) a code { color: white; } .markdown-preview:not([data-use-github-style]) img { max-width: 100%; } .markdown-preview:not([data-use-github-style])>p { margin-top: 0px; margin-bottom: 1.5em; } .markdown-preview:not([data-use-github-style])>ul, .markdown-preview:not([data-use-github-style])>ol { margin-bottom: 1.5em; } .markdown-preview:not([data-use-github-style]) blockquote { margin: 1.5em 0px; font-size: inherit; color: rgb(155, 160, 157); border-color: rgb(67, 72, 76); border-width: 4px; } .markdown-preview:not([data-use-github-style]) hr { margin: 3em 0px; border-top: 2px dashed rgb(67, 72, 76); background: none; } .markdown-preview:not([data-use-github-style]) table { margin: 1.5em 0px; } .markdown-preview:not([data-use-github-style]) th { color: rgb(255, 255, 255); } .markdown-preview:not([data-use-github-style]) th, .markdown-preview:not([data-use-github-style]) td { padding: 0.66em 1em; border: 1px solid rgb(67, 72, 76); } .markdown-preview:not([data-use-github-style]) code { color: rgb(255, 255, 255); background-color: rgb(48, 51, 55); } .markdown-preview:not([data-use-github-style]) pre.editor-colors { margin: 1.5em 0px; padding: 1em; font-size: 0.92em; border-radius: 3px; background-color: rgb(39, 41, 44); } .markdown-preview:not([data-use-github-style]) kbd { color: rgb(255, 255, 255); border-width: 1px 1px 2px; border-style: solid; border-color: rgb(67, 72, 76) rgb(67, 72, 76) rgb(53, 57, 60); border-image: initial; background-color: rgb(48, 51, 55); } .markdown-preview[data-use-github-style] { font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif; line-height: 1.6; overflow-wrap: break-word; padding: 30px; font-size: 16px; color: rgb(51, 51, 51); background-color: rgb(255, 255, 255); } .markdown-preview[data-use-github-style]> :first-child { margin-top: 0px !important; } .markdown-preview[data-use-github-style]> :last-child { margin-bottom: 0px !important; } .markdown-preview[data-use-github-style] a:not([href]) { color: inherit; text-decoration: none; } .markdown-preview[data-use-github-style] .absent { color: rgb(204, 0, 0); } .markdown-preview[data-use-github-style] .anchor { position: absolute; top: 0px; left: 0px; display: block; padding-right: 6px; padding-left: 30px; margin-left: -30px; } .markdown-preview[data-use-github-style] .anchor:focus { outline: none; } .markdown-preview[data-use-github-style] h1, .markdown-preview[data-use-github-style] h2, .markdown-preview[data-use-github-style] h3, .markdown-preview[data-use-github-style] h4, .markdown-preview[data-use-github-style] h5, .markdown-preview[data-use-github-style] h6 { position: relative; margin-top: 1em; margin-bottom: 16px; font-weight: bold; line-height: 1.4; } .markdown-preview[data-use-github-style] h1 .octicon-link, .markdown-preview[data-use-github-style] h2 .octicon-link, .markdown-preview[data-use-github-style] h3 .octicon-link, .markdown-preview[data-use-github-style] h4 .octicon-link, .markdown-preview[data-use-github-style] h5 .octicon-link, .markdown-preview[data-use-github-style] h6 .octicon-link { display: none; color: rgb(0, 0, 0); vertical-align: middle; } .markdown-preview[data-use-github-style] h1:hover .anchor, .markdown-preview[data-use-github-style] h2:hover .anchor, .markdown-preview[data-use-github-style] h3:hover .anchor, .markdown-preview[data-use-github-style] h4:hover .anchor, .markdown-preview[data-use-github-style] h5:hover .anchor, .markdown-preview[data-use-github-style] h6:hover .anchor { padding-left: 8px; margin-left: -30px; text-decoration: none; } .markdown-preview[data-use-github-style] h1:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h2:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h3:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h4:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h5:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h6:hover .anchor .octicon-link { display: inline-block; } .markdown-preview[data-use-github-style] h1 tt, .markdown-preview[data-use-github-style] h2 tt, .markdown-preview[data-use-github-style] h3 tt, .markdown-preview[data-use-github-style] h4 tt, .markdown-preview[data-use-github-style] h5 tt, .markdown-preview[data-use-github-style] h6 tt, .markdown-preview[data-use-github-style] h1 code, .markdown-preview[data-use-github-style] h2 code, .markdown-preview[data-use-github-style] h3 code, .markdown-preview[data-use-github-style] h4 code, .markdown-preview[data-use-github-style] h5 code, .markdown-preview[data-use-github-style] h6 code { font-size: inherit; } .markdown-preview[data-use-github-style] h1 { padding-bottom: 0.3em; font-size: 2.25em; line-height: 1.2; border-bottom: 1px solid rgb(238, 238, 238); } .markdown-preview[data-use-github-style] h1 .anchor { line-height: 1; } .markdown-preview[data-use-github-style] h2 { padding-bottom: 0.3em; font-size: 1.75em; line-height: 1.225; border-bottom: 1px solid rgb(238, 238, 238); } .markdown-preview[data-use-github-style] h2 .anchor { line-height: 1; } .markdown-preview[data-use-github-style] h3 { font-size: 1.5em; line-height: 1.43; } .markdown-preview[data-use-github-style] h3 .anchor { line-height: 1.2; } .markdown-preview[data-use-github-style] h4 { font-size: 1.25em; } .markdown-preview[data-use-github-style] h4 .anchor { line-height: 1.2; } .markdown-preview[data-use-github-style] h5 { font-size: 1em; } .markdown-preview[data-use-github-style] h5 .anchor { line-height: 1.1; } .markdown-preview[data-use-github-style] h6 { font-size: 1em; color: rgb(119, 119, 119); } .markdown-preview[data-use-github-style] h6 .anchor { line-height: 1.1; } .markdown-preview[data-use-github-style] p, .markdown-preview[data-use-github-style] blockquote, .markdown-preview[data-use-github-style] ul, .markdown-preview[data-use-github-style] ol, .markdown-preview[data-use-github-style] dl, .markdown-preview[data-use-github-style] table, .markdown-preview[data-use-github-style] pre { margin-top: 0px; margin-bottom: 16px; } .markdown-preview[data-use-github-style] hr { height: 4px; padding: 0px; margin: 16px 0px; background-color: rgb(231, 231, 231); border: 0px none; } .markdown-preview[data-use-github-style] ul, .markdown-preview[data-use-github-style] ol { padding-left: 2em; } .markdown-preview[data-use-github-style] ul.no-list, .markdown-preview[data-use-github-style] ol.no-list { padding: 0px; list-style-type: none; } .markdown-preview[data-use-github-style] ul ul, .markdown-preview[data-use-github-style] ul ol, .markdown-preview[data-use-github-style] ol ol, .markdown-preview[data-use-github-style] ol ul { margin-top: 0px; margin-bottom: 0px; } .markdown-preview[data-use-github-style] li>p { margin-top: 16px; } .markdown-preview[data-use-github-style] dl { padding: 0px; } .markdown-preview[data-use-github-style] dl dt { padding: 0px; margin-top: 16px; font-size: 1em; font-style: italic; font-weight: bold; } .markdown-preview[data-use-github-style] dl dd { padding: 0px 16px; margin-bottom: 16px; } .markdown-preview[data-use-github-style] blockquote { padding: 0px 15px; color: rgb(119, 119, 119); border-left: 4px solid rgb(221, 221, 221); } .markdown-preview[data-use-github-style] blockquote> :first-child { margin-top: 0px; } .markdown-preview[data-use-github-style] blockquote> :last-child { margin-bottom: 0px; } .markdown-preview[data-use-github-style] table { display: block; width: 100%; overflow: auto; word-break: keep-all; } .markdown-preview[data-use-github-style] table th { font-weight: bold; } .markdown-preview[data-use-github-style] table th, .markdown-preview[data-use-github-style] table td { padding: 6px 13px; border: 1px solid rgb(221, 221, 221); } .markdown-preview[data-use-github-style] table tr { background-color: rgb(255, 255, 255); border-top: 1px solid rgb(204, 204, 204); } .markdown-preview[data-use-github-style] table tr:nth-child(2n) { background-color: rgb(248, 248, 248); } .markdown-preview[data-use-github-style] img { max-width: 100%; box-sizing: border-box; } .markdown-preview[data-use-github-style] .emoji { max-width: none; } .markdown-preview[data-use-github-style] span.frame { display: block; overflow: hidden; } .markdown-preview[data-use-github-style] span.frame>span { display: block; float: left; width: auto; padding: 7px; margin: 13px 0px 0px; overflow: hidden; border: 1px solid rgb(221, 221, 221); } .markdown-preview[data-use-github-style] span.frame span img { display: block; float: left; } .markdown-preview[data-use-github-style] span.frame span span { display: block; padding: 5px 0px 0px; clear: both; color: rgb(51, 51, 51); } .markdown-preview[data-use-github-style] span.align-center { display: block; overflow: hidden; clear: both; } .markdown-preview[data-use-github-style] span.align-center>span { display: block; margin: 13px auto 0px; overflow: hidden; text-align: center; } .markdown-preview[data-use-github-style] span.align-center span img { margin: 0px auto; text-align: center; } .markdown-preview[data-use-github-style] span.align-right { display: block; overflow: hidden; clear: both; } .markdown-preview[data-use-github-style] span.align-right>span { display: block; margin: 13px 0px 0px; overflow: hidden; text-align: right; } .markdown-preview[data-use-github-style] span.align-right span img { margin: 0px; text-align: right; } .markdown-preview[data-use-github-style] span.float-left { display: block; float: left; margin-right: 13px; overflow: hidden; } .markdown-preview[data-use-github-style] span.float-left span { margin: 13px 0px 0px; } .markdown-preview[data-use-github-style] span.float-right { display: block; float: right; margin-left: 13px; overflow: hidden; } .markdown-preview[data-use-github-style] span.float-right>span { display: block; margin: 13px auto 0px; overflow: hidden; text-align: right; } .markdown-preview[data-use-github-style] code, .markdown-preview[data-use-github-style] tt { padding: 0.2em 0px; margin: 0px; font-size: 85%; background-color: rgba(0, 0, 0, 0.04); border-radius: 3px; } .markdown-preview[data-use-github-style] code::before, .markdown-preview[data-use-github-style] tt::before, .markdown-preview[data-use-github-style] code::after, .markdown-preview[data-use-github-style] tt::after { letter-spacing: -0.2em; content: " "; } .markdown-preview[data-use-github-style] code br, .markdown-preview[data-use-github-style] tt br { display: none; } .markdown-preview[data-use-github-style] del code { text-decoration: inherit; } .markdown-preview[data-use-github-style] pre>code { padding: 0px; margin: 0px; font-size: 100%; word-break: normal; white-space: pre; background: transparent; border: 0px; } .markdown-preview[data-use-github-style] .highlight { margin-bottom: 16px; } .markdown-preview[data-use-github-style] .highlight pre, .markdown-preview[data-use-github-style] pre { padding: 16px; overflow: auto; font-size: 85%; line-height: 1.45; background-color: rgb(247, 247, 247); border-radius: 3px; } .markdown-preview[data-use-github-style] .highlight pre { margin-bottom: 0px; word-break: normal; } .markdown-preview[data-use-github-style] pre { overflow-wrap: normal; } .markdown-preview[data-use-github-style] pre code, .markdown-preview[data-use-github-style] pre tt { display: inline; max-width: initial; padding: 0px; margin: 0px; overflow: initial; line-height: inherit; overflow-wrap: normal; background-color: transparent; border: 0px; } .markdown-preview[data-use-github-style] pre code::before, .markdown-preview[data-use-github-style] pre tt::before, .markdown-preview[data-use-github-style] pre code::after, .markdown-preview[data-use-github-style] pre tt::after { content: normal; } .markdown-preview[data-use-github-style] kbd { display: inline-block; padding: 3px 5px; font-size: 11px; line-height: 10px; color: rgb(85, 85, 85); vertical-align: middle; background-color: rgb(252, 252, 252); border-width: 1px; border-style: solid; border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(187, 187, 187); border-image: initial; border-radius: 3px; box-shadow: rgb(187, 187, 187) 0px -1px 0px inset; } .markdown-preview[data-use-github-style] a { color: rgb(51, 122, 183); } .markdown-preview[data-use-github-style] code { color: inherit; } .markdown-preview[data-use-github-style] pre.editor-colors { padding: 0.8em 1em; margin-bottom: 1em; font-size: 0.85em; border-radius: 4px; overflow: auto; } .markdown-preview pre.editor-colors { user-select: auto; } .scrollbars-visible-always .markdown-preview pre.editor-colors .vertical-scrollbar, .scrollbars-visible-always .markdown-preview pre.editor-colors .horizontal-scrollbar { visibility: hidden; } .scrollbars-visible-always .markdown-preview pre.editor-colors:hover .vertical-scrollbar, .scrollbars-visible-always .markdown-preview pre.editor-colors:hover .horizontal-scrollbar { visibility: visible; } .markdown-preview .task-list-item input[type="checkbox"] { position: absolute; margin: 0.25em 0px 0px -1.4em; } .markdown-preview .task-list-item { list-style-type: none; } .markdown-preview code { text-shadow: none; } @keyframes RotatingBackground { 0% { background-position-x: 0%; } 100% { background-position-x: 100%; } } .debugger-breakpoint-icon::before, .debugger-shadow-breakpoint-icon::before { font-family: 'Octicons Regular'; font-weight: normal; font-style: normal; display: inline-block; line-height: 1; -webkit-font-smoothing: antialiased; text-decoration: none; font-size: 130%; width: 130%; height: 130%; content: "\f052"; } .debugger-breakpoint-icon, .debugger-breakpoint-icon-disabled, .debugger-breakpoint-icon-unresolved, .debugger-breakpoint-icon-conditional, .debugger-shadow-breakpoint-icon { text-align: center; display: block; width: 0.8em; cursor: pointer; } .debugger-breakpoint-icon-nonconditional { color: #5293d8; } .debugger-breakpoint-icon-conditional { color: #ff982d; } .debugger-breakpoint-icon-disabled { position: relative; top: -4px; left: 2px; } .debugger-breakpoint-icon-disabled::before { font-family: 'Octicons Regular'; font-weight: normal; font-style: normal; display: inline-block; line-height: 1; -webkit-font-smoothing: antialiased; text-decoration: none; font-size: 78%; width: 78%; height: 78%; content: "\f084"; } .debugger-breakpoint-icon-unresolved { position: relative; top: -2px; } .debugger-breakpoint-icon-unresolved::before { font-family: 'Octicons Regular'; font-weight: normal; font-style: normal; display: inline-block; line-height: 1; -webkit-font-smoothing: antialiased; text-decoration: none; font-size: 80%; width: 80%; height: 80%; content: "\f0e8"; } .debugger-shadow-breakpoint-icon { color: rgba(82, 147, 216, 0.4); } .debugger-current-line-highlight { background: linear-gradient(to bottom, rgba(0, 152, 255, 0.8) 0%, rgba(0, 152, 255, 0.8) 5%, rgba(0, 152, 255, 0.3) 5%, rgba(0, 152, 255, 0.3) 95%, rgba(0, 152, 255, 0.8) 95%, rgba(0, 152, 255, 0.8) 100%); } .gutter[gutter-name=diagnostics-gutter] { width: 0.7em; } .diagnostics-gutter-ui-item { display: flex; } .diagnostics-gutter-ui-item .icon { display: flex; width: 0.7em; height: 0.7em; font-size: 0.7em; align-self: center; } .diagnostics-gutter-ui-item .icon::before { width: 1em; height: 1em; font-size: 1em; margin: 0; align-self: center; } .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-info, .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-review { color: #5293d8; } .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-error { color: #c00; } .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-action, .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-warning { color: #ff982d; } .bracket-matcher .region { border-bottom: 1px dotted lime; position: absolute; } .line-number.bracket-matcher.bracket-matcher { color: #c5c8c6; background-color: rgba(255, 255, 255, 0.14); } .spell-check-misspelling .region { border-bottom: 2px dotted rgba(255, 51, 51, 0.75); } .spell-check-corrections { width: 25em !important; } pre.editor-colors { background-color: #1d1f21; color: #c5c8c6; } pre.editor-colors .invisible-character { color: rgba(197, 200, 198, 0.2); } pre.editor-colors .indent-guide { color: rgba(197, 200, 198, 0.2); } pre.editor-colors .wrap-guide { background-color: rgba(197, 200, 198, 0.1); } pre.editor-colors .gutter { background-color: #292c2f; } pre.editor-colors .gutter .cursor-line { background-color: rgba(255, 255, 255, 0.14); } pre.editor-colors .line-number.cursor-line-no-selection { background-color: rgba(255, 255, 255, 0.14); } pre.editor-colors .gutter .line-number.folded, pre.editor-colors .gutter .line-number:after, pre.editor-colors .fold-marker:after { color: #fba0e3; } pre.editor-colors .invisible { color: #c5c8c6; } pre.editor-colors .cursor { border-color: white; } pre.editor-colors .selection .region { background-color: #444; } pre.editor-colors .bracket-matcher .region { border-bottom: 1px solid #f8de7e; margin-top: -1px; opacity: .7; } .syntax--comment { color: #8a8a8a; } .syntax--entity { color: #FFD2A7; } .syntax--entity.syntax--name.syntax--type { text-decoration: underline; color: #FFFFB6; } .syntax--entity.syntax--other.syntax--inherited-class { color: #9B5C2E; } .syntax--keyword { color: #96CBFE; } .syntax--keyword.syntax--control { color: #96CBFE; } .syntax--keyword.syntax--operator { color: #EDEDED; } .syntax--storage { color: #CFCB90; } .syntax--storage.syntax--modifier { color: #96CBFE; } .syntax--constant { color: #99CC99; } .syntax--constant.syntax--numeric { color: #FF73FD; } .syntax--variable { color: #C6C5FE; } .syntax--invalid.syntax--deprecated { text-decoration: underline; color: #FD5FF1; } .syntax--invalid.syntax--illegal { color: #FD5FF1; background-color: rgba(86, 45, 86, 0.75); } .syntax--string .syntax--source, .syntax--string .syntax--meta.syntax--embedded.syntax--line { color: #EDEDED; } .syntax--string .syntax--punctuation.syntax--section.syntax--embedded { color: #00A0A0; } .syntax--string .syntax--punctuation.syntax--section.syntax--embedded .syntax--source { color: #00A0A0; } .syntax--string { color: #A8FF60; } .syntax--string .syntax--constant { color: #00A0A0; } .syntax--string.syntax--regexp { color: #E9C062; } .syntax--string.syntax--regexp .syntax--constant.syntax--character.syntax--escape, .syntax--string.syntax--regexp .syntax--source.syntax--ruby.syntax--embedded, .syntax--string.syntax--regexp .syntax--string.syntax--regexp.syntax--arbitrary-repetition { color: #FF8000; } .syntax--string.syntax--regexp.syntax--group { color: #C6A24F; background-color: rgba(255, 255, 255, 0.06); } .syntax--string.syntax--regexp.syntax--character-class { color: #B18A3D; } .syntax--string .syntax--variable { color: #8A9A95; } .syntax--support { color: #FFFFB6; } .syntax--support.syntax--function { color: #DAD085; } .syntax--support.syntax--constant { color: #FFD2A7; } .syntax--support.syntax--type.syntax--property-name.syntax--css { color: #EDEDED; } .syntax--source .syntax--entity.syntax--name.syntax--tag, .syntax--source .syntax--punctuation.syntax--tag { color: #96CBFE; } .syntax--source .syntax--entity.syntax--other.syntax--attribute-name { color: #FF73FD; } .syntax--entity.syntax--other.syntax--attribute-name { color: #FF73FD; } .syntax--entity.syntax--name.syntax--tag.syntax--namespace, .syntax--entity.syntax--other.syntax--attribute-name.syntax--namespace { color: #E18964; } .syntax--meta.syntax--preprocessor.syntax--c { color: #8996A8; } .syntax--meta.syntax--preprocessor.syntax--c .syntax--keyword { color: #AFC4DB; } .syntax--meta.syntax--cast { color: #676767; } .syntax--meta.syntax--sgml.syntax--html .syntax--meta.syntax--doctype, .syntax--meta.syntax--sgml.syntax--html .syntax--meta.syntax--doctype .syntax--entity, .syntax--meta.syntax--sgml.syntax--html .syntax--meta.syntax--doctype .syntax--string, .syntax--meta.syntax--xml-processing, .syntax--meta.syntax--xml-processing .syntax--entity, .syntax--meta.syntax--xml-processing .syntax--string { color: #8a8a8a; } .syntax--meta.syntax--tag .syntax--entity, .syntax--meta.syntax--tag>.syntax--punctuation, .syntax--meta.syntax--tag.syntax--inline .syntax--entity { color: #FF73FD; } .syntax--meta.syntax--tag .syntax--name, .syntax--meta.syntax--tag.syntax--inline .syntax--name, .syntax--meta.syntax--tag>.syntax--punctuation { color: #96CBFE; } .syntax--meta.syntax--selector.syntax--css .syntax--entity.syntax--name.syntax--tag { text-decoration: underline; color: #96CBFE; } .syntax--meta.syntax--selector.syntax--css .syntax--entity.syntax--other.syntax--attribute-name.syntax--tag.syntax--pseudo-class { color: #8F9D6A; } .syntax--meta.syntax--selector.syntax--css .syntax--entity.syntax--other.syntax--attribute-name.syntax--id { color: #8B98AB; } .syntax--meta.syntax--selector.syntax--css .syntax--entity.syntax--other.syntax--attribute-name.syntax--class { color: #62B1FE; } .syntax--meta.syntax--property-group .syntax--support.syntax--constant.syntax--property-value.syntax--css, .syntax--meta.syntax--property-value .syntax--support.syntax--constant.syntax--property-value.syntax--css { color: #F9EE98; } .syntax--meta.syntax--preprocessor.syntax--at-rule .syntax--keyword.syntax--control.syntax--at-rule { color: #8693A5; } .syntax--meta.syntax--property-value .syntax--support.syntax--constant.syntax--named-color.syntax--css, .syntax--meta.syntax--property-value .syntax--constant { color: #87C38A; } .syntax--meta.syntax--constructor.syntax--argument.syntax--css { color: #8F9D6A; } .syntax--meta.syntax--diff, .syntax--meta.syntax--diff.syntax--header { color: #F8F8F8; background-color: #0E2231; } .syntax--meta.syntax--separator { color: #60A633; background-color: #242424; } .syntax--meta.syntax--line.syntax--entry.syntax--logfile, .syntax--meta.syntax--line.syntax--exit.syntax--logfile { background-color: rgba(238, 238, 238, 0.16); } .syntax--meta.syntax--line.syntax--error.syntax--logfile { background-color: #751012; } .syntax--source.syntax--gfm { color: #999; } .syntax--gfm .syntax--markup.syntax--heading { color: #eee; } .syntax--gfm .syntax--link { color: #555; } .syntax--gfm .syntax--variable.syntax--list, .syntax--gfm .syntax--support.syntax--quote { color: #555; } .syntax--gfm .syntax--link .syntax--entity { color: #ddd; } .syntax--gfm .syntax--raw { color: #aaa; } .syntax--markdown .syntax--paragraph { color: #999; } .syntax--markdown .syntax--heading { color: #eee; } .syntax--markdown .syntax--raw { color: #aaa; } .syntax--markdown .syntax--link { color: #555; } .syntax--markdown .syntax--link .syntax--string { color: #555; } .syntax--markdown .syntax--link .syntax--string.syntax--title { color: #ddd; }eel.jsは公式githubとかから取得してください
(このコードをそのまま使うなら必要ない)参考にしたサイト
CSSで作る!押したくなるボタンデザイン100(Web用)
Python eelでファイル選択ダイアログ動作風景
exeファイル
- 投稿日:2020-02-25T18:41:37+09:00
javascriptでcontent-typeを自動で取得する方法
content-typeを自動で取得する方法を探した結果、
mime-types
を使うことにしました。前提条件
- npmがインストールされていること
インストール
$ npm i --save mime-types使い方
設定
touch
コマンドでファイルを作成します。$ touch test.jstest.js
mime-typesモジュールの読み込みと、引数にパスを入れてメソッドを使用します。const mime = require('mime-types') console.log(mime.lookup('test.json')) console.log(mime.contentType('test.json'))実行
node
コマンドでtest.jsを実行します。$ node test出力結果
application/json application/json; charset=utf-8参考文献
この記事は以下の情報を参考にして執筆しました。
- 投稿日:2020-02-25T18:24:26+09:00
俺得な備忘録
ちょっとしたTipsを留めておく俺得な記事
setInterval系
setInterval
がうまく消えてくれない!!!
=> リストを作成して消せば消える!(日本語雑だけど未来の俺わかるよね?)// インターバルをストックするメモリ. var timerList = new Array(); // インターバルをセットする関数. function funcA() { timerList.push( setInterval(() => { console.log("setInterval"); }, 100) ); } // インターバルをすべて削除する関数. function funcB() { timerList.forEach((id) => { clearInterval(id); }); }
- 投稿日:2020-02-25T17:43:31+09:00
Nuxt.jsの始め方
Nuxt.jsを始めたい方に向けて、導入の仕方をまとめます。
ライフサイクルなど細かい内容は公式ドキュメントをご確認ください。前提条件
- npmの5.2.0以降のバージョンがインストールされていること
インストール
プロジェクトディレクトリの作成
$ mkdir test && cd $_Nuxt.jsフレームワークのインストール
$ npx create-nuxt-app
開発
開発サーバーを起動
$ npm run dev
デプロイ
SSRモードでサーバーを起動
$ npm run build && npm run start静的HTML生成
$ npm run generate
その他
pug/stylusの導入
pug
pugのモジュールをインストール
$ npm i --save pug pug-loader pug-plain-loader全*.vueファイルの
template
タグにlang="pug"
を追加する<!-- <template> --> <template lang="pug">stylus
stylusのモジュールをインストール
$ npm i --save stylus stylus-loader全*.vueファイルの
style
タグにlang="stylus"
を追加する
ここの内容を他のスタイルに影響させたくない場合はscoped
も追加する/* <style> */ <style lang="stylus" scoped>storeの導入
データ定義
store用のファイルを作成
$ touch store/index.jsstore/index.js
保持しておきたいデータをstate内にcounter
という名前で定義
state内のcounter
の数値を1ずつ増やすincrement
メソッドを定義export const state = () => ({ counter: 0 }) export const mutations = { increment (state) { state.counter++ } }データへのアクセス
state内のcounterの値を取得
this.$store.state.counter出力結果
0
データの変更
mutations内のincrementメソッドを実行
this.$store.commit('increment')transitionタグ
html(pug)の定義
transition
タグを追加して、子要素はv-if
などで存在確認をさせるtransition p(v-if="show") Hello world!css(stylus)の定義
v-enter
とv-leave-to
で最初(出現時)と最後(消失時)のstyle
を定義
そのスタイルにどういうtransition
をかけるかv-enter-active
とv-leave-active
で定義.v-enter-active .v-leave-active transition opacity .5s .v-enter .v-leave-to opacity 0ページ遷移transition
html(pug)の定義
nuxt-link
タグを追加するnuxt-link(to="/test/") go to test!css(stylus)の定義
page-enter
とpage-leave-to
で最初(出現時)と最後(消失時)のstyle
を定義
そのスタイルにどういうtransition
をかけるかpage-enter-active
とpage-leave-active
で定義.page-enter-active .page-leave-active transition opacity .5s .page-enter .page-leave-to opacity 0ページ読み込み時のLoading表示
Loading用のファイルを作成
$ mkdir components/Loading && touch components/Loading/index.vuecomponents/Loading/index.vue
<template lang="pug"> .loading-page(v-if="loading") p Loading... </template> <script> export default { data: () => ({ loading: false }), methods: { start () { this.loading = true }, finish () { setTimeout(() => { this.loading = false }, 3000) } } } </script> <style lang="stylus" scoped></style>nuxt.config.js
loadingの記述を追加module.exports = { loading: '~/components/Loading/index.vue' // 追記 }テンプレートレイアウト変更
テンプレート用のファイルを作成
$ touch layouts/another.vuelayouts/another.vue
<template lang="pug"> .l-another nuxt </template> <script> export default {} </script> <style lang="stylus" scoped></style>*.vue
layoutのカスタム読み込みをする記述を追加export default { layout: 'another', // 追記 }エラーページ
エラー用のファイルを作成
$ touch layouts/error.vuelayouts/error.vue
<template lang="pug"> .container h1(v-if="error.statusCode === 404") ページが見つかりません h1(v-else) エラーが発生しました nuxt-link(to="/") ホーム </template> <script> export default { props: { error: { type: Object, default: null } } } </script> <style lang="stylus" scoped></style>コンソールの削除
nuxt.config.js
build内にdrop_consoleの記述を追加module.exports = { build: { terser: { terserOptions: { compress: { drop_console: true } } } } }作業ディレクトリをまとめる
作業ディレクトリの作成、移動
$ mkdir src && mv assets components layouts pages plugins static store middleware src/nuxt.config.js
srcDirの記述を追加するmodule.exports = { srcDir: 'src/', // 追記 }参考文献
この記事は以下の情報を参考にして執筆しました。
- 投稿日:2020-02-25T16:12:48+09:00
PHPer脳の人がJavaScriptでループを回す
毎回for文書くたびに調べてるので
配列のforeach
phpだとこんな感じのやつ
$array = [1, 2, 3]; foreach($array as $a){ echo $a; } // 1 // 2 // 3jsだとこう
const array = [1, 2, 3]; for(let a of array){ console.log(a); } // 1 // 2 // 3連想配列のforeach
phpだとこんな感じのやつ
$array_assoc = [ 1 => 'one', 2 => 'two', 3 => 'three' ]; foreach($array_assoc as $k => $v){ echo $k . ' is ' . $v . "\n"; } // 1 is one // 2 is two // 3 is threejsだとこう
const array_assoc = { 1 : 'one', 2 : 'two', 3 : 'three' }; for(let [k, v] of Object.entries(array_assoc)){ console.log(k + ' is ' + v + "\n"); } // 1 is one // 2 is two // 3 is three※まあ、jsのObjectは正確には連想配列ではないけど
- 投稿日:2020-02-25T14:46:29+09:00
pythonで生徒を当てるアプリをつくる-GUI版
はじめに
以前投稿したpythonで生徒を当てるアプリをつくるをGUIソフトにしたってだけの記事.
プログラム
main.py data/ history.txt list.txt list_raw.txt web/ main.html css/ style.css js/ eel.js
main.py
main.pyimport locale import eel import random import pickle import os import sys import datetime from tkinter import filedialog, Tk import platform import copy def main(): eel.init("web") eel.start("main.html") Student_names = [] Student_FILENAME = "./data/list.txt" Student_FILENAME_raw = "./data/list_raw.txt" # Student @eel.expose def Student_load(): with open(select_file(), "r") as f: global Student_names Student_names = f.read().splitlines() Student_save(Student_FILENAME) Student_save(Student_FILENAME_raw) @eel.expose def Student_reset(): Student_names_load(Student_FILENAME_raw) @eel.expose def Student_show(): Student_names_load(Student_FILENAME) name_ls = "" a = 1 for name in Student_names: if a % 5 == 0: name_ls = name_ls + name + "<br>" else: name_ls = name_ls + name + " " a += 1 return name_ls @eel.expose def Student_choice(): Student_names_load(Student_FILENAME) global Student_names_raw Student_names_raw = copy.deepcopy(Student_names) if not Student_names: return global name name = random.choice(Student_names) Student_names.remove(name) if Student_names == []: Student_names_load(Student_FILENAME_raw) History_add(name) Student_save(Student_FILENAME) return name @eel.expose def Student_save(FILENAME): f = open(FILENAME, 'wb') pickle.dump(Student_names, f) @eel.expose def Student_names_load(FILENAME): f = open(FILENAME, "rb") global Student_names Student_names = pickle.load(f) # History History_FILENAME = "./data/history.txt" History_data = [] @eel.expose def History_load(): with open(History_FILENAME, "r") as f: global History_data History_data = f.read().splitlines() @eel.expose def History_save(): with open(History_FILENAME, "w") as f: for history in History_data: print(history, file=f) @eel.expose def History_show(): history_ls = "" History_load() for history in History_data: history_ls = history + "<br>" + history_ls return history_ls locale.setlocale(locale.LC_ALL, '') @eel.expose def History_add(name): now = datetime.datetime.now() History_data.append(f"{now:%m月%d日}:{name}") History_save() @eel.expose def History_cancel(): History_data.pop() History_save() global Student_names Student_names = copy.deepcopy(Student_names_raw) Student_save(Student_FILENAME) @eel.expose def History_clear(): global History_data History_data = [] History_save() # 名簿読み込み # ダイアログ用のルートウィンドウの作成 # (root自体はeelのウィンドウとは関係ないので非表示にしておくのが望ましい) root = Tk() # ウィンドウサイズを0にする root.geometry("0x0") # ウィンドウのタイトルバーを消す root.overrideredirect(1) # ウィンドウを非表示に root.withdraw() system = platform.system() @eel.expose def select_file(): # Windowsの場合withdrawの状態だとダイアログも # 非表示になるため、rootウィンドウを表示する if system == "Windows": root.deiconify() # macOS用にダイアログ作成前後でupdate()を呼ぶ root.update() # ダイアログを前面に # topmost指定(最前面) root.attributes('-topmost', True) root.withdraw() root.lift() root.focus_force() path_str = filedialog.askopenfilename() root.update() if system == "Windows": # 再度非表示化(Windowsのみ) root.withdraw() #path = Path(path_str) return path_str if __name__ == '__main__': main()
main.html
main.html<html> <head> <meta charset="UTF-8"> <title>生徒当てるヤツ</title> <link rel="stylesheet" type="text/css" href="./css/style.css"> <script type="text/javascript" src="/eel.js"></script> <script type="text/javascript"> async function Student_choice() { var demo2 = document.getElementById("div0"); demo2.innerHTML = ""; div0.insertAdjacentHTML('afterbegin', '<div id="name"></div>'); let val = await eel.Student_choice()(); var doc0 = document.getElementById("name"); doc0.innerHTML = val; } async function Student_load() { eel.Student_load(); } async function Student_show() { let val = await eel.Student_show()(); var doc0 = document.getElementById("div0"); doc0.innerHTML = val; } async function History_show() { let val = await eel.History_show()(); var doc0 = document.getElementById("div0"); doc0.innerHTML = val; } async function History_clear() { let val = await eel.History_clear()(); var doc0 = document.getElementById("div0"); doc0.innerHTML = val; } async function History_cancel() { let val = await eel.History_cancel()(); var doc0 = document.getElementById("div0"); doc0.innerHTML = val; } </script> </head> <body> <center> <div id="div0"> </div> <div class="bottom"> <a href="#" onclick="Student_choice()" class="btn-square">生徒を当てる</a> <a href="#" onclick="History_cancel()" class="btn-square">欠席者を飛ばす</a> <a href="#" onclick="Student_show()" class="btn-square">残りの生徒を表示</a> <a href="#" onclick="History_show()" class="btn-square">履歴の表示</a> <a href="#" onclick="History_clear()" class="btn-square">履歴の消去</a> <a href="#" onclick="Student_load()" class="btn-square">名簿を更新</a> </div> </center> <div class='markdown-preview' data-use-github-style> <details> <summary>名簿の更新方法</summary> <div> <h1 id="名簿の更新方法">名簿の更新方法</h1> <h3 id="1">1</h3> <p>任意のファイル名のテキストファイル(*.txt)を作成します.</p> <h3 id="2">2</h3> <p>その中に<br> 1.名前<br> 2.名前<br> ・<br> ・<br> ・<br> と入力します.</p> <h3 id="3">3</h3> <p>名簿を更新をクリックし,テキストファイルを選択する.</p> </div> </details> </div> </html>
style.css
style.css.btn-square { display: inline-block; padding: 0.5em 1em; text-decoration: none; background: #668ad8; /*ボタン色*/ color: #FFF; border-bottom: solid 4px #627295; border-radius: 3px; } .btn-square:active { /*ボタンを押したとき*/ -webkit-transform: translateY(4px); transform: translateY(4px); /*下に動く*/ border-bottom: none; /*線を消す*/ } #div0 { height: 300px; overflow: scroll; } #name { margin-top: 50px; font-size: 100px; } .bottom {} .markdown-preview:not([data-use-github-style]) { padding: 2em; font-size: 1.2em; color: rgb(197, 200, 198); background-color: rgb(29, 31, 33); overflow: auto; } .markdown-preview:not([data-use-github-style])> :first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-preview:not([data-use-github-style]) h2, .markdown-preview:not([data-use-github-style]) h3, .markdown-preview:not([data-use-github-style]) h4, .markdown-preview:not([data-use-github-style]) h5, .markdown-preview:not([data-use-github-style]) h6 { line-height: 1.2; margin-top: 1.5em; margin-bottom: 0.5em; color: rgb(255, 255, 255); } .markdown-preview:not([data-use-github-style]) h1 { font-size: 2.4em; font-weight: 300; } .markdown-preview:not([data-use-github-style]) h2 { font-size: 1.8em; font-weight: 400; } .markdown-preview:not([data-use-github-style]) h3 { font-size: 1.5em; font-weight: 500; } .markdown-preview:not([data-use-github-style]) h4 { font-size: 1.2em; font-weight: 600; } .markdown-preview:not([data-use-github-style]) h5 { font-size: 1.1em; font-weight: 600; } .markdown-preview:not([data-use-github-style]) h6 { font-size: 1em; font-weight: 600; } .markdown-preview:not([data-use-github-style]) strong { color: rgb(255, 255, 255); } .markdown-preview:not([data-use-github-style]) del { color: rgb(155, 160, 157); } .markdown-preview:not([data-use-github-style]) a, .markdown-preview:not([data-use-github-style]) a code { color: white; } .markdown-preview:not([data-use-github-style]) img { max-width: 100%; } .markdown-preview:not([data-use-github-style])>p { margin-top: 0px; margin-bottom: 1.5em; } .markdown-preview:not([data-use-github-style])>ul, .markdown-preview:not([data-use-github-style])>ol { margin-bottom: 1.5em; } .markdown-preview:not([data-use-github-style]) blockquote { margin: 1.5em 0px; font-size: inherit; color: rgb(155, 160, 157); border-color: rgb(67, 72, 76); border-width: 4px; } .markdown-preview:not([data-use-github-style]) hr { margin: 3em 0px; border-top: 2px dashed rgb(67, 72, 76); background: none; } .markdown-preview:not([data-use-github-style]) table { margin: 1.5em 0px; } .markdown-preview:not([data-use-github-style]) th { color: rgb(255, 255, 255); } .markdown-preview:not([data-use-github-style]) th, .markdown-preview:not([data-use-github-style]) td { padding: 0.66em 1em; border: 1px solid rgb(67, 72, 76); } .markdown-preview:not([data-use-github-style]) code { color: rgb(255, 255, 255); background-color: rgb(48, 51, 55); } .markdown-preview:not([data-use-github-style]) pre.editor-colors { margin: 1.5em 0px; padding: 1em; font-size: 0.92em; border-radius: 3px; background-color: rgb(39, 41, 44); } .markdown-preview:not([data-use-github-style]) kbd { color: rgb(255, 255, 255); border-width: 1px 1px 2px; border-style: solid; border-color: rgb(67, 72, 76) rgb(67, 72, 76) rgb(53, 57, 60); border-image: initial; background-color: rgb(48, 51, 55); } .markdown-preview[data-use-github-style] { font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif; line-height: 1.6; overflow-wrap: break-word; padding: 30px; font-size: 16px; color: rgb(51, 51, 51); background-color: rgb(255, 255, 255); } .markdown-preview[data-use-github-style]> :first-child { margin-top: 0px !important; } .markdown-preview[data-use-github-style]> :last-child { margin-bottom: 0px !important; } .markdown-preview[data-use-github-style] a:not([href]) { color: inherit; text-decoration: none; } .markdown-preview[data-use-github-style] .absent { color: rgb(204, 0, 0); } .markdown-preview[data-use-github-style] .anchor { position: absolute; top: 0px; left: 0px; display: block; padding-right: 6px; padding-left: 30px; margin-left: -30px; } .markdown-preview[data-use-github-style] .anchor:focus { outline: none; } .markdown-preview[data-use-github-style] h1, .markdown-preview[data-use-github-style] h2, .markdown-preview[data-use-github-style] h3, .markdown-preview[data-use-github-style] h4, .markdown-preview[data-use-github-style] h5, .markdown-preview[data-use-github-style] h6 { position: relative; margin-top: 1em; margin-bottom: 16px; font-weight: bold; line-height: 1.4; } .markdown-preview[data-use-github-style] h1 .octicon-link, .markdown-preview[data-use-github-style] h2 .octicon-link, .markdown-preview[data-use-github-style] h3 .octicon-link, .markdown-preview[data-use-github-style] h4 .octicon-link, .markdown-preview[data-use-github-style] h5 .octicon-link, .markdown-preview[data-use-github-style] h6 .octicon-link { display: none; color: rgb(0, 0, 0); vertical-align: middle; } .markdown-preview[data-use-github-style] h1:hover .anchor, .markdown-preview[data-use-github-style] h2:hover .anchor, .markdown-preview[data-use-github-style] h3:hover .anchor, .markdown-preview[data-use-github-style] h4:hover .anchor, .markdown-preview[data-use-github-style] h5:hover .anchor, .markdown-preview[data-use-github-style] h6:hover .anchor { padding-left: 8px; margin-left: -30px; text-decoration: none; } .markdown-preview[data-use-github-style] h1:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h2:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h3:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h4:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h5:hover .anchor .octicon-link, .markdown-preview[data-use-github-style] h6:hover .anchor .octicon-link { display: inline-block; } .markdown-preview[data-use-github-style] h1 tt, .markdown-preview[data-use-github-style] h2 tt, .markdown-preview[data-use-github-style] h3 tt, .markdown-preview[data-use-github-style] h4 tt, .markdown-preview[data-use-github-style] h5 tt, .markdown-preview[data-use-github-style] h6 tt, .markdown-preview[data-use-github-style] h1 code, .markdown-preview[data-use-github-style] h2 code, .markdown-preview[data-use-github-style] h3 code, .markdown-preview[data-use-github-style] h4 code, .markdown-preview[data-use-github-style] h5 code, .markdown-preview[data-use-github-style] h6 code { font-size: inherit; } .markdown-preview[data-use-github-style] h1 { padding-bottom: 0.3em; font-size: 2.25em; line-height: 1.2; border-bottom: 1px solid rgb(238, 238, 238); } .markdown-preview[data-use-github-style] h1 .anchor { line-height: 1; } .markdown-preview[data-use-github-style] h2 { padding-bottom: 0.3em; font-size: 1.75em; line-height: 1.225; border-bottom: 1px solid rgb(238, 238, 238); } .markdown-preview[data-use-github-style] h2 .anchor { line-height: 1; } .markdown-preview[data-use-github-style] h3 { font-size: 1.5em; line-height: 1.43; } .markdown-preview[data-use-github-style] h3 .anchor { line-height: 1.2; } .markdown-preview[data-use-github-style] h4 { font-size: 1.25em; } .markdown-preview[data-use-github-style] h4 .anchor { line-height: 1.2; } .markdown-preview[data-use-github-style] h5 { font-size: 1em; } .markdown-preview[data-use-github-style] h5 .anchor { line-height: 1.1; } .markdown-preview[data-use-github-style] h6 { font-size: 1em; color: rgb(119, 119, 119); } .markdown-preview[data-use-github-style] h6 .anchor { line-height: 1.1; } .markdown-preview[data-use-github-style] p, .markdown-preview[data-use-github-style] blockquote, .markdown-preview[data-use-github-style] ul, .markdown-preview[data-use-github-style] ol, .markdown-preview[data-use-github-style] dl, .markdown-preview[data-use-github-style] table, .markdown-preview[data-use-github-style] pre { margin-top: 0px; margin-bottom: 16px; } .markdown-preview[data-use-github-style] hr { height: 4px; padding: 0px; margin: 16px 0px; background-color: rgb(231, 231, 231); border: 0px none; } .markdown-preview[data-use-github-style] ul, .markdown-preview[data-use-github-style] ol { padding-left: 2em; } .markdown-preview[data-use-github-style] ul.no-list, .markdown-preview[data-use-github-style] ol.no-list { padding: 0px; list-style-type: none; } .markdown-preview[data-use-github-style] ul ul, .markdown-preview[data-use-github-style] ul ol, .markdown-preview[data-use-github-style] ol ol, .markdown-preview[data-use-github-style] ol ul { margin-top: 0px; margin-bottom: 0px; } .markdown-preview[data-use-github-style] li>p { margin-top: 16px; } .markdown-preview[data-use-github-style] dl { padding: 0px; } .markdown-preview[data-use-github-style] dl dt { padding: 0px; margin-top: 16px; font-size: 1em; font-style: italic; font-weight: bold; } .markdown-preview[data-use-github-style] dl dd { padding: 0px 16px; margin-bottom: 16px; } .markdown-preview[data-use-github-style] blockquote { padding: 0px 15px; color: rgb(119, 119, 119); border-left: 4px solid rgb(221, 221, 221); } .markdown-preview[data-use-github-style] blockquote> :first-child { margin-top: 0px; } .markdown-preview[data-use-github-style] blockquote> :last-child { margin-bottom: 0px; } .markdown-preview[data-use-github-style] table { display: block; width: 100%; overflow: auto; word-break: keep-all; } .markdown-preview[data-use-github-style] table th { font-weight: bold; } .markdown-preview[data-use-github-style] table th, .markdown-preview[data-use-github-style] table td { padding: 6px 13px; border: 1px solid rgb(221, 221, 221); } .markdown-preview[data-use-github-style] table tr { background-color: rgb(255, 255, 255); border-top: 1px solid rgb(204, 204, 204); } .markdown-preview[data-use-github-style] table tr:nth-child(2n) { background-color: rgb(248, 248, 248); } .markdown-preview[data-use-github-style] img { max-width: 100%; box-sizing: border-box; } .markdown-preview[data-use-github-style] .emoji { max-width: none; } .markdown-preview[data-use-github-style] span.frame { display: block; overflow: hidden; } .markdown-preview[data-use-github-style] span.frame>span { display: block; float: left; width: auto; padding: 7px; margin: 13px 0px 0px; overflow: hidden; border: 1px solid rgb(221, 221, 221); } .markdown-preview[data-use-github-style] span.frame span img { display: block; float: left; } .markdown-preview[data-use-github-style] span.frame span span { display: block; padding: 5px 0px 0px; clear: both; color: rgb(51, 51, 51); } .markdown-preview[data-use-github-style] span.align-center { display: block; overflow: hidden; clear: both; } .markdown-preview[data-use-github-style] span.align-center>span { display: block; margin: 13px auto 0px; overflow: hidden; text-align: center; } .markdown-preview[data-use-github-style] span.align-center span img { margin: 0px auto; text-align: center; } .markdown-preview[data-use-github-style] span.align-right { display: block; overflow: hidden; clear: both; } .markdown-preview[data-use-github-style] span.align-right>span { display: block; margin: 13px 0px 0px; overflow: hidden; text-align: right; } .markdown-preview[data-use-github-style] span.align-right span img { margin: 0px; text-align: right; } .markdown-preview[data-use-github-style] span.float-left { display: block; float: left; margin-right: 13px; overflow: hidden; } .markdown-preview[data-use-github-style] span.float-left span { margin: 13px 0px 0px; } .markdown-preview[data-use-github-style] span.float-right { display: block; float: right; margin-left: 13px; overflow: hidden; } .markdown-preview[data-use-github-style] span.float-right>span { display: block; margin: 13px auto 0px; overflow: hidden; text-align: right; } .markdown-preview[data-use-github-style] code, .markdown-preview[data-use-github-style] tt { padding: 0.2em 0px; margin: 0px; font-size: 85%; background-color: rgba(0, 0, 0, 0.04); border-radius: 3px; } .markdown-preview[data-use-github-style] code::before, .markdown-preview[data-use-github-style] tt::before, .markdown-preview[data-use-github-style] code::after, .markdown-preview[data-use-github-style] tt::after { letter-spacing: -0.2em; content: " "; } .markdown-preview[data-use-github-style] code br, .markdown-preview[data-use-github-style] tt br { display: none; } .markdown-preview[data-use-github-style] del code { text-decoration: inherit; } .markdown-preview[data-use-github-style] pre>code { padding: 0px; margin: 0px; font-size: 100%; word-break: normal; white-space: pre; background: transparent; border: 0px; } .markdown-preview[data-use-github-style] .highlight { margin-bottom: 16px; } .markdown-preview[data-use-github-style] .highlight pre, .markdown-preview[data-use-github-style] pre { padding: 16px; overflow: auto; font-size: 85%; line-height: 1.45; background-color: rgb(247, 247, 247); border-radius: 3px; } .markdown-preview[data-use-github-style] .highlight pre { margin-bottom: 0px; word-break: normal; } .markdown-preview[data-use-github-style] pre { overflow-wrap: normal; } .markdown-preview[data-use-github-style] pre code, .markdown-preview[data-use-github-style] pre tt { display: inline; max-width: initial; padding: 0px; margin: 0px; overflow: initial; line-height: inherit; overflow-wrap: normal; background-color: transparent; border: 0px; } .markdown-preview[data-use-github-style] pre code::before, .markdown-preview[data-use-github-style] pre tt::before, .markdown-preview[data-use-github-style] pre code::after, .markdown-preview[data-use-github-style] pre tt::after { content: normal; } .markdown-preview[data-use-github-style] kbd { display: inline-block; padding: 3px 5px; font-size: 11px; line-height: 10px; color: rgb(85, 85, 85); vertical-align: middle; background-color: rgb(252, 252, 252); border-width: 1px; border-style: solid; border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(187, 187, 187); border-image: initial; border-radius: 3px; box-shadow: rgb(187, 187, 187) 0px -1px 0px inset; } .markdown-preview[data-use-github-style] a { color: rgb(51, 122, 183); } .markdown-preview[data-use-github-style] code { color: inherit; } .markdown-preview[data-use-github-style] pre.editor-colors { padding: 0.8em 1em; margin-bottom: 1em; font-size: 0.85em; border-radius: 4px; overflow: auto; } .markdown-preview pre.editor-colors { user-select: auto; } .scrollbars-visible-always .markdown-preview pre.editor-colors .vertical-scrollbar, .scrollbars-visible-always .markdown-preview pre.editor-colors .horizontal-scrollbar { visibility: hidden; } .scrollbars-visible-always .markdown-preview pre.editor-colors:hover .vertical-scrollbar, .scrollbars-visible-always .markdown-preview pre.editor-colors:hover .horizontal-scrollbar { visibility: visible; } .markdown-preview .task-list-item input[type="checkbox"] { position: absolute; margin: 0.25em 0px 0px -1.4em; } .markdown-preview .task-list-item { list-style-type: none; } .markdown-preview code { text-shadow: none; } @keyframes RotatingBackground { 0% { background-position-x: 0%; } 100% { background-position-x: 100%; } } .debugger-breakpoint-icon::before, .debugger-shadow-breakpoint-icon::before { font-family: 'Octicons Regular'; font-weight: normal; font-style: normal; display: inline-block; line-height: 1; -webkit-font-smoothing: antialiased; text-decoration: none; font-size: 130%; width: 130%; height: 130%; content: "\f052"; } .debugger-breakpoint-icon, .debugger-breakpoint-icon-disabled, .debugger-breakpoint-icon-unresolved, .debugger-breakpoint-icon-conditional, .debugger-shadow-breakpoint-icon { text-align: center; display: block; width: 0.8em; cursor: pointer; } .debugger-breakpoint-icon-nonconditional { color: #5293d8; } .debugger-breakpoint-icon-conditional { color: #ff982d; } .debugger-breakpoint-icon-disabled { position: relative; top: -4px; left: 2px; } .debugger-breakpoint-icon-disabled::before { font-family: 'Octicons Regular'; font-weight: normal; font-style: normal; display: inline-block; line-height: 1; -webkit-font-smoothing: antialiased; text-decoration: none; font-size: 78%; width: 78%; height: 78%; content: "\f084"; } .debugger-breakpoint-icon-unresolved { position: relative; top: -2px; } .debugger-breakpoint-icon-unresolved::before { font-family: 'Octicons Regular'; font-weight: normal; font-style: normal; display: inline-block; line-height: 1; -webkit-font-smoothing: antialiased; text-decoration: none; font-size: 80%; width: 80%; height: 80%; content: "\f0e8"; } .debugger-shadow-breakpoint-icon { color: rgba(82, 147, 216, 0.4); } .debugger-current-line-highlight { background: linear-gradient(to bottom, rgba(0, 152, 255, 0.8) 0%, rgba(0, 152, 255, 0.8) 5%, rgba(0, 152, 255, 0.3) 5%, rgba(0, 152, 255, 0.3) 95%, rgba(0, 152, 255, 0.8) 95%, rgba(0, 152, 255, 0.8) 100%); } .gutter[gutter-name=diagnostics-gutter] { width: 0.7em; } .diagnostics-gutter-ui-item { display: flex; } .diagnostics-gutter-ui-item .icon { display: flex; width: 0.7em; height: 0.7em; font-size: 0.7em; align-self: center; } .diagnostics-gutter-ui-item .icon::before { width: 1em; height: 1em; font-size: 1em; margin: 0; align-self: center; } .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-info, .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-review { color: #5293d8; } .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-error { color: #c00; } .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-action, .diagnostics-gutter-ui-item.diagnostics-gutter-ui-gutter-warning { color: #ff982d; } .bracket-matcher .region { border-bottom: 1px dotted lime; position: absolute; } .line-number.bracket-matcher.bracket-matcher { color: #c5c8c6; background-color: rgba(255, 255, 255, 0.14); } .spell-check-misspelling .region { border-bottom: 2px dotted rgba(255, 51, 51, 0.75); } .spell-check-corrections { width: 25em !important; } pre.editor-colors { background-color: #1d1f21; color: #c5c8c6; } pre.editor-colors .invisible-character { color: rgba(197, 200, 198, 0.2); } pre.editor-colors .indent-guide { color: rgba(197, 200, 198, 0.2); } pre.editor-colors .wrap-guide { background-color: rgba(197, 200, 198, 0.1); } pre.editor-colors .gutter { background-color: #292c2f; } pre.editor-colors .gutter .cursor-line { background-color: rgba(255, 255, 255, 0.14); } pre.editor-colors .line-number.cursor-line-no-selection { background-color: rgba(255, 255, 255, 0.14); } pre.editor-colors .gutter .line-number.folded, pre.editor-colors .gutter .line-number:after, pre.editor-colors .fold-marker:after { color: #fba0e3; } pre.editor-colors .invisible { color: #c5c8c6; } pre.editor-colors .cursor { border-color: white; } pre.editor-colors .selection .region { background-color: #444; } pre.editor-colors .bracket-matcher .region { border-bottom: 1px solid #f8de7e; margin-top: -1px; opacity: .7; } .syntax--comment { color: #8a8a8a; } .syntax--entity { color: #FFD2A7; } .syntax--entity.syntax--name.syntax--type { text-decoration: underline; color: #FFFFB6; } .syntax--entity.syntax--other.syntax--inherited-class { color: #9B5C2E; } .syntax--keyword { color: #96CBFE; } .syntax--keyword.syntax--control { color: #96CBFE; } .syntax--keyword.syntax--operator { color: #EDEDED; } .syntax--storage { color: #CFCB90; } .syntax--storage.syntax--modifier { color: #96CBFE; } .syntax--constant { color: #99CC99; } .syntax--constant.syntax--numeric { color: #FF73FD; } .syntax--variable { color: #C6C5FE; } .syntax--invalid.syntax--deprecated { text-decoration: underline; color: #FD5FF1; } .syntax--invalid.syntax--illegal { color: #FD5FF1; background-color: rgba(86, 45, 86, 0.75); } .syntax--string .syntax--source, .syntax--string .syntax--meta.syntax--embedded.syntax--line { color: #EDEDED; } .syntax--string .syntax--punctuation.syntax--section.syntax--embedded { color: #00A0A0; } .syntax--string .syntax--punctuation.syntax--section.syntax--embedded .syntax--source { color: #00A0A0; } .syntax--string { color: #A8FF60; } .syntax--string .syntax--constant { color: #00A0A0; } .syntax--string.syntax--regexp { color: #E9C062; } .syntax--string.syntax--regexp .syntax--constant.syntax--character.syntax--escape, .syntax--string.syntax--regexp .syntax--source.syntax--ruby.syntax--embedded, .syntax--string.syntax--regexp .syntax--string.syntax--regexp.syntax--arbitrary-repetition { color: #FF8000; } .syntax--string.syntax--regexp.syntax--group { color: #C6A24F; background-color: rgba(255, 255, 255, 0.06); } .syntax--string.syntax--regexp.syntax--character-class { color: #B18A3D; } .syntax--string .syntax--variable { color: #8A9A95; } .syntax--support { color: #FFFFB6; } .syntax--support.syntax--function { color: #DAD085; } .syntax--support.syntax--constant { color: #FFD2A7; } .syntax--support.syntax--type.syntax--property-name.syntax--css { color: #EDEDED; } .syntax--source .syntax--entity.syntax--name.syntax--tag, .syntax--source .syntax--punctuation.syntax--tag { color: #96CBFE; } .syntax--source .syntax--entity.syntax--other.syntax--attribute-name { color: #FF73FD; } .syntax--entity.syntax--other.syntax--attribute-name { color: #FF73FD; } .syntax--entity.syntax--name.syntax--tag.syntax--namespace, .syntax--entity.syntax--other.syntax--attribute-name.syntax--namespace { color: #E18964; } .syntax--meta.syntax--preprocessor.syntax--c { color: #8996A8; } .syntax--meta.syntax--preprocessor.syntax--c .syntax--keyword { color: #AFC4DB; } .syntax--meta.syntax--cast { color: #676767; } .syntax--meta.syntax--sgml.syntax--html .syntax--meta.syntax--doctype, .syntax--meta.syntax--sgml.syntax--html .syntax--meta.syntax--doctype .syntax--entity, .syntax--meta.syntax--sgml.syntax--html .syntax--meta.syntax--doctype .syntax--string, .syntax--meta.syntax--xml-processing, .syntax--meta.syntax--xml-processing .syntax--entity, .syntax--meta.syntax--xml-processing .syntax--string { color: #8a8a8a; } .syntax--meta.syntax--tag .syntax--entity, .syntax--meta.syntax--tag>.syntax--punctuation, .syntax--meta.syntax--tag.syntax--inline .syntax--entity { color: #FF73FD; } .syntax--meta.syntax--tag .syntax--name, .syntax--meta.syntax--tag.syntax--inline .syntax--name, .syntax--meta.syntax--tag>.syntax--punctuation { color: #96CBFE; } .syntax--meta.syntax--selector.syntax--css .syntax--entity.syntax--name.syntax--tag { text-decoration: underline; color: #96CBFE; } .syntax--meta.syntax--selector.syntax--css .syntax--entity.syntax--other.syntax--attribute-name.syntax--tag.syntax--pseudo-class { color: #8F9D6A; } .syntax--meta.syntax--selector.syntax--css .syntax--entity.syntax--other.syntax--attribute-name.syntax--id { color: #8B98AB; } .syntax--meta.syntax--selector.syntax--css .syntax--entity.syntax--other.syntax--attribute-name.syntax--class { color: #62B1FE; } .syntax--meta.syntax--property-group .syntax--support.syntax--constant.syntax--property-value.syntax--css, .syntax--meta.syntax--property-value .syntax--support.syntax--constant.syntax--property-value.syntax--css { color: #F9EE98; } .syntax--meta.syntax--preprocessor.syntax--at-rule .syntax--keyword.syntax--control.syntax--at-rule { color: #8693A5; } .syntax--meta.syntax--property-value .syntax--support.syntax--constant.syntax--named-color.syntax--css, .syntax--meta.syntax--property-value .syntax--constant { color: #87C38A; } .syntax--meta.syntax--constructor.syntax--argument.syntax--css { color: #8F9D6A; } .syntax--meta.syntax--diff, .syntax--meta.syntax--diff.syntax--header { color: #F8F8F8; background-color: #0E2231; } .syntax--meta.syntax--separator { color: #60A633; background-color: #242424; } .syntax--meta.syntax--line.syntax--entry.syntax--logfile, .syntax--meta.syntax--line.syntax--exit.syntax--logfile { background-color: rgba(238, 238, 238, 0.16); } .syntax--meta.syntax--line.syntax--error.syntax--logfile { background-color: #751012; } .syntax--source.syntax--gfm { color: #999; } .syntax--gfm .syntax--markup.syntax--heading { color: #eee; } .syntax--gfm .syntax--link { color: #555; } .syntax--gfm .syntax--variable.syntax--list, .syntax--gfm .syntax--support.syntax--quote { color: #555; } .syntax--gfm .syntax--link .syntax--entity { color: #ddd; } .syntax--gfm .syntax--raw { color: #aaa; } .syntax--markdown .syntax--paragraph { color: #999; } .syntax--markdown .syntax--heading { color: #eee; } .syntax--markdown .syntax--raw { color: #aaa; } .syntax--markdown .syntax--link { color: #555; } .syntax--markdown .syntax--link .syntax--string { color: #555; } .syntax--markdown .syntax--link .syntax--string.syntax--title { color: #ddd; }eel.jsは公式githubとかから取得してください
参考にしたサイト
CSSで作る!押したくなるボタンデザイン100(Web用)
Python eelでファイル選択ダイアログ動作風景
exeファイル
- 投稿日:2020-02-25T13:30:18+09:00
URLのみ書かれたファイルからランダムにURLを10個抽出するPGM
改行で区切られたURLのみ書かれたファイルを読みだしてランダムに10個抽出するPGM(JavaScript)です
参考にしたサイト
【JavaScript入門】乱数の作り方(範囲指定/重複なし/ランダム文字列) | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト
githubURL:https://github.com/NanjoMiyako/RandomURLExtract
サンプルページURL:https://nanjomiyako.github.io/RandomURLExtract/
出力画像例:
- 投稿日:2020-02-25T13:27:28+09:00
OwlCarousel2でスムーススライドショー
OwlCarousel2 2.3.4 (https://owlcarousel2.github.io/OwlCarousel2/)
を使った複数枚のスライドショーで、
デフォルトでは、1枚ずつ、画像端に来ると一時停止するようになっており、
要件では、一時停止せず、リニアに動かしたい要望があった。リニアで調べると、オプションのslideTransitionにLinearを指定すると良いらしい。
slideTransition: 'linear',しかし、うまく行かない。
さらに調べると、下記にあたった。
https://codepen.io/osingh/pen/wOqrPX
実装済みのようで、ちゃんと思った通りの動きをしていた。
しかし、実際おなじオプションを当ててみると、
うごきがおかしい。さらに調べた際、
スムーズ ということばがおもいついたので、
それを調べると、Github内のページにあたった。
https://github.com/OwlCarousel2/OwlCarousel2/issues/296読み進めると、一番最後に、一番知りたい内容が書かれていた。
https://github.com/OwlCarousel2/OwlCarousel2/issues/296#issuecomment-400703465つまり、
autoplay : true, slideTransition: 'linear', autoplayTimeout : 4000, autoplaySpeed : 400autoplayTimeoutとautoplaySpeedを同値、
もしくは、autoplaySpeedの方を大きくするとのこと。
これにより、やりたいことが無事に実装できた。
- 投稿日:2020-02-25T12:59:57+09:00
【JavaScript】this
下記のようなクラスがあるとします。
class Person { constructor(name,age) { this.name = name this.age = age } hello() { console.log(`my name is = ${this.name}. ${this.age} years old.`) }関数内でthisを呼び出す場合、下記のような書き方だとTypeError: this.hello is not a functionとなりエラーになります。
remember(){ setTimeout(function() { this.hello(); }, 1000); }JavaScriptでは、関数内のthisは関数自体を指すため、hello()なんてないですよと怒られている状態です。
そのため、一度別の定数に退避させる必要があります。remember(){ const self = this setTimeout(function() { self.hello(); }, 1000); }一度退避することで、呼びたいthisを正しく呼び出すことができます。
thisを退避させずに呼び出すには、bindメソッドを使います。
remember2(){ // self = thisが不要 setTimeout(function() { this.hello(); }.bind(this), 1000); }bindは束縛という意味です。
また、アロー関数にしてしまうとさらに短縮できます。
remember3() { // self=thisが不要 setTimeout(()=>{ this.hello(); }, 1000); }
- 投稿日:2020-02-25T12:50:36+09:00
スクロールを一番下にもっていきたい(JavaScript)
- 投稿日:2020-02-25T11:14:34+09:00
顔認識していろんなリップを試せるアプリの開発と挫折
概要
作ったものはこちら(https://touchlip.koatech.info/)
対面カメラやアップロードした画像に対し、色々なリップを合わせることができます。
こういったソリューションはPerfect社さんが圧倒的ですが、再発明してみました。Perfectさんの製品は、CHANELのサイトを見ていただければ明らかですが、ラメやマット感など、リップによって異なる質感をうまく再現しています。僕が作ったのは残念ながら色を塗るだけです。
face-api.jsを使って顔認識も描画も全部クライアントサイドで完結しています。
Netlifyの無料枠がまだまだ余裕なので運用コストも無料です。以下、頑張ったところをメモ。
リップを塗る処理
- 顔認識して顔のパーツのランドマークを取る
どこにLandmarksのindex何番が表示されているのかを特定する
どうlandmarksを繋げば綺麗に唇を描けるかを特定する
canvas上で線を結んで塗りつぶす
1はface-api.jsがやってくれるので2以降を自力で作る必要があります。
const mouthLandmarks = [ {x: 275.4868933089642, y: 330.9715563375305}, {x: 282.46803207477615, y: 325.7225076276611}, {x: 292.1396419831185, y: 320.55676439588774}, {x: 299.4580142327218, y: 321.12185386007536}, {x: 306.25136206826255, y: 317.9190892297577}, {x: 321.9393919535546, y: 321.63006702249754}, {x: 337.6620153017907, y: 323.5335417110275}, {x: 325.27621345004127, y: 332.3888464290451}, {x: 315.2544691391854, y: 338.6371144372772}, {x: 304.66151045044944, y: 341.4427271205734}, {x: 295.3428850599198, y: 341.4085681754898}, {x: 285.4118543394475, y: 338.5544467288803} ] const __fill = (canvasCtx, points) => { canvasCtx.beginPath() canvasCtx.moveTo(points[0].x, points[0].y) points.splice(0, 1) points.forEach((point, i) => { // pointを結ぶ線を引く。fill()で塗りつぶされる canvasCtx.lineTo(point.x, point.y) // pointの座標にindexの数字を配置する(デバッグ用) canvasCtx.fillText(i, point.x, point.y) }) canvasCtx.fill() } canvasCtx.fillStyle = 'rgba(255,0,22,0.15)' __fill(canvasCtx, mouthLandmarks)関数ができたので、Vuexのactionから呼び出します。
draw ({ commit, state }, { canvasCtx, detection, color, transparent }) { const __mouthPoints = detection.landmarks.getMouth() const upperLip = [ ...__mouthPoints.slice(0, 7), __mouthPoints[16], __mouthPoints[15], __mouthPoints[14], __mouthPoints[13], __mouthPoints[12] ] const lowerLip = [ ...__mouthPoints.slice(6, 12), __mouthPoints[0], __mouthPoints[12], __mouthPoints[19], __mouthPoints[18], __mouthPoints[17], __mouthPoints[16] ] canvasCtx.fillStyle = `${color.slice(0, -1)}, ${transparent})` __fill(canvasCtx, upperLip) __fill(canvasCtx, lowerLip) },リップが点滅する
当初の実装と事象
対面カメラの映像にリップを塗るために以下を実装します。
videoの内容をcanvasに表示
顔認識
唇のランドマーク取得
リップ描画
1~4をsetIntervalで繰り返す
すると、前のintervalの4で書き込んだリップは、次のintervalの1で書き込まれたvideoに隠れてしまいます。
つまり、2と3の顔認識でラグればラグるほど、リップをvideoで上書きしてからもう一度リップを描画するまでが遅くなってしまい、ユーザーには、リップが点滅しているように見えてしまいます。
解決方法
唇のランドマークを取得したらその位置をキャッシュし、1の後すぐに描画する。
- videoの内容をcanvasに表示
- 顔認識結果がキャッシュされてたらリップ描画
- 顔認識
- 認識結果をキャッシュ
- 唇のランドマーク取得
- リップ描画
- 1~5をsetIntervalで繰り返す
video to canvasがiPhoneでインライン再生できない
canvasだけ表示したいのでvideoにhidden要素を指定して隠していましたが、safariではvideoを隠すと再生できないようになっています。
解決方法
#live-video { position: absolute; top: 10px; left: 10px; object-fit: fill; transform-origin: left top; transform: scale(.1); }canvasの左上にvideoも小さく表示するようにしました。
transform: scale(.001)
とかにしてしまえば見えないも同然です。webRTCのアスペクト比がなかなか合わない
解決方法
getUserMediaのconstraintsで設定します。
const constraints = { aspectRatio: 0.75 } const stream = await navigator.mediaDevices.getUserMedia({ video: constraints })ちなみにこれでもiPhone safariではアスペクト比をいじれませんでした。
気合いで3:4のcanvasに合わせる関数を実装しました。
drawImage ({ commit, state }, { canvasDiv, canvasCtx, imagePath }) { const image = new Image() image.addEventListener('load', () => { let width, height, xOffset, yOffset if (image.width * 1.34 > image.height) { height = canvasDiv.height width = image.width * (canvasDiv.height / image.height) xOffset = -(width - canvasDiv.width) / 2 yOffset = 0 } else { width = canvasDiv.width height = image.height * (canvasDiv.width / image.width) yOffset = -(height - canvasDiv.width) / 2 xOffset = 0 } canvasCtx.drawImage(image, xOffset, yOffset, width, height) }) image.src = imagePath }ちなみにこれでもダメでした。
方針を切り替え、スマホではカメラモードを使えないようにしてしまいます。
以下のような関数を作ってユーザーのデバイスを取得し、PC以外の端末ではカメラモードを使えないようにしてしまいました。const getDevice = () => { const ua = navigator.userAgent if ( (ua.indexOf('iPhone') > 0 || ua.indexOf('iPod') > 0 || ua.indexOf('Android') > 0) && ua.indexOf('Mobile') > 0) { return 'sp' } else if (ua.indexOf('iPad') > 0 || ua.indexOf('Android') > 0) { return 'tab' } else { return 'other' } } export default { getDevice, }iPhoneで画像アップロードすると回転する
iPhoneの画像はExifと呼ばれるメタデータを持っています。
ファイルサイズ、位置情報、撮影日時、回転情報などがこれに含まれます。
これを描画時に反映させないと意図しない方向に回転して表示されてしまいます。解決方法
便利なライブラリを使って解決しました。
ライブラリインストール
npm install blueimp-load-image
インポート
import loadImage from 'blueimp-load-image'実装例
onImageChange (file) { if (file !== undefined && file !== null) { if (file.name.lastIndexOf('.') <= 0) { return } loadImage.parseMetaData(file, (data) => { const options = { canvas: true } if (data.exif) { options.orientation = data.exif.get('Orientation') } loadImage(file, async (canvas) => { this.imageUrl = canvas.toDataURL('image/jpeg') // 顔認識と描画処理 }, options) }) } else { this.imageUrl = '' } }リップの製品情報を取得
こんな感じでデータを作っていきます。
公式サイトを訪問し、カラーピッカーで一つ一つリップの色を取得する地獄のような作業でした。
地球上の全ブランドを網羅するぐらいの気概で開発を始めましたが、ここで心折れました。brands: [ { name: 'THREE', items: [ { name: 'THREE Daringly Distinct Lipstick', colors: [ {id: '01', code: 'rgb(198,29,67)'}, {id: '02', code: 'rgb(189,38,79)'}, {id: '03', code: 'rgb(208,62,80)'}, {id: '04', code: 'rgb(221,72,110)'}, {id: '05', code: 'rgb(218,83,126)'}, {id: '06', code: 'rgb(232,114,136)'}, {id: '07', code: 'rgb(233,79,111)'}, {id: '08', code: 'rgb(232,57,74)'}, {id: '09', code: 'rgb(234,110,146)'}, ] }, { name: 'THREE Daringly Demure Lipstick', colors: [ {id: '01', code: 'rgb(216,49,105)'}, {id: '02', code: 'rgb(239,53,66)'}, {id: '03', code: 'rgb(241,81,105)'}, {id: '04', code: 'rgb(221,80,97)'}, {id: '05', code: 'rgb(210,97,97)'}, {id: '06', code: 'rgb(183,74,111)'}, {id: '07', code: 'rgb(128,17,33)'}, {id: '08', code: 'rgb(159,24,48)'}, {id: '09', code: 'rgb(95,19,24)'}, ] } ] }, ]終わり
リップの情報を取ってくるのが辛すぎたので、このプロダクトのことは一旦忘れることにしました。
それでも技術的に以下の知見が得られたので作ってよかったです。
- webRTC
- canvas
- 顔認識
- 投稿日:2020-02-25T10:24:36+09:00
node.jsインストール直後の状態でpackage.jsonをアップデートする方法 ~npmグローバルインストール一切不要~
package.jsonを更新する場合、npm-check-updatesをグローバルインストールして
ncu -u
とやることが多いです。ただ、nodebrewなどのnodeバージョン管理システムを使っている場合、node.jsの新バージョンがリリースされるたびにグローバルインストールをやり直す必要があります。この問題、何とかならないでしょうか。実はnpm-check-updatesをnpx経由で呼べば、node.jsインストール直後の状態でもpackage.jsonを更新することができます。package.jsonを更新する
npx npm-check-updates -u npm install解説
npx経由でnpm-check-updatesを呼び出しているだけです。試してみましたが、
npx ncu -u
とは出来ませんでした。注意点
環境にもよりますが、上記手順は
npx npm-check-updates -u
を実行するたびにnpm-check-updatesをローカル環境のインストールします。連続してnpm-check-updatesを呼びたい場合は、npx経由で呼び出すことはお勧めしません。自分の場合は上記コマンドを呼び出すのは1週間に1回程度なので、時間ロスについてはそこまで気にしていません。
- 投稿日:2020-02-25T02:09:11+09:00
PHPで独自フレームワークを作ってサイトも作ってみた
Lalavelが重いと感じたのでPHP7でフレームワークを作ってサイトも作ってみました
サイトは https://mokuzist.com ですlaravelが重いというところから始まったので無駄なものは出来るだけ入れないというスタンスです
Composerも名前空間も使っています
構造はDVECモデルとなっていますController、Entity Model、Data Model、Viewです
サイト自体は興味のある事をマッチング出来るサイトとなっています
サイトを使って頂いてバグ等あれば教えて頂けると幸いです機能的にここがダメとかこれが欲しいという要望も受け付けております
これからの予定としては言語選択出来るようにして英語版も作る
人のフォロー機能もつける
もう少しスマホで使いやすいようにボタンを大きくする
スマホアプリ版も作る
といったような改修を予定しておりますレビューありがとうございます
登録するとメールアドレスにhashがついたUrlが飛ぶのでそこにアクセスすると登録完了となります
ちなみにパスワードは某F社のように平文ではなくちゃんとhash化して保存してあり復元は不可能となっております
- 投稿日:2020-02-25T01:56:17+09:00
PHPで独自フレームワーク作ってサイトも作ってみた
Lalavelが重いと感じたのでPHPで独自フレームワークを作ってそれでサイトも作ってみました。
https://www.mokuzist.com
というのがサイトですフレームワーク自体はECDVという構造にしました
Controller、Entity Model、Data Model、viewという構造で余計なものを入れない超シンプル構造です
laravelが重いというところから始まっているので余計なものは一切入れてませんサイト、フレームワーク共にバグがないかテストして頂けると幸いです
- 投稿日:2020-02-25T01:08:17+09:00
Javascriptで画像付きツイートを行う
経緯
山手線 Ver.2020 by 東京感動線でWebARから画像付きツイートをすることになり、色々と悪戦苦闘して、動くものができたので残しておきます。ニーズが無いのか、ググってもビンゴの記事がないのですよね。
コード
プラットフォームとして、Oauth.ioを使っています。
ポイントをコメントで残しました。/* detail : base64エンコード済みの画像データ */ /* tweet_text : ツイート内容 */ function twitter_tweet(detail, tweet_text) { var oauth_result; OAuth.initialize("***public key***"); /* 各自PUBLIC KEYを設定 */ OAuth.popup('twitter').then(function(result) { oauth_result = result; }).fail(function(err){ /* エラー処理 */; }); /* multipartにするための区切り */ var bound_text = "------------------------1ae47d990b354d1b00a4eea60e6b5b72"; var image_src = "--" + bound_text + "\r\n" + 'Content-Disposition: form-data; name="media_data"' + "\r\n" + "\r\n" + detail + "\r\n" + "--" + bound_text + "--\r\n\r\n"; /* この書き方でOauth署名は正しく作成される模様 */ var param1 = { headers: { 'Content-Type' : 'multipart/form-data; boundary=' + bound_text }, data: image_src }; /* 画像のアップロード */ oauth_result.post('https://upload.twitter.com/1.1/media/upload.json', param1).done(function (response) { /* 画像のアップロードに成功したら、ツイートと紐づけるために */ /* 画像データのIDを取得する */ var media_id_ = response.media_id_string; var param2 = { data: { status: tweet_text, media_ids: media_id_ } }; /* ツイート */ oauth_result.post('/1.1/statuses/update.json', param2).done(function (response) { /* ツイート成功時の処理 */; }).fail(function (err) { /* ツイート失敗時のエラー処理 */; }); }).fail(function(err) { /* 画像アップロード失敗時のエラー処理 */; }); }参考
最後に
あまり親切な文書になってないと思うので、気が向いたら更新します。
ここをもっと書いて欲しいとうのご要望いただけるとありがたいです。