✅@2022-04-13 水理学の教科書をscrapbox書籍にする
作成方法
入力
Gyazoのpermalinkが入った配列
これは手元にある
uploadするだけ
節見出しとページ番号との対応
ここまでやらなくていいしやる時間もないので、省略したものを作り直す
以前やったときは、冒頭十数ページしか作成できなかったようだ
出力
書式は makePage()
で決める
2022-04-13
15:41:43 おしまい。あとは読みながら編集する
15:31:09 作成完了
当然だがprivate
見出しとページ番号との対応
ページ番号は表紙含めて0から始める
scriptの都合上、見出しに ,
が混じらないようにする
indexカバー | 0 |
表紙裏 | 1 |
表紙 | 2 |
執筆者一覧 | 3 |
まえがき | 6 |
目次 | 7 |
1.1 水理学とは? | 8 |
1.2 本書のねらいと構成 | 9 |
1.3 次元・単位・有効数字 | 11 |
1.4 流体の性質 | 15 |
1.5 流れの分類 | 18 |
2.1 なぜ「静水力学」を学ぶのか? | 20 |
2.2 静水圧 | 23 |
2.3 浮力とアルキメデスの原理 | 25 |
2.4 平面と曲面に働く静水圧 | 34 |
2.5 浮体の安定・不安定 | 43 |
3.1 水の持つエネルギー | 45 |
3.2 ベルヌーイの定理の導出 | 48 |
3.3 流管におけるエネルギーの流入・流出と仕事の関係による導出 | 51 |
3.4 ベルヌーイの定理を使ったトリチェリーの定理 | 53 |
3.5 ベルヌーイの定理の応用例 | 71 |
4.1 なぜ「運動量保存則」を学ぶのか? | 73 |
4.2 運動量保存則の導出 | 76 |
4.3 運動量保存則の応用 | 93 |
5.1 はじめに | 94 |
5.2 流体運動の記述方法 | 95 |
5.3 流体運動の基礎方程式 | 100 |
5.4 ナビエ・ストークスの式,連続式の導出 | 106 |
5.5 流体の基本運動要素と渦度 | 109 |
5.6 速度ポテンシャルと流関数 | 112 |
6.1 層流・乱流の性質 | 114 |
6.2 レイノルズ数 | 116 |
6.3 限界レイノルズ数 | 117 |
6.4 層流の流速分布―円管路の場合 | 120 |
6.5 乱流とレイノルズ応力 | 123 |
6.6 乱流の流速分布―壁面近傍の流れ― | 133 |
7.1 管路流れとは? | 134 |
7.2 管路流れの基礎式 | 136 |
7.3 摩擦損失 | 140 |
7.4 摩擦損失以外の損失 | 146 |
7.5 管路の損失計算 | 157 |
8.1 開水路流れとは? | 161 |
8.2 フルード数と常流・射流 | 165 |
8.3 比エネルギー | 168 |
8.4 開水路の断面変化に伴う水面形 | 175 |
8.5 比力 | 182 |
9.1 等流とは? | 183 |
9.2 等流における摩擦抵抗 | 185 |
9.3 平均流速公式 | 191 |
9.4 等流水深と限界勾配 | 197 |
10.1 漸変流とは? | 198 |
10.2 基礎式 | 202 |
10.3 基本的な水面形 | 205 |
10.4 水面形の出現例 | 209 |
11.1 水理模型実験と相似則 | 210 |
11.2 幾何学的相似と力学的相似 | 214 |
11.3 フルード相似則 | 216 |
11.4 レイノルズ相似則 | 219 |
演習問題解答 | 237 |
索引 | 239 |
出版情報 | 240 |
広告 | 241 |
裏表紙 | 242 |
shdeno cache -r=https://scrapbox.io https://scrapbox.io/api/code/takker/✅@2022-04-13_水理学の教科書をscrapbox書籍にする/script.ts
script.tsimport { getImage } from "../deno-gyazo/mod.ts";
import { getGyazoToken } from "../scrapbox-userscript-std/rest.ts";
import { useStatusBar } from "../scrapbox-userscript-std/dom.ts";
import { pool, sort } from "../async-lib/mod.ts";
import { upload } from "../scrapbox-file-uploader/mod.ts";
import { makePage, makePageInit } from "./makePage.ts";
import { makeSectionMap } from "./section.ts";
// 読み込み
const pending = fetch("/api/table/takker/『第3版_土質力学』/index.csv");
const file = await upload({ accept: "application/json, *.json"});
if (!file) throw new Error("no file specified");
// データ形成
const table = await (await pending).text();
const sectionMap = makeSectionMap(table);
const gyazoList = JSON.parse(await file.text()) as string[];
console.info(sectionMap);
console.log(gyazoList);
type Gyazo = { url: string; text: string; index: number; };
const result = await getGyazoToken();
if (!result.ok) throw new Error(JSON.stringify(result.value));
const accessToken = result.value;
if (!accessToken) throw new Error("Could not get the access token");
const { render, dispose } = useStatusBar();
// OCR取得
const reader = pool(
5,
Array(gyazoList.length).keys(),
async (index: number): Promise<Gyazo> => {
const gyazo = gyazoList[index];
const id = gyazo.match(/\/([^\/]+)$/)?.[1];
if (!id) throw new Error(`Could not find Gyazo ID from "${gyazo}"`);
const result = await getImage(id, { accessToken });
if (!result.ok) throw new Error(JSON.stringify(result.ok));
const { permalink_url, ocr } = result.value;
return { url: permalink_url, text: ocr?.description || "", index, };
},
);
const pages = [] as { title: string; lines: string[]; }[];
const stack = [] as makePageInit[];
let counter = 0;
for (const promise of reader) {
const result = await promise;
if (!result.success) throw new Error(JSON.stringify(result.reason));
const { url, text, index } = result.value;
// データを取得しながらページを作る
const data = {
section: sectionMap[counter],
pageNum: counter,
text: text,
gyazo: url,
};
stack.push(data);
if (stack.length === 2) {
pages.push(makePage({
...stack[0],
nextSection: stack[1].section,
}));
counter++;
} else if (stack.length === 3) {
pages.push(makePage({
...stack[1],
prevSection: stack[0].section,
nextSection: stack[2].section,
}));
stack.shift();
counter++;
} else {
counter++;
}
render(
{ type: "spinner" },
{
type: "text",
text: `${gyazoList.length} images, ${counter} got`,
},
);
}
dispose();
// 最後のページ
pages.push(makePage({
...stack[1],
prevSection: stack[0].section,
}));
// download
console.log(pages);
const blob = new Blob([JSON.stringify({ pages })], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "import.json";
a.click();
URL.revokeObjectURL(url);
以下の書式でページを作る
bodyOCRした本文
<=${prev}|${next}=>
[[${gyazo_url}]]
[${section}]
末尾に節へのリンクをつけて、同じ節のページを一覧できるようにする
編集しやすくするため
makePage.tsexport interface makePageInit {
section: string;
gyazo: string;
text: string;
/** ページ番号 */
pageNum: number;
prevSection?: string;
nextSection?: string;
}
export const makePage = (init: makePageInit): { title: string; lines: string[]; } => {
const {
section,
gyazo,
text,
pageNum,
prevSection,
nextSection,
} = init;
const title = `${format(section)} ${pageNum}`;
const prevTitle = prevSection ? `${format(prevSection)} ${pageNum - 1}` : undefined;
const nextTitle = nextSection ? `${format(nextSection)} ${pageNum + 1}` : undefined;
return {
title,
lines: [
title,
...format(text).split("\n"),
"",
`<=${
prevTitle ? `[${prevTitle}]` : ""
}|${
nextTitle ? `[${nextTitle}]` : ""
}=>`,
"",
`[${gyazo}]`,
`[${section}]`,
],
};
}
const format = (text: string): string =>
text
.replace(/\s+$/, "") // 末尾の余計な空白を消す
.replace(/^(\s*)・/, "$1 ") // ・を箇条書きに変える
.replace(
/[A-Za-z0-9]/g,
(s) => String.fromCharCode(s.charCodeAt(0) - 0xFEE0),
) // 全角英数を半角に直す
.replace(/\s?\[/g, "[") // リンク記法をescapeする
.replace(/\s?\[/g, "[")
.replace(/(\d+).\s*/g, "$1. ") // 番号付き箇条書きにする
.replaceAll(".", "。") // 句読点を変換する
.replaceAll(",", "、");
csvから、ページ番号と見出しとの対応配列を作る
section.tsexport const makeSectionMap = (csv: string): string[] => {
const data = csv.split("\n").map((row) => row.split(","));
const sections = [] as string[];
for (const [section, end] of data) {
while (sections.length <= parseInt(end)) {
sections.push(section);
}
}
return sections
};