diff --git a/.env.production b/.env.production
new file mode 100644
index 0000000..3782a41
--- /dev/null
+++ b/.env.production
@@ -0,0 +1 @@
+BUILD_MODE=production
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index f0f3abe..0000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "extends": "next/core-web-vitals",
- "rules": {
- "@next/next/no-img-element": "off"
- }
-}
diff --git a/.gitignore b/.gitignore
index eb1fa8d..c41f3bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,11 @@ yarn-error.log*
# vercel
.vercel
+
+
+
+tsconfig.tsbuildinfo
+
+
+public/data
+src/lib/generatedEventData.ts
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
index 6f1f11f..dc46161 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,3 +1,4 @@
.next
out
-node_modules
\ No newline at end of file
+node_modules
+next-env.d.ts
diff --git a/.prettierrc b/.prettierrc
index 59c336c..f3713c2 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -3,5 +3,5 @@
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "none",
- "semi": false
+ "semi": true
}
diff --git a/README.md b/README.md
index 1afb9ba..ce1138a 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ GitHub Actions で Push 時に自動デプロイされます.
| | |--index.tsx
| |--index.tsx
| |--links.tsx
-| |--menbers.tsx
+| |--members.tsx
| |--welcome.tsx
|--public
| |--static
diff --git a/components/EventList.tsx b/components/EventList.tsx
deleted file mode 100644
index 436575c..0000000
--- a/components/EventList.tsx
+++ /dev/null
@@ -1,601 +0,0 @@
-/** @format */
-import detailsStyle from '../styles/details.module.css'
-
-type problemSetType = {
- college: string
- link: string
-}
-
-type problemType = {
- title: string
- link: string
-}
-
-type otherContentType = {
- title: string
- content: JSX.Element
-}
-
-export type EventDetailType = {
- title: string
- day?: 'Day 1' | 'Day 2' | 'Day 3'
- date: {
- begin: string
- end: string
- }
- detailURL?: string
- problemSet: problemSetType[]
- commentary: problemType[]
- writer?: string[]
- picture?: string
- judge: string
- iodata?: JSX.Element
- schedule?: JSX.Element
- place: string
- otherContent?: otherContentType[]
-}
-
-type EventDetailsType = {
- [key: string]: EventDetailType
-}
-
-export const EventDetails: EventDetailsType = {
- rupc2024: {
- title: '立命合宿 2024',
- day: 'Day 1',
- date: {
- begin: '2024/3/23',
- end: '2024/3/24'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- detailURL: 'https://rippro.connpass.com/event/309923/',
- problemSet: [
- {
- college: 'Day 1 (立命館大学)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RUPC2024Day1'
- },
- {
- college: 'Day 2 (会津大学さん)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RUPC2024Day2'
- }
- ],
- commentary: [
- { title: 'A: Empire of the BIWAKO', link: 'A_Empire_of_the_BIWAKO.pdf' },
- { title: 'B: Goodbye, BKC', link: 'B_Goobye_BKC.pdf' },
- { title: 'C: Belt-line Bus Trip', link: 'C_Belt-line_bus_trip.pdf' },
- { title: 'D: 2xL Minesweeper', link: 'D_2xL_minesweeper.pdf' },
- { title: 'E: palindromic?', link: 'E_palindromic.pdf' },
- { title: 'F: MOD Party', link: 'F_MOD_party.pdf' },
- { title: 'G: Skating', link: 'G_Skating.pdf' },
- { title: 'H: miNIMum', link: 'H_miNIMum.pdf' },
- { title: 'I: jucumber', link: 'I_jucumber.pdf' }
- ],
- place: '立命館大学 BKC'
- },
- rupc2019: {
- title: '立命合宿 2019',
- day: 'Day 1',
- date: {
- begin: '2019/3/5',
- end: '2019/3/7'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- problemSet: [
- {
- college: 'Day 1 (立命館大学)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp19Day1'
- },
- {
- college: 'Day 2 (会津大学さん)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp19Day2'
- },
- {
- college: 'Day 3 (北海道大学さん)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp19Day3'
- }
- ],
- commentary: [
- { title: '全体講評', link: 'kohyo.pdf' },
- { title: 'A: タイル貼り', link: 'A.pdf' },
- { title: 'B: たぬきつね', link: 'B.pdf' },
- { title: 'C: オセロ', link: 'C.pdf' },
- { title: 'D: 場所当てゲーム', link: 'D.pdf' },
- { title: 'E: LISum', link: 'E.pdf' },
- { title: 'F: Absum', link: 'F.pdf' },
- { title: 'G: イルミネーション', link: 'G.pdf' }
- ],
- place: '立命館大学 BKC'
- },
- acpc2018: {
- title: '会津合宿 2018',
- day: 'Day 1',
- date: {
- begin: '2018/9/19',
- end: '2018/9/21'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- detailURL: 'https://web.archive.org/web/20190321162010/https://atnd.org/events/98718',
- problemSet: [
- {
- college: 'Day1(立命館大学)',
- link: 'https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2018Day1'
- },
- {
- college: 'Day2(会津大学)',
- link: 'https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2018Day2'
- },
- {
- college: 'Day3(北海道大学)',
- link: 'https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2018Day3'
- }
- ],
- commentary: [
- { title: '全体講評', link: 'kohyo.pdf' },
- { title: 'A: テスト', link: 'A.pdf' },
- { title: 'B: 直角三角形', link: 'B.pdf' },
- { title: 'C: 素数', link: 'C.pdf' },
- { title: 'D: 遭難', link: 'D.pdf' },
- { title: 'E: 凸凹数列', link: 'E.pdf' },
- { title: 'F: Swap', link: 'F.pdf' },
- { title: 'G: 式の切り取り', link: 'G.pdf' },
- { title: 'H: 板', link: 'H.pdf' }
- ],
- place: '会津大学'
- },
- rupc2018: {
- title: '立命合宿 2018',
- day: 'Day 1',
- date: {
- begin: '2018/3/26',
- end: '2018/3/28'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- detailURL: 'https://web.archive.org/web/20180202123544/https://atnd.org/events/94033',
- problemSet: [
- {
- college: 'Day 1 (立命館大学)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp18Day1'
- },
- {
- college: 'Day 2 (会津大学さん)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp18Day2'
- },
- {
- college: 'Day 3 (北海道大学さん)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp18Day3'
- }
- ],
- commentary: [
- { title: '全体講評', link: 'kohyo.pdf' },
- { title: 'A: 鳩ノ巣原理', link: 'A.pdf' },
- { title: 'B: 写像', link: 'B.pdf' },
- { title: 'C: 一致', link: 'C.pdf' },
- { title: 'D: 水槽', link: 'D.pdf' },
- { title: 'E: いたずらされたグラフ', link: 'E.pdf' },
- { title: 'F: ごちうさ数', link: 'F.pdf' },
- { title: 'G: エレベータ', link: 'G.pdf' }
- ],
- place: '立命館大学 BKC'
- },
- acpc2017: {
- title: '会津合宿 2017',
- day: 'Day 1',
- date: {
- begin: '2017/9/18',
- end: '2017/9/20'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- problemSet: [
- { college: 'Day1(立命館大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2017Day1' },
- { college: 'Day2(会津大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2017Day2' },
- { college: 'Day3(北海道大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2017Day3' }
- ],
- commentary: [
- { title: '全体講評', link: 'kohyo.pdf' },
- { title: 'A: 丸付け', link: 'A.pdf' },
- { title: 'B: 全日本帰りたい協会', link: 'B.pdf' },
- { title: 'C: ツイート数', link: 'C.pdf' },
- { title: 'D: 次元旅行', link: 'D.pdf' },
- { title: 'E: 敵襲から守れ', link: 'E.pdf' },
- { title: 'F: 階段', link: 'F.pdf' },
- { title: 'G: 鍵', link: 'G.pdf' }
- ],
- place: '会津大学'
- },
- rupc2017: {
- title: '立命合宿 2017',
- day: 'Day 1',
- date: {
- begin: '2017/3/22',
- end: '2017/3/24'
- },
- detailURL: 'https://web.archive.org/web/20181205111517/https://atnd.org/events/85691',
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- problemSet: [
- {
- college: 'Day 1 (立命館大学 & 大阪大学)',
- link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp17Day1'
- },
- { college: 'Day 2 (会津大学さん)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp17Day2' },
- { college: 'Day 3 (北海道大学さん)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp17Day3' }
- ],
- commentary: [
- { title: '全体講評', link: 'kohyo.pdf' },
- { title: 'A: トーナメント', link: 'A.pdf' },
- { title: 'B: 重さの範囲', link: 'B.pdf' },
- { title: 'C: Fractal Tree', link: 'C.pdf' },
- { title: 'D: パスワード', link: 'D.pdf' },
- { title: 'E: 卒業式', link: 'E.pdf' },
- { title: 'F: カードゲーム', link: 'F.pdf' },
- { title: 'G: 雨降りバス乗り替え', link: 'G.pdf' },
- { title: 'H: ジャンプパーティ', link: 'H.pdf' },
- { title: 'I: Islands Survival', link: 'I.pdf' },
- { title: 'J: エナジードリンク', link: 'J.pdf' },
- { title: 'K: AORイカちゃんの成績', link: 'K.pdf' }
- ],
- place: '立命館大学 BKC'
- },
- acpc2016: {
- title: '会津合宿 2016',
- day: 'Day 1',
- date: {
- begin: '2016/9/17',
- end: '2016/9/19'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- detailURL: 'https://web.archive.org/web/20200326193543/https://atnd.org/events/79743',
- problemSet: [
- { college: 'Day1(立命館大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2016Day1' },
- { college: 'Day2(会津大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2016Day2' },
- { college: 'Day3(北海道大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp16Day3' }
- ],
- commentary: [
- { title: '全体講評', link: 'kohyo.pdf' },
- { title: 'A: キャベツ', link: 'A.pdf' },
- { title: 'B: イカったー', link: 'B.pdf' },
- { title: 'C: 失われしグラフ', link: 'C.pdf' },
- { title: 'D: DAGトリオ(Easy)', link: 'D.pdf' },
- { title: 'E: 札', link: 'E.pdf' },
- { title: 'F: 紙の折りたたみ', link: 'F.pdf' },
- { title: 'G: DAGトリオ(Hard)', link: 'G.pdf' }
- ],
- place: '会津大学'
- },
- rupc2016: {
- title: '立命合宿 2016',
- day: 'Day 1',
- date: {
- begin: '2016/3/6',
- end: '2016/3/8'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- problemSet: [
- { college: 'Day 1 (立命館大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp16Day1' },
- { college: 'Day 2 (会津大学さん)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp16Day2' },
- { college: 'Day 3 (北海道大学さん)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp16Day3' }
- ],
- commentary: [
- { title: 'A: 秤', link: 'A.pdf' },
- { title: 'B: ハミング距離', link: 'B.pdf' },
- { title: 'C: 足し算掛け算', link: 'C.pdf' },
- { title: 'D: スキャナー', link: 'D.pdf' },
- { title: 'E: 28', link: 'E.pdf' },
- { title: 'F: リレー', link: 'F.pdf' },
- { title: '別解', link: 'F_tm.pdf' },
- { title: 'G: 塗るだけ', link: 'G.pdf' }
- ],
- place: '立命館大学 BKC'
- },
- acpc2015: {
- title: '会津合宿 2015',
- day: 'Day 1',
- date: {
- begin: '2015/9/21',
- end: '2015/9/23'
- },
- detailURL: '',
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- problemSet: [
- { college: 'Day1(立命館大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2015Day1' },
- { college: 'Day2(会津大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2015Day2' },
- { college: 'Day3(北海道大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2015Day3' }
- ],
- commentary: [
- { title: 'A: 指折り数えて', link: 'A.pdf' },
- { title: 'B: 平均値の嘘', link: 'B.pdf' },
- { title: 'C: 壺', link: 'C.pdf' },
- { title: 'D: 市松模様', link: 'D.pdf' },
- { title: 'E: 台風', link: 'E.pdf' },
- { title: 'F: 卵', link: 'F.pdf' }
- ],
- place: '会津大学'
- },
- rupc2015: {
- title: '立命合宿 2015',
- day: 'Day 1',
- date: {
- begin: '2015/3/14',
- end: '2015/3/16'
- },
- detailURL: 'https://web.archive.org/web/20150928232752/https://atnd.org/events/62742',
- problemSet: [
- { college: 'Day1(立命館大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp15Day1' },
- { college: 'Day2(会津大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp15Day2' },
- { college: 'Day3(北海道大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp15Day3' }
- ],
- commentary: [
- { title: '総評', link: 'all.pdf' },
- { title: 'A: Soccer', link: 'A.pdf' },
- { title: 'B: RUPC', link: 'B.pdf' },
- { title: 'C: Shopping', link: 'C.pdf' },
- { title: 'D: Hopping Hearts', link: 'D.pdf' },
- { title: 'E: Ocarina of Time', link: 'E.pdf' },
- { title: 'F: Tree', link: 'F.pdf' },
- { title: "G: Bob's Bomb", link: 'G.pdf' }
- ],
- picture: 'rupc2015.png',
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- place: '立命館大学 BKC',
- schedule: (
-
-
-
- | Day |
- Time |
- |
-
-
-
-
- |
- Day 1
- |
- 13:00 - 14:00 |
- 集合,開会,自己紹介など |
-
-
- | 14:00 - 14:30 |
- チーム編成 |
-
-
- | 14:30 - 17:30 |
- 模擬コンテスト1 (3時間セット) |
-
-
- | 17:30 - 18:30 |
- 問題解説 |
-
-
- | 19:00 - |
- 懇親会 |
-
-
- |
- Day 2
- |
- 10:00 - 11:00 |
- 集合・チーム編成 |
-
-
- | 11:00 - 16:00 |
- 模擬コンテスト2 (5時間セット) |
-
-
- | 16:00 - 17:00 |
- 問題解説 |
-
-
- | 19:00 - |
- 懇親会 |
-
-
- |
- Day 3
- |
- 09:00 - 10:00 |
- 集合・チーム編成 |
-
-
- | 10:00 - 13:00 |
- 模擬コンテスト3 (3時間セット) |
-
-
- | 13:00 - |
- 問題解説 |
-
-
-
- )
- },
- rupc2013: {
- title: '立命合宿 2013',
- day: 'Day 3',
- date: {
- begin: '2013/3/11',
- end: '2013/3/13'
- },
- problemSet: [
- { college: 'Day1(会津大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp13Day1' },
- { college: 'Day2(大阪大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp13Day2' },
- { college: 'Day3(立命館大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp13Day3' }
- ],
- commentary: [
- { title: 'A: Grid Mori', link: '' },
- { title: 'B: VOCAL ANDROID', link: '' },
- { title: 'C: Project Management ', link: '' },
- { title: 'D: Statement Coverage ', link: '' },
- { title: 'E: Twins Idol', link: '' },
- { title: 'F: Operation training for BYDOL', link: '' },
- { title: 'G: Computer Onesan', link: '' }
- ],
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- place: '立命館大学 BKC',
- schedule: (
-
-
-
- | Day |
- Time |
- |
-
-
-
-
- |
- Day 1
- |
- 13:00 - 14:00 |
- 集合,開会,自己紹介など |
-
-
- | 14:00 - 14:30 |
- チーム編成 |
-
-
- | 14:30 - 17:30 |
- 模擬コンテスト1 (3時間セット) |
-
-
- | 17:30 - 18:30 |
- 問題解説 |
-
-
- | 19:00 - |
- 懇親会 |
-
-
- |
- Day 2
- |
- 10:00 - 11:00 |
- 集合・チーム編成 |
-
-
- | 11:00 - 16:00 |
- 模擬コンテスト2 (5時間セット) |
-
-
- | 16:00 - 17:00 |
- 問題解説 |
-
-
- |
- Day 3
- |
- 09:00 - 10:00 |
- 集合・チーム編成 |
-
-
- | 10:00 - 13:00 |
- 模擬コンテスト3 (3時間セット) |
-
-
- | 14:00 - 15:00 |
- 問題解説 |
-
-
-
- )
- },
- acpc2012: {
- title: '会津合宿 2012',
- day: 'Day 1',
- date: {
- begin: '2012/9/3',
- end: '2012/9/5'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- problemSet: [
- { college: 'Day1(立命館大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2012Day1' },
- { college: 'Day2(会津大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2012Day2' },
- { college: 'Day3(会津大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2012Day3' }
- ],
- commentary: [
- { title: 'A: フリック入力', link: 'A.pdf' },
- { title: 'B: 第二次ProblemB大戦 ', link: 'B.pdf' },
- { title: 'C: 高所恐怖症', link: 'C.pdf' },
- { title: 'D: アニペロ2012', link: 'D.pdf' },
- { title: 'E: マークアップ言語は衰退しました', link: 'E.pdf' },
- { title: 'F: 透明な麻雀牌', link: 'F.pdf' },
- { title: 'G: コードアートオンライン', link: 'G.pdf' }
- ],
- place: '会津大学'
- },
- rupc2012: {
- title: '立命合宿 2012',
- day: 'Day 3',
- date: {
- begin: '2012/3/13',
- end: '2012/3/15'
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- problemSet: [
- { college: 'Day1(会津大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp12Day1' },
- { college: 'Day2(大阪大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp12Day2' },
- { college: 'Day3(立命館大学)', link: 'https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp12Day3' }
- ],
- commentary: [
- { title: 'A: Chicken or the Egg', link: 'kohyo.pdf' },
- { title: 'B: Unequal Dice', link: 'A.pdf' },
- { title: 'C: Lucky Dip', link: 'B.pdf' },
- { title: 'D: Memory Leak', link: 'C.pdf' },
- { title: 'E: Elevator', link: 'D.pdf' },
- { title: 'F: Icy Composer', link: 'E.pdf' },
- { title: 'G: Satan Attacks', link: 'F.pdf' }
- ],
- place: '立命館大学 BKC'
- },
- rupc2011: {
- title: '立命館プログラミングコンテスト2011',
- date: {
- begin: '2011/10/15',
- end: ''
- },
- judge: 'http://judge.u-aizu.ac.jp/onlinejudge/index.jsp',
- problemSet: [
- {
- college: '立命館大学',
- link: 'https://onlinejudge.u-aizu.ac.jp/challenges/sources/VPC/RUPC?year=2011'
- }
- ],
- commentary: [
- { title: '問題A: スワップ暗号', link: 'A.pdf' },
- { title: '問題B: B問題', link: 'B.pdf' },
- { title: '問題C: Seishun 18 Kippu', link: 'C.pdf' },
- { title: '問題D: 伝説の剣', link: 'D.pdf' },
- { title: '問題E: アニペロ', link: 'E.pdf' },
- { title: '問題F: Farey Sequence', link: 'F.pdf' },
- { title: '問題G: 水時計', link: 'G.pdf' },
- { title: '問題H: Oh, My Goat!', link: 'H.pdf' },
- { title: '問題I: カスタムペイント職人', link: 'I.pdf' }
- ],
- place: '立命館大学 BKC',
- iodata: (
-
- データセット
-
- ),
- writer: ['shirokurostone', 'kioa341', 'slip0110', 'epee_noir', 'Respect2D', '_shnyh']
- }
-}
-
-export type EventType = {
- title: string
- detail: string
- date?: 'Day 1' | 'Day 2' | 'Day 3'
- id: string
-}
-
-export const Events: EventType[] = Object.keys(EventDetails).map((id) => {
- const event: EventDetailType = EventDetails[id]
- const date = event.date?.begin && event.date?.end ? `${event.date.begin} - ${event.date.end}` : event.date?.begin
- const detail = event.place.includes('立命')
- ? `${event.place} にて ${date} 合宿を開催しました.`
- : `${event.place} にて ${date} 合宿に参加しました.`
- return {
- title: event.title,
- detail: detail,
- date: event.day,
- id: id
- }
-})
diff --git a/components/IndexArticles.module.css b/components/IndexArticles.module.css
deleted file mode 100644
index 4df8215..0000000
--- a/components/IndexArticles.module.css
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @format */
-
-.article dt {
- font-weight: bold;
-}
diff --git a/components/Layout/Footer.module.css b/components/Layout/Footer.module.css
deleted file mode 100644
index 90d0818..0000000
--- a/components/Layout/Footer.module.css
+++ /dev/null
@@ -1,10 +0,0 @@
-/** @format */
-
-.footer {
- clear: both;
- color: #fff;
- background: #004599;
- text-align: center;
- font-size: 10px;
- padding: 2px;
-}
diff --git a/components/Layout/Footer.tsx b/components/Layout/Footer.tsx
deleted file mode 100644
index 99ed897..0000000
--- a/components/Layout/Footer.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-/** @format */
-
-import { VFC } from 'react'
-
-import styles from './Footer.module.css'
-
-const Footer: VFC = () => {
- const date = new Date()
- const year = date.getFullYear()
- return Copyright (C) 2005-{year} RiPPro All rights reserved.
-}
-
-export default Footer
diff --git a/components/Layout/Head.module.css b/components/Layout/Head.module.css
deleted file mode 100644
index 55c45dd..0000000
--- a/components/Layout/Head.module.css
+++ /dev/null
@@ -1,24 +0,0 @@
-/** @format */
-
-.head {
- margin: 16px 16px;
- padding: 2px 0px;
- border-bottom: solid 2px #700;
- display: flex;
- justify-content: space-between;
-}
-
-.logo img {
- width: 200px;
- margin: 10px 5px 5px 5px;
- vertical-align: middle;
-}
-
-.logo a:hover {
- color: #000;
- text-decoration: underline;
-}
-
-.logo a:visited {
- text-decoration: none;
-}
diff --git a/components/Layout/Head.tsx b/components/Layout/Head.tsx
deleted file mode 100644
index b4a54de..0000000
--- a/components/Layout/Head.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-/** @format */
-
-import { VFC } from 'react'
-import Link from 'next/link'
-import Navigator from './Navigator'
-import styles from './Head.module.css'
-
-const Header: VFC = () => {
- return (
-
- )
-}
-
-export default Header
diff --git a/components/Layout/Header.tsx b/components/Layout/Header.tsx
deleted file mode 100644
index 88a6874..0000000
--- a/components/Layout/Header.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/** @format */
-
-import Head from 'next/head'
-
-interface Props {
- title?: string
- description?: string
-}
-
-const Header: React.FC = ({ title, description }: Props) => {
- const defaultDescription =
- '立命館大学情報理工学部プロジェクト団体 競技プログラミング部門「RiPPro」です。ACM-ICPC (プログラミングの学生世界大会) などの大会で入賞することを目的として活動しています。'
- const defaultTitle = 'RiPPro - 立命館大学情報理工学部プロジェクト団体'
- return (
-
- {title ? title : defaultTitle}
-
-
-
-
-
-
-
- )
-}
-
-export default Header
diff --git a/components/Layout/Layout.module.css b/components/Layout/Layout.module.css
deleted file mode 100644
index 1066432..0000000
--- a/components/Layout/Layout.module.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/** @format */
-
-.main {
- width: 800px;
- margin: 4px auto;
- background-color: #fff;
- border-radius: 10px;
- box-shadow: 0 10px 25px 0 rgba(0, 0, 0, 0.5);
-}
-
-.article {
- margin: 8px;
-}
diff --git a/components/Layout/Layout.tsx b/components/Layout/Layout.tsx
deleted file mode 100644
index 679030b..0000000
--- a/components/Layout/Layout.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { FC } from 'react'
-
-import Header from './Header'
-import Footer from './Footer'
-import Head from './Head'
-
-import styles from './Layout.module.css'
-
-export const Layout: FC<{
- headerChild?: JSX.Element
- title?: string
- description?: string
-}> = ({ children, title, description }) => (
-
-
-)
diff --git a/components/Layout/Navigator.module.css b/components/Layout/Navigator.module.css
deleted file mode 100644
index 3ce403f..0000000
--- a/components/Layout/Navigator.module.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.navibutton {
- font-size: 18px;
-}
-
-.welcome {
- font-weight: bold;
-}
diff --git a/components/Layout/Navigator.tsx b/components/Layout/Navigator.tsx
deleted file mode 100644
index 2d4736d..0000000
--- a/components/Layout/Navigator.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-/** @format */
-
-import { VFC } from 'react'
-import Link from 'next/link'
-
-import Stack from '@mui/material/Stack'
-import Button from '@mui/material/Button'
-
-import styles from './Navigator.module.css'
-
-const Navigator: VFC = () => {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-export default Navigator
diff --git a/components/Layout/index.tsx b/components/Layout/index.tsx
deleted file mode 100644
index 358469a..0000000
--- a/components/Layout/index.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export { Layout } from './Layout'
diff --git a/components/atcoder/AtCoderGraph.module.css b/components/atcoder/AtCoderGraph.module.css
deleted file mode 100644
index ec5a092..0000000
--- a/components/atcoder/AtCoderGraph.module.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.body {
- margin: 0 40px;
-}
diff --git a/components/discord.tsx b/components/discord.tsx
deleted file mode 100644
index e813848..0000000
--- a/components/discord.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import React, { useEffect } from 'react'
-import styles from '../styles/discord.module.css'
-
-function Discord() {
- useEffect(() => {
- const script = document.createElement('script')
- script.src = 'https://platform.twitter.com/widgets.js'
- document.body.appendChild(script)
- return () => {
- document.body.removeChild(script)
- }
- }, [])
- return (
-
- )
-}
-
-export default Discord
diff --git a/data/events/acpc2012.mdx b/data/events/acpc2012.mdx
new file mode 100644
index 0000000..6fb70dc
--- /dev/null
+++ b/data/events/acpc2012.mdx
@@ -0,0 +1,36 @@
+---
+id: acpc2012
+title: 会津合宿 2012
+date:
+ begin: 2012/9/3
+ end: 2012/9/5
+---
+## 開催日時
+
+2012/9/3 - 2012/9/5
+
+## 会場
+
+会津大学
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## 問題セット
+
+- [Day1(立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2012Day1)
+- [Day2(会津大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2012Day2)
+- [Day3(会津大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2012Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| A: フリック入力 | [PDF](/static/contestData/acpc2012/A.pdf) |
+| B: 第二次ProblemB大戦 | [PDF](/static/contestData/acpc2012/B.pdf) |
+| C: 高所恐怖症 | [PDF](/static/contestData/acpc2012/C.pdf) |
+| D: アニペロ2012 | [PDF](/static/contestData/acpc2012/D.pdf) |
+| E: マークアップ言語は衰退しました | [PDF](/static/contestData/acpc2012/E.pdf) |
+| F: 透明な麻雀牌 | [PDF](/static/contestData/acpc2012/F.pdf) |
+| G: コードアートオンライン | [PDF](/static/contestData/acpc2012/G.pdf) |
diff --git a/data/events/acpc2015.mdx b/data/events/acpc2015.mdx
new file mode 100644
index 0000000..6f8e0af
--- /dev/null
+++ b/data/events/acpc2015.mdx
@@ -0,0 +1,35 @@
+---
+id: acpc2015
+title: 会津合宿 2015
+date:
+ begin: 2015/9/21
+ end: 2015/9/23
+---
+## 開催日時
+
+2015/9/21 - 2015/9/23
+
+## 会場
+
+会津大学
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## 問題セット
+
+- [Day1(立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2015Day1)
+- [Day2(会津大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2015Day2)
+- [Day3(北海道大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2015Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| A: 指折り数えて | [PDF](/static/contestData/acpc2015/A.pdf) |
+| B: 平均値の嘘 | [PDF](/static/contestData/acpc2015/B.pdf) |
+| C: 壺 | [PDF](/static/contestData/acpc2015/C.pdf) |
+| D: 市松模様 | [PDF](/static/contestData/acpc2015/D.pdf) |
+| E: 台風 | [PDF](/static/contestData/acpc2015/E.pdf) |
+| F: 卵 | [PDF](/static/contestData/acpc2015/F.pdf) |
diff --git a/data/events/acpc2016.mdx b/data/events/acpc2016.mdx
new file mode 100644
index 0000000..2db3db9
--- /dev/null
+++ b/data/events/acpc2016.mdx
@@ -0,0 +1,41 @@
+---
+id: acpc2016
+title: 会津合宿 2016
+date:
+ begin: 2016/9/17
+ end: 2016/9/19
+---
+## 開催日時
+
+2016/9/17 - 2016/9/19
+
+## 会場
+
+会津大学
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## イベント概要
+
+[https://web.archive.org/web/20200326193543/https://atnd.org/events/79743](https://web.archive.org/web/20200326193543/https://atnd.org/events/79743)
+
+## 問題セット
+
+- [Day1(立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2016Day1)
+- [Day2(会津大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2016Day2)
+- [Day3(北海道大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp16Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| 全体講評 | [PDF](/static/contestData/acpc2016/kohyo.pdf) |
+| A: キャベツ | [PDF](/static/contestData/acpc2016/A.pdf) |
+| B: イカったー | [PDF](/static/contestData/acpc2016/B.pdf) |
+| C: 失われしグラフ | [PDF](/static/contestData/acpc2016/C.pdf) |
+| D: DAGトリオ(Easy) | [PDF](/static/contestData/acpc2016/D.pdf) |
+| E: 札 | [PDF](/static/contestData/acpc2016/E.pdf) |
+| F: 紙の折りたたみ | [PDF](/static/contestData/acpc2016/F.pdf) |
+| G: DAGトリオ(Hard) | [PDF](/static/contestData/acpc2016/G.pdf) |
diff --git a/data/events/acpc2017.mdx b/data/events/acpc2017.mdx
new file mode 100644
index 0000000..17d45e1
--- /dev/null
+++ b/data/events/acpc2017.mdx
@@ -0,0 +1,37 @@
+---
+id: acpc2017
+title: 会津合宿 2017
+date:
+ begin: 2017/9/18
+ end: 2017/9/20
+---
+## 開催日時
+
+2017/9/18 - 2017/9/20
+
+## 会場
+
+会津大学
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## 問題セット
+
+- [Day1(立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2017Day1)
+- [Day2(会津大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2017Day2)
+- [Day3(北海道大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#ACPC2017Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| 全体講評 | [PDF](/static/contestData/acpc2017/kohyo.pdf) |
+| A: 丸付け | [PDF](/static/contestData/acpc2017/A.pdf) |
+| B: 全日本帰りたい協会 | [PDF](/static/contestData/acpc2017/B.pdf) |
+| C: ツイート数 | [PDF](/static/contestData/acpc2017/C.pdf) |
+| D: 次元旅行 | [PDF](/static/contestData/acpc2017/D.pdf) |
+| E: 敵襲から守れ | [PDF](/static/contestData/acpc2017/E.pdf) |
+| F: 階段 | [PDF](/static/contestData/acpc2017/F.pdf) |
+| G: 鍵 | [PDF](/static/contestData/acpc2017/G.pdf) |
diff --git a/data/events/acpc2018.mdx b/data/events/acpc2018.mdx
new file mode 100644
index 0000000..c893ed1
--- /dev/null
+++ b/data/events/acpc2018.mdx
@@ -0,0 +1,42 @@
+---
+id: acpc2018
+title: 会津合宿 2018
+date:
+ begin: 2018/9/19
+ end: 2018/9/21
+---
+## 開催日時
+
+2018/9/19 - 2018/9/21
+
+## 会場
+
+会津大学
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## イベント概要
+
+[https://web.archive.org/web/20190321162010/https://atnd.org/events/98718](https://web.archive.org/web/20190321162010/https://atnd.org/events/98718)
+
+## 問題セット
+
+- [Day1(立命館大学)](https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2018Day1)
+- [Day2(会津大学)](https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2018Day2)
+- [Day3(北海道大学)](https://onlinejudge.u-aizu.ac.jp/services/room.html#ACPC2018Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| 全体講評 | [PDF](/static/contestData/acpc2018/kohyo.pdf) |
+| A: テスト | [PDF](/static/contestData/acpc2018/A.pdf) |
+| B: 直角三角形 | [PDF](/static/contestData/acpc2018/B.pdf) |
+| C: 素数 | [PDF](/static/contestData/acpc2018/C.pdf) |
+| D: 遭難 | [PDF](/static/contestData/acpc2018/D.pdf) |
+| E: 凸凹数列 | [PDF](/static/contestData/acpc2018/E.pdf) |
+| F: Swap | [PDF](/static/contestData/acpc2018/F.pdf) |
+| G: 式の切り取り | [PDF](/static/contestData/acpc2018/G.pdf) |
+| H: 板 | [PDF](/static/contestData/acpc2018/H.pdf) |
diff --git a/data/events/rupc2011.mdx b/data/events/rupc2011.mdx
new file mode 100644
index 0000000..80c65a6
--- /dev/null
+++ b/data/events/rupc2011.mdx
@@ -0,0 +1,48 @@
+---
+id: rupc2011
+title: 立命館プログラミングコンテスト2011
+date:
+ begin: 2011/10/15
+---
+## 開催日時
+
+2011/10/15
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## 問題セット
+
+- [立命館大学](https://onlinejudge.u-aizu.ac.jp/challenges/sources/VPC/RUPC?year=2011)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| 問題A: スワップ暗号 | [PDF](/static/contestData/rupc2011/A.pdf) |
+| 問題B: B問題 | [PDF](/static/contestData/rupc2011/B.pdf) |
+| 問題C: Seishun 18 Kippu | [PDF](/static/contestData/rupc2011/C.pdf) |
+| 問題D: 伝説の剣 | [PDF](/static/contestData/rupc2011/D.pdf) |
+| 問題E: アニペロ | [PDF](/static/contestData/rupc2011/E.pdf) |
+| 問題F: Farey Sequence | [PDF](/static/contestData/rupc2011/F.pdf) |
+| 問題G: 水時計 | [PDF](/static/contestData/rupc2011/G.pdf) |
+| 問題H: Oh, My Goat! | [PDF](/static/contestData/rupc2011/H.pdf) |
+| 問題I: カスタムペイント職人 | [PDF](/static/contestData/rupc2011/I.pdf) |
+
+## 問題作成・ジャッジ
+
+- [@shirokurostone](https://twitter.com/shirokurostone)
+- [@kioa341](https://twitter.com/kioa341)
+- [@slip0110](https://twitter.com/slip0110)
+- [@epee_noir](https://twitter.com/epee_noir)
+- [@Respect2D](https://twitter.com/Respect2D)
+- [@_shnyh](https://twitter.com/_shnyh)
+
+## 問題文・入出力データ
+
+[データセット](dataset.zip)
diff --git a/data/events/rupc2012.mdx b/data/events/rupc2012.mdx
new file mode 100644
index 0000000..3e1c85f
--- /dev/null
+++ b/data/events/rupc2012.mdx
@@ -0,0 +1,36 @@
+---
+id: rupc2012
+title: 立命合宿 2012
+date:
+ begin: 2012/3/13
+ end: 2012/3/15
+---
+## 開催日時
+
+2012/3/13 - 2012/3/15
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## 問題セット
+
+- [Day1(会津大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp12Day1)
+- [Day2(大阪大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp12Day2)
+- [Day3(立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp12Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| A: Chicken or the Egg | [PDF](/static/contestData/rupc2012/kohyo.pdf) |
+| B: Unequal Dice | [PDF](/static/contestData/rupc2012/A.pdf) |
+| C: Lucky Dip | [PDF](/static/contestData/rupc2012/B.pdf) |
+| D: Memory Leak | [PDF](/static/contestData/rupc2012/C.pdf) |
+| E: Elevator | [PDF](/static/contestData/rupc2012/D.pdf) |
+| F: Icy Composer | [PDF](/static/contestData/rupc2012/E.pdf) |
+| G: Satan Attacks | [PDF](/static/contestData/rupc2012/F.pdf) |
diff --git a/data/events/rupc2013.mdx b/data/events/rupc2013.mdx
new file mode 100644
index 0000000..c6f56cd
--- /dev/null
+++ b/data/events/rupc2013.mdx
@@ -0,0 +1,38 @@
+---
+id: rupc2013
+title: 立命合宿 2013
+date:
+ begin: 2013/3/11
+ end: 2013/3/13
+---
+## 開催日時
+
+2013/3/11 - 2013/3/13
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## 問題セット
+
+- [Day1(会津大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp13Day1)
+- [Day2(大阪大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp13Day2)
+- [Day3(立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp13Day3)
+
+## 合宿内容
+
+- Day 1 13:00-14:00 集合,開会,自己紹介など
+- Day 1 14:00-14:30 チーム編成
+- Day 1 14:30-17:30 模擬コンテスト1 (3時間セット)
+- Day 1 17:30-18:30 問題解説
+- Day 1 19:00- 懇親会
+- Day 2 10:00-11:00 集合・チーム編成
+- Day 2 11:00-16:00 模擬コンテスト2 (5時間セット)
+- Day 2 16:00-17:00 問題解説
+- Day 3 09:00-10:00 集合・チーム編成
+- Day 3 10:00-13:00 模擬コンテスト3 (3時間セット)
+- Day 3 14:00-15:00 問題解説
diff --git a/data/events/rupc2015.mdx b/data/events/rupc2015.mdx
new file mode 100644
index 0000000..29e5b7c
--- /dev/null
+++ b/data/events/rupc2015.mdx
@@ -0,0 +1,60 @@
+---
+id: rupc2015
+title: 立命合宿 2015
+date:
+ begin: 2015/3/14
+ end: 2015/3/16
+---
+## 開催日時
+
+2015/3/14 - 2015/3/16
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## イベント概要
+
+[https://web.archive.org/web/20150928232752/https://atnd.org/events/62742](https://web.archive.org/web/20150928232752/https://atnd.org/events/62742)
+
+## 問題セット
+
+- [Day1(立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp15Day1)
+- [Day2(会津大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp15Day2)
+- [Day3(北海道大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp15Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| 総評 | [PDF](/static/contestData/rupc2015/all.pdf) |
+| A: Soccer | [PDF](/static/contestData/rupc2015/A.pdf) |
+| B: RUPC | [PDF](/static/contestData/rupc2015/B.pdf) |
+| C: Shopping | [PDF](/static/contestData/rupc2015/C.pdf) |
+| D: Hopping Hearts | [PDF](/static/contestData/rupc2015/D.pdf) |
+| E: Ocarina of Time | [PDF](/static/contestData/rupc2015/E.pdf) |
+| F: Tree | [PDF](/static/contestData/rupc2015/F.pdf) |
+| G: Bob's Bomb | [PDF](/static/contestData/rupc2015/G.pdf) |
+
+## 写真
+
+
+
+## 合宿内容
+
+- Day 1 13:00-14:00 集合,開会,自己紹介など
+- Day 1 14:00-14:30 チーム編成
+- Day 1 14:30-17:30 模擬コンテスト1 (3時間セット)
+- Day 1 17:30-18:30 問題解説
+- Day 1 19:00- 懇親会
+- Day 2 10:00-11:00 集合・チーム編成
+- Day 2 11:00-16:00 模擬コンテスト2 (5時間セット)
+- Day 2 16:00-17:00 問題解説
+- Day 2 19:00- 懇親会
+- Day 3 09:00-10:00 集合・チーム編成
+- Day 3 10:00-13:00 模擬コンテスト3 (3時間セット)
+- Day 3 13:00- 問題解説
diff --git a/data/events/rupc2016.mdx b/data/events/rupc2016.mdx
new file mode 100644
index 0000000..17c5b3b
--- /dev/null
+++ b/data/events/rupc2016.mdx
@@ -0,0 +1,37 @@
+---
+id: rupc2016
+title: 立命合宿 2016
+date:
+ begin: 2016/3/6
+ end: 2016/3/8
+---
+## 開催日時
+
+2016/3/6 - 2016/3/8
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## 問題セット
+
+- [Day 1 (立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp16Day1)
+- [Day 2 (会津大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp16Day2)
+- [Day 3 (北海道大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp16Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| A: 秤 | [PDF](/static/contestData/rupc2016/A.pdf) |
+| B: ハミング距離 | [PDF](/static/contestData/rupc2016/B.pdf) |
+| C: 足し算掛け算 | [PDF](/static/contestData/rupc2016/C.pdf) |
+| D: スキャナー | [PDF](/static/contestData/rupc2016/D.pdf) |
+| E: 28 | [PDF](/static/contestData/rupc2016/E.pdf) |
+| F: リレー | [PDF](/static/contestData/rupc2016/F.pdf) |
+| 別解 | [PDF](/static/contestData/rupc2016/F_tm.pdf) |
+| G: 塗るだけ | [PDF](/static/contestData/rupc2016/G.pdf) |
diff --git a/data/events/rupc2017.mdx b/data/events/rupc2017.mdx
new file mode 100644
index 0000000..00a58f5
--- /dev/null
+++ b/data/events/rupc2017.mdx
@@ -0,0 +1,45 @@
+---
+id: rupc2017
+title: 立命合宿 2017
+date:
+ begin: 2017/3/22
+ end: 2017/3/24
+---
+## 開催日時
+
+2017/3/22 - 2017/3/24
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## イベント概要
+
+[https://web.archive.org/web/20181205111517/https://atnd.org/events/85691](https://web.archive.org/web/20181205111517/https://atnd.org/events/85691)
+
+## 問題セット
+
+- [Day 1 (立命館大学 & 大阪大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp17Day1)
+- [Day 2 (会津大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp17Day2)
+- [Day 3 (北海道大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp17Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| 全体講評 | [PDF](/static/contestData/rupc2017/kohyo.pdf) |
+| A: トーナメント | [PDF](/static/contestData/rupc2017/A.pdf) |
+| B: 重さの範囲 | [PDF](/static/contestData/rupc2017/B.pdf) |
+| C: Fractal Tree | [PDF](/static/contestData/rupc2017/C.pdf) |
+| D: パスワード | [PDF](/static/contestData/rupc2017/D.pdf) |
+| E: 卒業式 | [PDF](/static/contestData/rupc2017/E.pdf) |
+| F: カードゲーム | [PDF](/static/contestData/rupc2017/F.pdf) |
+| G: 雨降りバス乗り替え | [PDF](/static/contestData/rupc2017/G.pdf) |
+| H: ジャンプパーティ | [PDF](/static/contestData/rupc2017/H.pdf) |
+| I: Islands Survival | [PDF](/static/contestData/rupc2017/I.pdf) |
+| J: エナジードリンク | [PDF](/static/contestData/rupc2017/J.pdf) |
+| K: AORイカちゃんの成績 | [PDF](/static/contestData/rupc2017/K.pdf) |
diff --git a/data/events/rupc2018.mdx b/data/events/rupc2018.mdx
new file mode 100644
index 0000000..d3f0b4b
--- /dev/null
+++ b/data/events/rupc2018.mdx
@@ -0,0 +1,41 @@
+---
+id: rupc2018
+title: 立命合宿 2018
+date:
+ begin: 2018/3/26
+ end: 2018/3/28
+---
+## 開催日時
+
+2018/3/26 - 2018/3/28
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## イベント概要
+
+[https://web.archive.org/web/20180202123544/https://atnd.org/events/94033](https://web.archive.org/web/20180202123544/https://atnd.org/events/94033)
+
+## 問題セット
+
+- [Day 1 (立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp18Day1)
+- [Day 2 (会津大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp18Day2)
+- [Day 3 (北海道大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp18Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| 全体講評 | [PDF](/static/contestData/rupc2018/kohyo.pdf) |
+| A: 鳩ノ巣原理 | [PDF](/static/contestData/rupc2018/A.pdf) |
+| B: 写像 | [PDF](/static/contestData/rupc2018/B.pdf) |
+| C: 一致 | [PDF](/static/contestData/rupc2018/C.pdf) |
+| D: 水槽 | [PDF](/static/contestData/rupc2018/D.pdf) |
+| E: いたずらされたグラフ | [PDF](/static/contestData/rupc2018/E.pdf) |
+| F: ごちうさ数 | [PDF](/static/contestData/rupc2018/F.pdf) |
+| G: エレベータ | [PDF](/static/contestData/rupc2018/G.pdf) |
diff --git a/data/events/rupc2019.mdx b/data/events/rupc2019.mdx
new file mode 100644
index 0000000..7b89aed
--- /dev/null
+++ b/data/events/rupc2019.mdx
@@ -0,0 +1,37 @@
+---
+id: rupc2019
+title: 立命合宿 2019
+date:
+ begin: 2019/3/5
+ end: 2019/3/7
+---
+## 開催日時
+
+2019/3/5 - 2019/3/7
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## 問題セット
+
+- [Day 1 (立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp19Day1)
+- [Day 2 (会津大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp19Day2)
+- [Day 3 (北海道大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp19Day3)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| 全体講評 | [PDF](/static/contestData/rupc2019/kohyo.pdf) |
+| A: タイル貼り | [PDF](/static/contestData/rupc2019/A.pdf) |
+| B: たぬきつね | [PDF](/static/contestData/rupc2019/B.pdf) |
+| C: オセロ | [PDF](/static/contestData/rupc2019/C.pdf) |
+| D: 場所当てゲーム | [PDF](/static/contestData/rupc2019/D.pdf) |
+| E: LISum | [PDF](/static/contestData/rupc2019/E.pdf) |
+| F: Absum | [PDF](/static/contestData/rupc2019/F.pdf) |
+| G: イルミネーション | [PDF](/static/contestData/rupc2019/G.pdf) |
diff --git a/data/events/rupc2024.mdx b/data/events/rupc2024.mdx
new file mode 100644
index 0000000..822e030
--- /dev/null
+++ b/data/events/rupc2024.mdx
@@ -0,0 +1,41 @@
+---
+id: rupc2024
+title: 立命合宿 2024
+date:
+ begin: 2024/3/23
+ end: 2024/3/24
+---
+## 開催日時
+
+2024/3/23 - 2024/3/24
+
+## 会場
+
+立命館大学 BKC
+
+## ジャッジシステム
+
+[http://judge.u-aizu.ac.jp/onlinejudge/index.jsp](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp)
+
+## イベント概要
+
+[https://rippro.connpass.com/event/309923/](https://rippro.connpass.com/event/309923/)
+
+## 問題セット
+
+- [Day 1 (立命館大学)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RUPC2024Day1)
+- [Day 2 (会津大学さん)](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RUPC2024Day2)
+
+## 解説
+
+| 問題 | 解説 |
+| --- | --- |
+| A: Empire of the BIWAKO | [PDF](/static/contestData/rupc2024/A_Empire_of_the_BIWAKO.pdf) |
+| B: Goodbye, BKC | [PDF](/static/contestData/rupc2024/B_Goobye_BKC.pdf) |
+| C: Belt-line Bus Trip | [PDF](/static/contestData/rupc2024/C_Belt-line_bus_trip.pdf) |
+| D: 2xL Minesweeper | [PDF](/static/contestData/rupc2024/D_2xL_minesweeper.pdf) |
+| E: palindromic? | [PDF](/static/contestData/rupc2024/E_palindromic.pdf) |
+| F: MOD Party | [PDF](/static/contestData/rupc2024/F_MOD_party.pdf) |
+| G: Skating | [PDF](/static/contestData/rupc2024/G_Skating.pdf) |
+| H: miNIMum | [PDF](/static/contestData/rupc2024/H_miNIMum.pdf) |
+| I: jucumber | [PDF](/static/contestData/rupc2024/I_jucumber.pdf) |
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..df997bd
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,13 @@
+const nextCoreWebVitals = require('eslint-config-next/core-web-vitals');
+
+module.exports = [
+ {
+ ignores: ['node_modules/**', '.next/**', 'out/**']
+ },
+ ...nextCoreWebVitals,
+ {
+ rules: {
+ '@next/next/no-img-element': 'off'
+ }
+ }
+];
diff --git a/gas-api/api.js b/gas-api/api.js
index 9f55173..3d31454 100644
--- a/gas-api/api.js
+++ b/gas-api/api.js
@@ -1,62 +1,62 @@
/* ユーザ情報取得API */
const doGet = (e) => {
- const usersInfo = getUsersInfo()
- const json = JSON.stringify(usersInfo)
- return ContentService.createTextOutput().setMimeType(ContentService.MimeType.JSON).setContent(json)
-}
+ const usersInfo = getUsersInfo();
+ const json = JSON.stringify(usersInfo);
+ return ContentService.createTextOutput().setMimeType(ContentService.MimeType.JSON).setContent(json);
+};
const getUsersInfo = () => {
- const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('usersInfo')
- const data = sheet.getRange(`A1:B${sheet.getLastRow()}`).getValues()
+ const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('usersInfo');
+ const data = sheet.getRange(`A1:B${sheet.getLastRow()}`).getValues();
const usersInfo = data.map((user) => {
- return { userID: user[0], count: user[1] }
- })
- console.log(usersInfo)
- return usersInfo
-}
+ return { userID: user[0], count: user[1] };
+ });
+ console.log(usersInfo);
+ return usersInfo;
+};
/* ユーザID取得API */
const getUserIDs = () => {
- const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('index')
- const data = sheet.getRange(`A2:A${sheet.getLastRow()}`).getValues()
+ const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('index');
+ const data = sheet.getRange(`A2:A${sheet.getLastRow()}`).getValues();
const responseData = data
.map((user) => {
if (user[0] == '') {
- return
+ return;
}
- return user[0]
+ return user[0];
})
- .filter((e) => typeof e !== 'undefined')
- return responseData
-}
+ .filter((e) => typeof e !== 'undefined');
+ return responseData;
+};
/* userInfoシート更新API */
const saveUserIDs = () => {
// シートを取得
- const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('usersInfo')
+ const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('usersInfo');
// ユーザIDを取得
- const userIDs = getUserIDs()
+ const userIDs = getUserIDs();
const userInfo = userIDs.map((userID) => {
- const ACCount = request(userID)
- return [userID, ACCount]
- })
+ const ACCount = request(userID);
+ return [userID, ACCount];
+ });
// シートをクリアにしてからユーザID, AC Countをシートに保存
- sheet.clear()
- sheet.getRange(1, 1, userInfo.length, userInfo[0].length).setValues(userInfo)
-}
+ sheet.clear();
+ sheet.getRange(1, 1, userInfo.length, userInfo[0].length).setValues(userInfo);
+};
/* AtCoder API へのリクエスト */
const request = (userID) => {
- const url = `https://kenkoooo.com/atcoder/atcoder-api/v2/user_info?user=${userID}`
- const response = UrlFetchApp.fetch(url).getContentText()
- const resJson = JSON.parse(response)
- console.log(`fetched! ${JSON.stringify(resJson)}`)
+ const url = `https://kenkoooo.com/atcoder/atcoder-api/v2/user_info?user=${userID}`;
+ const response = UrlFetchApp.fetch(url).getContentText();
+ const resJson = JSON.parse(response);
+ console.log(`fetched! ${JSON.stringify(resJson)}`);
if ('accepted_count' in resJson) {
- return JSON.parse(response).accepted_count
+ return JSON.parse(response).accepted_count;
} else {
- return 0
+ return 0;
}
-}
+};
diff --git a/next-env.d.ts b/next-env.d.ts
index 4f11a03..c4b7818 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,5 +1,6 @@
///
///
+import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
-// see https://nextjs.org/docs/basic-features/typescript for more information.
+// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/next.config.js b/next.config.js
index 58a97fa..1a67889 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,3 +1,46 @@
-module.exports = {
- reactStrictMode: true
+/** @type {import('next').NextConfig} */
+
+// 環境変数から本番ビルドモードかどうかを判断
+const isProductionBuild = process.env.BUILD_MODE === 'production';
+
+let basePathEnv = process.env.NEXT_PUBLIC_BASE_PATH || '';
+// Normalize: ensure basePathEnv (if present) starts with a leading '/'
+if (basePathEnv && !basePathEnv.startsWith('/')) {
+ basePathEnv = '/' + basePathEnv;
}
+const configuredBasePath = basePathEnv || undefined;
+// 開発環境でも静的エクスポートに近い動作をさせるために共通設定を定義
+const commonConfig = {
+ // 画像設定
+ images: {
+ unoptimized: true // 静的エクスポートでは必須
+ },
+ env: {
+ NEXT_PUBLIC_IS_PRODUCTION_BUILD: String(isProductionBuild),
+ NEXT_PUBLIC_BASE_PATH: basePathEnv
+ },
+ // 開発環境と本番環境の共通設定
+ staticPageGenerationTimeout: 300
+};
+
+const nextConfig = {
+ // 共通設定を適用
+ ...commonConfig,
+
+ // 本番ビルドモード時のみ静的エクスポートを有効化
+ output: isProductionBuild ? 'export' : undefined,
+ trailingSlash: isProductionBuild,
+ // 静的エクスポート時のみ必要な設定
+ images: {
+ unoptimized: true
+ },
+ typescript: {
+ ignoreBuildErrors: isProductionBuild
+ },
+ basePath: configuredBasePath,
+ assetPrefix: configuredBasePath
+};
+
+console.log(`Building in ${isProductionBuild ? 'PRODUCTION' : 'DEVELOPMENT'} mode`);
+
+module.exports = nextConfig;
diff --git a/package.json b/package.json
index 0ac70e5..33aa572 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"dev": "next dev",
"export": "next export",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
- "lint": "next lint",
+ "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"prepare": "husky install",
"start": "next start"
},
@@ -22,24 +22,28 @@
"dependencies": {
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
- "@mui/material": "^5.2.4",
- "highcharts": "^9.3.2",
+ "@mui/material": "^9.0.0",
+ "gray-matter": "^4.0.3",
+ "highcharts": "^12.5.0",
"highcharts-react-official": "^3.1.0",
- "mui": "^0.0.1",
- "next": "^12.1.0",
- "react": "17.0.2",
- "react-dom": "17.0.2",
- "react-twitter-widgets": "^1.10.0",
- "react-youtube": "^7.13.1"
+ "marked": "^18.0.0",
+ "next": "^16",
+ "react": "19.2.5",
+ "react-dom": "19.2.5",
+ "react-twitter-widgets": "^1.11.0",
+ "react-youtube": "^10.1.0"
},
"devDependencies": {
- "@types/node": "17.0.0",
- "@types/react": "17.0.37",
- "eslint": "8.4.1",
- "eslint-config-next": "^12.0.7",
- "husky": "^7.0.4",
- "lint-staged": "^12.1.2",
- "prettier": "^2.5.1",
- "typescript": "4.5.4"
+ "@types/node": "25.6.0",
+ "@types/react": "19.2.14",
+ "autoprefixer": "^10.4.27",
+ "eslint": "^9.39.4",
+ "eslint-config-next": "^16.2.3",
+ "husky": "^9.1.7",
+ "lint-staged": "^16.4.0",
+ "postcss": "^8.5.9",
+ "prettier": "^3.8.2",
+ "tailwindcss": "^3.4.17",
+ "typescript": "6.0.2"
}
}
diff --git a/pages/_app.tsx b/pages/_app.tsx
deleted file mode 100644
index 3f5c9d5..0000000
--- a/pages/_app.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-import '../styles/globals.css'
-import type { AppProps } from 'next/app'
-
-function MyApp({ Component, pageProps }: AppProps) {
- return
-}
-
-export default MyApp
diff --git a/pages/event/[id].tsx b/pages/event/[id].tsx
deleted file mode 100644
index 7935d84..0000000
--- a/pages/event/[id].tsx
+++ /dev/null
@@ -1,252 +0,0 @@
-/** @format */
-
-import { VFC } from 'react'
-import { useRouter } from 'next/router'
-import { Layout } from '../../components/Layout'
-import { EventDetails, EventDetailType } from '../../components/EventList'
-import { useState, useEffect } from 'react'
-
-import styles from '../../styles/section.module.css'
-import detailsStyle from '../../styles/details.module.css'
-
-const defaultId = 'rupc2018'
-const getEntries: Function = (contentId: string, key: keyof EventDetailType) => {
- if (contentId in EventDetails) {
- if (key in EventDetails[contentId]) {
- return EventDetails[contentId][key]
- } else {
- return ''
- }
- } else {
- if (key in EventDetails[defaultId]) {
- return EventDetails[defaultId][key]
- } else {
- return ''
- }
- }
-}
-
-const extension: Function = (filename: string) => {
- const parts = filename.split('.')
- return parts[parts.length - 1]
-}
-
-type IODataProps = {
- iodata?: JSX.Element | null | undefined
-}
-const IODataElement: VFC = (Props: IODataProps) => {
- if (Props.iodata) {
- return (
- <>
- 問題文・入出力データ
- {Props.iodata}
- >
- )
- } else {
- return <>>
- }
-}
-
-type PlaceProps = {
- place?: string | null | undefined
-}
-const PlaceElement: VFC = (Props: PlaceProps) => {
- if (Props.place) {
- return (
- <>
- 会場
- {Props.place}
- >
- )
- } else {
- return <>>
- }
-}
-
-type PictureProps = {
- link?: string | null | undefined
- contestId?: string | null | undefined
-}
-const PictureElement: VFC = (Props: PictureProps) => {
- if (Props.link) {
- return (
-
-

-
- )
- } else {
- return <>>
- }
-}
-
-type ScheduleProps = {
- schedule?: JSX.Element | null | undefined
-}
-const ScheduleElement: VFC = (Props: ScheduleProps) => {
- if (Props.schedule) {
- return (
- <>
- 合宿内容
- {Props.schedule}
- >
- )
- } else {
- return <>>
- }
-}
-
-type EventDetailProps = {
- detailURL?: string | null | undefined
-}
-const EventDetailElement: VFC = (Props: EventDetailProps) => {
- if (Props.detailURL) {
- return (
- <>
- イベント概要
- {Props.detailURL}
- >
- )
- } else {
- return <>>
- }
-}
-
-type JudgeSiteProps = {
- judgeURL?: string | null | undefined
-}
-const JudgeSiteElement: VFC = (Props: JudgeSiteProps) => {
- if (Props.judgeURL) {
- return (
- <>
- ジャッジシステム
- {Props.judgeURL}
- >
- )
- } else {
- return <>>
- }
-}
-
-type EventDateProps = {
- date: { begin: string; end?: string | null | undefined }
-}
-const EventDateElement: VFC = (Props: EventDateProps) => {
- return (
- <>
- 開催日時
- {Props.date.begin}
- {Props.date.end ? ` - ${Props.date.end}` : ''}
- >
- )
-}
-
-type WriterProps = {
- writer?: string[] | null | undefined
-}
-const WriterElement: VFC = (Props: WriterProps) => {
- if (Props.writer) {
- return (
- <>
- 問題作成・ジャッジ
-
- {Props.writer.map((writer: string) => {
- return (
- -
- {`@${writer}`}
-
- )
- })}
-
- >
- )
- } else {
- return <>>
- }
-}
-
-type CommentaryProps = {
- contestId: string
- day: 'Day 1' | 'Day 2' | 'Day 3' | undefined
- commentary: { title: string; link: string }[]
-}
-const CommentaryElement: VFC = (Props: CommentaryProps) => {
- return (
- <>
- {Props.day + ' ' || ''}解説
-
- >
- )
-}
-
-type ProblemSetProps = {
- problemSet: { college: string; link: string }[]
- contestId: string
-}
-const ProblemSetElement: VFC = (Props: ProblemSetProps) => {
- return (
- <>
- 問題セット
-
- {Props.problemSet.map((college) => {
- return (
- -
- {college.link ? {college.college} : <>{college.college}>}
-
- )
- })}
-
- >
- )
-}
-
-const EventDetail: VFC = () => {
- const router = useRouter()
- const [contestId, setId] = useState()
- useEffect(() => {
- if (router.asPath !== router.route) {
- setId(String(router.query.id))
- }
- }, [router])
-
- return (
-
-
-
{getEntries(contestId, 'title')}
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-export default EventDetail
diff --git a/pages/event/index.tsx b/pages/event/index.tsx
deleted file mode 100644
index fac9b0e..0000000
--- a/pages/event/index.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-/** @format */
-
-import { VFC } from 'react'
-import Link from 'next/link'
-import { Layout } from '../../components/Layout'
-import { EventType, Events } from '../../components/EventList'
-
-import styles from '../../styles/section.module.css'
-import eventStyles from '../../styles/event.module.css'
-
-const Event: VFC = () => {
- return (
-
- {Events.map((event: EventType) => {
- return (
-
-
- {event.title} {event.date ? event.date + ' ' : ''}解説
-
- {event.detail}
-
- 詳細はこちら
-
-
- )
- })}
-
- )
-}
-
-export default Event
diff --git a/pages/menbers.tsx b/pages/menbers.tsx
deleted file mode 100644
index df1bb6f..0000000
--- a/pages/menbers.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-/** @format */
-
-import { VFC } from 'react'
-import { Layout } from '../components/Layout'
-import AtCoderGraph from '../components/atcoder/AtCoderGraph'
-import styles from '../styles/section.module.css'
-
-const AtCoderPage: VFC = () => {
- return (
-
-
-
AtCoder進捗どうですか
-
Summary
-
-
-
- )
-}
-
-export default AtCoderPage
diff --git a/pages/welcome.tsx b/pages/welcome.tsx
deleted file mode 100644
index 06b533f..0000000
--- a/pages/welcome.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-/** @format */
-
-import { VFC } from 'react'
-import Link from 'next/link'
-import { Layout } from '../components/Layout'
-import YouTube from 'react-youtube'
-
-import styles from '../styles/section.module.css'
-import welcomeStyles from '../styles/welcome.module.css'
-import flyer from '../public/RiPPro_Ad.png'
-import Discord from '../components/discord'
-
-const Welcome: VFC = () => {
- const currentDate = new Date()
-
- const courseDateStart = new Date(`${currentDate.getFullYear()}/5/11`)
- const courseDateEnd = new Date(`${currentDate.getFullYear()}/7/31`)
- const coueseWeek = ['月', '水']
- const workshopDate = '2025/4/7(金)'
- const coursePlace = 'OIC H234教室'
- const courseTime = '16:40〜18:15'
-
- const isCourceOpen: boolean = courseDateStart < currentDate && currentDate < courseDateEnd
- return (
-
-
-
新歓Discordサーバー
-
-
新歓講演会
-
-
私たちRiPRroの普段の活動内容や配布したビラの問題の解説などを行います!
-
どこの学部の方でもでも歓迎するので気軽に参加してください。
-
- - 日程 : {workshopDate}
- - 場所 : {coursePlace}
- - 時間 : {courseTime}
-
-
-
-
-
-
クリックで拡大画像を表示
-
競プロ新歓講習
-
仮入部者に向けてプログラムの書き方や、そのプログラムをどうやって競プロに使うのかをゼロから講習します!
-
各回につき2日の日程が用意されていますが、同じ内容をやるのでどちらに参加していただいても大丈夫です!
-
第1回講習 入門!プログラミング勉強会 #1
-
- - 日程 : 4/22(月) 4/23(火)
- - 場所 : 更新予定
- - 時間 : 16:20~17:50
-
-
第2回講習 実践!競プロ勉強会 #1
-
- - 日程 :4/24(水) 4/25(木)
- - 場所 : 更新予定
- - 時間 : 16:20~17:50
-
-
第3回講習 入門!プログラミング勉強会 #2
-
- - 日程 :4/29(月) 4/30(火)
- - 場所 : 更新予定
- - 時間 : 16:20~17:50
-
-
第4回講習 実践!競プロ勉強会 #2
-
- - 日程 :5/1(水) 5/2(木)
- - 場所 : 更新予定
- - 時間 : 16:20~17:50
-
-
RiPProとは
-
-
私たち RiPProは競技プログラミングの能力を高めコンテストでの入賞を目指す団体です。
-
競技プログラミングって聞いたことありますか?
-
競技プログラミングとは、与えられた問題をプログラムを用いて早く正確に解く種目です。
-
世界規模での大会が開催されるなどとても活発です。
-
- AtCoder
- {' '}
- などでは初心者から熟練者まで幅広く参加できるコンテストが毎週開催されています。
-
-
パソコンに問題を解かせよう!
-
-
良いプログラムとはどういうものでしょうか?
-
例えばこの動画のお姉さんは一つ一つ必死に数えていますが、もっと効率よく数える方法は無いでしょうか。
-
また、その方法をどうやってプログラムに落とし込みますか?
-
- このようなことを考えることはパズルを解くのと同じようにとても楽しいですし、実際のプログラム開発でも役に立ちます。
-
-
-
-
-
-
-
RiPProの普段の活動ではコンテスト形式でサークル内で競いながら問題を解いていきます。
-
- 年に 1~2 回ほどですが、問題を作ったりもしています。 (例:
-
- 立命合宿 2016
-
- ,
-
- 会津合宿 2015
-
- )
-
-
- プログラミングの勉強をしたい方、クイズやパズルが好きな方、是非部室に来てください
- 情報理工学部生以外も大歓迎です
-
-
-
連絡先
-
- 入部希望者または質問等がある方は,お問い合わせにアクセスしてください。
-
-
-
- )
-}
-
-export default Welcome
diff --git a/postcss.config.mjs b/postcss.config.mjs
new file mode 100644
index 0000000..598f711
--- /dev/null
+++ b/postcss.config.mjs
@@ -0,0 +1,8 @@
+const config = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {}
+ }
+};
+
+export default config;
\ No newline at end of file
diff --git a/pages/contact.tsx b/src/app/contact/page.tsx
similarity index 78%
rename from pages/contact.tsx
rename to src/app/contact/page.tsx
index 1482109..c683628 100644
--- a/pages/contact.tsx
+++ b/src/app/contact/page.tsx
@@ -1,18 +1,22 @@
-/** @format */
+'use client';
-import { VFC } from 'react'
-import { Layout } from '../components/Layout'
-import Twitter from '../components/Twitter'
+import type { FC } from 'react';
+import { Layout } from '../../components/PageLayout';
+import Twitter from '../../components/Twitter';
-import styles from '../styles/section.module.css'
+const sectionStyle = {
+ marginLeft: '8px',
+ padding: '2px',
+ fontSize: '11pt'
+};
-const Contact: VFC = () => {
+const Contact: FC = () => {
return (
-
+
お問い合わせ
連絡先
入部希望者または質問等がある方は,名前・学部学科・回生を明記の上,下記のメールアドレスにメールをしていただくか,
@@ -39,7 +43,7 @@ const Contact: VFC = () => {
- )
-}
+ );
+};
-export default Contact
+export default Contact;
diff --git a/src/app/event/[id]/page.tsx b/src/app/event/[id]/page.tsx
new file mode 100644
index 0000000..01e8d7d
--- /dev/null
+++ b/src/app/event/[id]/page.tsx
@@ -0,0 +1,53 @@
+import Link from 'next/link';
+import { getAllEventsFromMdx, getEventById } from '@/lib/eventMdx';
+import { Layout } from '../../../components/PageLayout';
+
+type PageProps = {
+ params: Promise<{
+ id: string;
+ }>;
+};
+
+const EventDetailPage = async ({ params }: PageProps) => {
+ const { id } = await params;
+ const event = getEventById(id);
+
+ if (!event) {
+ return (
+
+
+
+ 解説ページに戻る
+
+
イベントが見つかりません
+
+
+ );
+ }
+
+ const dateText = event.date.end ? `${event.date.begin} - ${event.date.end}` : event.date.begin;
+
+ return (
+
+
+
+ 解説ページに戻る
+
+
{event.title}
+
{dateText}
+
+
+
+ );
+};
+
+export async function generateStaticParams() {
+ return getAllEventsFromMdx().map((event) => ({
+ id: event.id
+ }));
+}
+
+export default EventDetailPage;
diff --git a/src/app/event/page.tsx b/src/app/event/page.tsx
new file mode 100644
index 0000000..fc907b9
--- /dev/null
+++ b/src/app/event/page.tsx
@@ -0,0 +1,30 @@
+import Link from 'next/link';
+import { getEventSummaries } from '@/lib/eventMdx';
+import { Layout } from '../../components/PageLayout';
+
+const Event = () => {
+ const events = getEventSummaries();
+
+ return (
+
+
+ {events.map((event) => {
+ return (
+
+ {event.title} 解説
+ {event.detail}
+
+ 詳細はこちら
+
+
+ );
+ })}
+
+
+ );
+};
+
+export default Event;
diff --git a/src/app/globals.css b/src/app/globals.css
new file mode 100644
index 0000000..0f9a5d6
--- /dev/null
+++ b/src/app/globals.css
@@ -0,0 +1,173 @@
+/** @format */
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ font-weight: 700;
+ line-height: 1.25;
+ margin: 0.75em 0 0.35em;
+ }
+
+ h2 {
+ font-size: 1.5rem;
+ }
+
+ h3 {
+ font-size: 1.125rem;
+ }
+
+ p {
+ margin: 0.5em 0;
+ }
+
+ ul,
+ ol {
+ margin: 0.5em 0;
+ padding-left: 1.5em;
+ }
+
+ dl {
+ margin: 0.5em 0;
+ }
+
+ dt {
+ font-weight: 700;
+ margin-top: 0.5em;
+ }
+
+ dd {
+ margin-left: 1.5em;
+ }
+
+ a {
+ color: #004599;
+ text-decoration: underline;
+ }
+
+ a:hover {
+ text-decoration-thickness: 2px;
+ }
+}
+
+body {
+ margin: 0;
+ min-height: 100vh;
+ overflow-y: scroll;
+ line-height: 1.5em;
+ font-family: sans-serif;
+ font-size: 16px;
+ color: #111;
+ background-image: linear-gradient(-45deg, rgba(135, 206, 255, 0.4), rgba(100, 149, 255, 0.4)), url('/background.jpg');
+ background-attachment: fixed;
+ background-position: center top;
+ background-repeat: no-repeat;
+ background-size: cover;
+}
+
+.event-page {
+ padding: 12px 12px 18px;
+}
+
+.event-page h2 {
+ margin-top: 0;
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 2px solid rgba(0, 69, 153, 0.18);
+}
+
+.event-list {
+ display: grid;
+ gap: 14px;
+}
+
+.event-card {
+ padding: 14px 16px;
+ border: 1px solid rgba(0, 69, 153, 0.14);
+}
+
+.event-card h2 {
+ margin: 0 0 8px;
+ border: 0;
+ padding: 0;
+}
+
+.event-summary {
+ margin: 0;
+ color: #334155;
+}
+
+.event-detail-link {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 10px;
+}
+
+.event-back-link {
+ display: inline-block;
+ margin-bottom: 14px;
+ padding: 6px 12px;
+ border: 1px solid rgba(0, 69, 153, 0.2);
+ border-radius: 999px;
+ background: rgba(255, 255, 255, 0.92);
+ text-decoration: none;
+}
+
+.event-meta {
+ margin: 0 0 14px;
+ color: #475569;
+ font-size: 0.96rem;
+}
+
+.event-content {
+ overflow-x: auto;
+}
+
+.event-content table {
+ width: 100%;
+ margin: 0.9rem 0 1.2rem;
+ border-collapse: collapse;
+ table-layout: fixed;
+ background: rgba(255, 255, 255, 0.92);
+ border: 1px solid rgba(0, 69, 153, 0.16);
+ border-radius: 10px;
+ overflow: hidden;
+}
+
+.event-content th,
+.event-content td {
+ padding: 10px 12px;
+ border-bottom: 1px solid rgba(0, 69, 153, 0.12);
+ vertical-align: top;
+}
+
+.event-content th {
+ background: linear-gradient(180deg, rgba(0, 69, 153, 0.08), rgba(0, 69, 153, 0.03));
+ text-align: left;
+}
+
+.event-content tr:last-child td {
+ border-bottom: 0;
+}
+
+.event-content td:first-child,
+.event-content th:first-child {
+ width: 65%;
+}
+
+.event-content td:last-child,
+.event-content th:last-child {
+ width: 35%;
+}
+
+.event-content img {
+ max-width: 100%;
+ height: auto;
+}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
new file mode 100644
index 0000000..35fbae4
--- /dev/null
+++ b/src/app/layout.tsx
@@ -0,0 +1,21 @@
+import type { Metadata } from 'next';
+import type { ReactNode } from 'react';
+import './globals.css';
+
+export const metadata: Metadata = {
+ title: 'RiPPro(立命館大学情報理工学部プロジェクト団体)',
+ description:
+ '立命館大学情報理工学部プロジェクト団体 RiPPro (Ritsumeikan Programming Project) は、ACM-ICPC (プログラミングの学生世界大会) などの大会で入賞することを目的として結成されました。'
+};
+
+type RootLayoutProps = {
+ children: ReactNode;
+};
+
+export default function RootLayout({ children }: RootLayoutProps) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/pages/links.tsx b/src/app/links/page.tsx
similarity index 62%
rename from pages/links.tsx
rename to src/app/links/page.tsx
index 40b8042..37e0e8b 100644
--- a/pages/links.tsx
+++ b/src/app/links/page.tsx
@@ -1,12 +1,16 @@
-/** @format */
+'use client';
-import { VFC } from 'react'
-import { Layout } from '../components/Layout'
-import { SectionType, LinksType, sections } from '../components/Links'
+import type { FC } from 'react';
+import { Layout } from '../../components/PageLayout';
+import { type LinksType, type SectionType, sections } from '../../components/Links';
-import styles from '../styles/section.module.css'
+const sectionStyle = {
+ marginLeft: '8px',
+ padding: '2px',
+ fontSize: '11pt'
+};
-const LinkSection: VFC
= (Props: SectionType): JSX.Element => {
+const LinkSection: FC = (Props: SectionType) => {
return (
<>
{Props.title}
@@ -18,27 +22,27 @@ const LinkSection: VFC = (Props: SectionType): JSX.Element => {
{linkItem.title}
- )
+ );
})}
>
- )
-}
+ );
+};
-const Links: VFC = () => {
+const Links: FC = () => {
return (
-
+
リンク
{sections.map((section: SectionType) => {
- return
+ return ;
})}
- )
-}
+ );
+};
-export default Links
+export default Links;
diff --git a/src/app/members/page.tsx b/src/app/members/page.tsx
new file mode 100644
index 0000000..97a1df2
--- /dev/null
+++ b/src/app/members/page.tsx
@@ -0,0 +1,46 @@
+/** @format */
+'use client';
+
+import AtCoderGraph from '../../components/atcoder/AtCoderGraph';
+import { Layout } from '../../components/PageLayout';
+
+const AtCoderPage = () => {
+ const sectionStyle = {
+ marginLeft: '8px',
+ padding: '2px',
+ fontSize: '11pt'
+ };
+
+ const heading2Style = {
+ margin: '24px 0',
+ padding: '0.5em',
+ color: '#000',
+ background: '#cdf0fd',
+ borderLeft: 'solid 5px #6cbad8'
+ };
+
+ const heading3Style = {
+ margin: '16px 0',
+ borderBottom: '1px dashed #6cbad8'
+ };
+
+ return (
+
+
+
AtCoder進捗どうですか
+
Summary
+
+
+
+ );
+};
+
+export default AtCoderPage;
diff --git a/pages/index.tsx b/src/app/page.tsx
similarity index 68%
rename from pages/index.tsx
rename to src/app/page.tsx
index 26f469c..25bac7c 100644
--- a/pages/index.tsx
+++ b/src/app/page.tsx
@@ -1,9 +1,10 @@
/** @format */
+'use client';
-import type { NextPage } from 'next'
-import { Layout } from '../components/Layout'
-import Twitter from '../components/Twitter'
-import IndexArticles from '../components/IndexArticles'
+import type { NextPage } from 'next';
+import IndexArticles from '../components/IndexArticles';
+import { Layout } from '../components/PageLayout';
+import Twitter from '../components/Twitter';
const Home: NextPage = () => {
return (
@@ -16,7 +17,7 @@ const Home: NextPage = () => {
- )
-}
+ );
+};
-export default Home
+export default Home;
diff --git a/src/app/welcome/page.tsx b/src/app/welcome/page.tsx
new file mode 100644
index 0000000..0c0982c
--- /dev/null
+++ b/src/app/welcome/page.tsx
@@ -0,0 +1,176 @@
+/** @format */
+'use client';
+
+import Link from 'next/link';
+import YouTube from 'react-youtube';
+import Discord from '../../components/discord';
+import { Layout } from '../../components/PageLayout';
+import type { CSSProperties } from 'react';
+
+const sectionStyle: CSSProperties = {
+ marginLeft: '8px',
+ padding: '2px',
+ fontSize: '11pt'
+};
+
+const lineParagraphStyle = {
+ margin: 0
+};
+
+const listStyle = {
+ listStyle: 'none',
+ display: 'block',
+ paddingLeft: 0
+};
+
+const bottomStyle: CSSProperties = {
+ marginBottom: '1em'
+};
+
+const flyerStyle: CSSProperties = {
+ justifyContent: 'flex-end',
+ display: 'flex',
+ position: 'relative',
+ paddingRight: '2%'
+};
+
+const pStyle: CSSProperties = {
+ float: 'right',
+ fontSize: 'small',
+ paddingRight: '2%'
+};
+
+const youtubeStyle: CSSProperties = {
+ width: '100%',
+ aspectRatio: '16 / 9'
+} as CSSProperties;
+
+const Welcome = () => {
+ // const currentDate = new Date();
+
+ // const courseDateStart = new Date(`${currentDate.getFullYear()}/5/11`);
+ // const courseDateEnd = new Date(`${currentDate.getFullYear()}/7/31`);
+ // const coueseWeek = ['月', '水'];
+ const workshopDate = '2025/4/7(金)';
+ const coursePlace = 'OIC H234教室';
+ const courseTime = '16:40〜18:15';
+
+ // const isCourceOpen: boolean = courseDateStart < currentDate && currentDate < courseDateEnd;
+ return (
+
+
+
新歓Discordサーバー
+
+
新歓講演会
+
+
私たちRiPRroの普段の活動内容や配布したビラの問題の解説などを行います!
+
どこの学部の方でもでも歓迎するので気軽に参加してください。
+
+ - 日程 : {workshopDate}
+ - 場所 : {coursePlace}
+ - 時間 : {courseTime}
+
+
+
+
+
+
クリックで拡大画像を表示
+
競プロ新歓講習
+
仮入部者に向けてプログラムの書き方や、そのプログラムをどうやって競プロに使うのかをゼロから講習します!
+
各回につき2日の日程が用意されていますが、同じ内容をやるのでどちらに参加していただいても大丈夫です!
+
第1回講習 入門!プログラミング勉強会 #1
+
+ - 日程 : 4/22(月) 4/23(火)
+ - 場所 : 更新予定
+ - 時間 : 16:20~17:50
+
+
第2回講習 実践!競プロ勉強会 #1
+
+ - 日程 :4/24(水) 4/25(木)
+ - 場所 : 更新予定
+ - 時間 : 16:20~17:50
+
+
第3回講習 入門!プログラミング勉強会 #2
+
+ - 日程 :4/29(月) 4/30(火)
+ - 場所 : 更新予定
+ - 時間 : 16:20~17:50
+
+
第4回講習 実践!競プロ勉強会 #2
+
+ - 日程 :5/1(水) 5/2(木)
+ - 場所 : 更新予定
+ - 時間 : 16:20~17:50
+
+
RiPProとは
+
+
+ 私たち RiPProは競技プログラミングの能力を高めコンテストでの入賞を目指す団体です。
+
+
競技プログラミングって聞いたことありますか?
+
+ 競技プログラミングとは、与えられた問題をプログラムを用いて早く正確に解く種目です。
+
+
世界規模での大会が開催されるなどとても活発です。
+
+ AtCoder
+ {' '}
+ などでは初心者から熟練者まで幅広く参加できるコンテストが毎週開催されています。
+
+
パソコンに問題を解かせよう!
+
+
良いプログラムとはどういうものでしょうか?
+
+ 例えばこの動画のお姉さんは一つ一つ必死に数えていますが、もっと効率よく数える方法は無いでしょうか。
+
+
また、その方法をどうやってプログラムに落とし込みますか?
+
+ このようなことを考えることはパズルを解くのと同じようにとても楽しいですし、実際のプログラム開発でも役に立ちます。
+
+
+
+
+
+
+
+ RiPProの普段の活動ではコンテスト形式でサークル内で競いながら問題を解いていきます。
+
+
+ 年に 1~2 回ほどですが、問題を作ったりもしています。 (例:
+
+ 立命合宿 2016
+
+ ,
+
+ 会津合宿 2015
+
+ )
+
+
+ プログラミングの勉強をしたい方、クイズやパズルが好きな方、是非部室に来てください
+ 情報理工学部生以外も大歓迎です
+
+
+
連絡先
+
+ 入部希望者または質問等がある方は,
+ お問い合わせにアクセスしてください。
+
+
+
+ );
+};
+
+export default Welcome;
diff --git a/components/IndexArticles.tsx b/src/components/IndexArticles.tsx
similarity index 58%
rename from components/IndexArticles.tsx
rename to src/components/IndexArticles.tsx
index 1ecf02c..9a770cf 100644
--- a/components/IndexArticles.tsx
+++ b/src/components/IndexArticles.tsx
@@ -1,22 +1,19 @@
/** @format */
-import { VFC } from 'react'
-import Link from 'next/link'
+import Link from 'next/link';
+import type { FC } from 'react';
-import styles from '../styles/section.module.css'
-import articleStyles from './IndexArticles.module.css'
-
-const IndexArticles: VFC = () => {
+const IndexArticles: FC = () => {
return (
-
-
+
+
入部希望の方へ
新入生のみなさん、ご入学おめでとうございます!
新入生に限らず、RiPPro に興味がある方は 新歓情報ページ をご覧ください。
-
- )
-}
+ );
+};
-export default IndexArticles
+export default IndexArticles;
diff --git a/components/Links.tsx b/src/components/Links.tsx
similarity index 94%
rename from components/Links.tsx
rename to src/components/Links.tsx
index b61b679..4e10751 100644
--- a/components/Links.tsx
+++ b/src/components/Links.tsx
@@ -1,8 +1,8 @@
/** @format */
export interface LinksType {
- title: string
- link: string
+ title: string;
+ link: string;
}
const ACMICPC: LinksType[] = [
@@ -14,7 +14,7 @@ const ACMICPC: LinksType[] = [
title: 'ICPC OB/OG の会',
link: 'https://jag-icpc.org/'
}
-]
+];
const InfoProjectClubs: LinksType[] = [
{
@@ -29,7 +29,7 @@ const InfoProjectClubs: LinksType[] = [
title: 'RiST',
link: 'https://risec.github.io/'
}
-]
+];
const ritsumeikan: LinksType[] = [
{
title: '立命館大学',
@@ -39,7 +39,7 @@ const ritsumeikan: LinksType[] = [
title: '立命館コンピュータクラブ',
link: 'http://www.rcc.ritsumei.ac.jp/'
}
-]
+];
const others: LinksType[] = [
{
title: 'TPC @ 筑波大',
@@ -61,11 +61,11 @@ const others: LinksType[] = [
title: '競技プログラミング部 @ 会津大',
link: 'http://web-ext.u-aizu.ac.jp/circles/acpc/ja/index.html'
}
-]
+];
export interface SectionType {
- title: string
- contents: LinksType[]
+ title: string;
+ contents: LinksType[];
}
export const sections: SectionType[] = [
@@ -73,4 +73,4 @@ export const sections: SectionType[] = [
{ title: '情報理工学部プロジェクト連合', contents: InfoProjectClubs },
{ title: '立命館大学', contents: ritsumeikan },
{ title: '他大学', contents: others }
-]
+];
diff --git a/src/components/PageLayout.tsx b/src/components/PageLayout.tsx
new file mode 100644
index 0000000..41e66dc
--- /dev/null
+++ b/src/components/PageLayout.tsx
@@ -0,0 +1,96 @@
+import Button from '@mui/material/Button';
+import Stack from '@mui/material/Stack';
+import NextHead from 'next/head';
+import Link from 'next/link';
+import type { FC, ReactNode } from 'react';
+
+type PageLayoutProps = {
+ title?: string;
+ description?: string;
+ children?: ReactNode;
+};
+
+const defaultDescription =
+ '立命館大学情報理工学部プロジェクト団体 競技プログラミング部門「RiPPro」です。ACM-ICPC (プログラミングの学生世界大会) などの大会で入賞することを目的として活動しています。';
+const defaultTitle = 'RiPPro - 立命館大学情報理工学部プロジェクト団体';
+
+type SiteMetaProps = {
+ title: string | undefined;
+ description: string | undefined;
+};
+
+const SiteMeta: FC
= ({ title, description }) => (
+
+ {title ?? defaultTitle}
+
+
+
+
+
+
+
+);
+
+const SiteNavigator: FC = () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
+
+const SiteHeader: FC = () => (
+
+
+

+
+
+
+);
+
+const SiteFooter: FC = () => {
+ const year = new Date().getFullYear();
+ return (
+
+ Copyright (C) 2005-{year} RiPPro All rights reserved.
+
+ );
+};
+
+export const Layout: FC = ({ children, title, description }) => (
+
+);
diff --git a/components/Twitter.tsx b/src/components/Twitter.tsx
similarity index 64%
rename from components/Twitter.tsx
rename to src/components/Twitter.tsx
index 6c50c67..7ad4eca 100644
--- a/components/Twitter.tsx
+++ b/src/components/Twitter.tsx
@@ -1,13 +1,17 @@
/** @format */
-import { VFC } from 'react'
-import { Timeline } from 'react-twitter-widgets'
+import type { FC } from 'react';
+import { Timeline } from 'react-twitter-widgets';
-import styles from '../styles/section.module.css'
+const sectionStyle = {
+ marginLeft: '8px',
+ padding: '2px',
+ fontSize: '11pt'
+};
-const Header: VFC = () => {
+const Header: FC = () => {
return (
-
+
- )
-}
+ );
+};
-export default Header
+export default Header;
diff --git a/components/atcoder/AtCoderGraph.tsx b/src/components/atcoder/AtCoderGraph.tsx
similarity index 57%
rename from components/atcoder/AtCoderGraph.tsx
rename to src/components/atcoder/AtCoderGraph.tsx
index 5585eb2..e0293c1 100644
--- a/components/atcoder/AtCoderGraph.tsx
+++ b/src/components/atcoder/AtCoderGraph.tsx
@@ -1,62 +1,79 @@
/** @format */
-import React from 'react'
-import styles from './AtCoderGraph.module.css'
+import Highcharts from 'highcharts';
+import HighchartsReact from 'highcharts-react-official';
+import React from 'react';
-import Highcharts from 'highcharts'
-import HighchartsExporting from 'highcharts/modules/exporting'
-import HighchartsReact from 'highcharts-react-official'
-
-type Props = {}
+type Props = {};
type State = {
- userIDs: string[]
- acceptedCounts: number[]
-}
+ userIDs: string[];
+ acceptedCounts: number[];
+ loaded: boolean;
+};
type UserInfoType = {
- userID: string
- acceptedCount: number
-}
+ userID: string;
+ acceptedCount: number;
+};
class AtCoderGraph extends React.Component<{}, State> {
constructor(props: Props) {
- super(props)
+ super(props);
this.state = {
userIDs: [],
- acceptedCounts: []
- }
- this.getUsersInfo()
+ acceptedCounts: [],
+ loaded: false
+ };
+ }
+
+ componentDidMount() {
+ import('highcharts/modules/exporting')
+ .then((module: any) => {
+ const HighchartsExporting = module.default ?? module;
+ if (typeof HighchartsExporting === 'function') {
+ HighchartsExporting(Highcharts);
+ }
+ })
+ .catch(() => {
+ // Silently ignore exporting module loading failures
+ });
+ this.getUsersInfo();
+ this.setState({ loaded: true });
}
+
getUsersInfo = () => {
const url =
- 'https://script.google.com/macros/s/AKfycbxZEjsW21O2Tg4IqwHZOS8T-JpoRIbyMwBvcvFtZI92LOT6yz-PfFjVdUihBlmZxzsH/exec'
+ 'https://script.google.com/macros/s/AKfycbxZEjsW21O2Tg4IqwHZOS8T-JpoRIbyMwBvcvFtZI92LOT6yz-PfFjVdUihBlmZxzsH/exec';
this.request(url).then((responseData: any) => {
const usersInfo: UserInfoType[] = responseData
.map((data: any) => {
- return { userID: data.userID as string, acceptedCount: data.count as number }
+ return {
+ userID: data.userID as string,
+ acceptedCount: data.count as number
+ };
})
- .sort((user1: UserInfoType, user2: UserInfoType) => user2.acceptedCount - user1.acceptedCount)
+ .sort((user1: UserInfoType, user2: UserInfoType) => user2.acceptedCount - user1.acceptedCount);
this.setState({
userIDs: usersInfo.map((userInfo: UserInfoType) => userInfo.userID),
acceptedCounts: usersInfo.map((userInfo: UserInfoType) => userInfo.acceptedCount)
- })
- })
- }
+ });
+ });
+ };
request = (url: string) => {
return fetch(url)
.then((res) => res.json())
.catch((error) => {
- console.error('Fetch Error:', error)
- })
- }
- RenderSummary: React.VFC = (): JSX.Element => {
- if (typeof Highcharts === 'object') {
- HighchartsExporting(Highcharts)
- }
+ console.error('Fetch Error:', error);
+ });
+ };
+
+ RenderSummary = () => {
const options = {
+ accessibility: {
+ enabled: false
+ },
chart: {
- polar: true,
type: 'bar',
height: '100%'
},
@@ -100,13 +117,17 @@ class AtCoderGraph extends React.Component<{}, State> {
}
]
}
- }
- return
- }
+ };
+ return
;
+ };
render() {
- return
{}
+ if (!this.state.loaded) {
+ return
;
+ }
+
+ return
{}
;
}
}
-export default AtCoderGraph
+export default AtCoderGraph;
diff --git a/src/components/discord.tsx b/src/components/discord.tsx
new file mode 100644
index 0000000..e30631e
--- /dev/null
+++ b/src/components/discord.tsx
@@ -0,0 +1,31 @@
+import { useEffect } from 'react';
+
+const discordWrapperStyle = {
+ display: 'flex',
+ justifyContent: 'center'
+};
+
+function Discord() {
+ useEffect(() => {
+ const script = document.createElement('script');
+ script.src = 'https://platform.twitter.com/widgets.js';
+ document.body.appendChild(script);
+ return () => {
+ document.body.removeChild(script);
+ };
+ }, []);
+ return (
+
+ );
+}
+
+export default Discord;
diff --git a/src/lib/eventMdx.ts b/src/lib/eventMdx.ts
new file mode 100644
index 0000000..3ebe520
--- /dev/null
+++ b/src/lib/eventMdx.ts
@@ -0,0 +1,119 @@
+import 'server-only';
+
+import fs from 'fs';
+import matter from 'gray-matter';
+import { marked } from 'marked';
+import path from 'path';
+
+const EVENTS_DIR = path.join(process.cwd(), 'data', 'events');
+
+type EventDate = {
+ begin: string;
+ end?: string;
+};
+
+export type EventMdxData = {
+ id: string;
+ title: string;
+ date: EventDate;
+ contentHtml: string;
+ raw: string;
+};
+
+export type EventSummary = {
+ id: string;
+ title: string;
+ detail: string;
+};
+
+function dateToTimestamp(dateText: string): number {
+ const parts = dateText.split('/').map((part) => Number(part));
+
+ if (parts.length !== 3 || parts.some((part) => Number.isNaN(part))) {
+ return 0;
+ }
+
+ const [year, month, day] = parts;
+ return Date.UTC(year, month - 1, day);
+}
+
+function resolveEventAssetPath(contestId: string, assetPath: string): string {
+ if (!assetPath || assetPath.startsWith('http') || assetPath.startsWith('/') || assetPath.startsWith('data:')) {
+ return assetPath;
+ }
+ return `/static/contestData/${contestId}/${assetPath}`;
+}
+
+function getMdxFiles(): string[] {
+ if (!fs.existsSync(EVENTS_DIR)) {
+ return [];
+ }
+ return fs
+ .readdirSync(EVENTS_DIR)
+ .filter((file) => file.endsWith('.md') || file.endsWith('.mdx'))
+ .sort();
+}
+
+function resolveImagePathsInHtml(html: string, contestId: string): string {
+ return html.replace(/src="(?!(?:https?:\/\/|\/|data:))([^"]+)"/g, (_match, imagePath) => {
+ return `src="${resolveEventAssetPath(contestId, imagePath)}"`;
+ });
+}
+
+function parseEventFrontmatter(frontmatter: Record
): Pick {
+ const date =
+ frontmatter.date && typeof frontmatter.date === 'object'
+ ? (frontmatter.date as { begin?: unknown; end?: unknown })
+ : undefined;
+
+ return {
+ id: String(frontmatter.id ?? ''),
+ title: String(frontmatter.title ?? ''),
+ date: {
+ begin: String(date?.begin ?? ''),
+ ...(date?.end ? { end: String(date.end) } : {})
+ }
+ };
+}
+
+export function getAllEventsFromMdx(): EventMdxData[] {
+ const files = getMdxFiles();
+
+ return files
+ .map((file) => {
+ const fullPath = path.join(EVENTS_DIR, file);
+ const raw = fs.readFileSync(fullPath, 'utf-8');
+ const { data, content } = matter(raw);
+ const rawContent = String(content ?? '');
+ const withoutScripts = rawContent.replace(/