「const」を含む日記 RSS

はてなキーワード: constとは

2024-04-14

モダンフロントエンドなんか意味ない

タイトル釣りです

去年から稼働している現場で、以前からあったReact Nativeの面倒を見ているんだがまあこれがひどい出来なんだ。

jQuery時代に見かけたようなコードをやたら見かけたので思わず懐かしくなってしまった。

リファクタリングしようとしたけど直す範囲が広すぎてアプリを壊しかねなかったので、早々に諦めてだましだまし保守をしていた。

そんな中今年に入ってアプリリニューアルの話が出てきた。React Native捨ててSwift/KotlinやらFlutterに書き換えるとかそういうのではなく、デザイン刷新といくつかの機能改修。

このままだとアプリが更に魔窟化するので、マネージャーに色々相談したところいくつかの事実がわかった。

ということだった。

結局現状のまま進めるわけにはいかず、要件定義の傍らリファクタリング作業をしている。

そういう経緯もあったので、リファクタリングテスト工数も積んだ上で見積もりだしてもらってる。

レガシーアーキテクチャモダンアーキテクチャ刷新」なんてよく聞く話しだけど、

実態は「長年の増改築とだましだましのリフォーム限界になってきたので新築で建て替えます」何だと思う。

最近は「Vue.jsからRemixマイグレーション」なんて見かけるけど、悪いのはVue.jsじゃなくて禄に設計しないでコード書いてるエンジニアと、

リファクタリングには予算でないけどマイグレーションなら予算取れるという悪しき風習

年がら年中フロントエンド刷新しているような会社地雷なので行かないほうがいい。

いくらRemixやらNext.jsやら最新鋭のフレームワーク使ってても、クソコードで書いたらクソが出来上がるだけだ。

新しいフレームワークを試す暇があったらリーダブルコード最初から読み直せ。

2024-01-25

スパム非表示

Tempermonkey にぶちこめ

// ==UserScript==
// @name         増田ミュート
// @namespace    http://tampermonkey.net/
// @version      2024-01-25
// @description  try to take over the world!
// @author       You
// @match        https://anond.hatelabo.jp/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hatelabo.jp
// @grant        none
// ==/UserScript==


function sleep(ms) {
    function timeout(resolve) {
         setTimeout(resolve, ms);
    }

    return new Promise(timeout);
}

(async function() {
    await sleep(100);

    const muteWords = [
        "https://huion.techinventory.com",
    ];

    const sections = document.getElementsByClassName("section");

    for (const sec of sections) {
        for (const word of muteWords) {
            if (sec.innerText.includes(word)) {
                sec.style.display = "none";
                break;
            }
        }
    }
})();

2024-01-10

まとめてユーザ非表示にする

しょうもない記事コメントしているしょうもないユーザーをまとめて非表示にする。

対象ページを開いてコンソールで下記を実行。

const targets = document.querySelectorAll('.entry-comment-ignoreuser');

targets.forEach((element)=>{

element.click();

});

(=>は半角にする)

2023-12-29

はてぶで松本人志顔写真を出さないようにするグリースモンキー

松本人志以外も消える

// ==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を使えよ。 これだと一瞬松本の顔が映るだろ

サンキューJS詳しくないから助かる

2023-12-08

[]標準的経済学MMT根本的違い

貨幣の総価値=y

単位あたりの貨幣価値=a

貨幣供給量=x

 

として、標準的経済学では(他の条件を一定とした時に)以下のように考えるのではないだろうか。

 

y = ax = const

 

重要なのはこの"const"という部分で、一定の値を取ることを意味する。つまり、aが増加すればxは減少する。

 

一方で、MMT仮定していることは何かというと、

 

y(x) = ax, a=const

 

である。この場合、aは減少も増加もしないので、xを増やせば増やすだけyが増加することになる。

これでMMT信者が言いたいことが大体分かってくる。以下は、標準的な考えからMMT批判するとどうなるのかというのを書く。

 

MMT現代貨幣理論)は、政府貨幣供給を増やすことで経済全体の価値を増やすことが可能であると主張する。しかし、この理論はいくつかの問題点がある。

まず、インフレーションリスクであるMMTは、貨幣供給を増やすことで経済活動を刺激すると主張している。しかし、貨幣供給が増えると、通常は物価が上昇する傾向がある。つまりインフレーションリスク高まる。これは、貨幣価値が下がり、生活費が上昇するという結果をもたらす。

次に財政規律の欠如であるMMTは、政府が無制限貨幣を発行できるという考え方を推奨している。しかし、これは財政規律を欠く可能性があり、長期的には経済の安定性を損なう

外国為替レートへの影響も懸念される。国が大量の貨幣を発行すると、その国の通貨価値他国通貨に対して下落する。これは、輸入費用の増加や投資流出を引き起こす。

MMT一見魅力的な理論に見えるが、実際には多くの経済的な問題を引き起こすだろう。

2023-08-04

綺麗なコードって綺麗に書くことじゃないよ

本当にあった話だけど、JavaScriptstrっていう変数テキストが入っていて

その変数に'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を書きましょう」

とかをPRレビューコメントしても

「動いてるからいいじゃない」

「綺麗に書いても性能上意味ない」

「言ってることが良く分からない。何が違うのか」

とか言ってくるし

言ってこなくて言われた通りに直しても次もまた同じことしてくるのでマジでレビューって大変だよ

2023-07-23

素早くブクマされた増田を強調 簡易セルクマ検知ユーザースクリプト

https://b.hatena.ne.jp/site/anond.hatelabo.jp

で動くスクリプトでたとえば投稿10分以内にブクマされページに乗ったら「1 user」が「1 user セルクマ 1とか5(何分後にブクマされたか)」になる。もしマイナスなら誤判定なので無視して。

時間を置いたセルクマには効かないし普通ファーストブクマカがどれぐらいの頻度で確認してるかしらないけど5分以内や1分以内もポロポロあるのでまあ目安に。

増田URLと一覧の時刻表示差分を取ってます

増田じゃpre記法でも記号が変換されるみたいだから作業

.forEach(div => {

('.entrylist-contents-title > a')

if(diffSec >

とかの

<>

<>

に変えてね

他にも見落としあるかも

誤判定が減るから非公開ファーストブクマを判定できたらいいんだけどね。

// ==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 =&gt; {
    const masuda = div.querySelector('.entrylist-contents-title &gt; 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 &gt; threshold) {
      return
    }
    // ブクマ user
    const user = div.querySelector('span.entrylist-contents-users a').lastChild
    user.textContent += ' セルクマ ' + (diffSec / 60)

    // 古い記事マイナスになる でも2015年ぐらいの記事までかな?新着はセーフ臭い
    /*
    if(diffSec &lt; 0) {
      user.textContent += ' 異常差分:' + diffSec
    }
    */
  })
})();

2023-03-04

朝日新聞digitalプレゼント機能

無料会員のタダ読み3本機能の代わりに導入された有料会員によるプレゼント機能が導入されてもう1年(?)。増田が初めて知ったのはwattoさんのブコメプレゼントURLを貼ってくれた時だが、最近になってTwitterスーパーインフルエンサーの暇空アノンいちゃもんのおかげで一気に機能が周知された。その結果なのかTwitterでもプレゼントURLの貼り付けが増えた感。

面白いのは、いわゆるリベラル系のアカウントの利用のみならず、反リベラル系の有名アカウントもちらほらとプレゼント機能を利用してるってことな。閲覧数は反リベラル系が圧倒的。まあそれなりにコンサル系や研究者系なら思想の左右問わず朝日読売日経辺りを読まないわけにはいかないし、中立アピールのためにあえて朝日ソースを使うってことかな

 

そして我ながらとんでもなくみみっちいブックマークレットをChatGPTに頼んで作ってもらった

朝日有料記事プレゼント検索

朝日デジタルの有料記事ページを開いている時にクリックするとTwitterで有料記事プレゼント機能を使ってる(と思われる)ツイート検索するブックマークレット

javascript: (() =&gt; { 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)}&amp;f=live`; window.open(searchUrl, %27_blank%27);})();

2023-02-15

リスト登録したユーザーはてブコメントを薄く表示するgreasemonkey

非表示機能で完全に無視したいって程でもないんだよな〜っていう。

タイプ別色分け機能とかこういうののはてなスター版とかも欲しい。面倒だから誰か書いて。

// ==UserScript==
// @name     hatebu_comment_usuku_hyouji
// @version  1
// @grant    none
// @include     https://b.hatena.ne.jp/entry/*
// ==/UserScript==

const userIdList = [
  'hoge',
  'piyo',
  ...
];

setInterval(() =&gt; {
  document.querySelectorAll('.entry-comment-contents').forEach((element, i) =&gt; {
    if (userIdList.includes(element.dataset.userName)) {
      element.style.opacity = '0.3';
    }
  });
}, 3000);

2023-02-09

anond:20230209202339

// 配列シャッフルする関数

const shuffle = (array) =&gt; {

for (let i = array.length - 1; i &gt;= 0; i--) {

const rand = Math.floor(Math.random() * (i + 1)); // 0〜iのランダムな数値を取得

[array[i], array[rand]] = [array[rand], array[i]]; // 要素の入れ替え

}

return array;

}

shuffle(['ラーメン', 'ピザ', 'カレー', 'ハンバーグ', 'チキン', 'オムライス', 'カツ丼', 'パスタ', 'フォーク', 'チャーハン', 'パン', 'パンケーキ', 'ライス', 'サラダ', 'チーズ', 'サンドイッチ'])[0]

'フォーク'

2023-02-03

最近UserScriptを書くのが楽しい

最近UserScriptを書くことに目覚めて、不便なWebサイトちょっと改造して好みにするのにハマってる

例えば「辞書系のサイトなのにページを開いた瞬間から入力欄にカーソルがあってないのがいや」とか、そういう細かい点をこちらで勝手に改修するするような感じね

で、増田において「この人記事に対して毎回○○って反応つけてるけど面白いと思ってやってんのかな? 面白いと思ってやってんなら致命的に自分センスが合わないから消したいし、面白いと思ってないならただの害悪から消したいな」と思うことがあるわけですが、そういった異なる価値観に対して自動的に適切な距離を置くためのスクリプトを作ったのでメモがてら貼り付けておきます

// ==UserScript==
// @name        ますどくさいスイッチ
// @namespace   Violentmonkey Scripts
// @match       https://anond.hatelabo.jp/2*
// @grant       none
// @version     1.0
// @author      anond
// @description description
// ==/UserScript==

(async () =&gt; {
    // ここにNGワードをどんどん追加する
    // 基本は文字列文字列で引っ掛けにくいなら正規表現でもいい
    const keywords = [
        "あえいうえおあお",
    ];

    const checkedMarker = `data-a${Math.random().toString(36).slice(-8)}`;
    const query = `div[id^="excerpt-"]:not([${checkedMarker}]`;

    const delTree = () =&gt;{
        const elems = [...document.querySelectorAll(query)];
        for(const elem of elems) {
            const textContent = elem.textContent;
            if(keywords.some((x) =&gt; (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 });
})();
  1. ブラウザーにTampermonkeyやViolentmonkeyをインストールしUserScriptを動かせるようにする
  2. インストールした拡張機能ダッシュボードを開き新規スクリプトを追加する
  3. 上記全てをペタッと貼り付ける
  4. 配列keywordsに消したい文字列またはそれにマッチする正規表現を入れる
    1. いくらでも追加可能
    2. 多少増えたところで大して重くはならないと思う
  5. Ctrl+Sを推して保存する
  6. 記事の反応のうち消したい文字列に当てはまる発言(とさらにそれに反応した発言)がツリーから消える

keywordsを増やして君だけのどくさいスイッチを育ててね!

(追記)

ぐええ 文字勝手に置換されてる…不便だなあ

&gt;」となっている箇所を「>」を半角で入力したものに置き換えてください

2022-12-04

Chat.OpenAIゲキヤバ。まじでちょっとした処理はググる必要なくなった

俺:

javascript言語で、現在時刻のタイムスタンプからMD5ハッシュ値を出力する関数、timeToMd5 を作ってください

JavaScriptでは、次のような関数作成することができます

function timeToMd5() {
  // 現在時刻のタイムスタンプを取得しまconst timestamp = Date.now();

  // ハッシュ値を出力するために、MD5ライブラリロードしまconst md5 = require('md5');

  // timestampを文字列に変換し、それをMD5ハッシュ値に変換して出力しまconst hash = md5(timestamp.toString());
  return hash;
}

このような関数作成することで、現在時刻のタイムスタンプからMD5ハッシュ値を出力することができます

ご参考までに。

俺:

nodeコマンドで実行しましたが、"Error: Cannot find module 'md5'" というエラーになってしまいました。なにか解決方法がありますか?

質問のように、JavaScript定義した関数を実行すると、"Error: Cannot find module 'md5'" というエラーが発生しているようです。

このエラーが発生する原因は、JavaScriptコード内で、MD5ライブラリロードしようとしたときに、そのライブラリインストールされていないためです。

JavaScriptコードで、MD5ライブラリを利用するには、まず、そのライブラリインストールする必要があります

インストールするには、次のように、nodeコマンドを実行します。

$ npm install md5

このコマンドを実行することで、MD5ライブラリインストールされ、JavaScriptコードから利用することができるようになります

また、JavaScriptコードを実行するには、次のようにnodeコマンド使用します。

$ node [JavaScriptファイル名]

このようにすることで、JavaScriptコードを実行することができます

ご参考までに。

俺:

ありがとうございます。実行できました😁

おめでとうございます!ご質問いただいた内容について、正しく解決されたようで嬉しいです。

しまだご質問があるようでしたら、お気軽にお問い合わせください。今後とも、Assistantをご利用いただけますよう、よろしくお願いいたします。

2022-11-06

anond:20221102154429

これまだ1/2だとか言っている人がいるので、本当に2/3かどうかプログラミングで確かめれば良い。

// 「ある夫婦に2人子供がいる」
// 1. 男or女 である確率は 1/2 (トランスジェンダーなどは考えない)
function child() { return ["男", "女"][Math.round(Math.random())]; }
// 2. 100000組の二人の子がいる夫婦を作る
const families = Array(100000).fill(null).map(function () { return [child(), child()] });

// 「片方の子が男であるとき」
// 3. その中で少なくとも一人が男である夫婦を選ぶ
const families_have_son = families.filter(function (children) { return ~children.indexOf("男"); });

// 「もう片方が女である確率は?」
// 4. 3の総数が母数である
const total = families_have_son.length;
// 5. 3の中で、女のいる夫婦を選ぶ
const families_have_son_and_dauter = families_have_son.filter(function (children) { return ~children.indexOf("女") });
// 6. 5を母数で割る
console.log(families_have_son_and_dauter.length / total);

ブラウザコンソールに打ち込めば動くので試してみてほしい。

私の環境では 0.6674999002778923 になった。

2/3が正しそうだ。

実際には、このコードを書いている時点で答えは明確になってしまう。

コードに落とし込むことによって隠された前提をつまびらかにする必要が出るため、実行ボタンを押す以前にはっきりする事がある。

よくわからない問題コードに落とし込むとよい。

ちなみに 1/2 にしたければ、

// 「片方の子が男であるとき」
// 3. その中で「はじめの子」が男である夫婦を選ぶ(間違い)
const families_first_is_son = families.filter(function (children) { return children[0] === "男" });
const total = families_first_is_son.length;
// 5. 3の中で、「次の子が」女である夫婦を選ぶ
const families_first_is_son_and_second_is_dauter = families_have_son.filter(function (children) { return children[1] === "女"; });
// 6. 5を母数で割る
console.log(families_first_is_son_and_second_is_dauter.length / total);

のようにすれば予想通り 0.49868384317792047...(1/2に近似する) のようになる。

しかしこれは問題文の読み間違いであるということがわかる。

2022-08-01

anond:20220731183342

自動安価をつけて返信するプログラムでもこんなに長く複雑になる(一部抜粋) 

/**************************************

以下のCSV_DIR, FILE_PATHS, SETTINGSを書き換えてね。 &lt;h3&gt;o- *************************************/&lt;/h3&gt;

//CSVファイルが置かれてるディレクトリパス投稿前にエラー出たら大体ここの設定ミス。 例:"C:\\Users\\sakuraimasahiro\\Documents\\iMacros\\Macros\\rentou\\";

const CSV_DIR =

'C:\\Users\\USER\\Desktop\\iMacros\\Macros\\rentou\\';

//ファイルパスCSV絶対パスで、拡張子必要。iimは相対パスでよく、拡張子不要

const FILE_PATHS = {

//投稿文が書かれたCSVファイル

textCsv: CSV_DIR + 'textNoAnker.csv',

//レス投稿文が書かれたCSV。通常とレス用で分けないなら同じファイルを使えばいい。

replyTextCsv: CSV_DIR + 'textReply.csv',

};

const SETTINGS = {

//投稿後の基本待ち時間

baseWaitTime: 5,

//baseWaitTime+0~waitTimeRange(ランダム)だけ待つ

waitTimeRange: 5,

//連投しすぎだと忠告された場合に処理を一時停止させる時間(秒)

waitTimeForAvoidingPunishment: 60 * 30,

//メール

mail: 'sage',

//名前設定

nameSettings: {

//名前名無しなら''。

name: '',

//以下、偽装ワッチョイ設定。浪人ワッチョイを非表示にしてるときだけtrueにしてね。

//妙なニックネーム(ワッチョイ、アウアウウーなど)をランダムで決めて付加するかどうか。true=付加する。false=付加しない。

nickname: false,

//妙なニックネームの後に付く8桁の文字列ランダムで決めて付加するかどうか。

korokoro: false,

//IPランダムで決めて付加するかどうか。

ip: false,

//地域ランダムで決めて付加するかどうか。

area: false,

},

postSettings: {

//アンカー無し投稿をするならtrue。しないならfalse。noAnkerPostかreplyPostのどちらかはtrueにすること(両方trueでもOK)。

noAnkerPost: false,

//アンカー付き投稿(返信)をするならtrue。しないならfalse。もしnoAnkerPostとreplyPostの両方がtrue場合投稿は返信が優先され、返信対象が見つからなくなったらアンカー無し投稿をする。

replyPost: true,

//最初に取得するアンカー無し投稿CSVファイルの行番号。もし返信用と同じCSVファイルを使うなら-1と入力

noAnkerPostTextCsvStartRow: 1,

//最初に取得する返信用投稿CSVファイルの行番号。もしアンカー無しと同じCSVファイルを使うなら-1と入力

replyPostTextCsvStartRow: 1,

//テキストCSV/返信用テキストCSVの取得行が最終行に達したら最初の行まで戻るかどうか。true=戻る。false=マクロ終了。

textCsvLoop: true,

//返信する場合、これより小さなレス番には返信しない。返信を投稿すると、この数値は前回の返信先のレス番に更新される。

minAnker: 895,

//返信する場合名前に以下の文字列を含む投稿アンカーをつけて返信する(ワッチョイやIPなど名前フィールドにあるものならなんでも可)。配列複数指定可能指定無しなら空配列([])。filterNamesとfilterNamesNotIncluded共に無指定ならレス番1から順に返信していく(minAnkerが設定されてればそこから順に)。以下のfilter系は全て併用可能

filterNames: [],

//↑とは逆に、名前に以下の文字列を含まない投稿アンカーをつけて返信する。↑と併用も可能

filterNamesNotIncluded: [],

//返信する場合、本文に以下の文字列を含む投稿アンカーをつけて返信する。

filterText: ['自演かな', '自演わらわら', 'スクリプト使うの', '安価ガバ', '&gt;&gt;660', '自演擁護', '最後' ,'あいうえお', 'かきくけこ', 'さしすせそ', 'なにぬねの', 'はひふへほ', 'まみむめも', 'やいゆえよ', 'やゆよ', 'らりるれろ', 'わいうえを', 'わをん', 'わいうえをん'],

},

//自分IPアドレス確認VPNとかでIPを変更してマクロを動かしてるとき、突然VPN作動しなくなってIPが元に戻ったときマクロを止めるためのもの

ipSettings: {

//自分現在IPアドレス確認をする。

checkIp: true,

//以下の文字列自分現在IPアドレスに含まれている場合マクロを一時停止する。基本的自分の本当のIPアドレス入力

avoidTheIp: '133.206.99.224',

},

//浪人設定。最後動作確認したのは5年くらい前で、今も同じように動作するかは、浪人を持ってないか確認できずわからない。

roninSettings: {

//浪人ログインしてるかどうかをチェックするかどうか。trueらするfalseならしない。trueにしていてもし浪人ログインしていないことを確認したらログインしにいく。

checkLogin: false,

//浪人ログインメールアドレス

mailAdress: 'abc@def.com',

//浪人ログインパスワード

password: '1234',

},

//false: run()実行させず(デバッグ用)

run: true,

//true: 投稿処理だけしない デバッグ

skipPost: false,

};

/**************************************

設定箇所終わり。

書き込めない時の早見表 - 5ちゃんねるwiki

https://info.5ch.net/index.php/%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%82%81%E3%81%AA%E3%81%84%E6%99%82%E3%81%AE%E6%97%A9%E8%A6%8B%E8%A1%A8 &lt;h3&gt;o- *************************************/&lt;/h3&gt;

/**************************************

メモ

クラスフィールド宣言できない。

・NULL演算子(??)は使えない。論理積(&amp;&amp;)は使える。

オブジェクトの分割代入はできない。

・importはできない。 &lt;h3&gt;o- *************************************/&lt;/h3&gt;

/**************************************

関数 &lt;h3&gt;o- *************************************/&lt;/h3&gt;

/**

* ここから始まる。

*/

function run() {

//設定ミスがないか調べる。

checkSettings();

var _TextCsvCursors = new TextCsvCursors(

new TextCsvCursor(

SETTINGS.postSettings.noAnkerPostTextCsvStartRow &gt; 0

? SETTINGS.postSettings.noAnkerPostTextCsvStartRow - 1

: SETTINGS.postSettings.noAnkerPostTextCsvStartRow,

FILE_PATHS.textCsv,

SETTINGS.postSettings.textCsvLoop,

),

new TextCsvCursor(

SETTINGS.postSettings.replyPostTextCsvStartRow &gt; 0

? SETTINGS.postSettings.replyPostTextCsvStartRow - 1

: SETTINGS.postSettings.replyPostTextCsvStartRow,

FILE_PATHS.replyTextCsv,

SETTINGS.postSettings.textCsvLoop,

),

);

var _LoopStatuses = new LoopStatuses(0, SETTINGS.postSettings.minAnker);

const _MyPosterName = new MyPosterName({

name: SETTINGS.nameSettings.name,

});

//スレURL指定

const _ThreadUrl = openPromptThreadUrl();

//ループ

while (true) {

//IP確認する設定なら、それをする。

SETTINGS.ipSettings.checkIp &amp;&amp; checkCurrentIpNotTheIp();

//スレを開く

openUrl(_ThreadUrl.fullUrlHttps());

//浪人ログインする設定なら、浪人ログインしているかどうかを確認し、していなければログインしにいく。

if (SETTINGS.roninSettings.checkLogin) {

if (!checkRoninLogin()) {

loginRonin();

continue;

}

}

//投稿に使うテキスト取得。

const p = (function () {

if (SETTINGS.postSettings.replyPost) {

//返信あり設定の場合。返信対象が無いか調べる。

const targetAnkerNumber = createPostDOMList()

.filterPostnumberHigher(_LoopStatuses.currentMinAnker())

.filterByPostername(SETTINGS.postSettings.filterNames)

.filterByPosternameNotIncluded(

SETTINGS.postSettings.filterNamesNotIncluded,

)

.filterByText(SETTINGS.postSettings.filterText)

.lowestPostNumber();

if (targetAnkerNumber !== null) {

//返信対象があったのでアンカー付き投稿文を作る。

const r = _TextCsvCursors.takeNextRowTextAsReply(targetAnkerNumber);

messageDisplay(`返信対象有り。アンカー先: ${targetAnkerNumber}`);

return {

...r,

updatedLoopStatuses:

_LoopStatuses.updateMinAnker(targetAnkerNumber),

};

}

}

if (SETTINGS.postSettings.noAnkerPost) {

//返信対象無し、或いは返信しない設定の場合アンカー無し投稿文を作る。

const r = _TextCsvCursors.takeNextRowTextAsNoAnker();

messageDisplay('返信対象無し。アンカー無し投稿。');

return {

...r,

updatedLoopStatuses: _LoopStatuses,

};

}

return null;

})();

if (p) {

//投稿

postThenCheckError(

_ThreadUrl.serverName(),

_MyPosterName.randomize({

nickname: SETTINGS.nameSettings.nickname,

korokoro: SETTINGS.nameSettings.korokoro,

ip: SETTINGS.nameSettings.ip,

area: SETTINGS.nameSettings.area,

}),

SETTINGS.mail,

p.text,

);

//_TextCsvCursorsと_LoopStatusesを更新

_TextCsvCursors = p.updatedTextCsvCursors;

_LoopStatuses = p.updatedLoopStatuses.incrementPostCount();

messageDisplay([

`投稿回数: ${_LoopStatuses.currentPostCount()}`,

`minAnker: ${_LoopStatuses.currentMinAnker()}`,

`今回アンカー無し投稿取得行: ${_TextCsvCursors.currentRows().noAnker}`,

`今回アンカー有り投稿取得行: ${_TextCsvCursors.currentRows().reply}`,

]);

} else {

messageDisplay([

`返信対象が現われるのを待機中...。`,

`投稿回数: ${_LoopStatuses.currentPostCount()}`,

`minAnker: ${_LoopStatuses.currentMinAnker()}`,

`今回アンカー無し投稿取得行: ${_TextCsvCursors.currentRows().noAnker}`,

`今回アンカー有り投稿取得行: ${_TextCsvCursors.currentRows().reply}`,

]);

}

//短時間で連投しまくると規制されるので一定時間待機。

wait(SETTINGS.baseWaitTime + randomRange(0, SETTINGS.waitTimeRange));

}

}

/**

* 投稿処理と投稿結果を見てリトライしたりマクロ終了したり。

* @param {string} serverName サーバー

* @param {MyPosterName} _MyPosterName

* @param {string} postMail メール

* @param {MyText} _MyText

* @param {number} retryTimes

* @returns {void}}

*/

function postThenCheckError(

serverName,

_MyPosterName,

postMail,

_MyText,

retryTimes = 0,

) {

const r =

retryTimes === 0

? new ValuesOfPost(serverName, _MyPosterName, postMail, _MyText).post(

postTo5chTread,

postConfirm,

)

: new ValuesOfPost(

serverName,

_MyPosterName,

postMail,

_MyText,

).postSubstring(retryTimes, postTo5chTread, postConfirm);

if (r) {

back();

return;

}

//エラーページに飛ばされた。エラー情報取得。

wait(7);

const error = createPostErrorMessage().analyze();

messageDisplay(error.message);

if (error.order === 'KILL') {

kill();

} else if (error.order === 'SKIP') {

return;

} else if (error.order === 'TRUNCATE') {

back();

return postThenCheckError(

serverName,

_MyPosterName,

postMail,

_MyText,

retryTimes + 1,

);

} else if (error.order === 'WAIT') {

wait(SETTINGS.waitTimeForAvoidingPunishment);

return postThenCheckError(

serverName,

_MyPosterName,

postMail,

_MyText,

retryTimes,

);

} else if (error.order === 'LOGIN') {

//動作未確認

return postThenCheckError(

serverName,

_MyPosterName,

postMail,

_MyText,

retryTimes,

);

}

return;

}

/**

* 現在IPアドレスに、SETTINGS.ipSettings.avoidTheIpの値が含まれていないことを確認する。含まれていたらマクロを一時停止。

* @returns

*/

function checkCurrentIpNotTheIp() {

//IP確認ページへ飛ぶ

openUrl('https://www.cman.jp/network/support/go_access.cgi');

const _IpAdress = createIpAdressFromCMan();

if (_IpAdress.includes(SETTINGS.ipSettings.avoidTheIp)) {

pause('現在IP指定した値が含まれていることを確認。');

//ポーズ解除したならもう一度確認しに。

checkCurrentIpNotTheIp();

}

return;

}

/**

* 設定に致命的な問題が無いか検査

* @returns

*/

function checkSettings() {

if (

SETTINGS.postSettings.noAnkerPost === false &amp;&amp;

SETTINGS.postSettings.replyPost === false

) {

return kill('設定エラー。noAnkerPostとreplyPost両方ともfalseになってる。');

}

if (

SETTINGS.postSettings.noAnkerPostTextCsvStartRow &lt; 0 &amp;&amp;

SETTINGS.postSettings.replyPostTextCsvStartRow &lt; 0

) {

return kill(

'設定エラー。noAnkerPostTextCsvStartRowとreplyPostTextCsvStartRow両方とも-1になってる。',

);

}

if (

SETTINGS.postSettings.noAnkerPostTextCsvStartRow === 0 ||

SETTINGS.postSettings.replyPostTextCsvStartRow === 0

) {

return kill(

'設定エラー。noAnkerPostTextCsvStartRow/replyPostTextCsvStartRowの初期値は-1或いは1以上で。',

);

}

}

/**

* 入力フォームを表示して入力されたスレURLを受け取る。

* @returns {ThreadUrl}

*/

function openPromptThreadUrl() {

const url = prompt('スレURL入力');

return new ThreadUrl(url);

}

/**

* 開いてるスレレス全て読み取ってPostListインスタンスを作って返す。

* 重すぎるので使うのやめ。どうやらインスタンスの大量生成が原因な模様。

* createPostDOMListを使う。

* @returns {PostList}

*/

function createPostList() {

const posts = window.document.getElementsByClassName('post');

return new PostList(Array.from(posts).map((e) =&gt; new Post(e)));

}

/**

* 開いてるスレレス全て取得してPostDOMListに格納して返す。

* @returns

*/

function createPostDOMList() {

const posts = window.document.getElementsByClassName('post');

var arrPostDOMList = [];

for (let index = 0; index &lt; posts.length; index++) {

//HTMLCollectionからElementを1つずつ抽出して配列に。

arrPostDOMList.push(posts.item(index));

}

return new PostDOMList(arrPostDOMList);

}

/**

* 開いてる投稿結果画面に表示されてるエラーを読み取ってPostErrorMessageインスタンスを作って返す。

* @returns {PostErrorMessage}

*/

function createPostErrorMessage() {

return new PostErrorMessage(

window.document

.g Permalink | 記事への反応(0) | 15:40

2022-05-29

anond:20220529230142

今はもう let と const が主流で var は使わないんだよ

2022-05-13

anond:20220513182540

シャッフル乱数の生成回数が多いので

const list = [0,1,2,3,4,5,6,7,8,9];
const a = list.splice(Math.floor( Math.random() * 10), 1); // 0~9のインデックスランダムに得てそのインデックスの値を取りだす、その要素を配列から削除。
const b = list.splice(Math.floor( Math.random() * 9), 1); // 0~8のインデックスランダムに得て(ry
const c = list.splice(Math.floor( Math.random() * 8), 1); // 0~7の(ry

とやると乱数生成3回で済むのでもしかしたら少し軽くなるかも

2022-05-12

White 200解いてみた

const inhtml = document.getElementById('problem_text').innerHTML.replace('この白を探せ!&lt;br&gt;#', 'col_');
const el = document.getElementsByClassName("alternatives");
let idd = '';
for( let i = 0 ; i &lt; el.length ; i ++ ) {
  idd=el[i].getAttribute("id");
  if(inhtml == idd){
    var clickMe = document.getElementById(idd);
    if( /*@cc_on ! @*/ false ) {
        clickMe.fireEvent("onclick");
    }
    else {
        var event = document.createEvent( "MouseEvents" );
        event.initEvent("click", false, true);
        clickMe.dispatchEvent(event);
    }
  }
}

はてなに棲息するスーパーハカーならもっと良いコードが書けるだろ?

2022-04-15

プログラミングだけ教えるのは難しい

例えばJavaScriptリストコピーするとき

const newList = list.slice();

って書かないとダメだよ、と教えるのは簡単

しかし、

「なんで const newList = listじゃダメなんですか?」

と聞かれると非常に困る。

例えばconst a = 123と入っているときに、bにコピーたかったらconst b=aで良い。

プリミティブと配列の違いとして覚えてもらう、という方法もあるけれど

じゃぁ文字列はどうなんですか?となると非常に困る。

JavaScriptだけを教えるならそれでも問題いかもしれないが、Pythonも一緒に教えるとかなるとカオスになる。

結局のところ、コンピュータの仕組みを理解してもらって、メモリアドレスとかポインタを知ってもらい

それからプリミティブや配列の話をしないと根本的には説明できない。

単純なプログラミング教育ってこの辺が破綻してると思っているので、結局はPC構造機械語アセンブリ言語C言語と順番に教える必要があると思っている。

2022-04-06

ニコニコプレミアムアワードランキングが酷いのでアレを非表示にするスクリプト

ニコニコプレミアムアワードランキング、某んがすランキングになっていて鬱陶しいので、ふにん某を非表示にするスクリプトを書いた。

Tempermonkeyとかで使ってくれ。文字実体参照は適宜置き換えること。

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       masuda
// @match        https://site.nicovideo.jp/premiumaward/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=nicovideo.jp
// @grant        none
// ==/UserScript==

const sleep = (ms) =&gt; new Promise((resolve) =&gt; setTimeout(resolve, ms));

const blockList = [
    "ふにんがす",
    "なのそん",
    "Among us",
    "Among Us",
    "アモアス",
];

(async function() {
    'use strict';

    await sleep(100);
    const list = document.querySelectorAll("li.game");

    for (const elem of list) {
        const title = elem.getElementsByClassName("title")[0].innerText;
        if (blockList.some((word) =&gt; title.includes(word))) {
             elem.remove();
        }
    }
})();

https://site.nicovideo.jp/premiumaward

2022-02-22

ES6

const masuda = (masuda_boyaki) => {

 return masuda_boyaki.map(el => el.includes("クンニ") ? "✋(👁👅👁)🤚せい!" : "クンニ🤚(👁_👁)✋せん" )

}

console.log(masuda(data))

2022-01-01

anond:20220101145248

正直動けばいいと思うので、現状でも問題ないと思うけれどちょっとだけ気になった点。

$$使ってる時点で、デベロッパーツール前提なのは分かるけど、 javascriptで動かしたいのか、デベロッパーツールで動かしたいのか、どっちつかずな書き方になっている。

$$('.hatena-star-inner-count').map(a =&gt; a.click());
let data = {};
Array.from($$('.entry-comment-contents')).forEach(x =&gt; {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y =&gt; y.href.split('/')[3]);data[userName] = [comment, stars];});
console.info(Object.entries(data).map(x =&gt; { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&#92;n"));

デペロッパツールだけで動くだけでいいなら、3行目のArray.fromがなくても動く。多分、forEachをmapに書き換えても動く。個人的にはforEachに統一したいけど、そこは好みレベル問題だと思う。

$$('.hatena-star-inner-count').map(a =&gt; a.click());
let data = {};
$$('.entry-comment-contents').forEach(x =&gt; {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y =&gt; y.href.split('/')[3]);data[userName] = [comment, stars];});
console.info(Object.entries(data).map(x =&gt; { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&#92;n"));

逆に、javascriptで動かしたいなら1行目と3行目はquerySelectorAllに書き換えれる。

document.querySelectorAll('.hatena-star-inner-count').forEach((a)=&gt;{a.click()});
let data = {};
document.querySelectorAll('.entry-comment-contents').forEach(x =&gt; {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y =&gt; y.href.split('/')[3]);data[userName] = [comment, stars];});
console.info(Object.entries(data).map(x =&gt; { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&#92;n"));

これも好みの問題だけど、途中のconst宣言は一回しか使ってないので、宣言せずにそのまんま入れてもいいんじゃないかと思った。

document.querySelectorAll('.hatena-star-inner-count').forEach((a)=&gt;{a.click()});
let data = {};
document.querySelectorAll('.entry-comment-contents').forEach(x =&gt; {data[x.querySelector('.entry-comment-username a').href.split('/')[3]] = [x.querySelector('.entry-comment-text').innerText, Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y =&gt; y.href.split('/')[3])];});
console.info(Object.entries(data).map(x =&gt; { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&amp;#92;n"));
|&lt;&lt;

2021-08-16

anond:20210816122630

でもよー、それJavaScriptだろ?

const sode = [];  // 袖が存在しない!
const swing = sode.every(it => it.canSwing); // 振れるだろ?
console.log(swing); //=> true(振れるぜ)

だぜ。

2021-08-05

クマをわらわらさせたい

anond:20210803181833

aa ʕ•̫͡•ʕ•̫͡•ʕ•̫͡•ʕ•̫͡•ʕ•̫͡•ʕ•̫͡•ʔ

じゃなくて

aa ʕ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ•̫͡•ʕ•̫͡•ʔ•̫͡•ʔ

にしたい

javascript:(function (d, lowerThan, count) {
  const MinimumRequiredLength = 33;
  let currentCount = count();

  const elem = d.querySelectorAll(".bookmarkadd-comment-form")[0];
  if (!elem) {
    return;
  }

  if (lowerThan(count(), MinimumRequiredLength)) {
    if (elem.value.slice(-1) !== " ") {
      elem.value += " ";
      currentCount += 1;
    }
  }

  if (lowerThan(count(), MinimumRequiredLength)) {
    const kumas = ['ʕ•̫͡•', 'ʔ•̫͡•'];
    const indexes = '001101';
    for (let i = 0; i === 0 || (lowerThan(currentCount + i * 5, MinimumRequiredLength) || currentCount + i * 5 === MinimumRequiredLength); i++) {
      elem.value += kumas[indexes[i % 6]];
    }

    elem.value += 'ʔ';
    elem.dispatchEvent(new Event("input"));
  }
})(document,
  function(a, b) { return Math.floor(b / a) !== 0 },
  function() { return Number(document.querySelectorAll('.js-bookmarkadd-comment-count')[0].innerText) || 0 }
); //add bear

こういう、特定URL特定bookmarklet を呼び出す extension とか欲しい。これは用途に合わないけれど、クマを消すやつは自動で実行されてほしいものだろうし

ログイン ユーザー登録
ようこそ ゲスト さん