はてなキーワード: constとは
地球は宇宙空間を動いているのだから、地球の進行方向と垂直方向では光の速さが変わるだろう。そう考えて実験してみたところ、どちらの速さも変わらなかった。つまり、どんな系でも光の速さは一定であるらしい。
これを式にするとこうなる。
光の速さをc, 時刻 t の間に光の進む距離を x として
x/t = c
式変形すると
ここで一旦休憩。座標系を回転させても'棒の長さは一定'という式を考えてみよう
x^2 + y^2 = const
かんたんのため z 方向は考えない
この時座系を回転させる式を行列で書くと
こうなる。(心の目で読んで欲しい)
という式を思い出すと
x'^2 + y'^2 = x^2 + y^2 = const
上の'棒の式'とは符号が逆だね。こんなときはsin cos ではなく sinh cosh を使う。
cosθ = ((exp iθ) + (exp -iθ))/2
sinθ = ((exp iθ) - (exp -iθ))/2
coshθ = ((exp θ) + (exp -θ))/2
sinhθ = ((exp θ) - (exp -θ))/2
計算すると
cosh^2 - sinh^2 = 1 になるのがわかると思う。
cos^2 + sin^2 = 1 とは符号が逆になってるね
光の速さが系を変換しても変わらないという式を行列で書くと
こうなる。 これがローレンツ変換。
棒の長さが一定、つまり空間回転は空間方向 (x,y,z)しか混ぜないけれど、
光のはやさが一定、つまりローレンツ変換は 時間と空間 (t, x ) を混ぜているでしょ?
速さ v で進むロケットを考えてみよう。
v=x/t
だ。
一方、ロケットには美加子さんが乗っていてその携帯電話の表示では地球を発ってから T時間後である。
Tを計算してみよう。
先程のローレンツ変換の式に代入すると
ここで x = ct を使ったよ。最後に cosh で全体を纏めると
になる。
ここまで誤魔化していたけど、cosh はロケットの速さ v で決まるパラメータで
1/cosh = \sqrt{1-(v/c)^2}
なんだ。天下りで申し訳ないけど、増田では式も図も書けないので導出は勘弁して欲しい
とにかくまとめると
T = t \sqrt{1-(v/c)^2}
だね。ロケットの速度 v は光速度以下なので T < t になる。
地上で待つ昇くんが大学生になっても美加子さんが中学生のままなのはこんなワケだね
v が大きくなるほど時間の遅れは大きくなるよ
AIインフルエンサーたちはChatGPTが世に出る前は何を投稿していたのか?(1/1)の続き
このTwitterアカウントは、主にYouTube、SEO、競馬、アニメなどの話題について呟いており、自身の活動や興味関心について発信しています。
このアカウントは、日々の米国株や暗号通貨の市場動向、特にテクノロジー関連株やビットコインの価格変動についてツイートしています。
「ゼロコロナ政策再び。 $AAPL の生産に影響が懸念され大きく下落。更に経済混乱が想定され、株価はSP500全業種で
一方で年末商戦売上堅調な滑り出しで $AMZN
暗号資産レンディングBlockFiが経営破綻、暗号通貨も軒並み下落。
チャート上、なんとか踏み止まるか? 」
このアカウントは、AI、特にプロマネAIや量子AIに関する話題や、仕事効率化、プログラミング、そして最新の技術トレンドについて呟いています。
"プロマネAIの実証実験を開始しました!量子AI×NotionによるプロマネAIの実証実験を開始 https://prtimes.jp/main/html/rd/p/000000003.000082094.html… via @PRTIMES_JP"
このアカウントは、主にOpenAIの最新言語モデル「text-davinci-003」の進化と、そのモデルを用いた英語学習ツールやサービスについて呟いています。特に、英語学習におけるAI活用とその重要性を強調しています。
"朝起きたら世界がまた変わっていた(笑)。@OpenAI が最新モデル「text-davinci-003」を発表。主な特徴は、①より明確で、説得力のある文章が書ける②より複雑な指示にも対応③より長い形式のコンテンツが生成可 1月に"InstructGPT"が出た時も感動したけどそれを遥かに上回る進化、です。"
このアカウントは、主にAI、特に画像生成AIに関する話題を呟いています。特にStable Diffusionのバージョンアップや使い方について多くのツイートをしています。
ここにリストアップした人たち以外もみましたが、分類すると3種類のアカウントがいて
またIDを変更してログがヒットしない人は含まれていません(IDから特定できるけどそこまでやらなかった)
javascript:(function() {
const text = Array.from(document.querySelectorAll('[data-testid="tweetText"]')).map(s => s.textContent.trim()).join('\n');
const textarea = document.createElement('textarea');
document.body.appendChild(textarea);
try {
document.execCommand('copy');
console.log('結果がクリップボードにコピーされました!');
} catch (err) {
console.error('クリップボードへのコピーに失敗しました:', err);
}
document.body.removeChild(textarea);
})();
const axios = require('axios'); // HTTPリクエストを行うためのモジュール
const fs = require('fs'); // ファイル操作モジュール
const xml2js = require('xml2js'); // XMLをJSONに変換するためのモジュール
const chardet = require('chardet'); // 文字エンコーディングを検出するためのモジュール
const iconv = require('iconv-lite'); // 文字エンコーディングを変換するためのモジュール
const rssUrl = 'https://www.mlit.go.jp/important.rdf'; // 例としてRSSフィードのURLを指定
async function fetchAndSaveRSS() {
try {
// RSSを取得
const response = await axios.get(rssUrl, { responseType: 'arraybuffer' });
const rssData = response.data;
const detectedEncoding = chardet.detect(rssData);
console.log('検出された文字エンコーディング:', detectedEncoding);
// UTF-8に変換
const utf8Data = iconv.decode(rssData, detectedEncoding);
xml2js.parseString(utf8Data, (err, result) => {
if (err) {
console.error('XML解析エラー:', err);
return;
}
const jsonData = JSON.stringify(result, null, 2);
fs.writeFileSync('rss_feed.json', jsonData, 'utf8');
console.log('RSSフィードがファイルに保存されました。');
});
console.error('エラーが発生しました:', error);
}
}
// 実行
fetchAndSaveRSS();
そんな手作業でやらなくてよいぞ
これで思う存分やりなさい
(function() {
const data = [];
$$('span.hatena-star-inner-count').map(x => x.click());
$$('.js-bookmarks-recent .entry-comment-contents').map(content => {
const userName = content.getAttribute('data-user-name');
const comment = content.querySelector('.entry-comment-text')?.textContent;
content.querySelectorAll('a.hatena-star-star').forEach(a => { stars.push(a.href.split('/')[3]); })
data.push([userName, comment, stars]);
});
data.sort((a,b) => b[2].length - a[2].length);
copy(data.map(d => `| ${d[0]} | ${d[1]} | ${d[2].join(',')} |`).join("\n"));
})();
特殊文字は、実体参照(& や <)ではうまくいきません。数値参照を使ってください。
出したい文字 | 数値文字参照 |
---|---|
& | & |
< | < |
> | > |
const dinner = (chicken, curry) => {
if (chicken && curry) {
console.log('チキンかつカレー')
}
}
このように入力してください。
<pre>const dinner = (chicken, curry) => {<br> if (chicken && curry) {<br> console.log('チキンかつカレー')<br> }<br>}</pre>
FANZAの検索結果から熟女を除外するブックマークレット がうまく動いたので、気を良くしてはてなブックマークのコメント欄をスター数順にソートするブックマークレットを作りました。
作った動機は、「注目コメントに入りきれなかったちょっといいコメント」をサクサク探したいから。結果として建設的コメント順位付けモデルを無効化していますが、あのアルゴリズムには特に不満は特にありません。
javascript: (async () => {
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
document.querySelector('.js-bookmarks-sort-tab[data-sort="recent"]').click();
window.scrollTo(0, document.body.scrollHeight);
await wait(1000);
window.scrollTo(0, 0);
await wait(1000);
const p = document.querySelector('.js-bookmarks-recent');
let l = Array.from(p.querySelectorAll('.entry-comment-contents'));
const g = e => {
let n = e.querySelectorAll('.hatena-star-star').length;
const c = e.querySelector('.hatena-star-inner-count');
return c ? n + Number(c.textContent) : n
};
l = l.filter(e => g(e) > 0);
l.sort((a, b) => g(b) - g(a));
p.replaceChildren(...l);
})();
ミニファイしたもの ※コードに一部誤りがありましたので訂正しました(2024-08-16 11:47)
javascript:(async()=>{const wait=ms=>new Promise(resolve=>setTimeout(resolve,ms));document.querySelector('.js-bookmarks-sort-tab[data-sort="recent"]').click();window.scrollTo(0,document.body.scrollHeight);await wait(1000);window.scrollTo(0,0);await wait(1000);const p=document.querySelector('.js-bookmarks-recent');let l=Array.from(p.querySelectorAll('.entry-comment-contents'));const g=e=>{let n=e.querySelectorAll('.hatena-star-star').length;const c=e.querySelector('.hatena-star-inner-count');return c?n+Number(c.textContent):n};l=l.filter(e=>g(e)>0);l.sort((a,b)=>g(b)-g(a));p.replaceChildren(...l)})()
FANZAの検索結果から熟女を除外するブックマークレット 参照
javascript:
ブックマークレットに必要な、URLの種類を示すスキーム名です。
(async () => {
// 処理
})();
ページに元々ある変数たちとバッティングしないように、まず無名関数でラップします。処理の中で await を使いたいので async 宣言しています。
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
document.querySelector('.js-bookmarks-sort-tab[data-sort="recent"]').click();
window.scrollTo(0, document.body.scrollHeight);
await wait(1000);
「新着コメント」タブをクリックし、ページの一番下までスクロールダウンしてから少し待つ動作です。新着コメントの後半部分(スクロールきっかけの遅延読み込みになっているところ)の読み込みをうながしています。
window.scrollTo(0, 0);
await wait(1000);
ページの先頭に戻ってまた少し待ちます。合計2秒の待ち時間は雰囲気で決めていますので、これでなければならない・これで過不足ないという値ではありません。単にコメントの読み込み完了を判定する処理を書くのがめんどうだっただけです。
const p = document.querySelector('.js-bookmarks-recent');
新着ブコメの親要素です。繰り返し呼び出すので名前をつけています。
let l = Array.from(p.querySelectorAll('.entry-comment-contents'));
const g = e => {
let n = e.querySelectorAll('.hatena-star-star').length;
const c = e.querySelector('.hatena-star-inner-count');
return c ? n + Number(c.textContent) : n
};
コメントのはてなスター数をカウントして返す関数です。たくさんスターがついてる ★256★ みたいなやつの数字も足します。
l = l.filter(e => g(e) > 0);
ソートする前に、無スターのコメントを消去しています。してもしなくてもいいことですが。
l.sort((a, b) => g(b) - g(a));
残ったコメントをスター数で降順ソートします。.querySelectorAll() で収集した要素を配列に入れ直したのは、この .sort() メソッドを使いたいからです(.querySelectorAll() が返す配列風の NodeList オブジェクトは、配列と共通のメソッドもいくつかあるものの、大半は使えないのです)。
p.replaceChildren(...l);
親要素の内容を、並び替えの終わったコメントでそっくり入れ替えて、処理完了です。画面を見ると新着コメントの中身が「スターのついたコメントのみ・スターの多い順」に並んでいます。元に戻す方法はないので、原状回復にはリロードします。ソート状態を示すフラグを立てておいてスター数ソート⇔日付ソートをかわりばんこに行うようにすればできそうだなと思ったけど実装はしません。連打スターを省く処理を追加してUU数でソートできればもっと厳正なランキングになるなーと今思いつきましたがそれも実装はしません。
私は熟女モノとか人妻モノは眼中にないのですが、なぜだか最近そっち系の作品が多くて閉口しています。
しかしFANZA側の検索システムはNOT検索できるようになっていません。そこで、検索結果から除外できそうなものを除外するブックマークレットを作ることにしました。
さいわい近年は内容の概要文をそのままタイトルにしたような作品ばかりなので、タイトルに含まれるキーワードで除外が簡単にできそうです。
「熟女」とか「五十路」のような単語を含む作品を非表示にしてしまえばよいのです。
javascript: (() => {
const r = /熟女|完熟|熟れ|四十路|五十路|六十路|人妻|奥様|妻|夫|母|ママ|おばさん|BBA|姑|嫁/;
const q = '#list>li';
document.querySelectorAll(q).forEach(l => {
if (r.test(l.textContent)) {
l.remove();
}
});
})();
javascript:(()=>{const r=/熟女|完熟|熟れ|四十路|五十路|六十路|人妻|奥様|妻|夫|母|ママ|おばさん|BBA|姑|嫁/;const q='#list>li';document.querySelectorAll(q).forEach(l=>{if(r.test(l.textContent)){l.remove()}})})()
このブックマークレットで、検索結果に含まれる熟女系作品の数を1/3くらいにまで減らすことができます。
ブックマークレットとは、ブックマークにURLではなくJavaScriptを登録して、閲覧中のページ上で自分(やほかの誰か)が作ったプログラムを実行できるしくみのことです。普通のブックマークと同じようにブックマークバーなどに並べておいて、クリックひとつで呼び出すことができて便利です。
①まず、どこのページでもいいので(今読んでいるこのページでもよい)ブックマークをひとつ作り、ブックマークバーなどの呼び出しやすいところに置きます。
②できたブックマークを右クリックして「編集...」を選びます。
③「名前」欄は、自分にわかりやすい名前に変更します。でも「FANZAフィルター」などあけすけな名前をつけると、誰かに画面を覗かれた時に困りますよ。
④「URL」欄に、上記したプログラムコードを入力します。ただし上記のコードは私向けのキーワード選定になっていますので、ご自身の好みに合わせたキーワード選定をしていただければよいかと思います。/単語1|単語2|単語3/
のように記述してください。
ふつうのソースコードと、改行・インデントなどを省いてミニファイ(最小化)したもの、どちらをコピペしても大丈夫です。
⑦このブックマークレットを起動します。すると、瞬時に検索結果が減ります。
キーワードだけが異なる複数のブックマークレットを登録しておいて、場面に応じて使い分けるなどの工夫もできるでしょう。
上記のスクリプトが何か悪さをするようなものではないことを説明するために、また、JavaScript を学習し始めたばかりの人のために、このシンプルなスクリプトの解説をします。
javascript:
URLの種類を示すスキーム名です。一般的なURLは https:
や mailto:
などで始まりますが、javascript:
と書くと、これに続くコードがプログラムとして実行されます。
(() => {
// 処理
})();
ここからが JavaScript です。まず処理全体をくるむ大きなカッコと最後に付け足された () は、自己実行無名関数という形式です。今回のブックマークレットは変数を含みますので、実行するページに元々ある変数たちとバッティングしないようこのようなかたちにします。
const r = /熟女|完熟|熟れ|四十路|五十路|六十路|人妻|奥様|妻|夫|母|ママ|おばさん|BBA|姑|嫁/;
除外したい単語を羅列した正規表現です。個人個人で設定が変わる部分なので、編集しやすいように切り出しておきました。
const q = '#list>li';
フィルター対象とするHTML要素群のクエリーセレクター文字列です。検索結果に一覧表示される、個々の作品要素を選択します。FANZAがシステム改修を行うと変わってしまう可能性がある部分なので、メンテしやすいようにここだけ切り出しておきました。
document.querySelectorAll(q).forEach(l => {
// 処理
});
クエリーセレクター q
に一致する要素 l
ひとつひとつについて反復して処理を行います。
if (r.test(l.textContent)) {
l.remove();
}
もし要素 l
内のテキストが正規表現 r
と一致していたら、要素 l
を取り除く、という処理です。正規表現 r
はキーワードの羅列ですので、テキストの一部にキーワードのどれかが含まれていたら一致したことになります。
そうじゃなくてクソコードが多いんだよ
可読性が低いだけならまだマシだし、可読性は人によるよ
例えばTypeScriptで
っていうIssueがあったとして
const toBanana = (apple: 'apple'[]) => apple.map((a, i) => (i % 3 === 0 ? 'banana' : a))
const toBanana = (apple: 'apple'[]) => { const appleAndBanana: ('apple' | 'banana') = for (let i = 0; i < apple.length; i++) { if (i % 3 === 0) { appleAndBanana.push('banana') } else { appleAndBanana.push(apple[i]) } } return appleAndBanana }
のどっちが可読性が高いかっていうのは人によるよ
(長いソースを読むのがしんどい人と、関数化されたソースを読むのがしんどい人)
クソコードっていうのは
const toB = (a: any[]) => { for (let i = 0; i < a.length; i++) { if (i == 3) a[i] = 'banana' if (i == 6) a[i] = 'banana' if (i == 9) a[i] = 'banana' } return a }
こういうの書いてくる人だよ
「お前これ10個以上来たらどうすんのよ」
みたいに返事してくるし、修正させても
const toB = (a: any[]) => { for (let i = 0; i < a.length; i++) { if (i == 3) a[i] = 'banana' if (i == 6) a[i] = 'banana' if (i == 9) a[i] = 'banana' if (i == 11) throw new Error('banana') } return a }
こんなんPRしてくる奴のことだよ
これを改善してってお願いした。何書いてあるかわからないけど動いたよ。
https://anond.hatelabo.jp/20240125203115
// ==UserScript== // @name 増田ミュート(白塗り版) // @namespace http://tampermonkey.net/ // @version 2024-06-26 // @description ミュートワードを含む最小限の範囲を白塗りにする // @author You // @match https://anond.hatelabo.jp/* // @icon https://www.google.com/s2/favicons?sz=64&amp;domain=hatelabo.jp // @grant none // ==/UserScript== (function() { 'use strict'; const muteWords = [ "弱者男性", "弱男", "弱者", "婚活", "男", "女", "年収", "下方婚", "発達障害", "発達", "ハッタツ", "ハッタショ", "ハッタショ", "競プロ", "競技プログラミング", "AtCoder", ]; function whiteoutElement(element) { element.style.backgroundColor = 'white'; element.style.color = 'white'; element.style.textShadow = 'none'; element.style.cursor = 'default'; element.style.userSelect = 'none'; // テキスト選択を防止 element.style.borderBottom = '1px dashed #ccc'; // 枠線を追加してテキストがあることを示す // リンクの場合、クリックを無効化 if (element.tagName === 'A') { element.style.pointerEvents = 'none'; element.removeAttribute('href'); } // 子要素にも適用 Array.from(element.children).forEach(child => { child.style.backgroundColor = 'white'; child.style.color = 'white'; child.style.textShadow = 'none'; }); // ツールチップを追加 element.title = 'この内容にはミュートワードが含まれています'; } function shouldMute(text) { return muteWords.some(word => { const parts = word.split(''); const regex = new RegExp(parts.map(char => `${char}92;92;s*`).join(''), 'i'); return regex.test(text); }); } function findSmallestMuteableElement(element) { if (element.nodeType === Node.TEXT_NODE) { return shouldMute(element.textContent) ? element.parentElement : null; } if (element.tagName === 'PRE' || element.tagName === 'CODE') { return shouldMute(element.textContent) ? element : null; } for (let child of element.childNodes) { const result = findSmallestMuteableElement(child); if (result) return result; } return shouldMute(element.textContent) ? element : null; } function processElement(element) { const muteableElement = findSmallestMuteableElement(element); if (muteableElement) { whiteoutElement(muteableElement); } } function processAllElements(root = document.body) { const walker = document.createTreeWalker( root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null, false ); let node; while (node = walker.nextNode()) { if (node.nodeType === Node.ELEMENT_NODE) { processElement(node); } else if (node.nodeType === Node.TEXT_NODE &amp;&amp; node.parentElement) { processElement(node.parentElement); } } } function handleClickEvent(event) { setTimeout(() => { processAllElements(event.target); }, 100); } // 初回実行 processAllElements(); // クリックイベントの監視 document.body.addEventListener('click', handleClickEvent); // DOM変更の監視 const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { processAllElements(node); } }); } else if (mutation.type === 'characterData') { processElement(mutation.target.parentNode); } }); }); observer.observe(document.body, { childList: true, subtree: true, characterData: true }); })();
おつかれさまです (どのような事に従事されているか存じ上げませんが、一旦それに割り込む形で私が対話者として主体的に関わってよろしいでしょうか?/”こちらから見て”あなたの大事な用はおおきいことであるのでひとしきり労をねぎらわせていただいて)
┗あんたがどれほど疲れてるかなんて知らんがな 格下の私からみたらすごい大変なんやろなって そんなんしたら疲れてまうわと思うけどこっちも用事があるんですんませんけど割り込んでええかって意味
┗「つかれてへんわ」って自分が自分の基準でなんもしてないアピールされても「すごいですね」としか言えんやろがい 自分を語ってくれるんはありがたいけどそんな事はきいてないというか聞いてほしいことがあるって言ってんの
ごくろうさまです (どんな方の何事も誰かのために大切な用でありその価値が自分の世界観からみて重くあるから労をねぎらって)
┗苦労してるかどうかとか人生についての価値観とかは聞いてない 尊重していますよというスタンスからの関係ない話をするけれども敵対的な目線でお聞きするのではないですよというアピール
┗「くろうなんかしてないわ」ってだれもあなたの人生を聞いたりしてへん いきなりちょっと関係ないっぽい話をするけどあくまで社会的な距離感たもつでって事
挨拶で使う場合は「おはようございます」でも同じで、自分がそこにおる/いなくなるを告知する儀を割り込ませるための発言でゆってみたら変数の宣言みたいなもん
いきなり出てきたら「はい!」で帰る時も「はい!」みたいなvarじゃなくてletとかconst使えって話
なんかするとゆうたらおらんなとおもったら「おるよ」とかそういえばおったっけとおもたらもういないみたいなtempな変数みたいな挨拶もせんやつに名前なんかいらんっちゅう話で個人名を「バイトくん」とかにしたらええって話
この度は って一期一会なのに何度もあるんかとか
拡張子については、例えば Excel の拡張子が変わったとき一括対応できる、とか?
あとは普通に".txt" で取り扱ってるファイルはどれだ、って時にその定数の参照箇所を見ればもれなく分かるとか、
取り扱うファイルの種別を段階的に変えようってときも、どのファイルは変え終わっててどのファイルはまだ、とかも同じように分かる
あとはあれだ、どのスコープにおける分類なんだって話を明確にする事も出来るだろうな。
とか。
パラメータについては、複数の選択肢から選ぶ奴は enum にしろよ、とは思うが、
文字コードも大体同じような話か。
.txt と .TXT で挙動を変えていた話しがあったやん?
プログラム全体で、TxtFileExt が一カ所でしか使われてないなら、変数にする必要はほぼないけど、
2か所、3カ所になったら、.txt を .TXT に変えるだけでもミスする人でてくる。
.txt を .debug.txt とか .masuda.txt に気分次第で変える時も楽やん
const 〇〇ParamIntMax = 25;
もプログラム全体で、一カ所しか使われてなければ変更ミスは生じないけど、
何カ所にも別れたら、変更時に見落とすやん。
いろんなアプリケーションのメンテ(バグ取りとか細かい機能追加とか)を何度か経験してきた。
主にテキストファイルとかCSVファイルとかExcelファイルとかを入出力するものばかりだったんだが、その大半がファイルの拡張子をグローバル変数化していた。
こんな感じ
const TxtFileExt = ".txt"; const CsvFileExt = ".csv"; const ExelFileExt = ".xlsx";
outFileName = 〇〇 + ×× + "ABCDEFG" + TxtFileExt;
みたいな指定をしなきゃならない。
あと、プログラム言語の標準的なメソッドのあらゆる引数も全部変数で定義されてて、そのまま渡すのは禁止、みたいな規約になってる。
たとえば引数が三種類(true、false(未指定時のデフォルト値)、任意の数値(ただし当該プログラムでは0、10、25以外指定不可))しかないやつはこんな感じ。
const 〇〇ParamTrue = true; const 〇〇ParamFalse = false; const 〇〇ParamIntMin = 0; const 〇〇ParamIntMid = 10; const 〇〇ParamIntMax = 25;
const charCodeSJIS = "Shift_JIS"; const charCodeUtf8 = "UTF-8";
以前関わった改修内容に「××の処理は開始時と終了時にそれぞれUTF-8(BOMなし)形式でログを出力する」みたいなのがあって、普通に文字コード指定する部分に「UTF-8」で直に書いたら、規約に従ってないからとコードレビューで指摘されて差し戻されたんだけど、そもそもこういう規約って何の意味があるの?
去年から稼働している現場で、以前からあったReact Nativeの面倒を見ているんだがまあこれがひどい出来なんだ。
jQuery時代に見かけたようなコードをやたら見かけたので思わず懐かしくなってしまった。
リファクタリングしようとしたけど直す範囲が広すぎてアプリを壊しかねなかったので、早々に諦めてだましだまし保守をしていた。
そんな中今年に入ってアプリのリニューアルの話が出てきた。React Native捨ててSwift/KotlinやらFlutterに書き換えるとかそういうのではなく、デザインの刷新といくつかの機能改修。
このままだとアプリが更に魔窟化するので、マネージャーに色々相談したところいくつかの事実がわかった。
ということだった。
結局現状のまま進めるわけにはいかず、要件定義の傍らリファクタリング作業をしている。
そういう経緯もあったので、リファクタリングとテストの工数も積んだ上で見積もりだしてもらってる。
「レガシーアーキテクチャをモダンアーキテクチャに刷新」なんてよく聞く話しだけど、
実態は「長年の増改築とだましだましのリフォームが限界になってきたので新築で建て替えます」何だと思う。
最近は「Vue.jsからRemixにマイグレーション」なんて見かけるけど、悪いのはVue.jsじゃなくて禄に設計しないでコード書いてるエンジニアと、
リファクタリングには予算でないけどマイグレーションなら予算取れるという悪しき風習。
年がら年中フロントエンド刷新しているような会社は地雷なので行かないほうがいい。
松本人志以外も消える
// ==UserScript== // @name hatebu-matsumoto // @version 1 // @grant none // @include https://b.hatena.ne.jp/ // ==/UserScript== var startTime = new Date().getTime(); var t = setInterval( () => { const list = document.querySelectorAll(".entrylist-contents-thumb,.entrylist-issue-thumb"); list.forEach(x => x.style.opacity = "0"); if (new Date().getTime() - startTime > 10000) { clearInterval(t); } }, 10 );
document.cssRulesを加工するかMutationObserverを使えよ。 これだと一瞬松本の顔が映るだろ
として、標準的経済学では(他の条件を一定とした時に)以下のように考えるのではないだろうか。
重要なのはこの"const"という部分で、一定の値を取ることを意味する。つまり、aが増加すればxは減少する。
である。この場合、aは減少も増加もしないので、xを増やせば増やすだけyが増加することになる。
これでMMT信者が言いたいことが大体分かってくる。以下は、標準的な考えからMMTを批判するとどうなるのかというのを書く。
MMT(現代貨幣理論)は、政府が貨幣供給を増やすことで経済全体の価値を増やすことが可能であると主張する。しかし、この理論にはいくつかの問題点がある。
まず、インフレーションのリスクである。MMTは、貨幣供給を増やすことで経済活動を刺激すると主張している。しかし、貨幣供給が増えると、通常は物価が上昇する傾向がある。つまり、インフレーションのリスクが高まる。これは、貨幣の価値が下がり、生活費が上昇するという結果をもたらす。
次に財政規律の欠如である。MMTは、政府が無制限に貨幣を発行できるという考え方を推奨している。しかし、これは財政規律を欠く可能性があり、長期的には経済の安定性を損なう。
外国為替レートへの影響も懸念される。国が大量の貨幣を発行すると、その国の通貨の価値が他国の通貨に対して下落する。これは、輸入費用の増加や投資の流出を引き起こす。
本当にあった話だけど、JavaScriptでstrっていう変数にテキストが入っていて
その変数に'apple'とか'banana'とかが入ってるかどうかを判別するっていうロジックを作るときに
const re = new RegExp("apple") if(re.test(str)) console.log("match")
const re_apple = new RegExp("apple") const re_banana = new RegExp("banana") if ( re_apple.test(str) || re_banana.test(str) ) console.log("match")
っていうコードを書く人がおるんよ
別にプログラミング初めて3ヶ月の初心者じゃ無くて20年以上やってるようなベテランだったり
なんならチーフプログラマーとして若手指導してるような人でもこういうレベルの人って割といるわけ
これに対して
「正規表現でORを書くべき」
「includeで十分」
綺麗にコードを書くっていうのは
「これってappleとかbanana以外に増えたりしないの?」
「fruitsかどうかを判別するならその変数を作った方が良くない?」
っていうのを考えて実装するのが綺麗にコードを書くっていうことで
ちなみに
「正規表現でORを書きましょう」
「動いてるからいいじゃない」
「綺麗に書いても性能上意味ない」
「言ってることが良く分からない。何が違うのか」
とか言ってくるし
https://b.hatena.ne.jp/site/anond.hatelabo.jp
で動くスクリプトでたとえば投稿後10分以内にブクマされページに乗ったら「1 user」が「1 user セルクマ 1とか5(何分後にブクマされたか)」になる。もしマイナスなら誤判定なので無視して。
時間を置いたセルクマには効かないし普通のファーストブクマカがどれぐらいの頻度で確認してるかしらないけど5分以内や1分以内もポロポロあるのでまあ目安に。
.forEach(div => {
('.entrylist-contents-title > a')
とかの
を
<>
に変えてね
他にも見落としあるかも
誤判定が減るから非公開ファーストブクマを判定できたらいいんだけどね。
// ==UserScript== // @name hatebu masuda selkmark // @namespace http://tampermonkey.net/ // @version 0.1 // @description 特定時間以内にブクマされた増田を強調する // @author You // @match https://b.hatena.ne.jp/site/anond.hatelabo.jp* // @grant none // ==/UserScript== (function() { 'use strict'; const threshold = 60 * 10 // 何秒以内か const domain = 'https://anond.hatelabo.jp/' const dateTemplate = '202301020304' // 時分まで urlの時刻表記 const dateTest = new RegExp('\\d{' + dateTemplate.length + '}') document.querySelectorAll('div.entrylist-contents').forEach(div => { const masuda = div.querySelector('.entrylist-contents-title > a') const dateStr = masuda.href.substring(domain.length + dateTemplate.length, domain.length) if (!dateTest.test(dateStr)) { // キーワードとか console.log('not diary', dateStr) return } // new Dateできるように変換 // https://amateur-engineer.com/javascript-date-yyyymmddhhmm/ const year = parseInt(dateStr.substring(0, 4)) const month = parseInt(dateStr.substring(4, 6)) const day = parseInt(dateStr.substring(6, 8)) const hour = parseInt(dateStr.substring(8, 10)) const min = parseInt(dateStr.substring(10, 12)) const date = new Date(year, month - 1, day, hour, min) const bukumaDate = new Date(div.querySelector('.entrylist-contents-date').textContent) // 2023/01/23 00:00 const diffSec = (bukumaDate - date) / 1000 // ms to sec if (diffSec > threshold) { return } // ブクマ数 user const user = div.querySelector('span.entrylist-contents-users a').lastChild user.textContent += ' セルクマ ' + (diffSec / 60) // 古い記事がマイナスになる でも2015年ぐらいの記事までかな?新着はセーフ臭い /* if(diffSec < 0) { user.textContent += ' 異常差分:' + diffSec } */ }) })();
無料会員のタダ読み3本機能の代わりに導入された有料会員によるプレゼント機能が導入されてもう1年(?)。増田が初めて知ったのはwattoさんのブコメでプレゼントURLを貼ってくれた時だが、最近になってTwitterでスーパーインフルエンサーの暇空アノンのいちゃもんのおかげで一気に機能が周知された。その結果なのかTwitterでもプレゼントURLの貼り付けが増えた感。
面白いのは、いわゆるリベラル系のアカウントの利用のみならず、反リベラル系の有名アカウントもちらほらとプレゼント機能を利用してるってことな。閲覧数は反リベラル系が圧倒的。まあそれなりにコンサル系や研究者系なら思想の左右問わず朝日読売日経辺りを読まないわけにはいかないし、中立アピールのためにあえて朝日ソースを使うってことかな
そして我ながらとんでもなくみみっちいブックマークレットをChatGPTに頼んで作ってもらった
朝日デジタルの有料記事ページを開いている時にクリックするとTwitterで有料記事プレゼント機能を使ってる(と思われる)ツイートを検索するブックマークレット。
javascript: (() => { const currentUrl = window.location.href; const digitalUrl = `digital${currentUrl.match(/\.asahi\.com\/articles\/.+\.html/i)[0]}`; const searchUrl = `https://twitter.com/search?q=${encodeURIComponent(digitalUrl)}&f=live`; window.open(searchUrl, %27_blank%27);})();
非表示機能で完全に無視したいって程でもないんだよな〜っていう。
タイプ別色分け機能とかこういうののはてなスター版とかも欲しい。面倒だから誰か書いて。
// ==UserScript== // @name hatebu_comment_usuku_hyouji // @version 1 // @grant none // @include https://b.hatena.ne.jp/entry/* // ==/UserScript== const userIdList = [ 'hoge', 'piyo', ... ]; setInterval(() => { document.querySelectorAll('.entry-comment-contents').forEach((element, i) => { if (userIdList.includes(element.dataset.userName)) { element.style.opacity = '0.3'; } }); }, 3000);
const shuffle = (array) => {
for (let i = array.length - 1; i >= 0; i--) {
const rand = Math.floor(Math.random() * (i + 1)); // 0〜iのランダムな数値を取得
[array[i], array[rand]] = [array[rand], array[i]]; // 要素の入れ替え
}
return array;
}
shuffle(['ラーメン', 'ピザ', 'カレー', 'ハンバーグ', 'チキン', 'オムライス', 'カツ丼', 'パスタ', 'フォーク', 'チャーハン', 'パン', 'パンケーキ', 'ライス', 'サラダ', 'チーズ', 'サンドイッチ'])[0]
'フォーク'
最近UserScriptを書くことに目覚めて、不便なWebサイトをちょっと改造して好みにするのにハマってる
例えば「辞書系のサイトなのにページを開いた瞬間から入力欄にカーソルがあってないのがいや」とか、そういう細かい点をこちらで勝手に改修するするような感じね
で、増田において「この人記事に対して毎回○○って反応つけてるけど面白いと思ってやってんのかな? 面白いと思ってやってんなら致命的に自分とセンスが合わないから消したいし、面白いと思ってないならただの害悪だから消したいな」と思うことがあるわけですが、そういった異なる価値観に対して自動的に適切な距離を置くためのスクリプトを作ったのでメモがてら貼り付けておきます
// ==UserScript== // @name ますだどくさいスイッチ // @namespace Violentmonkey Scripts // @match https://anond.hatelabo.jp/2* // @grant none // @version 1.0 // @author anond // @description description // ==/UserScript== (async () => { // ここにNGワードをどんどん追加する // 基本は文字列、文字列で引っ掛けにくいなら正規表現でもいい const keywords = [ "あえいうえおあお", ]; const checkedMarker = `data-a${Math.random().toString(36).slice(-8)}`; const query = `div[id^="excerpt-"]:not([${checkedMarker}]`; const delTree = () =>{ const elems = [...document.querySelectorAll(query)]; for(const elem of elems) { const textContent = elem.textContent; if(keywords.some((x) => (typeof x === "string") ? textContent.includes(x) : x.test(textContent))) { const parentContainer = elem.closest("li"); parentContainer?.remove(); } else { elem.setAttribute(checkedMarker, "true"); } } }; delTree(); const mo = new MutationObserver(delTree); mo.observe(document.body, { childList: true, subtree: true }); })();
keywordsを増やして君だけのどくさいスイッチを育ててね!
(追記)