diff --git a/README.md b/README.md index 4f27de9..bb6283d 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,11 @@ _Warning: This project is not suitable for free Vercel plan. There is insufficie ### Deploying to Cloudflare Pages [![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button?paid=true)](https://deploy.workers.cloudflare.com/?url=https://github.com/Trance-0/Notechondria) + +### Deploying as separated docker services + +Considering the memory usage for this project, it is better to deploy it as separated docker services. + +```bash +docker-compose up -d -f docker/docker-compose.yaml +``` diff --git a/content/Math4201/Math4201_L24.md b/content/Math4201/Math4201_L24.md new file mode 100644 index 0000000..c31133a --- /dev/null +++ b/content/Math4201/Math4201_L24.md @@ -0,0 +1,110 @@ +# Math4201 Topology I (Lecture 24) + +## Connected and compact spaces + +### Connectedness + +Recall from example last lecture, there exists a connected space but not path-connected space. + +#### Lemma on connectedness + +Let $X$ be a topological space and $A\subseteq X$ is a connected subspace. If $B\subseteq X$ satisfies $A\subseteq B\subseteq \overline{A}$, then $B$ is connected. In particular, $\overline{A}$ is connected. + +
+Proof + +Assume that $B$ is not connected. In particular, there are open subspaces $U$ and $V$ of $X$ such that $U\cap B, V\cap B$ is a separation of $B$. + +Take $U\cap A, V\cap A$, we show that this gives a separation of $A$. + +(i) Since $U,V$ are open, $U\cap A, V\cap A$ are open in $A$. + +(ii) Since $(U\cap B)\cap (V\cap B)=\emptyset$, $(U\cap A)\cap (V\cap A)=\emptyset$. + +(iii) Since $(U\cap B)\cup (V\cap B)=B$, any point in $B$ is in either $U\cap B$ or $V\cap B$. + +Since $A\subseteq B$, $(U\cap A)\cup (V\cap A)=A$. + +(iv) $U\cap A$ and $V\cap A$ is nonempty by assumption $U\cap B$ is nonempty and contains $x\in B\cap U\subseteq \overline{A}$. So any open neighborhood of $x$ have non-empty intersection $x'\in A$, so $x'\in U\cap A$ and $U\cap A$ is nonempty. Similarly, $V\cap A$ is nonempty. + +So $U\cap A$ and $V\cap A$ is a separation of $A$, which contradicts the assumption that $A$ is connected. + +Therefore, $B$ is connected. + +
+ +#### Topologists' sine curve + +Let $A=\{(x,y)\in \mathbb{R}^2\mid y=\sin(1/x), x>0\}$. Then $A$ is connected, and also path-connected. + +$$ +\gamma(t) = (t, \sin(1/t)) \text{ for } t\in (0,1] +$$ + +However, take $\overline{A}=A\cup \{0\}\times [-1,1]$. Then $\overline{A}$ is not path-connected but connected. + +
+Proof that topologists' sine curve is not path-connected + +We want to show $X=\overline{A}$ has no continuous path + +$$ +\gamma:([0,1])\to X +$$ + +such that $\gamma(0)=(0,0)$ and $\gamma(1)=(1,\sin(1))$. + +If there exists such a path, let $t_0\in [0,1]$ be defined as + +$$ +t_0=\sup\{t\in [0,1]\mid \gamma(t)=(0,x), x\in [0,1]\} +$$ + +By the assumption on $t_0$, we can find a sequence $\{t_n\}_{n\in\mathbb{N}_+}\subseteq A$ such that $t_n\to t$. + +By continuity of $\gamma$, we have $\gamma(t_n)\to \gamma(t_0)$, $(0,y_n)\to (0,y_0)$. + +Now focus on the restriction of $\gamma$ to $[t_0,1]$, $\gamma:[t_0,1]\to X$, $\gamma(t_0)=(0,y_0)$, $\gamma(1)=(1,\sin(1))$. + +$t\in (t_0,1]$, then $\gamma(t)\in$ graph of $y=\sin(1/x)$. + +Consider $\pi$ be the projection map to $x$-axis, $\pi\circ \gamma:[t_0,1]\to \mathbb{R}$, $\pi\circ \gamma(t_0)=0$ and $\pi\circ \gamma(1)=1$. + +In particular, there is a sequence $s_n\in [t_0,1]$ such that $s_n\to t_0$ and $\pi\circ \gamma(s_n)=\frac{1}{n\pi+\frac{\pi}{2}}$. (using intermediate value theorem) + +Then $\gamma(s_n)=(\frac{1}{n\pi},\sin(n\pi+\frac{\pi}{2}))=(\frac{1}{n\pi},(-1)^n)$. + +Since as $s_n\to t_0$, and $\gamma$ is continuous, then we get a contradiction that the sequence $\gamma(s_n)$ should converge to $(0,t_0)$ where it is not. + +
+ +### Compactness + +Motivation: in real numbers. + +#### Extreme value theorem + +Let $f:[a,b]\to \mathbb{R}$ be continuous. Then there are $x_m,x_M\in [a,b]$ such that $f(x_m)\leq f(x)\leq f(x_M)$ for all $x\in [a,b]$. + +#### Definition of cover + +Let $X$ be a topological space. A covering of $X$ is a collection of subsets of $X$ that covers $X$. + +$$ +\{U_\alpha\}_{\alpha\in I} +$$ + +such that $X=\bigcup_{\alpha\in I} U_\alpha$. + +An open cover of $X$ is a covering of $X$ such that each $U_\alpha$ is open. + +#### Definition of compact space + +A topological space $X$ is compact if for any open covering $\{U_\alpha\}_{\alpha\in I}$ of $X$, there exists a finite subcovering $\{U_{\alpha_i}\}_{i=1}^n$ such that $X=\bigcup_{i=1}^n U_{\alpha_i}$. + +
+Example of non-compact space + +Consider the interval $(0,1]$, the open covering $(\frac{1}{n},1]$ open in $(0,1]$, $\{(\frac{1}{n},1]\}_{n\in \mathbb{N}_+}$ has no finite subcovering. + +
diff --git a/content/Math4201/_meta.js b/content/Math4201/_meta.js index b2e8c41..b51774f 100644 --- a/content/Math4201/_meta.js +++ b/content/Math4201/_meta.js @@ -27,4 +27,5 @@ export default { Math4201_L21: "Topology I (Lecture 21)", Math4201_L22: "Topology I (Lecture 22)", Math4201_L23: "Topology I (Lecture 23)", + Math4201_L24: "Topology I (Lecture 24)", } diff --git a/content/_meta.js b/content/_meta.js index 427baf6..3210cc9 100644 --- a/content/_meta.js +++ b/content/_meta.js @@ -1,4 +1,11 @@ export default { + /** + * Do not remove the labels "Math Courses Start" + * and "Math Courses End" and "CSE Courses Start" and "CSE Courses End" + * or the separated builds will not work. + * + * WE USE THESE LABELS TO BUILD THE SEPARATED WEBSITES FOR MATH AND CSE COURSES. + */ menu: { title: 'Home', type: 'menu', @@ -17,6 +24,7 @@ export default { } }, }, + /* Math Courses Start */ Math3200: { type: 'page', theme:{ @@ -59,6 +67,8 @@ export default { timestamp: true, } }, + /* Math Courses End */ + /* CSE Courses Start */ CSE332S: { title: 'CSE332S', type: 'page', @@ -108,6 +118,7 @@ export default { timestamp: true, } }, + /* CSE Courses End */ Swap: { display: 'hidden', theme:{ diff --git a/docker/cse/Dockerfile b/docker/cse/Dockerfile index db2706f..a39da3d 100644 --- a/docker/cse/Dockerfile +++ b/docker/cse/Dockerfile @@ -1,4 +1,4 @@ -# Dockerfile for CSE folders +# Dockerfile for Math folders # Source: https://github.com/vercel/next.js/blob/canary/examples/with-docker-multi-env/docker/production/Dockerfile # syntax=docker.io/docker/dockerfile:1 @@ -28,10 +28,21 @@ FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . +RUN ls -la -# 2.1 Remove unnecessary files for build with title not starting with CSE -RUN find ./content -type d -not -name "CSE*" -exec rm -rf {} + -RUN find ./public -type f -not -name "*.md" -exec rm -rf {} + +# 2.1 Remove unnecessary files for build with title starting with CSE +RUN cd ./content && find . -maxdepth 1 -type d -name "Math*" -exec rm -rf {} + +RUN cd ./public && find . -maxdepth 1 -type d -name "Math*" -exec rm -rf {} + + +# 2.1.1 Check the updated folders +RUN cd ./content && ls -la +RUN cd ./public && ls -la + +# 2.2 Update the _meta.js files in the content folder +RUN sed -i '/\/\* Math Courses Start \*\//,/\/\* Math Courses End \*\//d' ./content/_meta.js + +# 2.2.1 Check the updated _meta.js file +RUN cat ./content/_meta.js # This will do the trick, use the corresponding env file for each environment. # COPY .env.production.sample .env.production @@ -55,8 +66,8 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs -EXPOSE 3000 +EXPOSE 4201 -ENV PORT=3000 +ENV PORT=4201 CMD HOSTNAME="0.0.0.0" node server.js \ No newline at end of file diff --git a/docker/cse/test-build.sh b/docker/cse/test-build.sh new file mode 100644 index 0000000..770469d --- /dev/null +++ b/docker/cse/test-build.sh @@ -0,0 +1 @@ +sudo docker build -t trance-0/notenextra-cse:v1.2.0 -f ./docker/cse/Dockerfile --no-cache --progress=plain . \ No newline at end of file diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml new file mode 100644 index 0000000..a2ad87e --- /dev/null +++ b/docker/docker-compose.yaml @@ -0,0 +1,30 @@ +services: + # you may need to update relative directories if you move this file + # default created directories is /docker/docker-compose.yaml + notenextra-math: + build: + context: ../ + dockerfile: ./docker/math/Dockerfile + tags: + - trance0/notenextra-math:latest + restart: on-failure:5 + ports: + - 13001:4201 + notenextra-cse: + build: + context: ../ + dockerfile: ./docker/cse/Dockerfile + tags: + - trance0/notenextra-cse:latest + restart: on-failure:5 + ports: + - 13002:4202 + nginx: + image: nginx:latest + ports: + - 13000:80 + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf + depends_on: + - notenextra-math + - notenextra-cse \ No newline at end of file diff --git a/docker/math/Dockerfile b/docker/math/Dockerfile index cba13de..9c4e37c 100644 --- a/docker/math/Dockerfile +++ b/docker/math/Dockerfile @@ -28,12 +28,21 @@ FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . +RUN ls -la # 2.1 Remove unnecessary files for build with title starting with CSE -RUN cd /app/content -RUN find . -maxdepth 1 -type d -name "CSE*" -delete -RUN cd /app/public -RUN find . -maxdepth 1 -type d -name "CSE*" -delete +RUN cd ./content && find . -maxdepth 1 -type d -name "CSE*" -exec rm -rf {} + +RUN cd ./public && find . -maxdepth 1 -type d -name "CSE*" -exec rm -rf {} + + +# 2.1.1 Check the updated folders +RUN cd ./content && ls -la +RUN cd ./public && ls -la + +# 2.2 Update the _meta.js files in the content folder +RUN sed -i '/\/\* CSE Courses Start \*\//,/\/\* CSE Courses End \*\//d' ./content/_meta.js + +# 2.2.1 Check the updated _meta.js file +RUN cat ./content/_meta.js # This will do the trick, use the corresponding env file for each environment. # COPY .env.production.sample .env.production diff --git a/docker/math/test-build.sh b/docker/math/test-build.sh new file mode 100644 index 0000000..f407689 --- /dev/null +++ b/docker/math/test-build.sh @@ -0,0 +1 @@ +sudo docker build -t trance-0/notenextra-math:v1.2.0 -f ./docker/math/Dockerfile --no-cache --progress=plain . \ No newline at end of file diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000..7240c14 --- /dev/null +++ b/docker/nginx.conf @@ -0,0 +1,23 @@ + # Example for conf.d/default.conf + server { + listen 80; + server_name localhost; + + location /Math* { + proxy_pass http://notenextra-math:4201; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /CSE* { + proxy_pass http://notenextra-cse:4202; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + + } \ No newline at end of file diff --git a/next-sitemap.config.js b/next-sitemap.config.js index 6a6027a..5f3a52e 100644 --- a/next-sitemap.config.js +++ b/next-sitemap.config.js @@ -1,8 +1,8 @@ /** @type {import('next-sitemap').IConfig} */ -export default { - siteUrl: 'https://notenextra.trance-0.com', - changefreq: 'weekly', - priority: '0.5', - generateIndexSitemap: false, - exclude: ['/icon.svg'] - } \ No newline at end of file +module.exports = { + siteUrl: 'https://notenextra.trance-0.com', + changefreq: 'daily', + priority: '0.5', + generateIndexSitemap: false, + exclude: ['/icon.svg'] +} \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs index 8441979..23dbd85 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -26,8 +26,8 @@ export default bundleAnalyzer(withNextra({ }, experimental: { webpackMemoryOptimizations: true, - staticGenerationMaxConcurrency: 2, // try 1–3 - staticGenerationMinPagesPerWorker: 1 // keep small + staticGenerationMaxConcurrency: 2, // try 1–3, default is 8 + staticGenerationMinPagesPerWorker: 1 // keep small, default is 25 } }))