This commit is contained in:
2026-07-17 20:07:01 +09:00
commit 814273d4d7
52 changed files with 8765 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
.DS_Store
.ipynb_checkpoints/
node_modules/
+197
View File
@@ -0,0 +1,197 @@
> This README is written by claude as I couldn't remember the project.
# 비선형회귀법으로 분석한 서열 위치 효과
> Pre-URP 연구 프로젝트 · 2024년 1월 · Serial Position Effect
Murdock(1962)의 자유회상 서열위치효과 실험을 **한국어 단어**로 재현하되, 원 논문이 사용한 선형 회귀 대신 **2차(비선형) 회귀로 U자 곡선을 직접 적합**한 연구입니다. 자체 제작한 웹앱으로 실험을 실행하고, 참가자 약 18명 × 8조건의 자유회상 데이터를 수집해 조건별 2차 계수를 비교했습니다.
최종 산출물은 발표자료 `SerialPositionEffect.pptx` (24장)입니다.
---
## 1. 실험 설계
**2×2×2 = 8조건** 요인 설계. 각 조건은 세 글자 코드로 표기하며, 파일명·엑셀 시트명·그래프 번호가 모두 이 체계를 따릅니다.
| 요인 | 수준 1 | 수준 2 |
|---|---|---|
| 단어 길이 | **A** = 1~3음절 (짧은 단어) | **B** = 4~6음절 (긴 단어) |
| 단어 제시 시간 | **C** = 2초 | **D** = 3초 |
| 배열의 총 단어 수 | **E** = 10개 | **F** = 20개 |
조건 코드 순서: `ACE → ACF → ADE → ADF → BCE → BCF → BDE → BDF`
(`Result graphs/1.png` ~ `8.png`이 이 순서에 대응합니다.)
### 절차
1. 단어를 1개씩 순차 제시 (제시 시간 2초 또는 3초, **각 단어 뒤 1초 공백**)
2. 배열 종료 시 빨간색 `Finish` 표시
3. 참가자가 기억나는 단어를 **순서와 무관하게** 종이 설문지에 작성 (`설문지 형식 초안.docx`)
4. 위치별 회상 성공 여부를 0/1로 코딩해 엑셀에 입력
### 자극
표준국어대사전의 **명사** (한자어·외래어·혼종어 포함). 원본 단어 목록은 `단어 목록.xlsx`(1to3 / 4to6 각 145행)와 `pre_urp/korean_words.xlsx`(음절 수별 컬럼)에 있습니다.
### 참가자
조건당 **17~18명** (BCE만 17명, 나머지 7개 조건은 18명).
---
## 2. 파일 구조
### 실험 실행 도구 — 3세대에 걸쳐 진화
| 세대 | 위치 | 설명 |
|---|---|---|
| 1세대 | `pre_urp_contents/*.pptm` | **파워포인트 매크로판.** `ACE.pptm`~`BDF.pptm` 8개 파일. VBA `GetRandom()` 매크로가 단어 순서를 셔플해 슬라이드로 제시. `Random100Direct.pptm`은 이 셔플 알고리즘을 100회 돌려 검증한 파일 |
| 2세대 | `Word View/` | **수동 웹앱.** Mix 버튼·제시 시간·단어 개수를 매번 직접 설정해 한 조건씩 실행 |
| 3세대 | `Word View Auto/` | **자동 웹앱.** Express 서버 위에서 `ACE ACF ADE ADF BCE BCF BDE BDF`를 한 번에 입력하면 8조건 자동 연속 실행. 페이지 로드 시 자동 셔플 |
### 데이터 · 분석
| 파일 | 설명 |
|---|---|
| `exp_results1.xlsx` | **실제 수집 데이터 (최종본).** 8개 조건 시트 + `Dummy` 시트. 행 = 참가자, 열 = 서열 위치, 값 = 회상 성공 0/1 |
| `pre_urp/exp_results.xlsx` | 데이터 수집 전 **빈 템플릿** (헤더만 존재) |
| `pre_urp/korean_words.xlsx` | 음절 수별 단어 원본 |
| `pre_urp.ipynb` | 분석 노트북 (sklearn 회귀 연습 → 단어 리스트 셔플/분할 → Dummy 적합) |
| `pre_urp/comp_libraries.txt` | 필요 패키지: matplotlib, scikit-learn, pandas, openpyxl |
### 산출물 · 문서
| 파일 | 설명 |
|---|---|
| `SerialPositionEffect.pptx` | **최종 발표자료** (24장, 32MB) |
| `Result graphs/1~8.png` | 조건별(ACE→BDF) 산점도 + 2차 적합 곡선 |
| `wordlength.png` / `wordshown.png` / `wordnumber.png` | 요인별 비교 그래프 (단어 길이 / 제시 시간 / 단어 개수) |
| `pre_urp_contents/배경지식.pptx` | 이론 정리 (감각기억, 단기기억, Sperling 1960, Miller의 매직넘버 7±2, 작업기억 음운루프) |
| `pre_urp_contents/Experiment_Instruction.pptx` | 실험 진행 안내 (2024-01-08) |
| `pre_urp_contents/exp_procedure.docx` | 실험 절차 초안 |
| `기존연구.pdf`, `pre_urp_contents/murdock_serial_position_effect.pdf` | 선행연구 논문 (서로 다른 파일) |
---
## 3. 실행 방법
### Word View Auto (3세대, 권장)
```bash
cd "Word View Auto"
npm install # node_modules는 이미 포함되어 있음
node server.js # → http://127.0.0.1:4000
```
`Test Type List`에 조건 코드를 공백으로 구분해 입력 (기본값 `ACE ACF ADE ADF BCE BCF BDE BDF`) → Start → **스페이스바**로 각 테스트 시작.
### Word View (2세대)
서버 불필요. `Word View/index.html`을 브라우저로 직접 열면 됩니다.
`R` 키로 설정 화면 복귀.
---
## 4. 결과
각 조건의 **위치별 평균 회상률**에 `y = ax² + bx + c` 를 최소제곱 적합한 결과입니다.
| 조건 | 설명 | N | 평균 회상률 | a (x²) | b (x) | c | R² |
|---|---|---:|---:|---:|---:|---:|---:|
| ACE | 짧은 / 2초 / 10개 | 18 | 0.578 | 0.0105 | 0.1009 | 0.7278 | 0.398 |
| ACF | 짧은 / 2초 / 20개 | 18 | 0.408 | 0.0033 | 0.0682 | 0.6444 | 0.447 |
| ADE | 짧은 / 3초 / 10개 | 18 | 0.622 | 0.0141 | 0.1840 | 1.0917 | 0.566 |
| ADF | 짧은 / 3초 / 20개 | 18 | 0.536 | 0.0040 | 0.0975 | 0.9822 | 0.771 |
| BCE | 긴 / 2초 / 10개 | 17 | 0.535 | 0.0189 | 0.2201 | 1.0167 | 0.587 |
| BCF | 긴 / 2초 / 20개 | 18 | 0.333 | 0.0038 | 0.0851 | 0.6881 | 0.599 |
| BDE | 긴 / 3초 / 10개 | 18 | 0.467 | 0.0078 | 0.0782 | 0.5972 | 0.267 |
| BDF | 긴 / 3초 / 20개 | 18 | 0.361 | 0.0040 | 0.0790 | 0.6152 | 0.428 |
### 핵심 발견
**8조건 모두 `a > 0`** — 아래로 볼록한 U자 곡선이 전 조건에서 재현되었습니다. 서열 위치 효과 자체는 성공적으로 확인되었습니다.
**주효과** (조건 평균 회상률)
| 요인 | 수준 1 | 수준 2 | 차이 |
|---|---:|---:|---:|
| 단어 개수 | E (10개) **0.550** | F (20개) **0.410** | **0.140** — 가장 큰 영향 |
| 단어 길이 | A (짧은) **0.536** | B (긴) **0.424** | **0.112** — 두 번째 |
| 제시 시간 | C (2초) **0.464** | D (3초) **0.497** | 0.033 — 거의 영향 없음 |
**초두 효과 vs 최신 효과** — 발표자료 13쪽의 논점이지만, 데이터상 **일관된 우열이 나오지 않았습니다.** 첫 3개 위치 평균과 마지막 3개 위치 평균을 비교하면 8조건 중 4개는 최신 효과가, 4개는 초두 효과가 우세합니다.
| 조건 | 초두(첫 3개) | 중간 | 최신(마지막 3개) | 우세 |
|---|---:|---:|---:|---|
| ACE | 0.611 | 0.514 | 0.630 | 최신 |
| ACF | 0.519 | 0.349 | 0.574 | 최신 |
| ADE | 0.815 | 0.514 | 0.574 | 초두 |
| ADF | 0.778 | 0.472 | 0.593 | 초두 |
| BCE | 0.647 | 0.441 | 0.549 | 초두 |
| BCF | 0.537 | 0.262 | 0.463 | 초두 |
| BDE | 0.426 | 0.472 | 0.500 | 최신 |
| BDF | 0.500 | 0.282 | 0.593 | 최신 |
### 위치별 평균 회상률 (원자료)
```
ACE (n=18, 10개): 0.61 0.61 0.61 0.28 0.50 0.61 0.67 0.44 0.61 0.83
ADE (n=18, 10개): 0.83 0.78 0.83 0.50 0.67 0.44 0.44 0.50 0.39 0.83
BCE (n=17, 10개): 0.76 0.65 0.53 0.59 0.41 0.24 0.53 0.41 0.35 0.88
BDE (n=18, 10개): 0.67 0.33 0.28 0.44 0.56 0.39 0.50 0.39 0.50 0.61
ACF (n=18, 20개): 0.67 0.39 0.50 0.39 0.22 0.28 0.50 0.44 0.44 0.39
0.39 0.22 0.17 0.33 0.28 0.39 0.44 0.39 0.50 0.83
ADF (n=18, 20개): 0.83 0.83 0.67 0.83 0.50 0.50 0.50 0.61 0.33 0.44
0.44 0.33 0.39 0.33 0.50 0.39 0.50 0.56 0.50 0.72
BCF (n=18, 20개): 0.72 0.39 0.50 0.28 0.44 0.28 0.28 0.33 0.28 0.22
0.06 0.22 0.39 0.28 0.28 0.17 0.17 0.39 0.39 0.61
BDF (n=18, 20개): 0.61 0.39 0.50 0.22 0.22 0.11 0.50 0.22 0.56 0.22
0.11 0.33 0.28 0.33 0.22 0.33 0.28 0.28 0.67 0.83
```
---
## 5. 알려진 문제
프로젝트를 다시 열 때 알아둬야 할 사항들입니다.
### 노트북의 셔플 버그
`pre_urp.ipynb` 셀 11에서 4~6음절 단어를 섞어야 하는데 `np.random.shuffle(sw_arr)`**짧은 단어 배열을 다시 섞고 있습니다** (`lw_arr` 이어야 함). 그 결과 `bce_list`~`bdf_list` 는 엑셀 원본 순서 그대로입니다.
> 다만 실제 제시 순서는 PPT의 VBA 매크로가 한 번 더 셔플했으므로(`ACE.pptm`의 단어 순서가 노트북 `ace_list`와 다름을 확인) **실험 자체의 무작위성은 훼손되지 않았습니다.**
### 최종 분석 코드 유실
`pre_urp.ipynb` 셀 17이 **정의된 적 없는 `temp` 변수**를 참조합니다. 위 결과표의 8조건 회귀와 `Result graphs/` 의 그래프를 생성한 코드는 노트북에 남아있지 않습니다. 현재 노트북에는 sklearn 회귀 연습 → 단어 분할 → Dummy 시트 적합까지만 있습니다.
> 위 결과표는 `exp_results1.xlsx` 로부터 독립적으로 재계산해 검증한 값입니다. 8개 조건 중 6개가 발표자료 14쪽 숫자와 소수점까지 일치합니다.
### 발표자료 14쪽 오타 2건
- **ADE의 b**: 발표자료에 `-0.2840` 으로 기재되어 있으나 실제 값은 `-0.1840` 입니다. (−0.2840을 쓰면 10번째 위치의 예측 회상률이 −0.34라는 불가능한 값이 나옵니다.)
- **ACF의 c**: 발표자료에 `0.6881` 로 기재되어 있으나 실제 값은 `0.6444` 입니다. 기재된 값이 BCF의 c와 동일해 복사·붙여넣기 실수로 보입니다.
### 중복 파일
`pre_urp.ipynb`, `pre_urp (1).ipynb`, `pre_urp/pre_urp.ipynb` 세 파일은 **md5 해시가 모두 동일**합니다. 하나만 남겨도 됩니다.
### 사소한 것들
- `Word View/main.js` 의 단어 오타 2개(`고구마입벌레`, `고리대급업자`)는 Auto 버전에서 `고구마잎벌레`, `고리대금업자` 로 수정되었습니다.
- `Word View/main.js``oneToThree` 배열에 `"칼"` 이 **중복**으로 들어있습니다.
- `wordnumber.png` 의 제목이 `"Word bumber difference"` 오타입니다.
- `Word View/history.json` (`{"Hello":"Me too"}`) 과 Auto 서버의 `/your-endpoint` 는 **미완성된 결과 자동저장 기능**의 흔적입니다. 최종적으로 응답은 종이 설문지로 수집했습니다.
---
## 6. 재현 방법
`exp_results1.xlsx` 로부터 위 결과표를 다시 계산하려면:
```python
import pandas as pd, numpy as np
from sklearn import linear_model
for cond in ['ACE','ACF','ADE','ADF','BCE','BCF','BDE','BDF']:
df = pd.read_excel('exp_results1.xlsx', sheet_name=cond)
means = df.mean().to_numpy() # 위치별 평균 회상률
x = np.arange(1, len(means) + 1).reshape(-1, 1)
X = np.concatenate((x**2, x), axis=1) # [x^2, x]
regr = linear_model.LinearRegression(fit_intercept=True).fit(X, means)
a, b = regr.coef_
print(f'{cond}: a={a:.4f} b={b:.4f} c={regr.intercept_:.4f}')
```
필요 패키지: `matplotlib`, `scikit-learn`, `pandas`, `openpyxl`
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
View File
Binary file not shown.
+657
View File
@@ -0,0 +1,657 @@
{
"name": "word-view-auto",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "word-view-auto",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
}
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.1",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/call-bind": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
"integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
"dependencies": {
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.1",
"set-function-length": "^1.1.1"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/content-type": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/define-data-property": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
"integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
"dependencies": {
"get-intrinsic": "^1.2.1",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
"body-parser": "1.20.1",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.5.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.2.0",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.7",
"qs": "6.11.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
"send": "0.18.0",
"serve-static": "1.15.0",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
"dependencies": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
"statuses": "2.0.1",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
"integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
"dependencies": {
"function-bind": "^1.1.2",
"has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
"hasown": "^2.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dependencies": {
"get-intrinsic": "^1.1.3"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-property-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
"integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
"dependencies": {
"get-intrinsic": "^1.2.2"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
},
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/qs": {
"version": "6.11.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
"dependencies": {
"side-channel": "^1.0.4"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/raw-body": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
"mime": "1.6.0",
"ms": "2.1.3",
"on-finished": "2.4.1",
"range-parser": "~1.2.1",
"statuses": "2.0.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/serve-static": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
"dependencies": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
"send": "0.18.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/set-function-length": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
"integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
"dependencies": {
"define-data-property": "^1.1.1",
"get-intrinsic": "^1.2.1",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dependencies": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"engines": {
"node": ">=0.6"
}
},
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"engines": {
"node": ">= 0.8"
}
}
}
}
+14
View File
@@ -0,0 +1,14 @@
{
"name": "word-view-auto",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
}
}
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Word Display</title>
<script src="/public/main.js" defer></script>
<link rel="stylesheet" href="/public/main.css">
</head>
<body>
<div id="settings">
<h1>Settings</h1>
<label for="TypeList">Test Type List: </label>
<input type="text" id="TypeList" value="ACE ACF ADE ADF BCE BCF BDE BDF">
<button id="start">Start</button>
</div>
<!-- Introduction -->
<ul id="Intro">
<li id="wordNumberValue">20개의 짧은 무작위 단어들이 제시됩니다.</li>
<br>
<li id="intervalValue">단어당 제시되는 시간은 2초이며 후에 1초의 공백이 표시됩니다.</li>
<br>
<li>테스트 종료 시, 빨간색의 Finish가 표시됩니다.</li>
<br>
<li>종료 후에는 기억나는 단어를 종이에 작성하세요.</li>
<br>
<li>스페이스바를 누르면 테스트가 바로 시작됩니다.</li>
</ul>
<div id="Word">Ready</div>
</body>
</html>
+26
View File
@@ -0,0 +1,26 @@
#Intro {
width: 1200px;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 60px;
font-family: Arial, Helvetica, sans-serif;
display: none;
}
#Word {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 150px;
font-family: Arial, Helvetica, sans-serif;
display: none;
}
/* #settings {
display: none;
} */
+103
View File
@@ -0,0 +1,103 @@
document.addEventListener('DOMContentLoaded', function () {
let oneToThree = ["낮", "논", "닭", "땀", "못", "빛", "솥", "짐", "턱", "코", "학", "회", "힘", "털", "칼", "춤", "칡", "죄", "값", "겁", "공", "너", "돌", "롤", "망", "벗", "실", "윷", "중", "초", "칼", "통", "폰", "홀", "검도", "결혼", "녹차", "나비", "행운", "등교", "루비", "만두", "무용", "박사", "보물", "사랑", "수리", "어깨", "역사", "윤곽", "자연", "저축", "졸업", "행복", "공간", "궁궐", "남자", "농심", "동심", "달력", "락스", "라임", "모집", "명동", "바람", "보정", "성종", "식기", "유행", "여우", "종점", "자리", "초코", "추위", "킬러", "콩밥", "틴더", "터널", "필적", "포도", "홍수", "형제", "자긍심", "전염병", "주인공", "칸막이", "친근감", "태양풍", "폐막식", "하반신", "황무지", "횡격막", "경기도", "농산물", "단백질", "대통령", "대장균", "동남아", "무기질", "오렌지", "캥거루", "칼국수", "거제도", "공유기", "네이버", "놀이터", "두리안", "달걀찜", "루시퍼", "롤리팝", "망아지", "메아리", "비비빅", "바밤바", "송중기", "성시경", "우리집", "아버지", "지킴이", "정관장", "청국장", "청록색", "큐피드", "코레일", "탕후루", "탕평책", "피해자", "폴라포", "헤이즈", "하르방"];
let fourToSix = ["어림짐작", "인문과학", "작심삼일", "착시효과", "중구난방", "천재지변", "팔방미인", "포화상태", "하루아침", "해수욕장", "허수아비", "홍익인간", "훈민정음", "거두절미", "대중교통", "두드러기", "만유인력", "물리화학", "가시광선", "고등학교", "가위눌림", "고기국수", "나무위키", "너비아니", "데리야끼", "도리토스", "라면사리", "롯데마트", "마음가짐", "모의재판", "보니하니", "바이올린", "세일즈맨", "삼단화환", "오징어회", "어버이날", "장례식장", "종종걸음", "초코머핀", "총알받이", "키득키득", "카이스트", "텔레토비", "토카토카", "피실험자", "페퍼로니", "호랑이굴", "하이마트", "우스갯소리", "청딱따구리", "크리스마스", "아르헨티나", "헌법재판소", "황소개구리", "게으름뱅이", "이데올로기", "순두부찌개", "대중목욕탕", "동음이의어", "프로그래밍", "정월대보름", "식기세척기", "지구온난화", "아이스크림", "오케스트라", "김치볶음밥", "최소공배수", "장수풍댕이", "괭이갈매기", "거짓말쟁이", "나이지리아", "나이팅게일", "담쟁이덩굴", "뒤치닥거리", "라티푼디움", "룩셈부르크", "막대그래프", "뮤직비디오", "바빌로니아", "바다코끼리", "산후조리원", "삼강행실도", "오므라이스", "오리온자리", "중모리장단", "증조할머니", "초코바나나", "초조대장경", "카트라이더", "카자흐스탄", "토이스토리", "타임스퀘어", "폴리에틸렌", "페이퍼타올", "하늘바라기", "하룻강아지", "어중이떠중이", "자이로스코프", "진인사대천명", "한해살이식물", "목도리도마뱀", "패러글라이딩", "자유의여신상", "콘트라베이스", "베이킹파우더", "에스컬레이터", "장대높이뛰기", "히말라야산맥", "나무아미타불", "스카치테이프", "아르키메데스", "조선왕조실록", "증조할아버지", "가시불가사리", "금메달리스트", "폭탄먼지벌레", "가슴지느러미", "가운뎃발가락", "고구마잎벌레", "고리대금업자", "네안데르탈인", "뉴펀들랜드주", "덩굴무늬매듭", "덧치마저고리", "라스베이거스", "라이스페이퍼", "마다가스카르", "마이크로미터", "빨강불가사리", "브레인스토밍", "상정고금예문", "샌프란시스코", "아메리칸드림", "알렉산드리아", "작은할아버지", "전민변정도감", "청분홍메뚜기", "콤팩트디스크", "코니아일랜드", "타이포그래피", "트리케라톱스", "파운드케이크", "프랑켄슈타인", "피보나치수열"];
let words = [];
let currentIndex = 0;
let onecurrentIndex = 0;
let fourcurrentIndex = 0;
let wordsNumber = 10;
let curEnd = 0;
let testType = [];
let curTest = 0;
// 사이트 로드시 리스트 섞기
oneToThree = oneToThree.sort(() => Math.random() - 0.5);
fourToSix = fourToSix.sort(() => Math.random() - 0.5);
console.log('Mixed')
console.log(oneToThree);
console.log(fourToSix);
const wordDisplay = document.getElementById('Word');
const startButton = document.getElementById('start');
startButton.addEventListener('click', () => {
for (i of document.getElementById('TypeList').value.split(' ')) {
let curType = [];
if (i.charAt(0) === 'A') { curType.push(13) } else { curType.push(46) }
if (i.charAt(1) === 'C') { curType.push(2000) } else { curType.push(3000) }
if (i.charAt(2) === 'E') { curType.push(10) } else { curType.push(20) }
testType.push(curType);
}
document.getElementById('settings').style.display = 'none';
newTest()
});
const newTest = () => {
if (testType[curTest][0] === 13) {
words = oneToThree;
curEnd = onecurrentIndex + testType[curTest][2];
currentIndex = onecurrentIndex;
} else {
words = fourToSix;
curEnd = fourcurrentIndex + testType[curTest][2];
currentIndex = fourcurrentIndex;
}
document.getElementById('wordNumberValue').textContent = `${testType[curTest][2]}개의 ${(testType[curTest][0] === 13) ? '짧은' : '긴'} 무작위 단어들이 제시됩니다.`;
document.getElementById('intervalValue').textContent = `단어당 제시되는 시간은 ${testType[curTest][1] / 1000}초이며 후에 1초의 공백이 표시됩니다.`;
document.getElementById('Word').style.display = 'none';
document.getElementById('Intro').style.display = 'block';
wordDisplay.style.color = '#000000';
}
document.addEventListener('keydown', function (event) {
if (event.code === 'Space') {
test()
document.getElementById('Intro').style.display = 'none';
document.getElementById('Word').style.display = 'block';
console.log(words.slice(currentIndex, curEnd));
sendDataToServer(document.getElementById('TypeList').value.split(' ')[currentIndex], words.slice(currentIndex, curEnd));
}
});
const test = () => {
if (currentIndex == curEnd) {
wordDisplay.textContent = 'Finish';
wordDisplay.style.color = '#D1080B';
if (testType[curTest][0] === 13) {
onecurrentIndex = currentIndex;
} else {
fourcurrentIndex = currentIndex;
}
if (curTest < 7) {
setTimeout(() => {
curTest += 1;
newTest()
}, 5000)
}
return
}
wordDisplay.textContent = words[currentIndex];
setTimeout(() => {
wordDisplay.textContent = '';
setTimeout(() => {
currentIndex += 1;
test();
}, 1000)
}, testType[curTest][1])
};
});
function sendDataToServer(ty ,li) {
console.log(JSON.stringify({ list: li }))
fetch('/your-endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ type: ty, list: li })
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch((error) => console.error('Error:', error));
}
+20
View File
@@ -0,0 +1,20 @@
const express = require("express");
const path = require('path')
const app = express();
app.use(express.json()); // JSON 본문을 파싱하기 위해 필요합니다.
app.use("/public", express.static(path.join(__dirname, 'public')));
app.listen(4000, () => {
console.log(`Server running at http://127.0.0.1:4000`);
});
app.get("/", (req, res) => {
res.sendFile(__dirname + "/public/index.html")
// res.send("hello world")
});
app.use(express.urlencoded({ extends: true }));
app.post('/your-endpoint', (req, res) => {
console.log('Received data:', req.body); // 받은 데이터를 콘솔에 출력합니다.
res.json({ message: 'Data received successfully' }); // 응답을 보냅니다.
});
+1
View File
@@ -0,0 +1 @@
{"Hello":"Me too"}
+49
View File
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Word Display</title>
<script src="./main.js" defer></script>
<link rel="stylesheet" href="./main.css">
</head>
<body>
<div id="settings">
<h1>Settings</h1>
<button id="shuffleButton">Mix</button>
<label for="interval">Period: </label>
<input type="number" id="interval" value="2">
<select id="wordLength">
<option value="13">1to3</option>
<option value="46">4to6</option>
</select>
<label for="wordNumber">Words: </label>
<input type="number" id="wordNumber" value="10">
<button id="start">Start</button>
<h2>Rules: </h2>
<p>A: 짧은 단어 / B: 긴 단어</p>
<p>C: 2초 / D: 3초</p>
<p>E: 10개 / F: 20개</p>
</div>
<!-- Introduction -->
<ul id="Intro">
<li id="wordNumberValue">20개의 짧은 무작위 단어들이 제시됩니다.</li>
<br>
<li id="intervalValue">단어당 제시되는 시간은 2초이며 후에 1초의 공백이 표시됩니다.</li>
<br>
<li>테스트 종료 시, 빨간색의 Finish가 표시됩니다.</li>
<br>
<li>종료 후에는 기억나는 단어를 종이에 작성하세요.</li>
<br>
<li>스페이스바를 누르면 테스트가 바로 시작됩니다.</li>
</ul>
<div id="Word">Ready</div>
</body>
</html>
+26
View File
@@ -0,0 +1,26 @@
#Intro {
width: 1200px;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 60px;
font-family: Arial, Helvetica, sans-serif;
display: none;
}
#Word {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 150px;
font-family: Arial, Helvetica, sans-serif;
display: none;
}
/* #settings {
display: none;
} */
+105
View File
@@ -0,0 +1,105 @@
// fetch('history.json')
// .then(response => response.json())
// .then(data => {
// let jsonData = JSON.parse(data);
// console.log(jsonData.hello);
// })
// .catch(error => {
// console.error('Error reading the JSON file:', error);
// });
document.addEventListener('DOMContentLoaded', function () {
let oneToThree = ["낮", "논", "닭", "땀", "못", "빛", "솥", "짐", "턱", "코", "학", "회", "힘", "털", "칼", "춤", "칡", "죄", "값", "겁", "공", "너", "돌", "롤", "망", "벗", "실", "윷", "중", "초", "칼", "통", "폰", "홀", "검도", "결혼", "녹차", "나비", "행운", "등교", "루비", "만두", "무용", "박사", "보물", "사랑", "수리", "어깨", "역사", "윤곽", "자연", "저축", "졸업", "행복", "공간", "궁궐", "남자", "농심", "동심", "달력", "락스", "라임", "모집", "명동", "바람", "보정", "성종", "식기", "유행", "여우", "종점", "자리", "초코", "추위", "킬러", "콩밥", "틴더", "터널", "필적", "포도", "홍수", "형제", "자긍심", "전염병", "주인공", "칸막이", "친근감", "태양풍", "폐막식", "하반신", "황무지", "횡격막", "경기도", "농산물", "단백질", "대통령", "대장균", "동남아", "무기질", "오렌지", "캥거루", "칼국수", "거제도", "공유기", "네이버", "놀이터", "두리안", "달걀찜", "루시퍼", "롤리팝", "망아지", "메아리", "비비빅", "바밤바", "송중기", "성시경", "우리집", "아버지", "지킴이", "정관장", "청국장", "청록색", "큐피드", "코레일", "탕후루", "탕평책", "피해자", "폴라포", "헤이즈", "하르방"];
let fourToSix = ["어림짐작", "인문과학", "작심삼일", "착시효과", "중구난방", "천재지변", "팔방미인", "포화상태", "하루아침", "해수욕장", "허수아비", "홍익인간", "훈민정음", "거두절미", "대중교통", "두드러기", "만유인력", "물리화학", "가시광선", "고등학교", "가위눌림", "고기국수", "나무위키", "너비아니", "데리야끼", "도리토스", "라면사리", "롯데마트", "마음가짐", "모의재판", "보니하니", "바이올린", "세일즈맨", "삼단화환", "오징어회", "어버이날", "장례식장", "종종걸음", "초코머핀", "총알받이", "키득키득", "카이스트", "텔레토비", "토카토카", "피실험자", "페퍼로니", "호랑이굴", "하이마트", "우스갯소리", "청딱따구리", "크리스마스", "아르헨티나", "헌법재판소", "황소개구리", "게으름뱅이", "이데올로기", "순두부찌개", "대중목욕탕", "동음이의어", "프로그래밍", "정월대보름", "식기세척기", "지구온난화", "아이스크림", "오케스트라", "김치볶음밥", "최소공배수", "장수풍댕이", "괭이갈매기", "거짓말쟁이", "나이지리아", "나이팅게일", "담쟁이덩굴", "뒤치닥거리", "라티푼디움", "룩셈부르크", "막대그래프", "뮤직비디오", "바빌로니아", "바다코끼리", "산후조리원", "삼강행실도", "오므라이스", "오리온자리", "중모리장단", "증조할머니", "초코바나나", "초조대장경", "카트라이더", "카자흐스탄", "토이스토리", "타임스퀘어", "폴리에틸렌", "페이퍼타올", "하늘바라기", "하룻강아지", "어중이떠중이", "자이로스코프", "진인사대천명", "한해살이식물", "목도리도마뱀", "패러글라이딩", "자유의여신상", "콘트라베이스", "베이킹파우더", "에스컬레이터", "장대높이뛰기", "히말라야산맥", "나무아미타불", "스카치테이프", "아르키메데스", "조선왕조실록", "증조할아버지", "가시불가사리", "금메달리스트", "폭탄먼지벌레", "가슴지느러미", "가운뎃발가락", "고구마입벌레", "고리대급업자", "네안데르탈인", "뉴펀들랜드주", "덩굴무늬매듭", "덧치마저고리", "라스베이거스", "라이스페이퍼", "마다가스카르", "마이크로미터", "빨강불가사리", "브레인스토밍", "상정고금예문", "샌프란시스코", "아메리칸드림", "알렉산드리아", "작은할아버지", "전민변정도감", "청분홍메뚜기", "콤팩트디스크", "코니아일랜드", "타이포그래피", "트리케라톱스", "파운드케이크", "프랑켄슈타인", "피보나치수열"];
let words = [];
let currentIndex = 0;
let onecurrentIndex = 0;
let fourcurrentIndex = 0;
let wordsNumber = 10;
let interval = 2000; // 기본 시간 간격 (밀리초 단위)
let curEnd = 0;
const wordDisplay = document.getElementById('Word');
const startButton = document.getElementById('start');
const shuffleButton = document.getElementById('shuffleButton');
const intervalInput = document.getElementById('interval');
const wordNumberInput = document.getElementById('wordNumber');
const exportButton = document.getElementById('export');
shuffleButton.addEventListener('click', () => {
oneToThree = oneToThree.sort(() => Math.random() - 0.5);
fourToSix = fourToSix.sort(() => Math.random() - 0.5);
console.log('Mixed')
console.log(oneToThree);
console.log(fourToSix);
});
intervalInput.addEventListener('change', (e) => {
interval = e.target.value * 1000;
});
wordNumberInput.addEventListener('change', (e) => {
wordsNumber = e.target.value;
});
startButton.addEventListener('click', () => {
let shortLong = '';
let wordLength = document.getElementById('wordLength');
if (wordLength.options[wordLength.selectedIndex].value == 13) {
words = oneToThree;
curEnd = onecurrentIndex + Number(wordsNumber);
currentIndex = onecurrentIndex;
shortLong = '짧은';
} else {
words = fourToSix;
curEnd = fourcurrentIndex + Number(wordsNumber);
currentIndex = fourcurrentIndex;
shortLong = '긴';
}
document.getElementById('wordNumberValue').textContent = `${wordsNumber}개의 ${shortLong} 무작위 단어들이 제시됩니다.`;
document.getElementById('intervalValue').textContent = `단어당 제시되는 시간은 ${interval / 1000}초이며 후에 1초의 공백이 표시됩니다.`;
document.getElementById('settings').style.display = 'none';
document.getElementById('Intro').style.display = 'block';
wordDisplay.style.color = '#000000';
});
document.addEventListener('keydown', function (event) {
if (event.code === 'Space') {
test()
document.getElementById('Intro').style.display = 'none';
document.getElementById('Word').style.display = 'block';
console.log(words.slice(currentIndex, curEnd))
}
if (event.code === 'KeyR') {
document.getElementById('Word').style.display = 'none';
document.getElementById('settings').style.display = 'block';
}
});
const test = () => {
if (currentIndex == curEnd) {
wordDisplay.textContent = 'Finish';
wordDisplay.style.color = '#D1080B';
let wordLength = document.getElementById('wordLength');
if (wordLength.options[wordLength.selectedIndex].value == 13) {
onecurrentIndex = currentIndex;
} else {
fourcurrentIndex = currentIndex;
}
return
}
wordDisplay.textContent = words[currentIndex];
setTimeout(() => {
wordDisplay.textContent = '';
setTimeout(() => {
currentIndex += 1;
test();
}, 1000)
}, interval)
};
});
BIN
View File
Binary file not shown.
+717
View File
File diff suppressed because one or more lines are too long
+717
View File
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
matplotlib
scikit-learn
pandas
openpyxl
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

+2360
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.