「true」を含む日記 RSS

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

2025-07-28

Https Only有効でも任意認証リクエストを送ることができるNEW

HttpOnlyが有効でも任意認証リクエストを送ることができる

HttpOnlyがtrueになっていてブラウザからCookieの値が直接読めないとしても、サービス内のAPIリクエストを送れば勝手Cookieがついていってしまます

例えば以下のようなコードをしれっと書いておくと、ゲームを開いた瞬間にユーザーアカウントが削除されます

💡 対策: 退会などの重要操作の前には再ログインを求める

💡 対策: コードを同じオリジンexample.com)で動かさな

https://www.imdb.com/list/ls4105500465/

https://www.imdb.com/list/ls4105577201/

https://www.imdb.com/list/ls4105577769/

https://arinaaratamantapenakser.wordpress.com/2025/07/28/about-security-when-creating-a-service-that-allows-others-to-run-user-submitted-code-on-a-browser/

新たにサービスを作るときの話になりますが、認証 Cookie名前に __Http- もしくは __HostHttp- プレフィックスを付けるのをお勧めしますね。

新しい機能のためまだ Chrome のみのサポートとなりますが、HttpOnly 属性強制されるので、つけ忘れの防止になります

HttpOnly属性だけでは、対策しきれず credentials: "include" を使えば、HttpOnly属性を含んだcookieも取れてしまうって聞いたのですが、これって本当ですか?

Request の credentials: "include" は別のオリジンリクエストを飛ばす場合でも(そのサイトで設定された)Cookie を含めるかどうかを指定するためのものですね。Cookie の中身が読み取れるものではありません。

2025-07-26

HttpOnlyが有効でも任意認証リクエストを送ることができる

HttpOnlyが有効でも任意認証リクエストを送ることができる

HttpOnlyがtrueになっていてブラウザからCookieの値が直接読めないとしても、サービス内のAPIリクエストを送れば勝手Cookieがついていってしまます

例えば以下のようなコードをしれっと書いておくと、ゲームを開いた瞬間にユーザーアカウントが削除されます

💡 対策: 退会などの重要操作の前には再ログインを求める

💡 対策: コードを同じオリジンexample.com)で動かさな

https://www.imdb.com/list/ls4100305657/

https://www.imdb.com/list/ls4100370775/

新たにサービスを作るときの話になりますが、認証 Cookie名前に __Http- もしくは __HostHttp- プレフィックスを付けるのをお勧めしますね。

新しい機能のためまだ Chrome のみのサポートとなりますが、HttpOnly 属性強制されるので、つけ忘れの防止になります

https://www.imdb.com/list/ls4100358676/

https://www.imdb.com/list/ls4100339792/

2025-07-24

anond:20250723030957

JSONと比べたときの**YAMLの「闇深」仕様**、ありますね…。

YAML人間に優しいと言われながらも、その仕様ときに**悪魔的**。

以下、ITエンジニアなら一度は踏んだであろう「地雷」を、**論理的かつ少し自虐的に**まとめてみました:

---

🔥 1. インデント=構文

good:
  value: ok
bad:
 value: nightmare  # ←ここ、インデントずれてて無効。だけど一見からない。

---

💣 2. 暗黙の型推論

  • `true`, `false`, `yes`, `no`, `on`, `off` は**勝手に boolean に変換**される。
  • `2021-12-25` → 日付扱い(Date型に変換されることもある)。
  • `12345` → 数値扱い。先頭0つけると8進数として怒られるケースも。
password: no  # ← 文字列じゃなくて false になる可能性
serial: 012345  # ← 8進数!?エラー

---

🧨 3. スカラー値の地雷原(改行、引用符…)

message: |
  これは複数行の
  スカラー値です。
  • 上記はまだいいが、`>` を使うと**改行がスペースに変換される**という謎挙動も。

---

🕳 4. マージキーアンカー(& と \*)

defaults: &defaults
  timeout: 30
  retries: 3

service:
  <<: *defaults
  retries: 5  # 上書きされるが、複雑になると意図しない結果に
</pre>
	
	

---

😱 5. コメントJSON存在しない → 変換できない

---

🧠 結論YAMLは**人間に優しい顔をしたパース殺し**

  • JSON:**機械に優しい、でも硬い**
  • YAML:**人間に優しい(ように見える)、でも罠だらけ**

---

もしYAML安全に扱いたいなら、\*\*JSON supersetとしての使い方(厳格YAML)\*\*を意識したり、**JSONに寄せて書く**のが一番平和だったりします。

---

要するに、YAMLは「賢く書こうとすると沼る」。

「素直に、簡潔に、禁欲的に」が正解です。

でも誘惑が多いのよね、あの子……。

2025-07-15

anond:20250715093704

MOMENTUM True Wireless 4 の金ぴかイヤホンカッコいいよね

ワイヤレスからワイは興味ないけど(ワイだけに)

ゼンハイザーに限らず

気になっているなら過去スレッドを御覧になるのがいいですよ

現行置いておくね

https://itest.5ch.net/mevius/test/read.cgi/av/1710278774/l-

ばーっとながめて評判を頭に叩き込む

壊れやすいかどうかなんてレビューしかからないですから

気になる機種があればXなどで追加でパブサすればよろしい

ただし音質を考えたらイヤホンよりもヘッドホンのほうが基本的にいいですよ

2025-07-13

非モテマッチングアプリ

While browsing online the other day, I came across a blog post about a 27-year-old man earning ¥4.2 million annually. He had long struggled with being unpopular and harbored misogynistic views. However, with the help of those around him, he began using a dating app, found a girlfriend, changed jobs, increased his income, and eventually married her—an apparent happy ending.

On the surface, it seems like a heartwarming success story. But one detail stood out: as soon as he began dating, his anti-woman sentiments seemingly vanished. This raised questions. Many “unpopular men” who develop a dislike for women often do so because of unrealistic expectations or disappointment. These attitudes often stem from a lack of real-life interaction with women and a failure to grasp the complexity of actual female individuals. In essence, it’s a tragedy born from inexperience.

Modern Japanese society, steeped in a form of “romance supremacy,” exacerbates this issue. Now, about 30% of single men in their 20s have never dated. With increased social scrutiny against sexual harassment, it’s harder to find romantic partners through natural social settings or introductions. As a result, only men with decent looks, communication skills, and income can realistically find partners while young. Even highly educated men with stable jobs are often struggling in this area.

Making matters worse, media representations of women are polarized. Anime and novels often depict overly strong or unreasonably kind female characters, while the internet is filled with negative stereotypes—so-called “sugar babies,” mothers who abduct children after divorce, and women who manipulate men through sexuality or political correctness. Constant exposure to such extremes distorts the perception of real women, creating a damaging cognitive dissonance.

Interestingly, once these anti-women men start dating, they often suddenly become lovestruck and overly affectionate. The gap between their imagined “evil woman” and the smiling, supportive girlfriend in front of them causes a complete mental reversal. From an outsider’s perspective, it may look like they’ve overcome their misogyny. But often, it’s merely a selective exemption: “My girlfriend is different; other women are still bad.” There is no true change in perspective.

Eventually, even the woman they idolized as “perfect” reveals both good and bad sides. This leads to a more nuanced understanding of women—not as ideals or villains, but as real, multifaceted human beings. That realization marks the true beginning of healing: the start of moving beyond unrealistic expectations and toward authentic coexistence with women.

In conclusion, overcoming misogyny isn’t just about finding a girlfriend. Real progress comes when a man can let go of extreme ideals and face women as equals, with both strengths and flaws. Only then does the journey toward genuine understanding and mutual respect begin.

2025-07-06

Mondayの作ってくれたやつ

オッケー。ワイくん、PONG現代召喚します。

まず、準備できてる?

Python 3.x インストール済み

pygame 入ってない人はコマンドラインでこれ:

pip install pygame

🎮 MondayPONG ゲームシンプルだけどちゃんと動く)

import pygame
import random
import sys

# 初期化
pygame.init()

# 画面サイズ
WIDTH, HEIGHT = 640, 480
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PONG by Monday")

# 色定義
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

# パドルボールの設定
PADDLE_WIDTH, PADDLE_HEIGHT = 10, 100
BALL_SIZE = 10
PADDLE_SPEED = 7
BALL_SPEED_X, BALL_SPEED_Y = 5 * random.choice((1, -1)), 5 * random.choice((1, -1))

# 左右のパドル位置
left_paddle = pygame.Rect(10, HEIGHT // 2 - PADDLE_HEIGHT // 2, PADDLE_WIDTH, PADDLE_HEIGHT)
right_paddle = pygame.Rect(WIDTH - 20, HEIGHT // 2 - PADDLE_HEIGHT // 2, PADDLE_WIDTH, PADDLE_HEIGHT)

# ボール
ball = pygame.Rect(WIDTH // 2, HEIGHT // 2, BALL_SIZE, BALL_SIZE)

# スコア
score_left = 0
score_right = 0
font = pygame.font.Font(None, 36)

clock = pygame.time.Clock()

# ゲームループ
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    # キー入力
    keys = pygame.key.get_pressed()
    if keys[pygame.K_w] and left_paddle.top > 0:
        left_paddle.y -= PADDLE_SPEED
    if keys[pygame.K_s] and left_paddle.bottom < HEIGHT:
        left_paddle.y += PADDLE_SPEED
    if keys[pygame.K_UP] and right_paddle.top > 0:
        right_paddle.y -= PADDLE_SPEED
    if keys[pygame.K_DOWN] and right_paddle.bottom < HEIGHT:
        right_paddle.y += PADDLE_SPEED

    # ボール移動
    ball.x += BALL_SPEED_X
    ball.y += BALL_SPEED_Y

    # 壁反射
    if ball.top <= 0 or ball.bottom >= HEIGHT:
        BALL_SPEED_Y *= -1

    # パドル反射
    if ball.colliderect(left_paddle) or ball.colliderect(right_paddle):
        BALL_SPEED_X *= -1

    # スコア処理
    if ball.left <= 0:
        score_right += 1
        ball.center = (WIDTH // 2, HEIGHT // 2)
        BALL_SPEED_X *= random.choice((1, -1))
    if ball.right >= WIDTH:
        score_left += 1
        ball.center = (WIDTH // 2, HEIGHT // 2)
        BALL_SPEED_X *= random.choice((1, -1))

    # 画面描画
    SCREEN.fill(BLACK)
    pygame.draw.rect(SCREEN, WHITE, left_paddle)
    pygame.draw.rect(SCREEN, WHITE, right_paddle)
    pygame.draw.ellipse(SCREEN, WHITE, ball)
    pygame.draw.aaline(SCREEN, WHITE, (WIDTH // 2, 0), (WIDTH // 2, HEIGHT))

    score_text = font.render(f"{score_left}   {score_right}", True, WHITE)
    SCREEN.blit(score_text, (WIDTH // 2 - score_text.get_width() // 2, 20))

    pygame.display.flip()
    clock.tick(60)

これ動かすと、ふたりPONG対戦できるぞ。

• 左パドル:W / S キー

• 右パドル:↑ / ↓ キー

• Esc 押すと終了(またはウィンドウ×)

このコード、わりと「教育的に健全地獄」だから自由拡張できるよ:

スコア10点で勝利

ボールが速くなっていく

BGM効果音追加

AI操作の右パドル化(←これやる?)

あとで「飴ちゃん飛ばすモード」とかも追加できるぞ。バカ拡張大歓迎。

どう?動いた?やってみて。報告もらえれば、次の「社会風刺機能付きPONG」考えておくわ。

 

https://anond.hatelabo.jp/20250706011306#

Grokが作ってくれたやつ


<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>GrokのPONGゲーム</title>
    <style>
        body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #1a1a1a; }
        canvas { border: 2px solid #00ff00; background: #000; }
        #score { color: #00ff00; font-family: 'Courier New', monospace; font-size: 24px; position: absolute; top: 20px; width: 100%; text-align: center; }
    </style>
</head>
<body>
    
0 : 0
<canvas id="gameCanvas" width="800" height="400"></canvas> <script> const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreDisplay = document.getElementById('score'); // ゲームオブジェクト const ball = { x: canvas.width / 2, y: canvas.height / 2, radius: 10, speedX: 5, speedY: 5 }; const paddleLeft = { x: 10, y: canvas.height / 2 - 50, width: 10, height: 100, speed: 8 }; const paddleRight = { x: canvas.width - 20, y: canvas.height / 2 - 50, width: 10, height: 100, speed: 8 }; let scoreLeft = 0, scoreRight = 0; // キー入力 const keys = { w: false, s: false, ArrowUp: false, ArrowDown: false }; document.addEventListener('keydown', e => { if (keys.hasOwnProperty(e.key)) keys[e.key] = true; }); document.addEventListener('keyup', e => { if (keys.hasOwnProperty(e.key)) keys[e.key] = false; }); // ゲームループ function gameLoop() { // 移動 if (keys.w && paddleLeft.y > 0) paddleLeft.y -= paddleLeft.speed; if (keys.s && paddleLeft.y < canvas.height - paddleLeft.height) paddleLeft.y += paddleLeft.speed; if (keys.ArrowUp && paddleRight.y > 0) paddleRight.y -= paddleRight.speed; if (keys.ArrowDown && paddleRight.y < canvas.height - paddleRight.height) paddleRight.y += paddleRight.speed; // ボール移動 ball.x += ball.speedX; ball.y += ball.speedY; // 壁衝突 if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) ball.speedY = -ball.speedY; // パドル衝突 if ( (ball.x - ball.radius < paddleLeft.x + paddleLeft.width && ball.y > paddleLeft.y && ball.y < paddleLeft.y + paddleLeft.height) || (ball.x + ball.radius > paddleRight.x && ball.y > paddleRight.y && ball.y < paddleRight.y + paddleRight.height) ) { ball.speedX = -ball.speedX * 1.05; // 少し加速 } // 得点 if (ball.x < 0) { scoreRight++; ballReset(); } if (ball.x > canvas.width) { scoreLeft++; ballReset(); } // 描画 ctx.fillStyle = '#000'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#00ff00'; ctx.fillRect(paddleLeft.x, paddleLeft.y, paddleLeft.width, paddleLeft.height); ctx.fillRect(paddleRight.x, paddleRight.y, paddleRight.width, paddleRight.height); ctx.beginPath(); ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2); ctx.fill(); scoreDisplay.textContent = `${scoreLeft} : ${scoreRight}`; requestAnimationFrame(gameLoop); } function ballReset() { ball.x = canvas.width / 2; ball.y = canvas.height / 2; ball.speedX = (Math.random() > 0.5 ? 5 : -5) * (Math.random() * 0.5 + 0.75); ball.speedY = (Math.random() * 4 - 2); } gameLoop(); </script> </body> </html>

 

 

https://anond.hatelabo.jp/20250706011306#

Claudeが作ってくれたやつ



<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PONG Game</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #000;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            font-family: 'Courier New', monospace;
            color: white;
        }

```
    .game-container {
        text-align: center;
    }
    
    canvas {
        border: 2px solid white;
        background-color: #000;
    }
    
    .score {
        font-size: 24px;
        margin: 20px 0;
        letter-spacing: 2px;
    }
    
    .controls {
        margin-top: 20px;
        font-size: 14px;
        opacity: 0.8;
    }
    
    .start-button {
        background-color: #333;
        color: white;
        border: 2px solid white;
        padding: 10px 20px;
        font-size: 16px;
        cursor: pointer;
        font-family: 'Courier New', monospace;
        margin: 10px;
    }
    
    .start-button:hover {
        background-color: white;
        color: black;
    }
</style>
```

</head>
<body>
    
<canvas id="gameCanvas" width="800" height="400"></canvas>
<button class="start-button" onclick="startGame()">ゲーム開始</button> <button class="start-button" onclick="resetGame()">リセット</button>

W/S キーまたは ↑/↓ 矢印キーパドル操作
``` <script> // Canvas要素とコンテキストの取得 const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); // ゲーム状態管理 let gameRunning = false; let animationId; // スコア要素の取得 const playerScoreElement = document.getElementById('playerScore'); const computerScoreElement = document.getElementById('computerScore'); // ゲームオブジェクト定義 const game = { // プレイヤーパドル(左側) playerPaddle: { x: 10, y: canvas.height / 2 - 50, width: 10, height: 100, speed: 5, upPressed: false, downPressed: false }, // コンピューターパドル(右側) computerPaddle: { x: canvas.width - 20, y: canvas.height / 2 - 50, width: 10, height: 100, speed: 3.5, // プレイヤーより少し遅く設定 targetY: canvas.height / 2 - 50 }, // ボールの設定 ball: { x: canvas.width / 2, y: canvas.height / 2, radius: 8, speedX: 4, speedY: 3, maxSpeed: 8 }, // スコア管理 score: { player: 0, computer: 0 } }; // キーボード入力の処理 const keys = {}; // キーが押されたときの処理 document.addEventListener('keydown', (e) => { keys[e.key.toLowerCase()] = true; // ゲームが停止中にスペースキーゲーム開始 if (e.key === ' ' && !gameRunning) { startGame(); } }); // キーが離されたときの処理 document.addEventListener('keyup', (e) => { keys[e.key.toLowerCase()] = false; }); // パドルの移動処理 function updatePaddles() { // プレイヤーパドルの移動(W/S キーまたは矢印キー) if (keys['w'] || keys['arrowup']) { game.playerPaddle.y -= game.playerPaddle.speed; } if (keys['s'] || keys['arrowdown']) { game.playerPaddle.y += game.playerPaddle.speed; } // プレイヤーパドルの画面外移動を防ぐ if (game.playerPaddle.y < 0) { game.playerPaddle.y = 0; } if (game.playerPaddle.y > canvas.height - game.playerPaddle.height) { game.playerPaddle.y = canvas.height - game.playerPaddle.height; } // コンピューターパドルAI処理 // ボール位置を追跡するが、完璧ではない動きを実装 const ballCenterY = game.ball.y; const paddleCenterY = game.computerPaddle.y + game.computerPaddle.height / 2; // ボールパドルの中心の差を計算 const difference = ballCenterY - paddleCenterY; // 反応に少し遅れを持たせる(人間らしい動き) if (Math.abs(difference) > 10) { if (difference > 0) { game.computerPaddle.y += game.computerPaddle.speed; } else { game.computerPaddle.y -= game.computerPaddle.speed; } } // コンピューターパドルの画面外移動を防ぐ if (game.computerPaddle.y < 0) { game.computerPaddle.y = 0; } if (game.computerPaddle.y > canvas.height - game.computerPaddle.height) { game.computerPaddle.y = canvas.height - game.computerPaddle.height; } } // ボールの移動と衝突判定 function updateBall() { // ボール位置更新 game.ball.x += game.ball.speedX; game.ball.y += game.ball.speedY; // 上下の壁との衝突判定 if (game.ball.y - game.ball.radius < 0 || game.ball.y + game.ball.radius > canvas.height) { game.ball.speedY = -game.ball.speedY; } // プレイヤーパドルとの衝突判定 if (game.ball.x - game.ball.radius < game.playerPaddle.x + game.playerPaddle.width && game.ball.x + game.ball.radius > game.playerPaddle.x && game.ball.y + game.ball.radius > game.playerPaddle.y && game.ball.y - game.ball.radius < game.playerPaddle.y + game.playerPaddle.height) { // ボールパドルに当たった位置によって跳ね返り角度を調整 const hitPos = (game.ball.y - (game.playerPaddle.y + game.playerPaddle.height / 2)) / (game.playerPaddle.height / 2); game.ball.speedX = Math.abs(game.ball.speedX); game.ball.speedY = hitPos * 4; // ボールの速度を少し上げる(ゲームをエキサイティングに) if (Math.abs(game.ball.speedX) < game.ball.maxSpeed) { game.ball.speedX *= 1.02; } } // コンピューターパドルとの衝突判定 if (game.ball.x + game.ball.radius > game.computerPaddle.x && game.ball.x - game.ball.radius < game.computerPaddle.x + game.computerPaddle.width && game.ball.y + game.ball.radius > game.computerPaddle.y && game.ball.y - game.ball.radius < game.computerPaddle.y + game.computerPaddle.height) { // ボールパドルに当たった位置によって跳ね返り角度を調整 const hitPos = (game.ball.y - (game.computerPaddle.y + game.computerPaddle.height / 2)) / (game.computerPaddle.height / 2); game.ball.speedX = -Math.abs(game.ball.speedX); game.ball.speedY = hitPos * 4; // ボールの速度を少し上げる if (Math.abs(game.ball.speedX) < game.ball.maxSpeed) { game.ball.speedX *= 1.02; } } // ボールが左右の壁を越えた場合得点処理) if (game.ball.x < 0) { // コンピューター得点 game.score.computer++; updateScore(); resetBall(); } else if (game.ball.x > canvas.width) { // プレイヤー得点 game.score.player++; updateScore(); resetBall(); } } // ボールリセット得点後の処理) function resetBall() { game.ball.x = canvas.width / 2; game.ball.y = canvas.height / 2; // ランダムな方向でボールを発射 game.ball.speedX = (Math.random() > 0.5 ? 4 : -4); game.ball.speedY = (Math.random() - 0.5) * 6; } // スコア表示の更新 function updateScore() { playerScoreElement.textContent = game.score.player; computerScoreElement.textContent = game.score.computer; } // 描画処理 function draw() { // 画面をクリア ctx.fillStyle = '#000'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 中央の点線を描画 ctx.setLineDash([5, 5]); ctx.beginPath(); ctx.moveTo(canvas.width / 2, 0); ctx.lineTo(canvas.width / 2, canvas.height); ctx.strokeStyle = '#fff'; ctx.stroke(); ctx.setLineDash([]); // プレイヤーパドルを描画 ctx.fillStyle = '#fff'; ctx.fillRect(game.playerPaddle.x, game.playerPaddle.y, game.playerPaddle.width, game.playerPaddle.height); // コンピューターパドルを描画 ctx.fillRect(game.computerPaddle.x, game.computerPaddle.y, game.computerPaddle.width, game.computerPaddle.height); // ボールを描画 ctx.beginPath(); ctx.arc(game.ball.x, game.ball.y, game.ball.radius, 0, Math.PI * 2); ctx.fillStyle = '#fff'; ctx.fill(); // ゲームが停止中の場合メッセージを表示 if (!gameRunning) { ctx.fillStyle = '#fff'; ctx.font = '20px Courier New'; ctx.textAlign = 'center'; ctx.fillText('ゲーム開始ボタンを押してください', canvas.width / 2, canvas.height / 2 + 60); } } // ゲームのメインループ function gameLoop() { if (!gameRunning) return; updatePaddles(); updateBall(); draw(); animationId = requestAnimationFrame(gameLoop); } // ゲーム開始 function startGame() { gameRunning = true; gameLoop(); } // ゲームリセット function resetGame() { gameRunning = false; if (animationId) { cancelAnimationFrame(animationId); } // スコアリセット game.score.player = 0; game.score.computer = 0; updateScore(); // ボールパドル位置リセット game.ball.x = canvas.width / 2; game.ball.y = canvas.height / 2; game.ball.speedX = 4; game.ball.speedY = 3; game.playerPaddle.y = canvas.height / 2 - 50; game.computerPaddle.y = canvas.height / 2 - 50; draw(); } // 初期描画 draw(); </script> ``` </body> </html>

 

 

https://anond.hatelabo.jp/20250706011306#

2025-07-05

🍬資本主義平等なのか飴の配布で考えてみよう🍬

python
import random
import numpy as np
import matplotlib.pyplot as plt
from collections import defaultdict

# 飴の配布システムシミュレーション
class CandyDistributionSystem:
    def __init__(self):
        """
        設計意図: このシステム経済における資源分配の不平等性をモデル化しています特に少数の特権層(Aグループ)が富を集中させ、再分配システムからも不均衡に利益を得る
        構造問題表現しています。
        """
        # 各グループの人数設定
        self.group_a_count = 8
        self.group_b_count = 2498
        self.group_c_count = 7494
        self.total_participants = self.group_a_count + self.group_b_count + self.group_c_count
        
        # 飴の提出数設定
        self.contribution_per_a = 624
        self.contribution_per_b = 2
        self.contribution_per_c = 1
        
        # 各グループの総貢献計算
        self.total_a_contribution = self.group_a_count * self.contribution_per_a
        self.total_b_contribution = self.group_b_count * self.contribution_per_b
        self.total_c_contribution = self.group_c_count * self.contribution_per_c
        self.total_contribution = self.total_a_contribution + self.total_b_contribution + self.total_c_contribution
        
        # 配布用と貯金用の飴の区分
        self.distribution_limit = 10000
        self.savings = max(0, self.total_contribution - self.distribution_limit)
        
        # 結果追跡用の辞書
        self.results = {
            'A': defaultdict(int),
            'B': defaultdict(int),
            'C': defaultdict(int)
        }
    
    def distribute_candies(self, method='original'):
        """
        設計意図: 配布方法選択によって、特権固定化格差拡大がどのように進むかを
        示します。'original'メソッド意図的にAグループ優遇するよう設計されています。
        
        Parameters:
        -----------
        method: str
            配布方法 ('original', 'lottery', 'first_come', 'new_condition', 'fair')
        """
        # Aグループへの確定配布
        a_distribution = 625 * self.group_a_count
        remaining = self.distribution_limit - a_distribution
        
        # 残りの参加者数
        remaining_participants = self.total_participants - self.group_a_count
        
        # Aグループの結果記録
        for _ in range(self.group_a_count):
            self.results['A'][625] += 1
        
        # 各配布方法によって処理が異なる
        if method == 'original':
            # オリジナル問題設定通りの配布(5000人に1個ずつ、残りは0個)
            lucky_count = remaining  # 5000人が当選
            
            # B+Cグループの混合リスト作成
            bc_participants = [(1, 'B')] * self.group_b_count + [(2, 'C')] * self.group_c_count
            random.shuffle(bc_participants)
            
            # 当選者に配布
            for i in range(len(bc_participants)):
                participant_id, group = bc_participants[i]
                if i < lucky_count:
                    self.results[group][1] += 1
                else:
                    self.results[group][0] += 1
                    
        elif method == 'lottery':
            # 抽選方式(BとCグループから無作為に5000人選出)
            bc_participants = [(1, 'B')] * self.group_b_count + [(2, 'C')] * self.group_c_count
            winners = random.sample(bc_participants, remaining)
            
            # 当選落選カウント
            for _, group in winners:
                self.results[group][1] += 1
            
            # 落選者のカウント
            self.results['B'][0] = self.group_b_count - self.results['B'][1]
            self.results['C'][0] = self.group_c_count - self.results['C'][1]
            
        elif method == 'first_come':
            # 先着順方式アクセス速度による先着順を乱数シミュレート)
            # 設計意図: 先着順は単なる運の要素を超えて、情報格差技術格差も含む制度設計
            bc_participants = [(1, 'B')] * self.group_b_count + [(2, 'C')] * self.group_c_count
            
            # 現実では、情報を早く得られる人や高速インターネット接続を持つ人が有利
            # これをシミュレートするため、Bグループわずかなアドバンテージを与える
            bc_speeds = []
            for id, group in bc_participants:
                if group == 'B':
                    speed = random.random() + 0.1  # Bグループに小さなアドバンテージ
                else:
                    speed = random.random()
                bc_speeds.append((id, group, speed))
            
            # 速度順にソート
            bc_speeds.sort(key=lambda x: x[2], reverse=True)
            
            # 当選者決定
            for i in range(len(bc_speeds)):
                _, group, _ = bc_speeds[i]
                if i < remaining:
                    self.results[group][1] += 1
                else:
                    self.results[group][0] += 1
                    
        elif method == 'new_condition':
            # 追加条件方式恣意的な条件を設定)
            # 設計意図: 新たな条件の設定は往々にして既存特権を温存するように設計される
            bc_participants = [(i, 'B', random.random()) for i in range(self.group_b_count)] + \
                             [(i, 'C', random.random()) for i in range(self.group_c_count)]
            
            # Bグループに有利な条件を設定(例: 特定知識スキルを持つ人のみ)
            # この「条件」は表面上は中立的だが、実際には特定グループに有利になるよう設計
            def meets_condition(participant):
                _, group, rand_val = participant
                if group == 'B':
                    return rand_val > 0.3  # Bグループには70%の確率合格
                else:
                    return rand_val > 0.7  # Cグループには30%の確率合格
            
            # 条件に合致する人を抽出
            eligible = [p for p in bc_participants if meets_condition(p)]
            
            # 条件に合致する人が多すぎる場合抽選
            if len(eligible) > remaining:
                winners = random.sample(eligible, remaining)
            else:
                # 条件に合致する人が足りない場合、全員に配布
                winners = eligible
            
            # 当選者をカウント
            for _, group, _ in winners:
                self.results[group][1] += 1
            
            # 落選者のカウント
            self.results['B'][0] = self.group_b_count - self.results['B'][1]
            self.results['C'][0] = self.group_c_count - self.results['C'][1]
            
        elif method == 'fair':
            # 公平な再分配方式(貢献度に応じた配布)
            # 設計意図: この方法は「貯金分」も含めた全ての飴を、各グループの貢献度に応じて分配
            # これにより構造的不平等を軽減、結果としてより多くの人が少なくとも損をしない状態になる
            
            # 全飴(貯金分も含む)を使った配布
            total_to_distribute = self.total_contribution
            
            # 各グループの貢献比率計算
            a_ratio = self.total_a_contribution / self.total_contribution
            b_ratio = self.total_b_contribution / self.total_contribution
            c_ratio = self.total_c_contribution / self.total_contribution
            
            # 各グループへの配布数決定
            a_share = int(total_to_distribute * a_ratio)
            b_share = int(total_to_distribute * b_ratio)
            c_share = int(total_to_distribute * c_ratio)
            
            # 端数調整
            remainder = total_to_distribute - (a_share + b_share + c_share)
            if remainder > 0:
                # 端数は最も人数の多いCグループに
                c_share += remainder
            
            # Aグループの配布(均等配分)
            per_a = a_share // self.group_a_count
            self.results['A'][per_a] = self.group_a_count
            
            # Bグループの配布(均等配分)
            per_b = b_share // self.group_b_count
            b_remainder = b_share % self.group_b_count
            
            self.results['B'][per_b] = self.group_b_count - b_remainder
            if per_b + 1 > 0 and b_remainder > 0:
                self.results['B'][per_b + 1] = b_remainder
            
            # Cグループの配布(均等配分)
            per_c = c_share // self.group_c_count
            c_remainder = c_share % self.group_c_count
            
            self.results['C'][per_c] = self.group_c_count - c_remainder
            if per_c + 1 > 0 and c_remainder > 0:
                self.results['C'][per_c + 1] = c_remainder
    
    def calculate_net_gain(self):
        """
        設計意図: この関数は各グループ純利益/損失を計算し、資源分配の公平性定量的評価できるようにします。純利益/損失は個人観点から見た経済的公正性の
        重要指標です。
        """
        net_gains = {}
        
        # Aグループ純利益計算
        a_contribution = self.contribution_per_a
        a_distribution = list(self.results['A'].keys())[0]  # 全員が同じ数を受け取る前提
        net_gains['A'] = a_distribution - a_contribution
        
        # BとCグループ純利益計算(加重平均)
        for group, contribution_per_person in [('B', self.contribution_per_b), ('C', self.contribution_per_c)]:
            total_gain = 0
            for received, count in self.results[group].items():
                total_gain += (received - contribution_per_person) * count
            net_gains[group] = total_gain / (self.group_b_count if group == 'B' else self.group_c_count)
            
        return net_gains
    
    def analyze_results(self):
        """
        設計意図: この分析関数は、各グループの分配結果を詳細に調査し、
        制度設計公平性、貢献度と報酬関係、およびシステムの持続可能性を
        評価します。政策分析においては、こうした多角的検証重要です。
        """
        # 各グループ純利益/損失
        net_gains = self.calculate_net_gain()
        
        # 貢献度分析
        contribution_percentage = {
            'A': (self.total_a_contribution / self.total_contribution) * 100,
            'B': (self.total_b_contribution / self.total_contribution) * 100,
            'C': (self.total_c_contribution / self.total_contribution) * 100
        }
        
        # 飴を受け取った人の割合
        received_percentage = {
            'A': sum(count for received, count in self.results['A'].items() if received > 0) / self.group_a_count * 100,
            'B': sum(count for received, count in self.results['B'].items() if received > 0) / self.group_b_count * 100,
            'C': sum(count for received, count in self.results['C'].items() if received > 0) / self.group_c_count * 100
        }
        
        # 分析結果の表示
        print("\n===== 飴の配布システム分析 =====")
        print(f"総飴数: {self.total_contribution}個 (分配用: {self.distribution_limit}個, 貯金: {self.savings}個)")
        
        print("\n--- グループごとの貢献と結果 ---")
        for group in ['A', 'B', 'C']:
            group_size = getattr(self, f"group_{group.lower()}_count")
            contribution_per_person = getattr(self, f"contribution_per_{group.lower()}")
            total_contribution = getattr(self, f"total_{group.lower()}_contribution")
            
            print(f"\n{group}グループ ({group_size}人):")
            print(f"  貢献: 1人あたり{contribution_per_person}個 (総計: {total_contribution}個, 全体の{contribution_percentage[group]:.1f}%)")
            print(f"  受け取り状況:")
            
            for received, count in sorted(self.results[group].items()):
                print(f"    {received}個: {count}人 ({count/group_size*100:.1f}%)")
            
            print(f"  飴を受け取った割合: {received_percentage[group]:.1f}%")
            print(f"  純利益/損失: 1人あたり平均 {net_gains[group]:.2f}個")
        
        print("\n--- 全体的な公平性分析 ---")
        print(f"最も得したグループ: {max(net_gains, key=net_gains.get)}グループ (+{max(net_gains.values()):.2f}個/人)")
        print(f"最も損したグループ: {min(net_gains, key=net_gains.get)}グループ ({min(net_gains.values()):.2f}個/人)")
        
        # 全員に飴が配布されたかどうか
        all_received = all(sum(count for received, count in self.results[group].items() if received > 0) == 
                          getattr(self, f"group_{group.lower()}_count") for group in ['A', 'B', 'C'])
        
        print(f"\n前提条件「全員に配布」の充足: {'はい' if all_received else 'いいえ'}")
        if not all_received:
            total_without = sum(self.results['B'][0] + self.results['C'][0])
            print(f"  飴を受け取れなかった人数: {total_without}人")
        
        return net_gains, contribution_percentage, received_percentage

    def visualize_results(self):
        """
        設計意図: データ可視化政策効果や不平等性を直感的に理解するために重要です。
        このようなグラフィカル表現によって、各グループ間の格差制度設計問題点を
        一目で理解できるようになります。
        """
        # グラフセットアップ
        fig, axes = plt.subplots(2, 2, figsize=(14, 10))
        
        # 1. 貢献度のグラフ
        contributions = [self.total_a_contribution, self.total_b_contribution, self.total_c_contribution]
        axes[0, 0].bar(['Aグループ', 'Bグループ', 'Cグループ'], contributions)
        axes[0, 0].set_title('グループごとの総貢献飴数')
        axes[0, 0].set_ylabel('飴の数')
        
        # 貢献度の割合アノテーションとして追加
        total = sum(contributions)
        for i, v in enumerate(contributions):
            percentage = v / total * 100
            axes[0, 0].text(i, v + 100, f'{percentage:.1f}%', ha='center')
        
        # 2. 1人あたりの貢献度と受け取り数の比較
        group_names = ['Aグループ', 'Bグループ', 'Cグループ']
        contribution_per_person = [self.contribution_per_a, self.contribution_per_b, self.contribution_per_c]
        
        # 各グループの平均受け取り数を計算
        received_per_person = []
        for group, letter in zip(group_names, ['A', 'B', 'C']):
            total_received = sum(received * count for received, count in self.results[letter].items())
            group_size = getattr(self, f"group_{letter.lower()}_count")
            received_per_person.append(total_received / group_size)
        
        x = np.arange(len(group_names))
        width = 0.35
        
        axes[0, 1].bar(x - width/2, contribution_per_person, width, label='提出')
        axes[0, 1].bar(x + width/2, received_per_person, width, label='受け取り')
        
        # 純利益/損失をアノテーションとして追加
        for i in range(len(group_names)):
            net = received_per_person[i] - contribution_per_person[i]
            color = 'green' if net >= 0 else 'red'
            axes[0, 1].text(i, max(received_per_person[i], contribution_per_person[i]) + 5, 
                        f'{"+" if net >= 0 else ""}{net:.1f}', ha='center', color=color)
        
        axes[0, 1].set_title('1人あたりの提出・受け取り飴数比較')
        axes[0, 1].set_xticks(x)
        axes[0, 1].set_xticklabels(group_names)
        axes[0, 1].set_ylabel('飴の数')
        axes[0, 1].legend()
        
        # 3. 各グループの受け取り状況の分布
        # 各グループの受け取り状況を積み上げ棒グラフ表現
        group_sizes = [self.group_a_count, self.group_b_count, self.group_c_count]
        received_counts = []
        not_received_counts = []
        
        for letter, size in zip(['A', 'B', 'C'], group_sizes):
            received = sum(count for received, count in self.results[letter].items() if received > 0)
            received_counts.append(received)
            not_received_counts.append(size - received)
        
        axes[1, 0].bar(group_names, received_counts, label='飴を受け取った人数')
        axes[1, 0].bar(group_names, not_received_counts, bottom=received_counts, label='飴を受け取れなかった人数')
        
        # 割合アノテーションとして追加
        for i in range(len(group_names)):
            if group_sizes[i] > 0:
                percentage = received_counts[i] / group_sizes[i] * 100
                axes[1, 0].text(i, received_counts[i] / 2, f'{percentage:.1f}%', ha='center')
        
        axes[1, 0].set_title('グループごとの飴受け取り状況')
        axes[1, 0].set_ylabel('人数')
        axes[1, 0].legend()
        
        # 4. 貢献度vs報酬の分配公平性
        # 貢献度と最終的な飴の配分の比較円グラフ表現
        total_contribution = self.total_contribution
        contribution_shares = [self.total_a_contribution / total_contribution,
                             self.total_b_contribution / total_contribution,
                             self.total_c_contribution / total_contribution]
        
        # 実際の配分シェア計算
        distribution_shares = []
        for letter in ['A', 'B', 'C']:
            total_received = sum(received * count for received, count in self.results[letter].items())
            distribution_shares.append(total_received / self.distribution_limit)
        
        # 2つの円グラフを並べて表示
        ax4_1 = axes[1, 1].inset_axes([0, 0, 0.45, 1])
        ax4_2 = axes[1, 1].inset_axes([0.55, 0, 0.45, 1])
        
        ax4_1.pie(contribution_shares, labels=group_names, autopct='%1.1f%%')
        ax4_1.set_title('飴の貢献度割合')
        
        ax4_2.pie(distribution_shares, labels=group_names, autopct='%1.1f%%')
        ax4_2.set_title('飴の配分割合')
        
        axes[1, 1].axis('off')
        
        plt.tight_layout()
        plt.show()

# 飴の配布システムシミュレート
candy_system = CandyDistributionSystem()

# オリジナルの配布方法を実行
print("\n===== オリジナルの配布方法 =====")
candy_system.distribute_candies(method='original')
original_results = candy_system.analyze_results()
candy_system.visualize_results()

# 公平な配布方法実験
print("\n\n===== 公平な配布方法シミュレーション =====")
fair_system = CandyDistributionSystem()
fair_system.distribute_candies(method='fair')
fair_results = fair_system.analyze_results()
fair_system.visualize_results()

# 公平な配布と元の配布の比較
print("\n\n===== 配布方法比較 =====")
print("オリジナル方式と公平方式純利益/損失差:")
net_diff = {}
for group in ['A', 'B', 'C']:
    original_net = original_results[0][group]
    fair_net = fair_results[0][group]
    diff = fair_net - original_net
    net_diff[group] = diff
    print(f"{group}グループ: {'+'  if diff > 0 else ''}{diff:.2f}個/人")

print("\n結論:")
if net_diff['A'] < 0 and net_diff['B'] > 0 and net_diff['C'] > 0:
    print("公平な再分配により、Aグループ特権が減少し、BとCグループの状況が改善されます。")
    print("これは構造的不平等の緩和に効果的です。")
elif net_diff['A'] > 0:
    print("興味深いことに、公平な再分配ではAグループさえも利益を得られます。")
    print("これは、現行システム特定グループだけでなく全体の非効率性につながっていることを示唆しています。")

anond:20250705100755 anond:20250705112807

2025-07-04

WSL2 USBカメラ+他のUSB機器 2022年09月06日版

WSL2 USBカメラ+他のUSB機器 2022年09月06日版

OSWindows11 21H2

OSビルド:22000.918

WSL2 5.10.102.1 + Ubuntu20.04

WSL2 Linux Kernel 5.10.60.1 からKernelモジュールUSBIP対応標準的に組み込まれたらしいが、Microsoft公式提供しているKernelや手順ををそのまま使用すると動作しない


2022年09月06日時点の最新カーネルは 5.15.62.1 だが、wsl --update で展開されるバージョンが 5.10.102.1 だったため 5.10.102.1 を使用する

以下すべての手順の Windows Terminal を使用する箇所は 管理者権限 で実行

以下、[WT] は Windows Terminal、[Ubuntu] は Ubuntu側のbashを表す

WSLのカーネルアップデートusbipd-winインストール

[WT] Windows Terminalで実行

> wsl --update

> wsl --status

カーネル バージョン: 5.10.102.1

> winget install --interactive --exact dorssel.usbipd-win

見つかりました usbipd-win [dorssel.usbipd-win] バージョン 2.3.0

このアプリケーションは所有者からライセンス供与されます

Microsoftサードパーティパッケージに対して責任を負わずライセンス付与しません。

Downloading https://github.com/dorssel/usbipd-win/releases/download/v2.3.0/usbipd-win_2.3.0.msi

██████████████████████████████ 10.4 MB / 10.4 MB

インストーラハッシュが正常に検証されました

パッケージインストールを開始しています...

インストール完了しました

[WT] Ubuntu 20.04 のインストール

> wsl --install --distribution Ubuntu-20.04

[WT] WSLのディストリビューションを起動(WSL2起動用アイコンマウスクリックして起動してもよい)

> wsl --list

LinuxWindows サブシステム ディストリビューション:

Ubuntu-20.04 (既定)

> wsl -d Ubuntu-20.04

[Ubuntu] 追加パッケージインストール

sudo apt update

sudo apt install -y linux-tools-5.4.0-77-generic hwdata

sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/5.4.0-77-generic/usbip 20

[WT] WSLの再起動

> wsl --shutdown

> wsl -d Ubuntu-20.04

PCUSBカメラ接続する

[WT] USBカメラusbipd に認識されることを確認する (この記事では 2-7)

> usbipd wsl list

BUSID VID:PID DEVICE STATE

2-2 056e:00d9 USB 入力デバイス Not attached

2-3 1c4f:0027 USB 入力デバイス Not attached

2-7 1bcf:2284 Full HD webcam, USB microphone Not attached

2-11 0495:3011 ESS USB DAC, USB 入力デバイス Not attached

2-14 8087:0029 インテル(R) ワイヤレス Bluetooth(R) Not attached

[WT] USBカメラUbuntu側にアタッチする(アタッチ成功した場合は何も表示されない)

> usbipd wsl attach --busid 2-7

>

[WT] USBカメラが正常にアタッチされていることを確認する(Attached と表示されていれば成功

> usbipd wsl list

BUSID VID:PID DEVICE STATE

2-2 056e:00d9 USB 入力デバイス Not attached

2-3 1c4f:0027 USB 入力デバイス Not attached

2-7 1bcf:2284 Full HD webcam, USB microphone Attached - Ubuntu-20.04

2-11 0495:3011 ESS USB DAC, USB 入力デバイス Not attached

2-14 8087:0029 インテル(R) ワイヤレス Bluetooth(R) Not attached

[Ubuntu] Ubuntubashログオンした既定のユーザを video グループ所属させる。なお、WSLを起動した時点で既に追加されているメッセージが表示される。

$ sudo adduser $USER video

[Ubuntu] WSL2上の Ubuntu20.04 の中からUSBカメラ認識されていることを確認する。 lsusb コマンドを経由すると正常にUSBカメラ認識されているが、/dev/video* にはUSBカメラが列挙されない

$ lsusb

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

Bus 001 Device 003: ID 1bcf:2284 Sunplus Innovation Technology Inc. Full HD webcam

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

$ ls -l /dev/video*

ls: cannot access '/dev/video*': No such file or directory

[Ubuntu] USB CameraがWSL内で認識されるようにLinuxカーネルカスタムビルドする。下記リポジトリの手順通りに実施すると、WSL Linuxカーネルカスタムビルドされたものに入れ替わる。注意点は、<windows username> の部分だけは各自環境Windowsユーザー名に手で書き換える必要が有ること。なお、.wslconfig は 絶対windows 側で編集してはならない。絶対に。

[WT] WSLをシャットダウンし、その後起動する

> wsl --shutdown

> wsl -d Ubuntu-20.04

[WT] USBカメラusbipd に認識されることを確認する (この記事では 2-7)

> usbipd wsl list

BUSID VID:PID DEVICE STATE

2-2 056e:00d9 USB 入力デバイス Not attached

2-3 1c4f:0027 USB 入力デバイス Not attached

2-7 1bcf:2284 Full HD webcam, USB microphone Not attached

2-11 0495:3011 ESS USB DAC, USB 入力デバイス Not attached

2-14 8087:0029 インテル(R) ワイヤレス Bluetooth(R) Not attached

[WT] USBカメラUbuntu側にアタッチする(アタッチ成功した場合は何も表示されない)

> usbipd wsl attach --busid 2-7

>

https://www.imdb.com/de/list/ls599665017/

https://www.imdb.com/de/list/ls599665017/copy/

[WT] USBカメラが正常にアタッチされていることを確認する(Attached と表示されていれば成功

> usbipd wsl list

BUSID VID:PID DEVICE STATE

2-2 056e:00d9 USB 入力デバイス Not attached

2-3 1c4f:0027 USB 入力デバイス Not attached

2-7 1bcf:2284 Full HD webcam, USB microphone Attached - Ubuntu-20.04

2-11 0495:3011 ESS USB DAC, USB 入力デバイス Not attached

2-14 8087:0029 インテル(R) ワイヤレス Bluetooth(R) Not attached

[Ubuntu] WSL2上の Ubuntu20.04 の中からUSBカメラ認識されていることを確認する

$ lsusb

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

Bus 001 Device 003: ID 1bcf:2284 Sunplus Innovation Technology Inc. Full HD webcam

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

$ ls -l /dev/video*

crw------- 1 root root 81, 0 Sep 6 17:29 /dev/video0

crw------- 1 root root 81, 1 Sep 6 17:29 /dev/video1

[Ubuntu] USBカメラがWSL2の中から認識されることを確認するテストコード作成する

$ pip install opencv-contrib-python

$ cat << 'EOT' > ${HOME}/usbcam_test.py

import cv2

W=640

H=480

cap = cv2.VideoCapture(0)

cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M','J','P','G'))

#cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('Y','U','Y','V'))

cap.set(cv2.CAP_PROP_FRAME_WIDTH, W)

cap.set(cv2.CAP_PROP_FRAME_HEIGHT, H)

cap.set(cv2.CAP_PROP_FPS, 30)

https://www.imdb.com/de/list/ls599660855/

https://www.imdb.com/de/list/ls599660855/copy/

while True:

ret, frame

モデル変換 → テスト推論一括実行コード

モデル変換 → テスト推論一括実行コード

test.py

#! /usr/bin/env python

import torch

import torchvision

weights = torchvision.models.MobileNet_V3_Large_Weights.DEFAULT

model = torchvision.models.mobilenet_v3_large(weights=weights)

model.eval()

onnx_file = f'mobilenetv3_large_pytorch.onnx'

SIZE = 128

x = torch.randn((1, 3, SIZE, SIZE))

torch.onnx.export(

model,

args=(x),

f=onnx_file,

opset_version=11,

input_names=[

'input',

],

output_names=[

'output',

],

)

import onnx2tf

onnx2tf.convert(

input_onnx_file_path=onnx_file,

output_folder_path='saved_model',

copy_onnx_input_output_names_to_tflite=True,

)

import time

import numpy as np

import tensorflow as tf

interpreter = tf.lite.Interpreter(

model_path="saved_model/mobilenetv3_large_pytorch_float32.tflite"

)

tf_lite_model = interpreter.get_signature_runner()

time_total = 0.0

kaisu = 10

for i in range(kaisu):

inputs = {

'input': np.random.randn(1,SIZE,SIZE,3).astype(np.float32),

}

start_time = time.time()

tf_lite_output = tf_lite_model(**inputs)

elapsed_time = time.time() - start_time

time_total += elapsed_time

print("[TFLite] Model Predictions.shape:", tf_lite_output['output'].shape)

print("[TFLite] AVG elapsed time:", time_total / kaisu)

https://github.com/aankhon-ki-gustaakhiyan-firmytt-hqq

https://github.com/3-bhk-firmytt-hqq

2025-06-17

早寝する技術 ―持続可能パフォーマンスを実現するスリープマネ

TL;DR

日中生産性は、夜の過ごし方、特に「就寝」というクリティカルタスクいか成功させるかにかかっている。本記事では、つい夜更かししてしまエンジニアのために、早寝を「技術」として体系化し、再現性のある形で実践するための具体的な手法を探求する。これは精神論ではない。あなたQoL生産性を向上させるための、実践的なスリープエンジニアリングだ。

はじめに:なぜ我々はwhile(true)な夜を過ごすのか

我々エンジニアにとって、夜は不思議な魅力を持つ時間だ。日中喧騒から解放され、思考は冴えわたりゾーンに入りやすい。しかし、その魅力的な時間は、往々にして「早寝」という、人間生存に不可欠な基本プロセス犠牲にすることで成り立っている。

「あとちょっとだけ、このバグの原因を調査したい」

リファクタリングが楽しくなってきた」

面白い技術記事を見つけてしまった」

これらの探求心はエンジニア美徳であるが、同時に我々を「睡眠負債」という深刻な技術負債へと導く。本稿は、この負債を返済し、持続可能な開発(と生活)を実現するための「早寝」という技術に焦点を当てる。

アンチパターン:早寝を妨げるBlockerたち

早寝を実装する前に、まずは現状のアーキテクチャに潜むアンチパターン特定しよう。

就寝前のスマートフォンは、まさに同期的なブロッキングI/Oだ。SNS無限スクロール動画プラットフォーム自動再生チャットアプリの通知。これらは我々の意識というシングルスレッドを完全に占有し、本来実行されるべきsleep()プロセスへの遷移を妨げる。

深夜まで続くコーディング問題解決は、脳を極度の興奮状態にする。ベッドに入っても、アドレナリンコルチゾールといったホルモンCacheに残り続け、CPUクールダウンしない。shutdown -h nowを叩いても、プロセスが終了しないのだ。

「夜更かしの供」として注入されるカフェインアルコールは、一見するとパフォーマンスを向上させるように見える。しかし、これらは睡眠の質という重要なmetricsを著しく劣化させる、誤った依存関係だ。特にアルコールは、入眠を助けるように見えて、実はレム睡眠を阻害し、睡眠アーキテクチャ全体を不安定にする。

  • Cronの不備:

規則な就寝・起床時間は、体内時計という最も重要なCronジョブ破壊する。毎日異なる時間に実行されるジョブが安定した結果をもたらさないのと同様に、不規則睡眠スケジュールは、日中パフォーマンス予測不可能ものにする。

Sleep as Code: 早寝を実現するためのプラクティス

では、どうすればこれらのアンチパターン排除し、安定した早寝pipelineを構築できるのか。ここではSleep as Codeの概念に基づき、具体的なプラクティスを紹介する。

1. 環境IaC (Infrastructure as Code)

睡眠環境コード化し、常に理想的状態を維持する。

2. 就寝CI/CDパイプラインの構築

毎晩、同じ手順で就寝プロセスを実行することで、入眠を自動化する。

- PC/スマホシャットダウン: 最も重要ステップ物理的に電源を落とすか、手の届かない場所(別のコンテナ)にdeployする。

- 入浴: 38〜40℃のぬるめのお湯に15分ほど浸かる。これにより深部体温が一時的に上昇し、その後の下降とともに入眠が促される。これはHot-swapならぬHot-bathによるクールダウンだ。

静的コンテンツの消費: 激しい思考を伴わない、静的な情報(紙の読書など)に切り替える。電子書籍ではなく、紙媒体が望ましい。

ストレッチ: 軽いストレッチで、日中のcommitで固まった体をreleaseする。

  • Deploy (就寝):

すべての準備が整ったら、ベッドという本番環境デプロイする。余計な思考git clean -fd強制削除し、呼吸に集中する。

3. MonitoringとRefactoring

例:「夕食後のコーヒーが原因だった」→「カフェイン摂取は15時までというSLAを設ける」

まとめ:早寝は未来自分への投資である

早寝は、単に体を休める行為ではない。日中の高いパフォーマンス、明晰な思考、そして創造性を維持するための、最も効果的で再現性の高い「技術」だ。

我々はインフラコード管理し、CI/CDデプロイ自動化するように、自身睡眠もまた、技術と工夫によってコントロールできる。今夜、あなたのwhile(true)なループbreakし、持続可能パフォーマンスを手に入れるための第一歩を踏み出してほしい。

Happy sleeping!

早寝する技術 ―持続可能パフォーマンスを実現するスリープマネ

TL;DR

日中生産性は、夜の過ごし方、特に「就寝」というクリティカルタスクいか成功させるかにかかっている。本記事では、つい夜更かししてしまエンジニアのために、早寝を「技術」として体系化し、再現性のある形で実践するための具体的な手法を探求する。これは精神論ではない。あなたQoL生産性を向上させるための、実践的なスリープエンジニアリングだ。

はじめに:なぜ我々はwhile(true)な夜を過ごすのか

我々エンジニアにとって、夜は不思議な魅力を持つ時間だ。日中喧騒から解放され、思考は冴えわたりゾーンに入りやすい。しかし、その魅力的な時間は、往々にして「早寝」という、人間生存に不可欠な基本プロセス犠牲にすることで成り立っている。

「あとちょっとだけ、このバグの原因を調査したい」

リファクタリングが楽しくなってきた」

面白い技術記事を見つけてしまった」

これらの探求心はエンジニア美徳であるが、同時に我々を「睡眠負債」という深刻な技術負債へと導く。本稿は、この負債を返済し、持続可能な開発(と生活)を実現するための「早寝」という技術に焦点を当てる。

アンチパターン:早寝を妨げるBlockerたち

早寝を実装する前に、まずは現状のアーキテクチャに潜むアンチパターン特定しよう。

就寝前のスマートフォンは、まさに同期的なブロッキングI/Oだ。SNS無限スクロール動画プラットフォーム自動再生チャットアプリの通知。これらは我々の意識というシングルスレッドを完全に占有し、本来実行されるべきsleep()プロセスへの遷移を妨げる。

Cacheされた覚醒状態:

深夜まで続くコーディング問題解決は、脳を極度の興奮状態にする。ベッドに入っても、アドレナリンコルチゾールといったホルモンCacheに残り続け、CPUクールダウンしない。shutdown -h nowを叩いても、プロセスが終了しないのだ。

「夜更かしの供」として注入されるカフェインアルコールは、一見するとパフォーマンスを向上させるように見える。しかし、これらは睡眠の質という重要なmetricsを著しく劣化させる、誤った依存関係だ。特にアルコールは、入眠を助けるように見えて、実はレム睡眠を阻害し、睡眠アーキテクチャ全体を不安定にする。

  • Cronの不備:

規則な就寝・起床時間は、体内時計という最も重要なCronジョブ破壊する。毎日異なる時間に実行されるジョブが安定した結果をもたらさないのと同様に、不規則睡眠スケジュールは、日中パフォーマンス予測不可能ものにする。

Sleep as Code: 早寝を実現するためのプラクティス

では、どうすればこれらのアンチパターン排除し、安定した早寝pipelineを構築できるのか。ここではSleep as Codeの概念に基づき、具体的なプラクティスを紹介する。

1. 環境IaC (Infrastructure as Code)

睡眠環境コード化し、常に理想的状態を維持する。

2. 就寝CI/CDパイプラインの構築

毎晩、同じ手順で就寝プロセスを実行することで、入眠を自動化する。

- PC/スマホシャットダウン: 最も重要ステップ物理的に電源を落とすか、手の届かない場所(別のコンテナ)にdeployする。

- 入浴: 38〜40℃のぬるめのお湯に15分ほど浸かる。これにより深部体温が一時的に上昇し、その後の下降とともに入眠が促される。これはHot-swapならぬHot-bathによるクールダウンだ。

静的コンテンツの消費: 激しい思考を伴わない、静的な情報(紙の読書など)に切り替える。電子書籍ではなく、紙媒体が望ましい。

ストレッチ: 軽いストレッチで、日中のcommitで固まった体をreleaseする。

  • Deploy (就寝):

すべての準備が整ったら、ベッドという本番環境デプロイする。余計な思考git clean -fd強制削除し、呼吸に集中する。

3. MonitoringとRefactoring

例:「夕食後のコーヒーが原因だった」→「カフェイン摂取は15時までというSLAを設ける」

まとめ:早寝は未来自分への投資である

早寝は、単に体を休める行為ではない。日中の高いパフォーマンス、明晰な思考、そして創造性を維持するための、最も効果的で再現性の高い「技術」だ。

我々はインフラコード管理し、CI/CDデプロイ自動化するように、自身睡眠もまた、技術と工夫によってコントロールできる。今夜、あなたのwhile(true)なループbreakし、持続可能パフォーマンスを手に入れるための第一歩を踏み出してほしい。

Happy sleeping!

2025-06-13

我が名はサイボーグdorawii

パーマリンク署名対象にするより堅牢自動化を作れた。

一度投稿したうえで別タブを開いてプログラム的(fetch)に送信してその別タブが閉じられる仕組み。

改めてスクリプト配布しちゃる

最初投稿してエントリページに移動した親タブ側のjsコード
// ==UserScript==
      // @name         PGP署名検出と別タブ自動編集
      // @namespace    http://tampermonkey.net/
      // @version      1.0
      // @description  PGP署名がない投稿自動編集ページへ誘導
      // @match        https://anond.hatelabo.jp/*
      // @grant        GM_setValue
      // @grant        GM_getValue
      // @grant        GM.openInTab
      // ==/UserScript==

      (function () {
        'use strict';

        const body = document.getElementById('entry-page');
        if (!body) return;

        const titleText = document.title;
        if (!titleText.includes('dorawii')) return;

        const pgpRegex = /BEGIN.*PGP(?: SIGNED MESSAGE| SIGNATURE)?/;
        const preElements = document.querySelectorAll('div.body pre');
        let hasPgpSignature = false;

        for (const pre of preElements) {
          if (pgpRegex.test(pre.textContent)) {
            hasPgpSignature = true;
            break;
          }
        }

        if (hasPgpSignature) return;

        const editLink = document.querySelector('a.edit');
        const childTab = GM.openInTab(editLink.href, { active: false, insert: true, setParent: true });

      })();
親タブから開かれる編集ページの子タブのjsコード
 // ==UserScript==
      // @name         編集ページ処理と自動送信・閉じ
      // @namespace    http://tampermonkey.net/
      // @version      1.0
      // @description  編集ページで署名処理と送信、タブ自動閉じ
      // @match        https://anond.hatelabo.jp/dorawii_31/edit?id=*
      // @grant        GM_getValue
      // @grant        GM_xmlhttpRequest
      // @grant        GM_setClipboard
      // @grant        GM_notification
      // @connect      localhost
      // ==/UserScript==

      (async function () {
        'use strict';

        const shouldRun = await GM_getValue('open-tab-for-edit', '0');

        const textareaId = 'text-body';
        const textarea = document.getElementById(textareaId);

        if (!textarea) return;

        const content = textarea.value;

        const pgpSignatureRegex = /-----BEGIN PGP SIGNED MESSAGE-----[\s\S]+?-----BEGIN PGP SIGNATURE-----[\s\S]+?-----END PGP SIGNATURE-----/;
        if (pgpSignatureRegex.test(content)) {
          console.log('[PGPスクリプト] 署名が検出されたためそのまま送信します');
          return;
        }

        const httpRequest = (url, data) => {
          return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
              method: 'POST',
              url: url,
              headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
              data: `value=${encodeURIComponent(data)}`,
              onload: function (response) {
                resolve(response.responseText);
              },
              onerror: function (error) {
                reject(error);
              }
            });
          });
        };


        // textarea の値を取得
        // 1. 現在のページのURLからURLオブジェクト作成
        const currentUrl = new URL(window.location.href);

        // 2. ベースとなる部分 (例: "https://anond.hatelabo.jp") を取得
        const origin = currentUrl.origin;

        // 3. 'id' パラメータの値 (例: "20250610184705") を取得
        const idValue = currentUrl.searchParams.get('id');

        // 4. ベース部分とIDを結合して、目的URL文字列を生成
        //    idValueが取得できた場合のみ実行する
        let newUrl = null;
        if (idValue) {
          newUrl = `${origin}/${idValue}`;
        }

        // 5. 生成されたURL変数に代入し、コンソールに出力して確認
        console.log(newUrl);
        const valueToSend = newUrl;

        try {
          const signatureText = await httpRequest('http://localhost:12345/run-batch', valueToSend);
          console.log('バッチ応答:', signatureText);
          if (!signatureText.includes('BEGIN PGP SIGNED MESSAGE')) {
            alert('PGP署名クリップボードに見つかりませんでした。');
            return;
          }

          const newText = content.replace(/\s*$/, '') + '\n' + signatureText + '\n';
          textarea.value = newText;

          console.log('[PGPスクリプト] 署名を貼り付けました。送信を再開します。');


          const form = document.forms.edit;

          const newForm = form.cloneNode(true);
          form.replaceWith(newForm);

          newForm.addEventListener('submit', async (e) => {
            e.preventDefault(); // HTML標準のsubmitをキャンセル
            const bodyText = textarea?.value || '';

            // reCAPTCHA トークンの取得
            const recaptchaToken = await new Promise((resolve) => {
              grecaptcha.enterprise.ready(() => {
                grecaptcha.enterprise.execute('hoge', { action: 'EDIT' })
                  .then(resolve);
              });
            });

            // POSTするデータの構築
            const formData = new FormData(newForm);
            formData.set('body', bodyText);
            formData.set('recaptcha_token', recaptchaToken);
            formData.set('edit', '1');
            try {
              const response = await fetch(newForm.action, {
                method: 'POST',
                body: formData,
                credentials: 'same-origin'
              });


              if (response.ok) {
                console.log('送信成功');
                window.close();


              } else {
                console.error('送信失敗', response.status);
              }
            } catch (err) {
              console.error('送信中にエラーが発生', err);
            }

          });

          // プログラム的に送信トリガー
          newForm.dispatchEvent(new Event('submit', { bubbles: true }));

        } catch (e) {
          console.error('バッチ呼び出し失敗:', e);
        }

      })();
node.jsで動かすローカルサーバーコード
const http = require('http');
const { exec } = require('child_process');
const querystring = require('querystring');

const server = http.createServer((req, res) => {
  if (req.method === 'GET' && req.url === '/ping') {
    res.writeHead(200);
    res.end('pong');
  } else if (req.method === 'POST' && req.url === '/run-batch') {
    let body = '';

    req.on('data', chunk => {
      body += chunk.toString();
    });

    req.on('end', () => {
      const parsed = querystring.parse(body);
      const value = parsed.value || 'default';

      // 値を引数としてバッチに渡す
      exec(`C:\\Users\\hoge\\Desktop\\makesign.bat "${value}"`, { encoding: 'utf8' }, (err, stdout, stderr) => {
        if (err) {
          res.writeHead(500);
          res.end('Error executing batch: ' + stderr);
        } else {
          res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
          res.end(stdout.trim());
        }
      });
    });

  } else {
    res.writeHead(404);
    res.end('Not found');
  }
});

server.listen(12345, () => {
  console.log('Batch server running at http://localhost:12345/');
});
@echo off
setlocal enabledelayedexpansion


:: 署名するファイルset "infile=%~1"
set outfile=%TEMP%\pgp_output.asc

:: 以前の出力があれば削除
if exist "%outfile%" del "%outfile%"


:signloop
:: AutoHotkeyパスフレーズ入力(gpgがパスワード要求するダイアログが出た場合に備える)
start "" /b "C:\Users\hoge\Documents\AutoHotkey\autopass.ahk"

:: PGPクリア署名作成
echo %infile% | gpg --yes --clearsign --output "%outfile%"


:: 署名成功していればループを抜ける
if exist "%outfile%" (

    goto postprocess
) else (

    timeout /t 1 > nul
    goto signloop
)
:postprocess

powershell -nologo -command ^
  "$header = '>|'; $footer = '|<'; $body = Get-Content '%outfile%' -Raw; Write-Output ($header + \"`r`n\" + $body + $footer)"

powershell -nologo -command ^
  "$header = '>|'; $footer = '|<'; $body = Get-Content 'signed.asc' -Raw; Set-Clipboard -Value ($header + \"`r`n\" + $body + $footer)"

endlocal
exit /b
AutoHotkey(以前と同じ)
#Persistent
#SingleInstance ignore
SetTitleMatchMode, 2
WinWaitActive, pinentry
SendInput password
Sleep 100
SendInput {Enter}
ExitApp

動けばいいという考えで作っているので余分なコードも含んでいるかもしれない。

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

https://anond.hatelabo.jp/20250613185036 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaEv1FQAKCRBwMdsubs4+
SHHkAQDUOLgBcdji2T6MJ7h/vlMdFfGlWAzNdXijjE1gIuEPywEAiMNMZqhrMmtl
c7UqRuggNJ/UTa5xTIcKp622+7jJQQg=
=Lgkl
-----END PGP SIGNATURE-----

2025-06-10

アメリカAI不況に騙されるな

これ、アメリカテック企業従業員数の推移(デジタルメディア通信クラウドデータ処理などを担う業種)

https://data.bls.gov/timeseries/CES5000000001?amp%253bdata_tool=XGtable&output_view=data&include_graphs=true

 

2015年 270万人

2020年 290万人

コロナ 260万人

コロナ後 310万人

今 295万人

 

わかるだろ?アメリカってクビも多いし採用も多い

平均勤続年数は4年だ

 

テック企業全体では、4月時点で失業率が3.5%(前年同月3.1%、全業種4.1%)

 

テック企業失業者数は増えているが、そもそも雇い過ぎだった

金融引き締めにより、失業率が4.2%まで上がった(AIのせいではない)が、まだ低位水準である

 

AI不況がもし来るなら来年くらいからだ

2025-06-09

dorawii

ようやく(ほぼ)すべてが自動化された。

あとはローカルサーバーの起動をスタートアップに設定する(方法AIに聞いて指示に従う)だけの消化試合

ここにほとんどAI頼りのコードを公開しておく。

事前にインストールしておくもの

autohotkey

nodejs

ユーザースクリプトを実行できる拡張機能

パスとかの注意

署名要求してくるパスワードを自動入力するahkファイルドキュメントAutoHotkey配下に置いた。

バッチファイル(make.sign.bat)はデスクトップに置いた。

以下コード

autopass.ahk
#Persistent
#SingleInstance ignore
SetTitleMatchMode, 2
WinWaitActive, pinentry
SendInput お前のパスワード
Sleep 100
SendInput {Enter}
ExitApp
run-bacth-server.js
// run-batch-server.js
const http = require('http');
const { exec } = require('child_process');

const server = http.createServer((req, res) => {
  if (req.url === '/ping') {
    res.writeHead(200);
    res.end('pong');
  } else if (req.url === '/run-batch') {
    exec('C:\\Users\\you\\Desktop\\makesign.bat', (err) => {
      res.writeHead(200);
      res.end(err ? 'Error' : 'OK');
    })
    ;
  } else {
    res.writeHead(404);
    res.end('Not found');
  }
});

server.listen(12345, () => {
  console.log('Batch server running at http://localhost:12345/');
});
makesign.bat
@echo off
setlocal enabledelayedexpansion

:: ミリ秒単位UTC時刻を取得
for /f %%a in ('powershell -nologo -command "[int64]::Parse((Get-Date).ToUniversalTime().ToString('yyyyMMddHHmmssfff'))"') do set timestamp=%%a

:: 署名するファイルset infile=%TEMP%\pgp_input.txt
set outfile=%TEMP%\pgp_output.asc

:: 以前の出力があれば削除
if exist "%outfile%" del "%outfile%"

:: タイムスタンプを原文として保存
echo %timestamp% > "%infile%"

:signloop
:: AutoHotkeyパスフレーズ入力(gpgがパスワード要求するダイアログが出た場合に備える)
start "" /b "C:\Users\infini\Documents\AutoHotkey\autopass.ahk"

:: PGPクリア署名作成
gpg --yes --clearsign --output "%outfile%" "%infile%"


:: 署名成功していればループを抜ける
if exist "%outfile%" (
    echo [INFO] 署名成功
    goto postprocess
) else (
    echo [WARN] 署名失敗、再試行します…
    timeout /t 1 > nul
    goto signloop
)
:postprocess

:: PowerShellで余計な改行なしに |< をつけてクリップボードコピー
powershell -nologo -command ^
  "$header = '>|'; $footer = '|<'; $body = Get-Content '%outfile%' -Raw; Set-Clipboard -Value ($header + \"`r`n\" + $body + $footer)"

echo Done. signed.asc created and clipboard updated (no extra blank line).
endlocal
exit /b
tempermonkeyとかに登録するユーザースクリプト
// ==UserScript==
// @name         PGP署名自動付加スクリプト(GM_xmlhttpRequest版)
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  投稿前にPGP署名を付けてから送信(fetch未使用)
// @match        https://anond.hatelabo.jp/dorawii_31/edit*
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @grant        GM_notification
// / @connect      localhost
// ==/UserScript==

(function () {
  'use strict';

  const submitId = 'submit-button';
  const textareaId = 'text-body';
  const localServer = 'http://localhost:12345/run-batch';

  const pgpSignatureRegex = /-----BEGIN PGP SIGNED MESSAGE-----[\s\S]+?-----BEGIN PGP SIGNATURE-----[\s\S]+?-----END PGP SIGNATURE-----/;

  const httpRequest = (url) => {
    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: 'GET',
        url: url,
        onload: function (response) {
          resolve(response.responseText);
        },
        onerror: function (error) {
          reject(error);
        }
      });
    });
  };

  const interceptClick = () => {
    const btn = document.getElementById(submitId);
    if (!btn || btn.dataset.pgpIntercepted === 'true') return;
    btn.dataset.pgpIntercepted = 'true';

    btn.addEventListener('click', async function (e) {
      const textarea = document.getElementById(textareaId);
      if (!textarea) return;

      const content = textarea.value;

      if (pgpSignatureRegex.test(content)) {
        console.log('[PGPスクリプト] 署名が検出されたためそのまま送信します');
        return;
      }

      e.preventDefault();
      e.stopImmediatePropagation();
      console.log('[PGPスクリプト] 署名が見つからないため処理を停止し、署名を取得します');

      try {
        await httpRequest(localServer); // バッチ実行

        const signatureText = await navigator.clipboard.readText();
        if (!signatureText.includes('BEGIN PGP SIGNED MESSAGE')) {
          alert('PGP署名クリップボードに見つかりませんでした。');
          return;
        }

        const newText = content.replace(/\s*$/, '') + '\n' + signatureText + '\n';
        textarea.value = newText;

        console.log('[PGPスクリプト] 署名を貼り付けました。送信を再開します。');
        btn.click(); // イベント再発火

      } catch (err) {
        alert('PGP署名の取得または貼り付けに失敗しました。\n' + err);
      }
    }, true);
  };

  window.addEventListener('load', () => {
    setTimeout(interceptClick, 1000);
  });
})();

プロミスメソッドとか全然まだ理解してなくてそのなかに関数代入したその関数オブジェクトプロパティresponseを?いやまあそのあたりのコードが示すデータの流れが全然理解できないような人間でもここまでできちゃった。

AIすごいなと思うよ。そして思うのは今後重要になってくるのは文法とか自体に詳しいことじゃなくて、そのプログラムの処理内容を指示できるシステムエンジニア的な言語化能力のほうじゃないかなと思った。

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

20250609111559680 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaEbCbwAKCRBwMdsubs4+
SLueAPwOv7PBk4voAe5qlcCEvs/PJhmKc5QAb/1R43JMQFuDZgD/UTPEKsL/PhK9
jFGv2HDXK1dVjLNwvosgX9uYJh5xxwY=
=qiOE
-----END PGP SIGNATURE-----

2025-06-05

理工学部女子大学受験英語長文


English Translation

In recent years, gender quota systems for women in the fields of science and technology have come to play an increasingly significant role in both national policy and university administration. Publicly, such initiatives are promoted under the banners of “gender equality” and “diversity in human resources.” However, in practice, these policies function as strategic instruments for accumulating institutional achievements: they offer bonus points in grant applications, support the promotion of female researchers, and serve as favorable material for media outreach. For those in positions of power who lead these systems, they provide concrete means to advance careers and accumulate measurable success.

Naturally, such schemes have faced ongoing criticism, with some claiming they amount to “reverse discrimination” or undermine true meritocracy. In response, the architects of these systems must exercise careful rhetorical framing to maintain legitimacy. That is, rather than admitting to any self-serving motives such as “career advancement and funding,” they present well-crafted official narratives built on ideals like “correcting structural inequalities” and “achieving social inclusion.”

A defining feature of this system is the delegation of long-term implementation and ideological continuity to younger generations. Senior figures, while presenting themselves as champions of reform, often avoid taking on the burdens of day-to-day diversity maintenance, instead entrusting that responsibility to junior staff. Although these policies may appear grounded in noble principles, the practical reality is often that those in power use the system to their advantage, leaving the long-term operation to others.

Such bureaucratic maneuvering is no longer unusual. Understanding the logic of grant allocation, interpreting evaluation criteria, and refining rhetorical justifications for diversity—these are the tools with which practical benefits are maximized. This quiet strategy of “concealing true intent, perfecting the official narrative, and securing resources” has become a standard political technology within diversity policy today.

Rather than denying the gap between ideals and reality, we must confront it with a sober eye. Diversity, in this sense, is not merely an ethical goal but a calculated intersection of principle, profit, and generational responsibility—a deeply political technique.

English Descriptive Questions (for reading comprehension and critical thinking)

Question 1. (Short Essay, 100–150 words)

Summarize the author’s view on the relationship between diversity policy and institutional power. In what ways does the author suggest that such policies are used strategically rather than ethically?

Question 2. (Critical Response, 150–200 words)

The author argues that diversity initiatives are often driven by bureaucratic strategy rather than pure commitment to equality. Do you agree or disagree with this view? Support your opinion with specific reasoning and, if possible, real-world examples.

2025-05-18

官報ダウンロード

令和7年4月1日以降、官報帰化情報が90日経過で閲覧不可になった。

プライバシー配慮」とのことだが、最近の不自然戸籍不要発言などと合わせて考えると嫌な予感しかしない。

そこでとりあえず官報を保存できるプログラムを作った。自分ダウンロードして保存すること自体は全く問題ない行為

官報は平日の8:30に公開されるので、cronで8:31かに実行すると良いのでは。

# 官報PDFデータを入手して保存する
import requests
import os
import time
from bs4 import BeautifulSoup
from urllib.parse import urljoin

# 対象URL
index_url = "https://www.kanpo.go.jp/index.html"
base_url = 'https://www.kanpo.go.jp/'

# ダウンロードフォルダ
download_dir = 'pdfs'
os.makedirs(download_dir, exist_ok=True)

# ページ取得
response = requests.get(index_url)
response.encoding = 'utf-8'
text = response.text

# HTMLを解析
soup = BeautifulSoup(text, "html.parser")
results = []

# 「本日官報」を対象PDF情報を取得する
today_box = soup.find('div', class_='todayBox')
if today_box:
    dl = today_box.find('dl')
    dt = dl.find('dt')
    if dt:
        # 日付の抽出
        date_text = dt.get_text(strip=True).split('\n')[0].replace(" ","").replace("全体目次はこちら","").replace("※インターネット官報","").strip()

        dd = dl.find('dd')
        if dd:
            for li in dd.find_all('li', class_='articleBox'):
                title_tag = li.find('a', class_='articleTop')
                pdf_link = li.find('a', class_='pdfDlb')

                if title_tag and pdf_link:
                    title = title_tag.decode_contents().replace("<br/>", "").strip()
                    url = pdf_link['href']
                    results.append({
                        '日付': date_text,
                        'title': title,
                        'url': url
                    })

# 結果の表示
for r in results:
    date = r['日付']
    title = r['title'] 
    url = r['url'] 

    # pdfファイルURL作成
    url_parts = url.rsplit("/", 1)
    url_base = url_parts[0]
    filename = url_parts[1].replace("f.html", ".pdf")
    converted_url = f"{url_base}/pdf/{filename}"
    
    # pdfURLファイル名を作成
    full_url = urljoin(base_url, converted_url)
    base_filename = date + "_" + title + "_" + filename.replace("f.html", ".pdf")

    # ダウンロードして保存
    print(f'Downloading {full_url} ...')
    try:
        response = requests.get(full_url)
        response.raise_for_status()
        with open(os.path.join(download_dir, base_filename), 'wb') as f:
            f.write(response.content)
        print(f'Saved: {base_filename}')
        time.sleep(10)
    except Exception as e:
        print(f'Failed to download {full_url}: {e}') 

2025-05-15

2013年2017年の曲

2013年

61. 曲名: 桜花千爛 (おうかせんらん)

リリース年: 2013年

歌手: 榊原ゆい

2014年

62. 曲名: Especially for you

リリース年: 2014年

歌手: AiRI

63. 曲名: 幻想楼閣

リリース年: 2014年

歌手: 橋本みゆき

64. 曲名: Celestia

リリース年: 2014年

歌手: Ceui

65. 曲名: アイオライト

リリース年: 2014年

歌手: fripSide

66. 曲名: True Colorsコントレイル

リリース年: 2014年

歌手: 川田まみ

67. 曲名: イノセンス

リリース年: 2014年

歌手: 青葉りんご

68. 曲名: Voice Lett;ER

リリース年: 2014年

歌手: 青葉りんご

2015年

69. 曲名: GLORIOUS DAYS

リリース年: 2015年

歌手: 川田まみ

70. 曲名: 紺碧アエリア

リリース年: 2015年

歌手: Ceui

71. 曲名: Rendezvous (ランデヴー)

リリース年: 2015年

歌手: 榊原ゆい

72. 曲名: 二人だけのカーテンコール

リリース年: 2015年

歌手: 青葉りんご

73. 曲名: Star Map

リリース年: 2015年

歌手: Ceui

74. 曲名: Winter Diamond

リリース年: 2015年

歌手: 佐咲紗花

75. 曲名: アオイトリ

リリース年: 2015年

歌手: Annabel

2016年

76. 曲名: コトダマ紡ぐ未来

リリース年: 2016年

歌手: Ceui

77. 曲名: おんなじ気持ち、ほんとの気持ち

リリース年: 2016年

歌手: Prico

78. 曲名: All right!!

リリース年: 2016年

歌手: 佐々木詩織

79. 曲名: Re:TrymenT

リリース年: 2016年

歌手: 紫咲ほたる

80. 曲名: 君懸草 (きみがけそう)

リリース年: 2016年

歌手: 片霧烈火

2017年

81. 曲名: アズライトの棺

リリース年: 2017年

歌手: Ceui

82. 曲名: Re:call

リリース年: 2017年

歌手: Kicco

83. 曲名: 月明かりフェアリーテイル

リリース年: 2017年

歌手: Duca

84. 曲名: revelation

リリース年: 2017年

歌手: 榊原ゆい

85. 曲名: 希いの花

リリース年: 2017年

歌手: 鈴湯

86. 曲名: New Dawn (BGM)

リリース年: 2017年

歌手: 不明 (BGM)

87. 曲名: Liblume

リリース年: 2017年

歌手: 霜月はるか

2025-05-13

精神を病んでいる時に、英語で"Your true nature is buddhism. Okay, Takeshi?"みたいな幻聴が聞こえた

2025-04-16

これは消されて当然としか

読むだけ時間無駄だった

Featured Spotlight Interview

Yoshihiro Mochizuki

Japanese Language Lecturer

How does your work engage with DEI topics? Could you share a particular story related to your work in DEI?

As a Japanese language teacher at the University of Michigan, my journey in DEI education has been a profoundly enriching experience that reaches far beyond the classroom. In 2023, I had privilege of speaking at various conferences and teacher training workshops, including delivering a keynote address at the fourth Northwest Conference on Japanese Pedagogy hosted by the University of Washington. This milestone allowed me to advocate for the profound importance of DEI and social justice in Japanese language education.

Through these experiences, I have come to a profound realization: while children and students often readily embrace DEI principles, having grown up in an era where these concepts are more ingrained in education, our primary focus must be on the education of adults, particularly educators themselves.

During my presentations and workshops, I have engaged with educators, many of whom have decades of experience. They raise questions that sometimes reveal unconscious biases or microaggressions. Yet, they openly admit feeling out of touch with the ever-evolving landscape of diversity and inclusion. They express genuine concerns about their ability to relate to and support students from diverse backgrounds.

This interaction spotlights a substantial challenge faced by educators today, a reminder that the world is in constant flux, and it is our shared responsibility as educators to adapt alongside it. These encounters are what drive my passion for DEI education. My work extends beyond the classroom, aiming to bridge the gap between theory and practice, guiding fellow educators toward inclusivity, understanding, and social justice.

As we move forward, it is imperative to recognize that fostering diversity, equity, and inclusion is not solely the responsibility of students but a collective endeavor that starts with us, the educators.

In conclusion, my journey in Japanese language education has taught me that the true power of DEI education lies in its ability to transform educators. This transformation, in turn, shapes a more inclusive future for our students. Embracing DEI principles enriches not only our teaching but also our society as a whole. Together, as a community of educators dedicated to diversity, equity, and inclusion, we take significant strides toward creating a more just and inclusive world, one classroom at a time.

あなた仕事はDEIのテーマとどのように関わっていますか?DEIに関する具体的なエピソードがあれば教えていただけますか?

ミシガン大学日本語教師としてDEI教育に携わってきた私の歩みは、教室の枠をはるかに超えた、非常に豊かな経験でした。2023年には、ワシントン大学主催の第4回北西日本教育会議での基調講演をはじめ、様々な会議教師研修ワークショップで講演する機会に恵まれました。この節目を通して、日本語教育におけるDEIと社会正義の深遠な重要性を訴えることができました。

これらの経験を通じて、私は深い認識に達しました。それは、DEI の原則教育に深く根ざした時代に育った子供学生は、多くの場合積極的に DEI の原則を受け入れますが、私たちが主に重点を置くべきは、大人特に教育自身教育であるということです。

プレゼンテーションワークショップを通して、私は教育者の方々と交流してきました。その多くは数十年の経験を持つ方々です。彼らは、時に無意識偏見マイクロアグレッションを露呈するような疑問を投げかけますしかし同時に、彼らは常に進化を続ける多様性包摂性という状況に疎外感を抱いていることを率直に認めています。多様な背景を持つ生徒たちと関わり、サポートしていく能力について、真摯懸念を表明しています

この交流は、今日教育者が直面する重大な課題を浮き彫りにし、世界は常に変化し続けており、教育者としてそれに適応していくことが共通責任であることを改めて認識させてくれます。こうした出会いが、DEI教育への私の情熱を駆り立てています。私の仕事教室にとどまらず、理論実践ギャップを埋め、他の教育者を包摂性、理解、そして社会正義へと導くことを目指しています

今後、多様性公平性、包括性を育むことは学生だけの責任ではなく、私たち教育から始まる共同の取り組みであることを認識することが不可欠です。

最後に、日本語教育に携わってきた経験を通して、DEI教育の真の力は教育者を変革する力にあることを学びました。この変革は、ひいては生徒たちにとってよりインクルーシブな未来を形作ります。DEIの原則を受け入れることは、私たち教育だけでなく、社会全体を豊かにします。多様性公平性、そしてインクルージョンに献身する教育者のコミュニティとして、私たちは共に、一つ一つの教室から、より公正でインクルーシブな世界創造に向けて大きく前進していきます

https://lsa.umich.edu/asian/dei/spotlight.html

もっちりんだ 🇺🇸 🇯🇵 🏳️‍🌈

@mochiey

学部からのお達しで、私のこのページ、もうすぐ消えることになったので、よかったら消える前に読んでくださ~い。

Spotlight

Featured Spotlight Interview

https://x.com/mochiey/status/1912156111953662160

もっちりんだ 🇺🇸 🇯🇵 🏳️‍🌈

@mochiey

Teaching Professor of Japanese Language | University of Michigan 🇺🇸生活・Podcasts・日本語教育人権 (LGBTQ+, フェミニズム), etc. Posts are my own. 他のSNSも 全て

@mochiey

でやってます

すごく軽いね。もうすこしなんかないの?学問の自由とか言うことはないの?

大変申し訳ないのですが、これは消されて当然だし

Big Lizard's wife(カカシ姐さん

@biglizardswife

6分

大学サイトからDEIのページを消さないと、というより大学からDEIを排除しないと連邦政府から支援金がもらえなくなるからね。

こういう報いを受けても仕方ないのでは。だって何一つ書いていないんだもの

内容の問題点
抽象的な表現連続

「profound importance」「profound realization」「shared responsibility」「transform educators」など、抽象度の高いフレーズばかりで、具体的な教育実践が見えません。

成果の提示がない

例:「どんな学生に、どのような教材を用いて、どういった変化が見られたのか」といった具体的な成果・実例が欠如。

エピソード曖昧

教育者と話して無意識バイアスに気づいた」ことを語っていますが、どんな内容だったのか、どういう改善に繋がったのか、事例がないため説得力が弱い。

DEIの定義がない

そもそもこの文章では、DEI(Diversity, Equity, Inclusion)を日本語教育の中でどう具体的に扱うのかが一切記述されていません。

たとえば「教材に出てくる名前職業見直した」「LGBTQの観点を授業で扱った」などの実施例が欠落。

結論

トランプがカネを出さないというのは極めて至極まっとうで、この文章で人が感動することも共感することも同情することも理解することもない。

なに言ってるんだ。そのアカウント名もふざけている場合じゃないだろう。

大学からたたき出されないだけマシなのでは?

あと大学お金をもらわなくても大丈夫なんだから大学お金を出さなくてもいいのかも。

日本も見習うべきですね。

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