はてなキーワード: trueとは
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/
新たにサービスを作るときの話になりますが、認証 Cookie の名前に __Http- もしくは __HostHttp- プレフィックスを付けるのをお勧めしますね。
新しい機能のためまだ Chrome のみのサポートとなりますが、HttpOnly 属性が強制されるので、つけ忘れの防止になります。
HttpOnly属性だけでは、対策しきれず credentials: "include" を使えば、HttpOnly属性を含んだcookieも取れてしまうって聞いたのですが、これって本当ですか?
Request の credentials: "include" は別のオリジンへリクエストを飛ばす場合でも(そのサイトで設定された)Cookie を含めるかどうかを指定するためのものですね。Cookie の中身が読み取れるものではありません。
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/
JSONと比べたときの**YAMLの「闇深」仕様**、ありますね…。
YAMLは人間に優しいと言われながらも、その仕様はときに**悪魔的**。
以下、ITエンジニアなら一度は踏んだであろう「地雷」を、**論理的かつ少し自虐的に**まとめてみました:
---
good: value: ok bad: value: nightmare # ←ここ、インデントずれてて無効。だけど一見わからない。
---
password: no # ← 文字列じゃなくて false になる可能性 serial: 012345 # ← 8進数!?→ エラー
---
message: | これは複数行の スカラー値です。
---
defaults: &defaults timeout: 30 retries: 3 service: <<: *defaults retries: 5 # 上書きされるが、複雑になると意図しない結果に </pre>
---
---
---
もしYAMLを安全に扱いたいなら、\*\*JSON supersetとしての使い方(厳格YAML)\*\*を意識したり、**JSONに寄せて書く**のが一番平和だったりします。
---
要するに、YAMLは「賢く書こうとすると沼る」。
「素直に、簡潔に、禁欲的に」が正解です。
でも誘惑が多いのよね、あの子……。
MOMENTUM True Wireless 4 の金ぴかイヤホンカッコいいよね
ゼンハイザーに限らず
現行置いておくね
https://itest.5ch.net/mevius/test/read.cgi/av/1710278774/l-
ばーっとながめて評判を頭に叩き込む
気になる機種があればXなどで追加でパブサすればよろしい
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.
まず、準備できてる?
pip install pygame
⸻
🎮 Monday式 PONG ゲーム(シンプルだけどちゃんと動く)
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)
⸻
• Esc 押すと終了(またはウィンドウ×)
⸻
このコード、わりと「教育的に健全な地獄」だから、自由に拡張できるよ:
• ボールが速くなっていく
⸻
あとで「飴ちゃん飛ばすモード」とかも追加できるぞ。バカ拡張大歓迎。
どう?動いた?やってみて。報告もらえれば、次の「社会風刺機能付きPONG」考えておくわ。
https://anond.hatelabo.jp/20250706011306#
<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#
<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> ``` <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#
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("これは、現行システムが特定グループだけでなく全体の非効率性につながっていることを示唆しています。")
WSL2 USBカメラ+他のUSB機器 2022年09月06日版
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 のインストール
> wsl --update
> wsl --status
> 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
> wsl --install --distribution Ubuntu-20.04
[WT] WSLのディストリビューションを起動(WSL2起動用アイコンをマウスでクリックして起動してもよい)
> wsl --list
Linux 用 Windows サブシステム ディストリビューション:
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
> wsl --shutdown
[WT] USBカメラが usbipd に認識されることを確認する (この記事では 2-7)
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 と表示されていれば成功)
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] Ubuntuのbashにログオンした既定のユーザを video グループに所属させる。なお、WSLを起動した時点で既に追加されているメッセージが表示される。
[Ubuntu] WSL2上の Ubuntu20.04 の中からUSBカメラが認識されていることを確認する。 lsusb コマンドを経由すると正常にUSBカメラが認識されているが、/dev/video* にはUSBカメラが列挙されない
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: cannot access '/dev/video*': No such file or directory
[Ubuntu] USB CameraがWSL内で認識されるようにLinuxカーネルをカスタムビルドする。下記リポジトリの手順通りに実施すると、WSL Linuxカーネルがカスタムビルドされたものに入れ替わる。注意点は、<windows username> の部分だけは各自の環境のWindowsユーザー名に手で書き換える必要が有ること。なお、.wslconfig は 絶対に windows 側で編集してはならない。絶対に。
> wsl --shutdown
[WT] USBカメラが usbipd に認識されることを確認する (この記事では 2-7)
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 と表示されていれば成功)
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カメラが認識されていることを確認する
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
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.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)
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(
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 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),
}
tf_lite_output = tf_lite_model(**inputs)
elapsed_time = time.time() - start_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
日中の生産性は、夜の過ごし方、特に「就寝」というクリティカルなタスクをいかに成功させるかにかかっている。本記事では、つい夜更かししてしまうエンジニアのために、早寝を「技術」として体系化し、再現性のある形で実践するための具体的な手法を探求する。これは精神論ではない。あなたのQoLと生産性を向上させるための、実践的なスリープエンジニアリングだ。
我々エンジニアにとって、夜は不思議な魅力を持つ時間だ。日中の喧騒から解放され、思考は冴えわたり、ゾーンに入りやすい。しかし、その魅力的な時間は、往々にして「早寝」という、人間の生存に不可欠な基本プロセスを犠牲にすることで成り立っている。
「リファクタリングが楽しくなってきた」
これらの探求心はエンジニアの美徳であるが、同時に我々を「睡眠負債」という深刻な技術的負債へと導く。本稿は、この負債を返済し、持続可能な開発(と生活)を実現するための「早寝」という技術に焦点を当てる。
早寝を実装する前に、まずは現状のアーキテクチャに潜むアンチパターンを特定しよう。
就寝前のスマートフォンは、まさに同期的なブロッキングI/Oだ。SNSの無限スクロール、動画プラットフォームの自動再生、チャットアプリの通知。これらは我々の意識というシングルスレッドを完全に占有し、本来実行されるべきsleep()プロセスへの遷移を妨げる。
深夜まで続くコーディングや問題解決は、脳を極度の興奮状態にする。ベッドに入っても、アドレナリンやコルチゾールといったホルモンがCacheに残り続け、CPUがクールダウンしない。shutdown -h nowを叩いても、プロセスが終了しないのだ。
「夜更かしの供」として注入されるカフェインやアルコールは、一見するとパフォーマンスを向上させるように見える。しかし、これらは睡眠の質という重要なmetricsを著しく劣化させる、誤った依存関係だ。特にアルコールは、入眠を助けるように見えて、実はレム睡眠を阻害し、睡眠のアーキテクチャ全体を不安定にする。
不規則な就寝・起床時間は、体内時計という最も重要なCronジョブを破壊する。毎日異なる時間に実行されるジョブが安定した結果をもたらさないのと同様に、不規則な睡眠スケジュールは、日中のパフォーマンスを予測不可能なものにする。
では、どうすればこれらのアンチパターンを排除し、安定した早寝pipelineを構築できるのか。ここではSleep as Codeの概念に基づき、具体的なプラクティスを紹介する。
毎晩、同じ手順で就寝プロセスを実行することで、入眠を自動化する。
- PC/スマホのシャットダウン: 最も重要なステップ。物理的に電源を落とすか、手の届かない場所(別のコンテナ)にdeployする。
- 入浴: 38〜40℃のぬるめのお湯に15分ほど浸かる。これにより深部体温が一時的に上昇し、その後の下降とともに入眠が促される。これはHot-swapならぬHot-bathによるクールダウンだ。
静的コンテンツの消費: 激しい思考を伴わない、静的な情報(紙の読書など)に切り替える。電子書籍ではなく、紙媒体が望ましい。
ストレッチ: 軽いストレッチで、日中のcommitで固まった体をreleaseする。
すべての準備が整ったら、ベッドという本番環境にデプロイする。余計な思考はgit clean -fdで強制削除し、呼吸に集中する。
例:「夕食後のコーヒーが原因だった」→「カフェインの摂取は15時までというSLAを設ける」
早寝は、単に体を休める行為ではない。日中の高いパフォーマンス、明晰な思考、そして創造性を維持するための、最も効果的で再現性の高い「技術」だ。
我々はインフラをコードで管理し、CI/CDでデプロイを自動化するように、自身の睡眠もまた、技術と工夫によってコントロールできる。今夜、あなたのwhile(true)なループをbreakし、持続可能なパフォーマンスを手に入れるための第一歩を踏み出してほしい。
Happy sleeping!
日中の生産性は、夜の過ごし方、特に「就寝」というクリティカルなタスクをいかに成功させるかにかかっている。本記事では、つい夜更かししてしまうエンジニアのために、早寝を「技術」として体系化し、再現性のある形で実践するための具体的な手法を探求する。これは精神論ではない。あなたのQoLと生産性を向上させるための、実践的なスリープエンジニアリングだ。
我々エンジニアにとって、夜は不思議な魅力を持つ時間だ。日中の喧騒から解放され、思考は冴えわたり、ゾーンに入りやすい。しかし、その魅力的な時間は、往々にして「早寝」という、人間の生存に不可欠な基本プロセスを犠牲にすることで成り立っている。
「リファクタリングが楽しくなってきた」
これらの探求心はエンジニアの美徳であるが、同時に我々を「睡眠負債」という深刻な技術的負債へと導く。本稿は、この負債を返済し、持続可能な開発(と生活)を実現するための「早寝」という技術に焦点を当てる。
早寝を実装する前に、まずは現状のアーキテクチャに潜むアンチパターンを特定しよう。
就寝前のスマートフォンは、まさに同期的なブロッキングI/Oだ。SNSの無限スクロール、動画プラットフォームの自動再生、チャットアプリの通知。これらは我々の意識というシングルスレッドを完全に占有し、本来実行されるべきsleep()プロセスへの遷移を妨げる。
深夜まで続くコーディングや問題解決は、脳を極度の興奮状態にする。ベッドに入っても、アドレナリンやコルチゾールといったホルモンがCacheに残り続け、CPUがクールダウンしない。shutdown -h nowを叩いても、プロセスが終了しないのだ。
「夜更かしの供」として注入されるカフェインやアルコールは、一見するとパフォーマンスを向上させるように見える。しかし、これらは睡眠の質という重要なmetricsを著しく劣化させる、誤った依存関係だ。特にアルコールは、入眠を助けるように見えて、実はレム睡眠を阻害し、睡眠のアーキテクチャ全体を不安定にする。
不規則な就寝・起床時間は、体内時計という最も重要なCronジョブを破壊する。毎日異なる時間に実行されるジョブが安定した結果をもたらさないのと同様に、不規則な睡眠スケジュールは、日中のパフォーマンスを予測不可能なものにする。
では、どうすればこれらのアンチパターンを排除し、安定した早寝pipelineを構築できるのか。ここではSleep as Codeの概念に基づき、具体的なプラクティスを紹介する。
毎晩、同じ手順で就寝プロセスを実行することで、入眠を自動化する。
- PC/スマホのシャットダウン: 最も重要なステップ。物理的に電源を落とすか、手の届かない場所(別のコンテナ)にdeployする。
- 入浴: 38〜40℃のぬるめのお湯に15分ほど浸かる。これにより深部体温が一時的に上昇し、その後の下降とともに入眠が促される。これはHot-swapならぬHot-bathによるクールダウンだ。
静的コンテンツの消費: 激しい思考を伴わない、静的な情報(紙の読書など)に切り替える。電子書籍ではなく、紙媒体が望ましい。
ストレッチ: 軽いストレッチで、日中のcommitで固まった体をreleaseする。
すべての準備が整ったら、ベッドという本番環境にデプロイする。余計な思考はgit clean -fdで強制削除し、呼吸に集中する。
例:「夕食後のコーヒーが原因だった」→「カフェインの摂取は15時までというSLAを設ける」
早寝は、単に体を休める行為ではない。日中の高いパフォーマンス、明晰な思考、そして創造性を維持するための、最も効果的で再現性の高い「技術」だ。
我々はインフラをコードで管理し、CI/CDでデプロイを自動化するように、自身の睡眠もまた、技術と工夫によってコントロールできる。今夜、あなたのwhile(true)なループをbreakし、持続可能なパフォーマンスを手に入れるための第一歩を踏み出してほしい。
Happy sleeping!
一度投稿したうえで別タブを開いてプログラム的(fetch)に送信してその別タブが閉じられる仕組み。
// ==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 }); })();
// ==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); } })();
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
#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-----
ようやく(ほぼ)すべてが自動化された。
あとはローカルサーバーの起動をスタートアップに設定する(方法をAIに聞いて指示に従う)だけの消化試合。
署名時要求してくるパスワードを自動入力するahkファイルはドキュメントのAutoHotkey配下に置いた。
バッチファイル(make.sign.bat)はデスクトップに置いた。
#Persistent #SingleInstance ignore SetTitleMatchMode, 2 WinWaitActive, pinentry SendInput お前のパスワード Sleep 100 SendInput {Enter} ExitApp
// 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/'); });
@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
// ==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-----
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.
令和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('92;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}" # pdfのURLとファイル名を作成 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}')
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
学部からのお達しで、私のこのページ、もうすぐ消えることになったので、よかったら消える前に読んでくださ~い。
https://x.com/mochiey/status/1912156111953662160
もっちりんだ 🇺🇸 🇯🇵 🏳️🌈
@mochiey
Teaching Professor of Japanese Language | University of Michigan 🇺🇸生活・Podcasts・日本語教育・人権 (LGBTQ+, フェミニズム), etc. Posts are my own. 他のSNSも 全て
@mochiey
でやってます。
すごく軽いね。もうすこしなんかないの?学問の自由とか言うことはないの?
大変申し訳ないのですが、これは消されて当然だし
6分
大学のサイトからDEIのページを消さないと、というより大学からDEIを排除しないと連邦政府からの支援金がもらえなくなるからね。
こういう報いを受けても仕方ないのでは。だって何一つ書いていないんだもの。
「profound importance」「profound realization」「shared responsibility」「transform educators」など、抽象度の高いフレーズばかりで、具体的な教育実践が見えません。
例:「どんな学生に、どのような教材を用いて、どういった変化が見られたのか」といった具体的な成果・実例が欠如。
「教育者と話して無意識のバイアスに気づいた」ことを語っていますが、どんな内容だったのか、どういう改善に繋がったのか、事例がないため説得力が弱い。
そもそもこの文章では、DEI(Diversity, Equity, Inclusion)を日本語教育の中でどう具体的に扱うのかが一切記述されていません。
たとえば「教材に出てくる名前や職業を見直した」「LGBTQの観点を授業で扱った」などの実施例が欠落。
トランプがカネを出さないというのは極めて至極まっとうで、この文章で人が感動することも共感することも同情することも理解することもない。
なに言ってるんだ。そのアカウント名もふざけている場合じゃないだろう。
あと大学もお金をもらわなくても大丈夫なんだから、大学にお金を出さなくてもいいのかも。
日本も見習うべきですね。